The program I am writing is using System.Management.Automation
library to make use of powershell classes and interfaces that are defined there. There are two versions of those libraries: 1.0.0.0 and 3.0.0.0. Windows Server 2008 has in its GAC version 1.0 and Windows Server 2012 has in its GAC both 1.0 and 3.0.
我正在编写的程序正在使用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。
To be able to use this library in the VS project, I have to reference it. Now it is a decision to make, which one should I reference? Well, since both servers have 1.0 in their GAC, it should be safe to reference to the 1.0 one. Still, just in case, I'll copy it locally if there was some rare (or common?) case where it doesn't exist in the GAC.
为了能够在VS项目中使用这个库,我必须引用它。现在这是一个决定,我应该参考哪一个?好吧,既然两台服务器的GAC都是1.0,那么引用1.0的服务器应该是安全的。不过,为了以防万一,我会在本地复制它,如果有一些罕见的(或常见的?)情况,它在GAC中不存在。
Example code of using this library:
使用此库的示例代码:
using (PowerShell PS = PowerShell.Create())
{
PS.AddScript("Import-Module ServerManager")
.Invoke();
}
The Import-Module Servermanager
command causes powershell to import another dll, Microsoft.Windows.ServerManager
. Here the problem starts.
Import-Module Servermanager命令导致powershell导入另一个dll,即Microsoft.Windows.ServerManager。问题开始了。
Windows Server 2008 has only version 6.1.0.0 of this library where Windows Server 2012 has version 6.3.0.0. I assume that Automation
's 1.0 to 6.1 and 3.0 to 6.3 version similarity is not a coincidence.
Windows Server 2008只有此库的6.1.0.0版,其中Windows Server 2012的版本为6.3.0.0。我认为Automation的1.0到6.1和3.0到6.3版本的相似性并不是巧合。
When I'm using my program on Windows Server 2008, it works fine but when I am trying to use it on Windows Server 2012, this Automation 1.0 assembly is trying to load ServerManager assembly version 6.1 (!) which 2012 doesn't have. 2012 would prefer to use Automation assembly v3.0 and load ServerManager v6.3.
当我在Windows Server 2008上使用我的程序时,它工作正常,但当我尝试在Windows Server 2012上使用它时,此Automation 1.0程序集正在尝试加载2012年没有的ServerManager程序集版本6.1(!)。 2012年更愿意使用Automation assembly v3.0并加载ServerManager v6.3。
I assume there is some way to "tell" the program to load assembly X if server version Y and assembly A if server version B but where does it go? How can I be sure then that I wont encounter some server where there will be version 2.0 or 4.0 or whatever.
我假设有一些方法可以“告诉”程序加载程序集X,如果服务器版本Y和程序集A,如果服务器版本B,但它去哪里?我怎么能确定我不会遇到一些服务器,那里会有版本2.0或4.0或其他什么。
The problem is that I can't reference (copy locally) the ServerManager assembly because (I think) as long as I can "tell" my program where it should look for assemblies, I can't tell the Automation's assembly where to look for other assemblies. By analysis using procmon, I could see as it exactly knew where to look for because it instantly navigated to C:\Windows\System32\WindowsPowerShell\v1.0\Modules\ServerManager
to look for the ServerManager assembly.
问题是我不能引用(本地复制)ServerManager程序集,因为(我认为),只要我能“告诉”我的程序应该在哪里查找程序集,我无法告诉自动化程序集在何处查找其他组件。通过使用procmon进行分析,我可以看到它确切地知道在哪里寻找,因为它立即导航到C:\ Windows \ System32 \ WindowsPowerShell \ v1.0 \ Modules \ ServerManager以查找ServerManager程序集。
The possible solutions I know are:
我所知道的可能解决方案是:
-
I could try to dynamically load the assemblies without referencing to them in visual studion using
Assembly.Load()
anddynamic
object for which using, as someone suggested, I should burn in fiery hell (I assume that person referred to that it's extremely bug prone).我可以尝试使用Assembly.Load()和动态对象动态加载程序集,而无需使用Assembly.Load()和动态对象引用它们,正如有人建议的那样,我应该在火热的地狱中使用(我假设那个人提到它非常容易出错) )。
-
I can add the assemblies I need to GAC but this may lead to some dependency hell because the both Automation and ServerManager may have lots of other dependencies and I only right now discovered two of them.
我可以将我需要的程序集添加到GAC,但这可能导致一些依赖地狱,因为Automation和ServerManager可能有很多其他依赖项,我现在才发现其中两个。
What other options do I have?
我还有其他选择吗?
2 个解决方案
#1
0
Have you tried assembly redirection in your .config file for those references?
您是否在.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
0
You could just check for the OS Version and depending on that import the corresponding library.
您可以检查操作系统版本,并根据导入相应的库。
# show complete OS information
$os = Get-CimInstance Win32_OperatingSystem | Format-List *
Just check the name or directly use the version.
只需检查名称或直接使用该版本。
$os.version #6.3.9600
$os.name #Microsoft Windows Server 2012 R2
Hope this serves as another option.
希望这是另一种选择。
#1
0
Have you tried assembly redirection in your .config file for those references?
您是否在.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
0
You could just check for the OS Version and depending on that import the corresponding library.
您可以检查操作系统版本,并根据导入相应的库。
# show complete OS information
$os = Get-CimInstance Win32_OperatingSystem | Format-List *
Just check the name or directly use the version.
只需检查名称或直接使用该版本。
$os.version #6.3.9600
$os.name #Microsoft Windows Server 2012 R2
Hope this serves as another option.
希望这是另一种选择。