Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cross platform system libraries reference for PowerShell and Server Manager module

Tags:

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.

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.

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.

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.

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.

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.

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.

The possible solutions I know are:

  1. I could try to dynamically load the assemblies without referencing to them in visual studio using Assembly.Load() and dynamic 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).

  2. I can add the assemblies I need to GAC but this may lead to some dependency hell because both Automation and ServerManager may have lots of other dependencies and I only right now discovered two of them.

What other options do I have?

like image 348
Mike Avatar asked Oct 05 '15 23:10

Mike


1 Answers

Have you tried assembly redirection in your .config file for those references?

  <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>
like image 99
Cleptus Avatar answered Oct 07 '22 16:10

Cleptus