首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >无法使用Powershell中的GitHttpClient,Newtonsoft.Json版本冲突

无法使用Powershell中的GitHttpClient,Newtonsoft.Json版本冲突
EN

Stack Overflow用户
提问于 2022-03-04 19:52:36
回答 1查看 205关注 0票数 1

我正在尝试使用Powershell 5.1中的Azure DevOps .NET API,特别是Git客户机。在C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer下有一个所有客户端库的副本。

因此,首先,我在一个C#程序中尝试了这一点:

代码语言:javascript
运行
复制
GitHttpClient Cli = new GitHttpClient(new Uri("http://tfs.example.com:8080/tfs/MyCollection/"), new VssCredentials(true));

这一行将抛出一个错误,没有找到Newtonsoft.Json,v9.0.0.0。Newtonsoft.Json.dll的一个副本存在于同一个文件夹中,但它的版本为12。我已经对项目添加了一个对Newtonsoft.Json.dll的显式引用,重新构建了它,并且它工作了--大概是因为该程序在AzDevOps客户端DLL之前加载了Newtonsoft.Json.dll v12,而依赖项解决方案在版本不匹配的情况下获得了这个值。

现在,我在Windows 5.1中尝试了同样的方法(目前是交互式的)。所以首先,我会

代码语言:javascript
运行
复制
$APIPath = "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer"
Add-Type -Path "$APIPath\Newtonsoft.Json.dll" 

那我就会

代码语言:javascript
运行
复制
Add-Type -Path "$APIPath\Microsoft.TeamFoundation.SourceControl.WebApi.dll"

这会引发一个错误,无法找到Newtonsoft.JSON,v9.0.0.0或其依赖项之一。为什么会有这种差异?之前的Add-Type是否会像C#的对应方那样,将DLL加载到进程中并缩短依赖度解析呢?

尝试在第二次Add-Type之前构造一个随机的Newtonsoft对象来强制Newtonsoft加载,假设Add是懒惰的--同样的结果。对象构造。

如果有一种方法可以告诉Powershell“每当请求Newtonsoft9时都要使用Newtonsoft 12”,我很乐意使用它。

UPD:如https://www.koskila.net/how-to-list-all-of-the-assemblies-loaded-in-a-powershell-session/所述,加载的程序集转储确认Newtonsoft 12已加载。Elsewhere at SO,他们声称第一个加载版本获胜,同时加载多个版本是不允许的,除非有一些深层次的魔力(多个AppDomains等等)。但这不是我所看到的。

加载的程序集列表声称已经加载了Microsoft.TeamFoundation.SourceControl.WebApi.dll,但是试图构造GitHttpClient会抛出“无法加载Newtonsoft”错误。

UPD2:更毛茸茸的。所以我在系统上找到了一份Newtonsoft 9的副本,并将其加载到Powershell中。现在执行Add-Type -Path "$APIPath\Microsoft.TeamFoundation.SourceControl.WebApi.dll"行,但是无法找到声称Newtonsoft 6构造函数错误。我曾与ILSpy周旋,发现:

  • MS.TF.SourceControl.WebApi需要Newtonsoft 9
  • MS.TF.SourceControl.WebApi需要System.Net.Http.Formatting (在同一个API中,folder)
  • System.Net.Http.Formatting需要Newtonsoft 6

)。

因此,如果没有桌面应用程序中存在的任何魔法,并且允许上游依赖解决方案,这是不可能的。

UPD3:被认为是挂钩AppDomain.AssemblyResolve,但是Powershell (至少v5)不能用返回值挂钩事件。在其他地方,他们声称程序集的后期版本应该满足早期版本的要求,但它似乎只适用于主要版本。在AppDomain的C#应用程序中,AssemblyResolve方法似乎没有被捕获。它能被AppDomain属性驱动吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-03-22 19:05:33

序言: C#程序中的依赖解决方案并不是在自动请求v9/6的地方获取v12的;它这样做只是因为编译程序的配置文件告诉了它,而且这种情况只发生过一次,因为项目中引用了Newtonsoft v12。感谢@n0rd指出这一点。将强命名的依赖程序集解析为更高的主要版本是而不是,这是.NET 4.5-8中的默认行为。

修改Powershell的配置以实现同样的目标可能是可能的,但我没有去那里。最初需要这种逻辑的部分最终将在我无法控制的服务器上运行,因此管理开销越少,越好。现在,关于工作的答案。

--您可以在Powershell 5中提供一个解析处理程序--毕竟是,它告诉.NET使用加载的Newtonsoft版本,而不是其他版本。事情是这样的:

代码语言:javascript
运行
复制
$OnAssemblyResolve = [ResolveEventHandler] {
    param($o, $e)
    if($e.Name.StartsWith("Newtonsoft.Json,"))
    {
        return [AppDomain]::CurrentDomain.GetAssemblies() | ?{$_.FullName.StartsWith("Newtonsoft.Json,")}
    }
    return $null
}

Add-Type -Path "$APIPath\Newtonsoft.Json.dll"
[AppDomain]::CurrentDomain.add_AssemblyResolve($OnAssemblyResolve)
Add-Type -Path "$APIPath\Microsoft.TeamFoundation.SourceControl.WebApi.dll"
Add-Type -Path "$APIPath\Microsoft.VisualStudio.Services.WebApi.dll"
Add-Type -Path "$APIPath\System.Net.Http.Formatting.dll"
[AppDomain]::CurrentDomain.remove_AssemblyResolve($OnAssemblyResolve)

一旦加载了依赖于Newtonsoft的程序集(特别是System.Net.Http.Formatting),就会删除处理程序。否则,它可能会干扰Powershell自身的功能,并导致堆栈溢出异常,其中Powershell中的“程序集未找到”条件将触发处理程序,该处理程序要求运行相同的程序集,从而导致无休止的递归。在我的例子中,它发生在下游,当脚本试图抛出一个不相关的异常时,需要加载System.Management.Automation.resources,没有找到它,等等。

我之前所说的Powershell 5不能用返回值连接.NET事件的说法是错误的。我隐约记得读过一些事件处理cmdlet的文档,其中提到不支持从处理程序块返回值,我猜这就是我的误解的来源。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71356583

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档