5

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

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

有谁知道从 Visual Studio 扩展访问 Microsoft 帐户的(相对)简单的方法?

编辑

我尝试了 Hadi Brais 的建议,起初它似乎有效(我成功检索了信息);但是,每次,Visual Studio 都会在大约 30 秒后崩溃。我注释掉了与注册表交互的行,并将它们替换为变量的静态值,然后崩溃停止了。显然,访问 Visual Studio 的注册表项会导致它崩溃。我什至尝试过using声明和其他保护措施,但似乎没有办法从扩展中安全地访问 Visual Studio 注册表项。那么有没有人知道任何官方 API可以用来检索这些信息而不会导致 Visual Studio 崩溃?

4

2 回答 2

6

对于 Visual Studio 2015(版本 14.0),这是获取有关当前在 Visual Studio 中登录的用户的信息的方法。您需要添加using 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);
    }
}
于 2015-07-13T07:52:19.087 回答
3

现在有多个版本的 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;
}

此算法尝试从最新版本开始的所有版本,然后是所有其他兄弟版本。如果发生故障,它会返回 null。

于 2019-08-23T14:04:32.243 回答