C# 从Visual Studio扩展访问当前Microsoft帐户

C# 从Visual Studio扩展访问当前Microsoft帐户,c#,visual-studio,visual-studio-2015,visual-studio-extensions,microsoft-account,C#,Visual Studio,Visual Studio 2015,Visual Studio Extensions,Microsoft Account,我正在编写一个VS扩展,它需要与服务器通信并识别用户,我认为如果可能的话,由于此扩展将是连接到服务器的唯一客户端,使用Visual Studio对Microsoft帐户的内置支持将比实现我自己的帐户管理基础架构更有意义 首先,由于VisualStudio开发人员可以使用各种有用的API,人们可能会认为获取当前用户的信息很容易。然而,实际上似乎没有任何明显的API可用于访问帐户;我检查了一下,没有列出任何相关的服务(“配置文件”服务只允许您读取/写入为当前用户存储的设置) 有人知道从VisualS

我正在编写一个VS扩展,它需要与服务器通信并识别用户,我认为如果可能的话,由于此扩展将是连接到服务器的唯一客户端,使用Visual Studio对Microsoft帐户的内置支持将比实现我自己的帐户管理基础架构更有意义

首先,由于VisualStudio开发人员可以使用各种有用的API,人们可能会认为获取当前用户的信息很容易。然而,实际上似乎没有任何明显的API可用于访问帐户;我检查了一下,没有列出任何相关的服务(“配置文件”服务只允许您读取/写入为当前用户存储的设置)

有人知道从VisualStudio扩展访问Microsoft帐户的(相对)简单方法吗

编辑

我尝试了哈迪·布拉什的建议,起初它似乎奏效了(我成功地检索到了信息);然而,每一次,VisualStudio都会在30秒后崩溃。我注释掉了与注册表交互的行,并用变量的静态值替换它们,崩溃停止了。显然,访问VisualStudio的注册表项导致它崩溃。我甚至尝试使用语句和其他保护措施来
,但是似乎没有从扩展安全访问VisualStudio注册表项的方法。那么,是否有人知道可以在不破坏Visual Studio的情况下使用任何官方API来检索此信息?

对于Visual Studio 2015(14.0版),这是如何获取当前在Visual Studio中登录的用户的信息。您需要使用Microsoft.Win32添加

private static string GetUserEmailAddressVS14()
{
    // It's a good practice to request explicit permission from
    // the user that you want to use his email address and any
    // other information. This enables the user to be in control
    // of his/her privacy.

    // Assuming permission is granted, we obtain the email address.

    const string SubKey = "Software\\Microsoft\\VSCommon\\ConnectedUser\\IdeUser\\Cache";
    const string EmailAddressKeyName = "EmailAddress";
    const string UserNameKeyName = "DisplayName";

    RegistryKey root = Registry.CurrentUser;
    RegistryKey sk = root.OpenSubKey(SubKey);
    if (sk == null)
    {
        // The user is currently not signed in.
        return null;
    }
    else
    {
        // Get user email address.
        return (string)sk.GetValue(EmailAddressKeyName);

        // You can also get user name like this.
        // return (string)sk.GetValue(UserNameKeyName);
    }
}

IdeUser密钥现在有多个版本。我以这种方式重新实现了另一个答案中的算法:

public static string GetUserEmailAddressFromVisualStudioRegistry()
{
    try
    {
        const string ConnectedUserSubKey = @"Software\Microsoft\VSCommon\ConnectedUser";
        const string EmailAddressKeyName = "EmailAddress";

        RegistryKey connectedUserSubKey = Registry.CurrentUser.OpenSubKey( ConnectedUserSubKey );

        string[] subKeyNames = connectedUserSubKey?.GetSubKeyNames();

        if ( subKeyNames == null || subKeyNames.Length == 0 )
        {
            return null;
        }

        int[] subKeysOrder = new int[subKeyNames.Length];

        for ( int i = 0; i < subKeyNames.Length; i++ )
        {
            Match match = Regex.Match( subKeyNames[i], @"^IdeUser(?:V(?<version>\d+))?$" );

            if ( !match.Success )
            {
                subKeysOrder[i] = -1;
                continue;
            }

            string versionString = match.Groups["version"]?.Value;

            if ( string.IsNullOrEmpty( versionString ) )
            {
                subKeysOrder[i] = 0;
            }
            else if ( !int.TryParse( versionString, out subKeysOrder[i] ) )
            {
                subKeysOrder[i] = -1;
            }
        }

        Array.Sort( subKeysOrder, subKeyNames );

        for ( int i = subKeyNames.Length - 1; i >= 0; i++ )
        {
            string cacheSubKeyName = $@"{subKeyNames[i]}\Cache";
            RegistryKey cacheKey = connectedUserSubKey.OpenSubKey( cacheSubKeyName );
            string emailAddress = cacheKey?.GetValue( EmailAddressKeyName ) as string;

            if ( !string.IsNullOrWhiteSpace( emailAddress ) )
            {
                return emailAddress;
            }
        }
    }
    catch
    {
        // Handle exceptions here if it's wanted.
    }

    return null;
}
公共静态字符串GetUserEmailAddressFromVisualStudioRegistry()
{
尝试
{
常量字符串ConnectedUserSubKey=@“Software\Microsoft\VSCommon\ConnectedUser”;
常量字符串EmailAddressKeyName=“EmailAddress”;
RegistryKey connectedUserSubKey=Registry.CurrentUser.OpenSubKey(connectedUserSubKey);
string[]subKeyNames=connectedUserSubKey?.GetSubKeyNames();
if(subKeyNames==null | | subKeyNames.Length==0)
{
返回null;
}
int[]subKeysOrder=newint[subKeyNames.Length];
for(int i=0;i=0;i++)
{
字符串cacheSubKeyName=$@“{subKeyNames[i]}\Cache”;
RegistryKey cacheKey=connectedUserSubKey.OpenSubKey(cacheSubKeyName);
字符串emailAddress=cacheKey?.GetValue(EmailAddressKeyName)作为字符串;
如果(!string.IsNullOrWhiteSpace(emailAddress))
{
返回电子邮件地址;
}
}
}
抓住
{
//如果需要,请在此处处理异常。
}
返回null;
}

此算法尝试从最新版本开始的所有版本,然后尝试所有其他同级版本。如果出现故障,它将返回null。

谢谢,我将尝试解决某种注册表访问问题,请参阅编辑我的问题。我无法重现崩溃。是否可以指定详细的复制步骤?还有向您显示的错误是什么?@HadiBrais我有一个承载TCP服务器的Visual Studio扩展,还有一个单独的控制台应用程序连接到它;两者都是用C#编写的,出于调试目的,它们都在同一台计算机上运行。控制台应用程序在连接时,从VS的注册表项检索当前Microsoft帐户,并通过TCP将其发送到扩展。然后,即使我关闭了console应用程序中的
RegistryKey
对象,VS还是神秘地崩溃了。我调试了VS进程以便测试我的扩展,而主机VS实例甚至没有意识到发生了崩溃。这是VS2017或2019的新版本吗?我已经安装了VS 2013和2015,但我只看到没有版本的IdeUser。那个reg表达式是双向的吗?最好能提供更多细节,说明为什么一个系统上同时会有多个IdeUser,以及应该选择哪一个。我还没有搜索到为什么会有更多的IdeUser密钥,但这可能是VS2017+中新增的。该算法首先获取最新版本,最后获取没有版本的版本,然后以未定义的顺序获取同一级别的所有其他密钥。