简体   繁体   中英

PowerShell Binary Module assembly dependency error

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

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

On hard drive I have an updated version of it (version 7.0.2)

Problems like that are easily solved in console, web or desktop application, with 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 similar for PowerShell binary module?

After coming across this issue myself while developing a PowerShell module that uses multiple 3rd party libraries (Google API, Dropbox, Graph, etc) I found the following solution was 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;
    }
}

Note in the method, I've got two possible ways to reference the assembly, but both of them do the same thing, they force the current version of that assembly to be used. (Regardless if it is loaded via class reference or dll file load)

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

AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_BindingRedirect;

The closest i've found so far is:

  1. Add the problem assembly to the manifest's RequiredAssemblies - this causes it to be loaded into the AppDomain when the module is loaded.
  2. Use the code from this SO answer - it adds an AssemblyResolve handler to the current AppDomain, which searches for assemblies already loaded and returns ones which match by strong name and PublicKeyToken
  3. After using the module, you have to do the following to avoid stack overflows when exiting: [System.AppDomain]::CurrentDomain.remove_AssemblyResolve($OnAssemblyResolve)

Steps 1 and 2 could both be encapsulated in the module, but step 3 can't, which means this isn't suitable as a general solution - the caller has to know about it. So I'm still searching for a better way.

You need to add a manifest to your module.

The simplest way is:

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

Then modify the manifest file manually for any other tweaks.

If the manifest doesn't solve the problem, you may need to pull out the nuclear hammer and set the binding redirects for ALL of powershell as mentioned in Powershell - Assembly binding redirect NOT found in application configuration file

For binary modules, there are a few keys that need to be populated in the manifest file for successful import/functionality:

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.

Those are the only keys you need to populate for the module to 'work' -- though I highly suggest combing through the .psd1 file generated by New-ModuleManifest -path MyNewModule.psd1 to what other metadata values would help enrich the functionality of your module.

Also, ensure the names of the directory structure, .psd1 file, and assembly are all consistent.

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

...that should do it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM