服务程序如何取windows当前登陆的用户名 ( 积分: 48 )

  • 主题发起人 主题发起人 pub66cn
  • 开始时间 开始时间
P

pub66cn

Unregistered / Unconfirmed
GUEST, unregistred user!
我使用的用户是Adminstrator,
我把程序注册为系统服务,以SYSTEM身份运行,我想在程序中获取当前登陆的用户名Adminstrator,该怎样实现?
用GetUserName只能得到,运行程序权限的用户SYSTEM

倾尽身家只有48分了,大虾们得帮帮忙~~…
 
OpenInputDesktop 打开接受输入的桌面
EnumDesktopWindows 枚举桌面的窗口
GetWindowThreadProcessId 取得窗口的进程ID
OpenProcess 打开进程
OpenProcessToken 打开进程访问令牌
GetTokenInformation 取得令牌信息
LookupAccountSid 取得令牌的帐户信息

打开令牌好象还得用EnableProcessPrivilege取得SeSecurityPrivilege权限.有SeDebugPrivilege权限也可以.
 
找一下相关的 API
 
有没有便捷点的阿,给个示例代码~
 
用 GetEnvironmentVariable 取得环境变量,
然后 pos 'USERNAME' 就是了。
 
BOOL GetUserName(
LPTSTR lpBuffer, // address of name buffer
LPDWORD nSize // address of size of name buffer
);
 
function GUserName: String;
var
pcUser : PChar;
dwUSize : DWORD;
begin
dwUSize := 21;
result:='';
GetMem( pcUser, dwUSize );
try
if Windows.GetUserName( pcUser, dwUSize ) then
Result := pcUser
finally
FreeMem( pcUser );
end;
end;
 
