3

我正在尝试使用我们内部 .net 应用程序中的 DLL。

DLL 有一个 App.config 文件,并且有一个配置部分,用于指定配置处理程序。

我无法让我的 PowerShell 脚本加载此 dll。

我已将问题归结为最简单的形式。

这是我正在尝试的 PowerShell 脚本:

[appdomain]::CurrentDomain.SetData("APP_CONFIG_FILE", "D:\CustomConfig\CustomConfig\CustomConfigTestHarness\bin\Debug\CustomConfigTestHarness.exe.config")
Add-Type -Path 'D:\CustomConfig\CustomConfig\CustomConfigTestHarness\bin\Debug\CustomConfig.dll'
$mainClass = New-Object CustomConfig.Main
$mainClass.TestConfig()

这是配置文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <section name="PrimarySqlServers" type="CustomConfig.ServerConfiguration, CustomConfig" />
    </configSections>
    <PrimarySqlServers>
        <Server name="data source=SQL\SQL2005; Initial Catalog=master;  Trusted_Connection=yes;"/>
    </PrimarySqlServers>
</configuration>

这是DLL:

namespace CustomConfig
{
    public class Main
    {
        public string TestEcho(string message)
        {
            return message;
        }

        public string TestConfig()
        {
            Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            string sectionName = "PrimarySqlServers";
            ServerConfiguration serverConfiguration = configuration.GetSection(sectionName) as ServerConfiguration;
            if (serverConfiguration == null || serverConfiguration.ServerList.Count == 0)
            {
                throw new ConfigurationErrorsException(string.Format(CultureInfo.InvariantCulture, "ERR_MISSING_OR_EMPTY_SECTION", sectionName));
            }
            ServerConfigurationEntry entry = serverConfiguration.ServerList[0];
            {
                return entry.Name;
            }
        }
    }
}

configClass.cs 文件内容如下:

using System;
using System.Configuration;
using System.Diagnostics;

namespace CustomConfig
{
    /// <summary>
    /// Contains individual configuration information about a site to be deployed
    /// </summary>
    public class ServerConfiguration : ConfigurationSection
    {
        /// <summary>
        /// Get the collection of assembly items
        /// </summary>
        [ConfigurationProperty("", IsDefaultCollection = true)]
        public ServerConfigurationCollection ServerList
        {
            get { return (ServerConfigurationCollection) base[""]; }
        }
    }

    /// <summary>
    /// ContextCollection - represents the collection of context nodes
    /// </summary>
    public class ServerConfigurationCollection : ConfigurationElementCollection
    {
        /// <summary>
        /// Get the assembly item element with the given name
        /// </summary>
        /// <param name="name">The name of the item you want</param>
        /// <returns>The item specified</returns>
        public new ServerConfigurationEntry this[string name]
        {
            get
            {
                if (IndexOf(name) < 0) return null;
                return (ServerConfigurationEntry) BaseGet(name);
            }
        }

        /// <summary>
        /// Get a assembly item element by index
        /// </summary>
        /// <param name="index">The index of the item to get</param>
        /// <returns>The item specified</returns>
        public ServerConfigurationEntry this[int index]
        {
            get { return (ServerConfigurationEntry) BaseGet(index); }
        }

        /// <summary>
        /// Clear the collection of items
        /// </summary>
        public void Clear()
        {
            BaseClear();
        }

        /// <summary>
        /// Add a new item to the collection
        /// </summary>
        /// <param name="name">The name of the site to add</param>
        public void AddItem(string name)
        {
            ServerConfigurationEntry newEntry = new ServerConfigurationEntry();
            newEntry.Name = name;
            this.BaseAdd(newEntry, true);
        }


