5

I am writing a VS extension which will need to communicate with a server and identify the user, and I figured that if possible, since this extension will be the only client connecting to the server, using Visual Studio's built-in support for Microsoft accounts would make more sense than implementing my own account management infrastructure.

At first, because of the variety of useful APIs available to a Visual Studio developer, one might think that getting info on the current user would be easy. However, there actually don't seem to be any obvious APIs that can be used to access accounts; I checked here and there weren't any related services listed (the "profile" services just allow you to read/write settings that are stored for the current user).

Does anyone know of a (relatively) simple way to access the Microsoft account from a Visual Studio extension?

EDIT

I tried Hadi Brais's suggestion, and at first it appeared to work (I successfully retrieved the information); however, each time, Visual Studio would crash about 30s afterward. I commented out the lines that interacted with the registry and replaced them with static values for the variables, and the crashes stopped. Clearly, accessing Visual Studio's registry keys was causing it to crash. I even tried using statements and other safeguards, however there doesn't seem to be a way to safely access the Visual Studio registry keys from an extension. So does anyone know of any official APIs that can be used to retrieve this information without crashing Visual Studio?

Nick Mertin
  • 1,149
  • 12
  • 27
  • I am not able to reproduce the crash. Can specify detailed steps to reproduce it? Also what is the error shown to you? – Hadi Brais Jul 15 '15 at 05:55
  • @HadiBrais I have a Visual Studio extension that hosts a TCP server, and a separate console app that connects to it; both are written in C#, and for debugging purposes both are running on the same computer. The console app, when it connects, retrieves the current Microsoft account from VS's registry keys, and sends them to the extension over TCP. Then, even though I have closed the `RegistryKey` objects within the console app, VS mysteriously crashes. I was debugging the VS process so that I can test my extension, and the host VS instance doesn't even realize that there has been a crash. – Nick Mertin Jul 15 '15 at 19:05

2 Answers2

6

For Visual Studio 2015 (Version 14.0), this is how to get information about the user that is currently signed in in Visual Studio. You need to add 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);
    }
}
Hadi Brais
  • 22,259
  • 3
  • 54
  • 95
3

There are now multiple versions of the IdeUser key. I've reimplemented the algorithm from the other answer this way:

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;
}

This algorithm tries all versions from the newest one and then all other siblings. It returns null in case of a failure.

Antonín Procházka
  • 1,388
  • 8
  • 16
  • Is this new with VS 2017 or 2019? I've VS 2013 and 2015 installed, but I only see IdeUser without a version. Does that reg expression work either way? It'd be nice to give more details on why there would be multiple IdeUser at the same time on a system and which one should be chosen. – Hadi Brais Aug 23 '19 at 18:18
  • I haven't searched at why there are more of the IdeUser keys, but it's probably new in VS 2017+. This algorithm takes the newest version first, the one without a version last and then all other keys at the same level in an undefined order. – Antonín Procházka Aug 26 '19 at 12:17