PowerShell二进制模块组件依赖错误

本文关键字:依赖 错误 组件 模块 二进制 PowerShell | 更新日期: 2023-09-27 18:11:07

我正在开发PowerShell二进制模块它使用Json。. NET和其他库

我得到这个异常"无法加载文件或程序集"Newtonsoft。Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed'或其依赖项之一。系统找不到指定的文件

在硬盘上我有一个更新的版本(版本7.0.2)

这样的问题很容易在控制台,web或桌面应用程序中解决,使用应用程序。配置或"web. conf"。通过这样的行配置

<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>

如何为PowerShell二进制模块做类似的事情?

PowerShell二进制模块组件依赖错误

在开发使用多个第三方库(Google API, Dropbox, Graph等)的PowerShell模块时遇到了这个问题,我发现以下解决方案是最简单的:

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;
    }
}

注意,在方法中,我有两种可能的方法来引用程序集,但它们都做同样的事情,它们强制使用该程序集的当前版本。(不管它是通过类引用还是通过dll文件加载)

要在任何命令行中使用它,请在PSCmdLet的BeginProcessing()方法中添加以下事件处理程序。

AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_BindingRedirect;

目前为止我发现最接近的是:

  1. 将问题程序集添加到manifest的RequiredAssemblies中——这会导致它在加载模块时被加载到AppDomain中。
  2. 使用这个SO答案中的代码-它向当前的AppDomain添加了一个AssemblyResolve处理程序,该处理程序搜索已经加载的程序集并返回通过强名称和PublicKeyToken匹配的程序集
  3. 使用模块后,您必须做以下操作以避免退出时堆栈溢出:[System.AppDomain]::CurrentDomain.remove_AssemblyResolve($OnAssemblyResolve)

步骤1和步骤2都可以封装在模块中,但步骤3不能,这意味着这不适合作为通用解决方案-调用者必须知道它。所以我还在寻找一个更好的方法。

你需要在你的模块中添加一个清单。

最简单的方法是:

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

然后手动修改manifest文件以进行任何其他调整。

如果清单不能解决问题,您可能需要拉出核锤并为所有powershell设置绑定重定向,如powershell - Assembly绑定重定向中提到的在应用程序配置文件

对于二进制模块,为了成功导入/功能,需要在manifest文件中填充一些键:

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.

这些是您需要为模块"工作"填充的唯一键-尽管我强烈建议通过New-ModuleManifest -path MyNewModule.psd1生成的.psd1文件来梳理其他元数据值,以帮助丰富模块的功能。

另外,确保目录结构、.psd1文件和程序集的名称都是一致的。

SampleModule'
SampleModule'SamleModule.dll
SampleModule'SampleModule.psd1

…应该可以了