PowerShell binary module assembly dependency error

I am developing a PowerShell binary module. It uses Json.NET and other libraries.

I get this exception "Failed to load the file or assembly" Newtonsoft.Json, Version = 6.0.0.0, Culture = neutral, PublicKeyToken = 30ad4fe6b2a6aeed "or one of its dependencies. The system cannot find the specified file. '

On the hard drive, I have an updated version (version 7.0.2)

Problems like this are easily resolved in a console, web or desktop application using app.config or "web.config" via lines like this

<dependentAssembly>
    <assemblyIdentity name="Newtonsoft.Json" culture="neutral" publicKeyToken="30ad4fe6b2a6aeed" />
    <bindingRedirect oldVersion="0.0.0.0-7.0.0.0" newVersion="7.0.0.0" />
  </dependentAssembly>

How can I do something like this for a PowerShell binary module?

+4
source share
4 answers

Having collected this problem myself when developing a PowerShell module that uses several third-party libraries (Google API, Dropbox, Graph, etc.), I found the following solution the simplest:

public static Assembly CurrentDomain_BindingRedirect(object sender, ResolveEventArgs args)
{
    var name = new AssemblyName(args.Name);
    switch (name.Name)
    {
        case "Microsoft.Graph.Core":
            return typeof(Microsoft.Graph.IBaseClient).Assembly;

        case "Newtonsoft.Json":
            return typeof(Newtonsoft.Json.JsonSerializer).Assembly;

        case "System.Net.Http.Primitives":
            return Assembly.LoadFrom("System.Net.Http.Primitives.dll");

        default:
            return null;
    }
}

Please note that in the method I have two possible ways to reference the assembly, but both of them do the same thing, they force the current version of this assembly to be used. (Regardless of whether it is loaded through a class link or a dll file upload)

To use this in any cmd-let, add the following event handler to the BeginProcessing () method for PSCmdLet.

AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_BindingRedirect;
+3
source

The closest I have found so far:

  • Add a problem assembly to the RequiredAssemblies manifest - this forces it to load into the AppDomain when the module loads.
  • this SO answer - AssemblyResolve AppDomain, , PublicKeyToken
  • , : [System.AppDomain]::CurrentDomain.remove_AssemblyResolve($OnAssemblyResolve)

1 2 , 3 , , - . .

+2

.

:

New-ModuleManifest -RequiredAssemblies:"path\to\newtonSoft.dll"

.

, powershell, Powershell - NOT

0

, /:

RootModule = <'binaryModule.dll'>
RequiredAssemblies = <'binaryModule.dll'>
CmdletstoExport = '*' <--no need to restrict anything here, as
    only the public functions you've developed in the assembly
    will be exported to the user.

These are the only keys you need to fill in for the module to work. Although I highly recommend combing the .psd1 file generated New-ModuleManifest -path MyNewModule.psd1by the fact that other metadata values ​​will help enrich the functionality of your module.

Also, make sure that the names of the directory structure, .psd1 file, and assembly are consistent.

SampleModule\
SampleModule\SamleModule.dll
SampleModule\SampleModule.psd1

... that should do it.

0
source

Source: https://habr.com/ru/post/1605940/


All Articles