【发布时间】: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 程序集。
我知道的可能的解决方案是:
我可以尝试使用
Assembly.Load()和dynamic对象在 Visual Studio 中动态加载程序集而不引用它们,正如有人建议的那样,我应该在火热的地狱中燃烧(我假设那个人提到它非常容易出错)。我可以将我需要的程序集添加到 GAC,但这可能会导致一些依赖地狱,因为 Automation 和 ServerManager 可能有很多其他依赖项,而我现在才发现其中两个。
我还有什么其他选择?
【问题讨论】:
标签: c# powershell visual-studio-2012 .net-assembly