Get Microsoft Account Id from Windows 8 desktop application

懵懂的女人 提交于 2019-11-28 01:32:37

问题


Trying to find out the active email / id of the user logged into Windows 8 with a Microsoft Account, assuming it is not a local account they are authenticated as.

  • Trying to find that out from a WPF desktop C# application, not a Windows Store app
  • Found the Live SDK to be potentially relevant, e.g. the me shortcut, but am not sure this API can be used from a full-fledged .NET application?

回答1:


Warning: undocumented behavior begins. this code can break any time Microsoft pushes a Windows Update.

when your user token is created a group named "Microsoft Account\YourAccountId" is added to the user token. You can use it to find the active user's Microsoft Account.

undocumented behavior ends

The API to list the current user's group names are :

  • OpenProcessToken GetCurrentProcess TOKEN_QUERY to get the process token
  • GetTokenInformation TokenGroups to get the groups in the token
  • LookupAccountSid to get group names

It is much easier to write an example using System.Security.Principal classes:

public static string GetAccoutName()
{
    var wi= WindowsIdentity.GetCurrent();
    var groups=from g in wi.Groups                       
               select new SecurityIdentifier(g.Value)
               .Translate(typeof(NTAccount)).Value;
    var msAccount = (from g in groups
                     where g.StartsWith(@"MicrosoftAccount\")
                     select g).FirstOrDefault();
    return msAccount == null ? wi.Name:
          msAccount.Substring(@"MicrosoftAccount\".Length);
}



回答2:


  1. Open Registry Editor and navigate to:

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList

  2. Under the ProfileList key, you will see the SIDs. By selecting each one individually, you can look at the value entry and see what username is associated with that particular SID.




回答3:


referring to the method described by Sheng (using tokens) here is a code on Delphi that we've created to get current MS account id:

function GetNameFromSid(ASid: Pointer): string;
var
  snu: SID_NAME_USE;

  szDomain, szUser : array [0..50] of Char;
  chDomain, chUser : Cardinal;
begin
    chDomain := 50;
    chUser   := 50;

    if LookupAccountSid(nil, ASID, szUser, chUser, szDomain, chDomain, snu) then
      Result := string(szDomain) + '\' + string(szUser);
end;

function GetUserGroups(AStrings: TStrings): Boolean;
var
  hAccessToken       : tHandle;
  ptgGroups          : pTokenGroups;
  dwInfoBufferSize   : DWORD;
  psidAdministrators : PSID;
  int                : integer;            // counter
  blnResult          : boolean;            // return flag

  ProcessId: Integer;
  hWindow, hProcess, TokenHandle: THandle;
  si: Tstartupinfo;
  p: Tprocessinformation;

const
  SECURITY_NT_AUTHORITY: SID_IDENTIFIER_AUTHORITY =
    (Value: (0,0,0,0,0,5)); // ntifs
  SECURITY_BUILTIN_DOMAIN_RID: DWORD = $00000020;
  DOMAIN_ALIAS_RID_ADMINS: DWORD = $00000220;
  DOMAIN_ALIAS_RID_USERS : DWORD = $00000221;
  DOMAIN_ALIAS_RID_GUESTS: DWORD = $00000222;
  DOMAIN_ALIAS_RID_POWER_: DWORD = $00000223;


begin
  Result := False;
  p.dwProcessId := 0;

  hWindow := FindWindow('Progman', 'Program Manager');
  GetWindowThreadProcessID(hWindow, @ProcessID);
  hProcess := OpenProcess (PROCESS_ALL_ACCESS, FALSE, ProcessID);
  if OpenProcessToken(hProcess, TOKEN_QUERY, TokenHandle) then
  begin
    GetMem(ptgGroups, 1024);
    try
      blnResult := GetTokenInformation( TokenHandle, TokenGroups,
                                        ptgGroups, 1024,
                                        dwInfoBufferSize );
      CloseHandle( TokenHandle );

      if blnResult then
      begin
        for int := 0 to ptgGroups.GroupCount - 1 do
          AStrings.Add(GetNameFromSid(ptgGroups.Groups[ int ].Sid));
      end;
    finally
      FreeMem( ptgGroups );
    end;
  end;
end;

function GetCurrnetMSAccoundId: string;
const
  msAccStr = 'MicrosoftAccount\';
var
  AGroups: TStrings;
  i: Integer;
begin
  Result := '';
  AGroups := TStringList.Create;
  try
    GetUserGroups(AGroups);
    for i := 0 to AGroups.Count-1 do
      if Pos(msAccStr, AGroups[i]) > 0 then
      begin
        Result := Copy(AGroups[i], Length(msAccStr)+1, Length(AGroups[i])-Length(msAccStr));
        Break;
      end;
  finally
    AGroups.Free;
  end;
end;


来源:https://stackoverflow.com/questions/19740975/get-microsoft-account-id-from-windows-8-desktop-application

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!