C# 获取VisualStudio在VSIX项目中存储的Nuget凭据
我正在开发一个VisualStudio扩展(VSIX项目),它需要管理给定项目的Nuget包 我已经在使用C# 获取VisualStudio在VSIX项目中存储的Nuget凭据,c#,visual-studio,nuget,visual-studio-extensions,vsix,C#,Visual Studio,Nuget,Visual Studio Extensions,Vsix,我正在开发一个VisualStudio扩展(VSIX项目),它需要管理给定项目的Nuget包 我已经在使用IVsPackageInstaller服务,但这是有限的,我需要更多功能(例如获取给定软件包的最新版本号) 我搜索了,但没有找到任何关于如何以编程方式与VisualStudio包管理器交互的信息,所以我决定直接使用NuGetAPI 我使用WebRequest类向NuGetAPI发送HTTP请求(因为我们不能在VSIX项目中使用HttpClient),但我遇到了一个问题:请求将发送到需要身份验
IVsPackageInstaller
服务,但这是有限的,我需要更多功能(例如获取给定软件包的最新版本号)
我搜索了,但没有找到任何关于如何以编程方式与VisualStudio包管理器交互的信息,所以我决定直接使用NuGetAPI
我使用WebRequest
类向NuGetAPI发送HTTP请求(因为我们不能在VSIX项目中使用HttpClient
),但我遇到了一个问题:请求将发送到需要身份验证的私有Nuget提要!(托管在Azure DevOps上)
我曾经检查发送到Azure DevOps服务器的HTTP请求。我看到一个POST请求转到https://app.vssps.visualstudio.com/_apis/Token/SessionTokens
带有响应令牌,但这不是我要找的令牌
传递给Nuget API的令牌是一个Basic
令牌,它来自我不知道在哪里。我在捕获的HTTP响应中找不到该令牌
我还可以看到,对我们的Azure DevOps服务器的一些响应包含一些类似这样的标题(我更改了GUID)
我可以在%userprofile%\AppData\Local\.IdentityService\AccountStore.json
文件中找到这个GUID,这里肯定发生了一些事情。同一文件夹中的SessionTokens.json
文件看起来也很有趣,但它是加密的
我还尝试在注册表中挖掘,看看是否可以在中指定的路径中找到感兴趣的信息,但似乎VS2017不再在那里存储令牌
我还加载了privateregistry.bin
文件(也称为visualstudio设置存储
)并到处搜索,但找不到任何东西
因此,我不想尝试对VisualStudio进行反向工程,而是想直接访问它的凭据提供程序。我试图访问几个服务和类
var componentModel = await ServiceProvider.GetGlobalServiceAsync(typeof(SComponentModel)) as IComponentModel;
var credentialProvider = componentModel.GetService<IVsCredentialProvider>();
var credentialServiceProvider = componentModel.GetService<ICredentialServiceProvider>();
var defaultCredentialServiceProvider = new DefaultVSCredentialServiceProvider();
var componentModel=wait ServiceProvider.GetGlobalServiceAsync(typeof(scoComponentModel))作为IComponentModel;
var credentialProvider=componentModel.GetService();
var-credentialServiceProvider=componentModel.GetService();
var defaultCredentialServiceProvider=新的DefaultVSCredentialServiceProvider();
但它们都不起作用(返回null或Exception)
我在Github的项目中漫游,但找不到我的答案
还有许多Nuget软件包,如Nuget.PackageManagement.VisualStudio
,Microsoft.VisualStudio.Services.Release.Client
,Microsoft.VisualStudio.Services.ExtensionManagement.WebApi
,Microsoft.VisualStudio.Services.InteractiveClient
仅举几个例子,但老实说,我不知道我要找的是不是有
那么如何访问VisualStudio使用的Nuget凭据呢
我采用任何允许我访问所有reading Nuget功能的解决方案,例如以编程方式使用Visual Studio包管理,或解密此SessionTokens.json
文件,或访问Visual Studio凭据提供程序
答案越不老套越好
此时,您可能已经猜到了,我不想将用户名
和密码
存储在我自己的某个地方。我需要创建一个用户友好的VS扩展,这就是为什么我要检索和使用用户已经保存在VisualStudio中的凭据
非常感谢您能解决此问题。NuGet Client SDK
非常感谢你
这是一个链接,但它们也给出了一个很好的提示:
这些博客文章是在3.4.3版本的NuGet client SDK软件包发布后不久撰写的。更新版本的软件包可能与博客文章中的信息不兼容
好吧,那我想我们就用Dave的博客吧
您应该安装两个软件包:和
下面是获取软件包最新版本的示例代码:
using NuGet.Configuration;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MyProject
{
public class NugetHelper
{
public async Task<string> GetLatestVersionNumberFromNugetFeedAsync(NugetPackage package)
{
try
{
Logger logger = new Logger(); //Just a class implementing the Nuget.Common.ILogger interface
List<Lazy<INuGetResourceProvider>> providers = new List<Lazy<INuGetResourceProvider>>();
providers.AddRange(Repository.Provider.GetCoreV3()); // Add v3 API support
PackageSource packageSource = new PackageSource(package.Source.ToString());
SourceRepository sourceRepository = new SourceRepository(packageSource, providers);
PackageMetadataResource packageMetadataResource = await sourceRepository.GetResourceAsync<PackageMetadataResource>();
var searchMetadata = await packageMetadataResource.GetMetadataAsync(package.Name, false, false, new SourceCacheContext(), logger, new CancellationToken());
var versionNumber = searchMetadata.FirstOrDefault().Identity.Version.OriginalVersion;
return versionNumber;
}
catch (Exception ex)
{
return null;
}
}
}
public class NugetPackage
{
public string Name { get; set; }
public string Version { get; set; }
public string MinimumVersion { get; set; }
public Uri Source { get; set; }
}
}
但是这不起作用,所以如果有人知道如何访问Visual Studio凭据提供程序,我很高兴知道答案。为什么不使用nuget客户端API?这就是VisualStudio所使用的。哇,非常感谢,老实说,我有点惊讶关于这一点的唯一文档是2016年的一篇非官方博客文章。这解决了我的裸体问题,但我很固执,当我面对问题时,我喜欢理解。开发人员是否可以使用服务提供商正式访问VS存储的凭据?如果是,我们怎么办?谢谢你的回答现在所有的东西都是开源的,有一些缺点。现在官方发布的是一个灰色地带,文档也大大减少了。作为开发人员,我们现在依靠自己。。。许多VS软件包现在都在使用MEF,因此我认为您可以向MEF索要在NuGet.PackageManagement.VisualStudio中定义的ICredentialServiceProvider接口。如果您想更深入,只需分析这是如何实现的。Visual Studio代码库很大,祝您好运:-)就是这样,我尝试了
componentModel.GetService()
,但它没有给我任何实际的凭据提供程序。是的,它是巨大的,我迷失在所有的代码中,这就是为什么我希望你有神奇的答案。但是谢谢,您通过指向NuGet.Client
帮助了我很多。有了这些代码,我完全不知道我应该用什么东西。你应该提供一个小的复制样本太好了,谢谢你在这里分享你的解决方案,你可以。这对阅读此帖子的其他社区成员有益,我们可以关闭此帖子,谢谢。它解决了我的问题,但实际上并没有完全回答我的问题。我开始创建一个示例项目,但我现在没有太多时间。我也是sti
using NuGet.Configuration;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace MyProject
{
public class NugetHelper
{
public async Task<string> GetLatestVersionNumberFromNugetFeedAsync(NugetPackage package)
{
try
{
Logger logger = new Logger(); //Just a class implementing the Nuget.Common.ILogger interface
List<Lazy<INuGetResourceProvider>> providers = new List<Lazy<INuGetResourceProvider>>();
providers.AddRange(Repository.Provider.GetCoreV3()); // Add v3 API support
PackageSource packageSource = new PackageSource(package.Source.ToString());
SourceRepository sourceRepository = new SourceRepository(packageSource, providers);
PackageMetadataResource packageMetadataResource = await sourceRepository.GetResourceAsync<PackageMetadataResource>();
var searchMetadata = await packageMetadataResource.GetMetadataAsync(package.Name, false, false, new SourceCacheContext(), logger, new CancellationToken());
var versionNumber = searchMetadata.FirstOrDefault().Identity.Version.OriginalVersion;
return versionNumber;
}
catch (Exception ex)
{
return null;
}
}
}
public class NugetPackage
{
public string Name { get; set; }
public string Version { get; set; }
public string MinimumVersion { get; set; }
public Uri Source { get; set; }
}
}
var componentModel = await ServiceProvider.GetGlobalServiceAsync(typeof(SComponentModel)) as IComponentModel;
componentModel.GetService<ICredentialServiceProvider>()