我的流程(常规应用,不是服务。应用是由服务启动,而不是由用户启动,但在用户会话中)在用户会话中在 SYSTEM帐户(其他原因需要)下运行( S)。如果PC在工作组中 ,有没有办法获得当前会话的用户友好名称?
-getting desktop('Progrman')用户为-GetTokenInformation - LookupAccountSid - 并且使TranslateName不会给我工作组中的f.name()(如msdn中所述,它在域中工作)。
-GetUserNameExW没有给我f.name,因为我的进程在SYSTEM帐户下运行(GetUserNameExW检索调用进程帐户的数据)
那么,与流程无关的用户友好名称还有其他方式为工作组提供 吗?
function GetUserNameEx(var AUserName: string; var AFriendlyUserName: string): Boolean;
var
ProcessID: Integer;
phToken, hProcess, hWindow: THandle;
cbBuf: Cardinal;
ptiUser: PTOKEN_USER;
snu: SID_NAME_USE;
szDomain, szUser : array [0..50] of Char;
chDomain, chUser : Cardinal;
UserName1: array[0..250] of Char;
FriendlyUserName: array[0..250] of Char;
Size: DWORD;
const
NameUnknown = 0; // Unknown name type.
NameFullyQualifiedDN = 1; // Fully qualified distinguished name
NameSamCompatible = 2; // Windows NT® 4.0 account name
NameDisplay = 3; // A "friendly" display name
NameUniqueId = 6; // GUID string that the IIDFromString function returns
NameCanonical = 7; // Complete canonical name
NameUserPrincipal = 8; // User principal name
NameCanonicalEx = 9;
NameServicePrincipal = 10; // Generalized service principal name
DNSDomainName = 11; // DNS domain name, plus the user name
begin
Result := False;
AUserName := '';
AFriendlyUserName := '';
hWindow := FindWindow('Progman', 'Program Manager');
if hWindow <> 0 then
begin
GetWindowThreadProcessID(hWindow, @ProcessID);
hProcess := OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID);
if hProcess <> 0 then
begin
if OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, phToken) then
begin
if not GetTokenInformation(phToken, TokenUser, nil, 0, cbBuf) then
if GetLastError()<> ERROR_INSUFFICIENT_BUFFER then exit;
if cbBuf = 0 then exit;
GetMem(ptiUser, cbBuf);
try
chDomain := 50;
chUser := 50;
if GetTokenInformation(phToken, TokenUser, ptiUser, cbBuf, cbBuf) then
if LookupAccountSid(nil, ptiUser.User.Sid, szUser, chUser, szDomain,
chDomain, snu) then
begin
AUserName := szUser;
Result := True;
if Trim(szDomain) <> '' then
begin
FillChar(UserName1, 251, 0);
FillChar(FriendlyUserName, 251, 0);
StrCopy(UserName1, PChar(Trim(szDomain) + '\' + Trim(szUser)));
Size := 251;
//THIS CODE WORKS FOR DOMAINS ONLY, NOT FOR WORKGROUPS
if TranslateName(@UserName1, NameSamCompatible, NameDisplay, @FriendlyUserName, @Size) then
AFriendlyUserName := Trim(FriendlyUserName);
end;
end
else
raise Exception.Create('Error in GetTokenUser');
finally
FreeMem(ptiUser);
end;
end
else begin
AUserName := 'OpenProcessToken = False';
Result := False;
end
end
else begin
AUserName := '';
Result := False;
end
end
else begin
AUserName := '';
Result := False;
end
end;
答案 0 :(得分:1)
GetUserNameEx
respects impersonation so you can call ImpersonateLoggedOnUser
with your token to get information about the user.
However, in a workgroup environment only NameSamCompatible
seems to work and everything else returns ERROR_NONE_MAPPED (The user name is not available in the specified format).
Calling NetUserGetInfo
also just returns a empty string for usri*_full_name
.
There is also a undocumented shell function to retrieve the display name but it just falls back to GetUserName
when GetUserNameEx
fails.