还是不行呀,用下面代码测试
var s:string;
p,env:pchar;
begin
Memo1.lines.clear;
env:=GetEnvironmentStrings;
p:=env;
while (p^<>#0) do begin
s:='';
while (p^<>#0) do begin
s:=s+p^;
inc(p);
end;
memo1.Lines.add(s);
inc(p);
end;
FreeEnvironmentStrings(env);
end;
/////////////////////////////////////////////////
在正常程序里反回结果:
=::=::/
ALLUSERSPROFILE=C:/Documents and Settings/All Users
APPDATA=C:/Documents and Settings/LdupNet/Application Data
BDSCOMMONDIR=C:/Documents and Settings/All Users/Documents/RAD Studio/5.0
CLIENTNAME=Console
CommonProgramFiles=C:/Program Files/Common Files
COMPUTERNAME=LDUP
ComSpec=C:/WINDOWS/system32/cmd.exe
DELPHI=e:/program files/borland/delphi7
FP_NO_HOST_CHECK=NO
HOMEDRIVE=C:
HOMEPATH=/Documents and Settings/LdupNet
LOGONSERVER=//LDUP
NUMBER_OF_PROCESSORS=1
OS=Windows_NT
Path=E:/Program Files/CodeGear/RAD Studio/5.0/bin;C:/Documents and Settings/All Users/Documents/RAD Studio/5.0/Bpl;E:/Program Files/Borland/Delphi7/Bin;E:/Program Files/Borland/Delphi7/Projects/Bpl/;C:/WINDOWS/system32;C:/WINDOWS;C:/WINDOWS/System32/Wbem
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_IDENTIFIER=x86 Family 15 Model 4 Stepping 1, GenuineIntel
PROCESSOR_LEVEL=15
PROCESSOR_REVISION=0401
ProgramFiles=C:/Program Files
SESSIONNAME=Console
SystemDrive=C:
SystemRoot=C:/WINDOWS
TEMP=C:/DOCUME~1/LdupNet/LOCALS~1/Temp
TMP=C:/DOCUME~1/LdupNet/LOCALS~1/Temp
USERDOMAIN=LDUP
USERNAME=LdupNet
USERPROFILE=C:/Documents and Settings/LdupNet
windir=C:/WINDOWS
------------------------------

在SYSTEM服务程序里返回以下
ALLUSERSPROFILE=C:/Documents and Settings/All Users
BDSCOMMONDIR=C:/Documents and Settings/All Users/Documents/RAD Studio/5.0
CommonProgramFiles=C:/Program Files/Common Files
COMPUTERNAME=LDUP
ComSpec=C:/WINDOWS/system32/cmd.exe
FP_NO_HOST_CHECK=NO
NUMBER_OF_PROCESSORS=1
OS=Windows_NT
Path=E:/Program Files/CodeGear/RAD Studio/5.0/bin;C:/Documents and Settings/All Users/Documents/RAD Studio/5.0/Bpl;E:/Program Files/Borland/Delphi7/Bin;E:/Program Files/Borland/Delphi7/Projects/Bpl/;C:/WINDOWS/system32;C:/WINDOWS;C:/WINDOWS/System32/Wbem
PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH
PROCESSOR_ARCHITECTURE=x86
PROCESSOR_IDENTIFIER=x86 Family 15 Model 4 Stepping 1, GenuineIntel
PROCESSOR_LEVEL=15
PROCESSOR_REVISION=0401
ProgramFiles=C:/Program Files
SystemDrive=C:
SystemRoot=C:/WINDOWS
TEMP=C:/WINDOWS/TEMP
TMP=C:/WINDOWS/TEMP
USERPROFILE=C:/Documents and Settings/LocalService
windir=C:/WINDOWS
__COMPAT_LAYER=EnableNXShowUI

还是得不到当前登陆的用户名。
 
在系统进程(例如服务)(交互式进程)中,创建了一个窗口,平时此窗口为关闭状态,当接收到一特定消息时窗口要显示在当前用户桌面上。我按照windows sdk里面方法作出程序如下:
procedure TForm1.事件(Sender: TObject);
var hdesk1,hdesk2:HDESK;
hWndsta1,hWndsta2:HWINSTA;
begin
GetdesktopWindow();
hdesk2 := GetThreadDesktop(GetCurrentThreadId());
hdesk1 := OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK,True,MAXIMUM_ALLOWED);
hWndsta1:= GetprocessWindowstation();

// RpcImpersonateClient(0);
hWndsta2 := Openwindowstation('winsta0',false,MAXIMUM_ALLOWED);
SetProcessWindowStation(hwndsta2);

SetThreadDesktop(hdesk1);
//显示前初始化;
try
showmodal ;
except
end;
SetThreadDesktop(hdesk2);
SetprocesswindowStation( hWndsta1);
CloseDesktop(hdesk1);
closeWindowStation(hWndsta1);
end;
此程序显示时只在原来开始运行的用户桌面显示而没有显示在当前桌面。
如:程序启动时是用户A。然后用户B进入系统,此时用户B激发了事件窗口将显示在A的桌面而不显示在B的桌面上。
而我要求的功能类似于打印驱动一样的,哪个用户激发的事件窗口显示在那个用户的桌面上



盒子上拷贝的代码
看下有用没
 
以下是在CSDN找到的一段VC代码,有没有高手能翻译一下为DELPHI代码:
//根据进程名称得到进程token

BOOL GetTokenByName(HANDLE &amp;hToken,LPSTR lpName)
{
if(!lpName)
{
return FALSE

}
HANDLE hProcessSnap = NULL

BOOL bRet = FALSE

PROCESSENTRY32 pe32 = {0}


hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)

if (hProcessSnap == INVALID_HANDLE_VALUE)
return (FALSE)


pe32.dwSize = sizeof(PROCESSENTRY32)


if (Process32First(hProcessSnap, &amp;pe32))
{
do
{
if(!strcmp(_strupr(pe32.szExeFile),_strupr(lpName)))
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION,
FALSE,pe32.th32ProcessID)

bRet = OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&amp;hToken)

CloseHandle (hProcessSnap)

return (bRet)

}
}
while (Process32Next(hProcessSnap, &amp;pe32))