        /// <summary>
        /// Get the index of a given assembly item
        /// </summary>
        /// <param name="name">The name of the item to get the index of</param>
        /// <returns>The index of the given item, or -1 if not found</returns>
        public int IndexOf(string name)
        {
            for (int index = 0; index < base.Count; index++)
            {
                if (string.Compare(this[index].Name, name, StringComparison.OrdinalIgnoreCase) == 0)
                    return index;
            }

            return -1;
        }

        /// <summary>
        /// Get the type of collection. BasicMap in this case.
        /// </summary>
        public override ConfigurationElementCollectionType CollectionType
        {
            get { return ConfigurationElementCollectionType.BasicMap; }
        }

        /// <summary>
        /// Factory up a new element
        /// </summary>
        /// <returns>A new element</returns>
        protected override ConfigurationElement CreateNewElement()
        {
            return new ServerConfigurationEntry();
        }

        /// <summary>
        /// Get the unique key for a assembly item element
        /// </summary>
        /// <param name="element">The element to get the key for</param>
        /// <returns>A unique identifier for the element</returns>
        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((ServerConfigurationEntry) element).Name;
        }

        /// <summary>
        /// Get the XML element name for elements of this type
        /// </summary>
        protected override string ElementName
        {
            get { return "Server"; }
        }
    }

    /// <summary>
    /// ContextElement - represents a single context element in the config
    /// </summary>
    [DebuggerDisplay("{Name}")]
    public class ServerConfigurationEntry : ConfigurationElement
    {
        private const string NAME = "name";

        /// <summary>
        /// Get or set the server name or connection string
        /// </summary>
        [ConfigurationProperty(NAME, DefaultValue = "", IsRequired = true, IsKey = true)]
        public string Name
        {
            [DebuggerStepThrough]
            get { return (string) this[NAME]; }
            [DebuggerStepThrough]
            set { this[NAME] = value; }
        }
    }
}

当我尝试运行它时收到的错误消息是:

 Exception calling `"TestConfig" with "0" argument(s)`: 

 "An error occurred creating the configuration section handler for PrimarySqlServers:
 Could not load file or assembly 'CustomConfig' or one of its dependencies. The system cannot find the file specified. 
(D:\CustomConfig\CustomConfig\CustomConfigTestHarness\bin\Debug\CustomConfigTestHarness.exe.config line 4)"
    At C:\dll.ps1:15 char:1
    + $mainClass.TestConfig()
    + ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : ConfigurationErrorsException
4

2 回答 2

3

您遇到的问题是程序集不在.net 的程序集搜索路径中。

您可以通过许多不同的方式来解决这个问题(包括将程序集放入 GAC 等)。

将有关程序集的其余信息添加到您的部分密钥(版本、文化、公钥令牌......类似这样的东西)可能就足够了:

<section name="PrimarySqlServers" type="CustomConfig.ServerConfiguration, CustomConfig, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /> 

另一种方法是编写事件处理程序:

$configdll = 'D:\CustomConfig\CustomConfig\CustomConfigTestHarness\bin\Debug\CustomConfig.dll'

[System.AppDomain]::CurrentDomain.add_AssemblyResolve({
    param($source, $assembly)
    # Detect that they're looking for YOUR assembly specifically
    if($assembly.Name.Split(",")[0] -eq "CustomConfig") {
        # And load it for them: your path will be difference
        return [System.Reflection.Assembly]::LoadFile( $configdll  )
    }
})

另一种方法是将 dll 放在应用程序的主目录中。但在这种情况下,那是你的 Windows\System32\WindowsPowerShell\v1.0\ ...所以这可能不是一个好计划。

于 2014-05-09T16:47:52.153 回答
0

好吧,我认为在您的自定义配置部分中,您的程序集名称不正确。

根据您的帖子,这应该是:

<section name="PrimarySqlServers" type="CustomConfig.ServerConfiguration, CustomConfigTestHarness.exe" />

第二个参数是包含 CustomConfig.ServerConfiguration 类型定义的程序集或可执行文件名称。

于 2013-02-26T08:23:54.843 回答