我有一个自定义.NET程序集,其中包含一些PowerShell cmdlet,而不是我用于常见域相关任务。我刚刚创建了一个新的cmdlet,它引用了第三方库,该库引用了Newtonsoft.Json 4.5.0.0。但是我的其他项目之一使用最新版本的json.net(6.0.0.0)。所以在PowerShell Fusion的运行时抛出一个错误,说它无法加载newtonsoft.json 4.5.0.0。
我尝试过创建一个powershell.exe.config并在其中放置一个程序集重定向:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json", Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed/>
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
但这似乎不起作用。融合日志确实表明它正在查找这个新的配置文件中的powershell,但它似乎没有获得重定向。
在这里难以理解解决方案。任何线索可能是什么问题?同样的重定向在我的一些商业服务中起作用,否则会出现同样的问题(他们也使用第三方库和json.net 6)。
干杯
答案 0 :(得分:22)
不确定它是如何在一年多以前工作的,但是今天在Windows 10上使用PowerShell 5.0.10240.16384我能够进行程序集重定向(在我的情况下从FSharp.Core
4.3到4.4)的唯一方法是手动根据{{3}}解决程序集依赖关系。我尝试了其他所有解决方案,例如创建powershell.exe.config
文件或尝试加载其他*.config file
,但这些都没有。
唯一的“陷阱”(至少对我而言)是,因为我不在任何地方都有FSharp.Core 4.3,我需要手动将其重定向到4.4。我最终使用
$FSharpCore = [reflection.assembly]::LoadFrom($PSScriptRoot + "\bin\LIBRARY\FSharp.Core.dll")
$OnAssemblyResolve = [System.ResolveEventHandler] {
param($sender, $e)
# from:FSharp.Core, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
# to: FSharp.Core, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
if ($e.Name -eq "FSharp.Core, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") { return $FSharpCore }
foreach($a in [System.AppDomain]::CurrentDomain.GetAssemblies())
{
if ($a.FullName -eq $e.Name)
{
return $a
}
}
return $null
}
[System.AppDomain]::CurrentDomain.add_AssemblyResolve($OnAssemblyResolve)
我首先从某个地方加载正确版本的FSharp.Core
,因为GAC中的版本已经过时了(我想这可能也是你的情况)
答案 1 :(得分:0)
我发现尝试使用 [System.AppDomain]::CurrentDomain.add_AssemblyResolve
解析在 PowerShell 中附加了处理程序的程序集可能会导致问题,尤其是在 PowerShell ISE 中。
或者,这可以通过实现 PSCmdlet
接口在根模块程序集(包含 IModuleAssemblyInitializer
类)中处理。
以接受的答案为例,它可以重写为:
public class ModuleInitializer : IModuleAssemblyInitializer
{
public void OnImport()
{
var fSharpCore = Assembly.LoadFrom(Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "FSharp.Core.dll"));
AppDomain.CurrentDomain.AssemblyResolve += (object sender, ResolveEventArgs e) =>
{
// from:FSharp.Core, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// to: FSharp.Core, Version=4.4.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
if (e.Name == "FSharp.Core, Version=4.3.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a") { return fSharpCore; }
foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
{
if (a.FullName == e.Name)
{
return a;
}
}
return null;
};
}
}
就我而言,我使用这种机制来查找伴随的 .dll.config
并根据 dependentAssembly/bindingRedirect
元素进行重定向。