bRet = TRUE

}
else
bRet = FALSE


CloseHandle (hProcessSnap)

return (bRet)

}

BOOL GetCurrentUserName()
{
HANDLE hToken


//得到shell的token
if(!GetTokenByName(hToken,&quot;EXPLORER.EXE&quot;))
{
return FALSE

}
DWORD cbti = 0

PTOKEN_USER ptiUser = NULL

SID_NAME_USE snu


//取得所需空间大小
if (GetTokenInformation(hToken, TokenUser, NULL, 0, &amp;cbti))
{
CloseHandle(hToken)

return FALSE

}

//分配空间
ptiUser = (PTOKEN_USER) HeapAlloc(GetProcessHeap(), 0, cbti)

if(!ptiUser)
{
CloseHandle(hToken)

return FALSE

}

//取得token信息
if (!GetTokenInformation(hToken, TokenUser, ptiUser, cbti, &amp;cbti))
{
CloseHandle(hToken)

HeapFree(GetProcessHeap(), 0, ptiUser)

return FALSE

}

char szUser[50]

char szDomain[50]

DWORD nUser = 50

DWORD nDomain = 50


//根据用户的sid得到用户名和domain

if (!LookupAccountSid(NULL, ptiUser->User.Sid, szUser, &amp;nUser,
szDomain, &amp;nDomain, &amp;snu))
{
CloseHandle(hToken)

HeapFree(GetProcessHeap(), 0, ptiUser)

return FALSE

}
OutputDebugString(szUser)

OutputDebugString(&quot;/r/n&quot;)

OutputDebugString(szDomain)

OutputDebugString(&quot;/r/n&quot;)


CloseHandle(hToken)

HeapFree(GetProcessHeap(), 0, ptiUser)

return TRUE

}
 
function GetUserAndDomainFromPID(ProcessId: DWORD;
var User, Domain: string): Integer;
var
hToken: THandle;
cbBuf: Cardinal;
ptiUser: PTOKEN_USER;
snu: SID_NAME_USE;
ProcessHandle: THandle;
UserSize, DomainSize: DWORD;
bSuccess: Boolean;
begin
Result := 0;
ProcessHandle := OpenProcess(PROCESS_QUERY_INFORMATION, False, ProcessId);
if ProcessHandle <> 0 then
try
//EnableProcessPrivilege(ProcessHandle, 'SeSecurityPrivilege', True);
if OpenProcessToken(ProcessHandle, TOKEN_QUERY, hToken) then
begin
bSuccess := GetTokenInformation(hToken, TokenUser, nil, 0, cbBuf);
ptiUser := nil;
while (not bSuccess) and (GetLastError = ERROR_INSUFFICIENT_BUFFER) do
begin
ReallocMem(ptiUser, cbBuf);
bSuccess := GetTokenInformation(hToken, TokenUser, ptiUser, cbBuf, cbBuf);
end;
CloseHandle(hToken);

if not bSuccess then
begin
Exit;
end;

UserSize := 0;
DomainSize := 0;
LookupAccountSid(nil, ptiUser.User.Sid, nil, UserSize, nil, DomainSize, snu);
if (UserSize <> 0) and (DomainSize <> 0) then
begin
SetLength(User, UserSize);
SetLength(Domain, DomainSize);
if LookupAccountSid(nil, ptiUser.User.Sid, PChar(User), UserSize,
PChar(Domain), DomainSize, snu) then
begin
Result := 1;
User := StrPas(PChar(User));
Domain := StrPas(PChar(Domain));
end;
end;

if bSuccess then
begin
FreeMem(ptiUser);
end;
end
else begin
Result := -2;
end;
finally
CloseHandle(ProcessHandle);
end
else
Result := -1;
end;
 
这家伙在用Delphi2007[:)]
 
后退
顶部