如何在VSIX扩展中处理VSTS凭据

时间:2018-03-09 15:39:01

标签: c# azure-devops vsix

我有一个Visual Studio扩展,我们在内部用于项目,它需要做的一件事就是将门票发布到VSTS。以前我们使用的是现场TFS,并且建立与邮政票证的连接非常简单:

var vssCreds = new VssCredentials(true);    
projectCollection = new TfsTeamProjectCollection(url, vssCreds);
workItems = projectCollection.GetService<WorkItemStore>();
project = workItems.Projects["My Project"];
defaultType = project.WorkItemTypes["Bug"];

//...
var newItem = new WorkItem(defaultType)
{
    Title = title
};
newItem.Fields["Assigned To"].Value = assignTo;
newItem.Fields["Repro Steps"].Value = repoSteps;
var validationResult = newItem.Validate();
newItem.Save();

这很好用。但升级到VSTS之后,我很难获得凭据部分的工作。我更改了这一行:

projectCollection = new TfsTeamProjectCollection(url, vssCreds);

对此:

projectCollection = new TfsTeamProjectCollection(url, new VssClientCredentials());

这对我来说很好。但是,当我与团队中的其他人分享时,它首先没有工作,然后开始工作一段时间。我猜测与VSTS交互导致他们的凭据被加载,以便它可以工作。但我至少有一个人似乎完全无法使其发挥作用。

那么使用VSTS凭证(应该已经存在于VS中)的正确方法是什么?

我看到VssClientCredentialshttps://msdn.microsoft.com/en-us/library/dn228355(v=vs.120).aspx)的重载:

public VssClientCredentials(
    IVssCredentialPrompt credentialPrompt
)

我怀疑这可能有用,但我似乎无法找出某个地方是否内置了IVssCredentialPrompt,或者如果没有,如何实现它。

2 个答案:

答案 0 :(得分:1)

从中删除相关密钥 Computer\HKEY_CURRENT_USER\Software\Microsoft\VSCommon\14.0\ClientServices\TokenStorage\VisualStudio\VssApp,然后再次进行身份验证。

您还可以使用以下代码指定其他Kind(默认为vssApp)和Namespace(默认为VisualStudio):

var c = new VssClientCredentials();
c.Storage = new VssClientCredentialStorage(storageKind: "VssApp2", storageNamespace: "VisualStudio");
projectCollection = new TfsTeamProjectCollection(url, c);

答案 1 :(得分:0)

由于完全不清楚的原因以及对这个完全不同的问题的回答:https://stackoverflow.com/a/40256731/1250301

似乎产生一个新线程会导致在需要时出现登录提示并修复所有问题。所以,如果我这样做:

Task.Run(() =>
{
    var url = new Uri(_tfsUrl);
    var cred = new VssClientCredentials();
    projectCollection = new TfsTeamProjectCollection(url, cred);
    workItems = projectCollection.GetService<WorkItemStore>();
}).Wait();

project = workItems.Projects["Job Posting Data"];
defaultType = project.WorkItemTypes["Bug"];
taskType = project.WorkItemTypes["Task"];

然后它有效。我不知道它为什么有用,或者为什么这是必要的(起初我认为这可能是在UI线程中的问题所以我试过Application.Current.Dispatcher.Invoke没有用)但似乎已经解决了这个问题。