【问题标题】:Cross platform system libraries reference for PowerShell and Server Manager modulePowerShell 和服务器管理器模块的跨平台系统库参考
【发布时间】:2016-01-02 18:13:34
【问题描述】:

我正在编写的程序使用System.Management.Automation 库来利用在那里定义的PowerShell 类和接口。这些库有两个版本:1.0.0.0 和 3.0.0.0。 Windows Server 2008 的 GAC 版本为 1.0,Windows Server 2012 的 GAC 版本为 1.0 和 3.0。

为了能够在VS项目中使用这个库,我必须引用它。现在是一个决定,我应该参考哪一个?好吧,既然两台服务器的 GAC 中都有 1.0,那么引用 1.0 应该是安全的。不过,以防万一,如果 GAC 中不存在一些罕见(或常见?)的情况,我会在本地复制它。

使用该库的示例代码:

using (PowerShell PS = PowerShell.Create())
{

    PS.AddScript("Import-Module ServerManager")
        .Invoke();
}

Import-Module Servermanager 命令导致 PowerShell 导入另一个 dll,Microsoft.Windows.ServerManager。问题从这里开始。

Windows Server 2008 仅具有此库的 6.1.0.0 版本,而 Windows Server 2012 具有 6.3.0.0 版本。我假设 Automation 的 1.0 到 6.1 和 3.0 到 6.3 的版本相似性不是巧合。

当我在 Windows Server 2008 上使用我的程序时,它工作正常,但是当我尝试在 Windows Server 2012 上使用它时,这个自动化 1.0 程序集正在尝试加载 2012 年没有的 ServerManager 程序集版本 6.1 (!)没有。 2012 更喜欢使用自动化程序集 v3.0 并加载 ServerManager v6.3。

我假设有一些方法可以“告诉”程序加载程序集 X 如果服务器版本 Y 和程序集 A 如果服务器版本 B 但它会去哪里?我怎么能确定我不会遇到一些有 2.0 或 4.0 或其他版本的服务器。

问题是我无法引用(在本地复制)ServerManager 程序集,因为(我认为)只要我可以“告诉”我的程序应该在哪里查找程序集,我就可以'不要告诉自动化程序集在哪里寻找其他程序集。通过使用 procmon 进行分析,我可以看到它确切地知道要查找的位置,因为它立即导航到 C:\Windows\System32\WindowsPowerShell\v1.0\Modules\ServerManager 以查找 ServerManager 程序集。

我知道的可能的解决方案是:

  1. 我可以尝试使用 Assembly.Load()dynamic 对象在 Visual Studio 中动态加载程序集而不引用它们,正如有人建议的那样,我应该在火热的地狱中燃烧(我假设那个人提到它非常容易出错)。

  2. 我可以将我需要的程序集添加到 GAC,但这可能会导致一些依赖地狱,因为 Automation 和 ServerManager 可能有很多其他依赖项,而我现在才发现其中两个。

我还有什么其他选择?

【问题讨论】:

    标签: c# powershell visual-studio-2012 .net-assembly


    【解决方案1】:

    您是否尝试过在 .config 文件中针对这些引用进行程序集重定向?

      <runtime>
        <assemblyBinding appliesTo="v2.0.50727" xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="System.Web.Extensions" publicKeyToken="31bf3856ad364e35"/>
            <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
          </dependentAssembly>
          <dependentAssembly>
            <assemblyIdentity name="System.Web.Extensions.Design" publicKeyToken="31bf3856ad364e35"/>
            <bindingRedirect oldVersion="1.0.0.0-1.1.0.0" newVersion="3.5.0.0"/>
          </dependentAssembly>
        </assemblyBinding>
      </runtime>

    【讨论】:

      【解决方案2】:

      您可以只检查操作系统版本并根据该版本导入相应的库。

      # show complete OS information
      $os = Get-CimInstance Win32_OperatingSystem | Format-List *
      

      只需检查名称或直接使用版本。

      $os.version #6.3.9600
      $os.name #Microsoft Windows Server 2012 R2
      

      希望这是另一种选择。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-11
        • 2022-07-26
        • 2012-09-15
        • 2011-06-22
        • 2017-10-12
        • 2014-04-27
        相关资源
        最近更新 更多