问题
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:
Open Registry Editor and navigate to:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList
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