2017-01-20 2 views
-1

Мне нужно запустить процесс под текущим пользователем из другого процесса, который запускается под SYSTEM (системный процесс запускает другой процесс как текущий пользователь).delphi: запустить процесс как пользователь и переменные окружения учетной записи SYSTEM

Я могу запустить его с помощью этого кода, но есть проблема с переменными окружения. в новом 'пользовательском режиме' процесса, я вижу, что значение APPDATA является C: \ Windows \ System32 \ Config \ systemprofile \ AppData \ Roaming вместо C: \ Users \ имя пользователя \ AppData \ Roaming

function RunProcessAsCurrentUser(FileName: string): Boolean; 
var 
    ProcessId: Integer; 
    hWindow, hProcess, TokenHandle: THandle; 
    si: Tstartupinfo; 
    p: Tprocessinformation; 
begin 
    Result := False; 
    hWindow := FindWindow('Progman', 'Program Manager'); 
    GetWindowThreadProcessID(hWindow, @ProcessID); 
    hProcess := OpenProcess (PROCESS_ALL_ACCESS, FALSE, ProcessID); 
    if OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, TokenHandle) then 
    begin 

     FillChar(si,SizeOf(si),0); 
     with Si do begin 
     cb := SizeOf(Si); 
     dwFlags := startf_UseShowWindow; 
     wShowWindow := SW_NORMAL; 
     lpDesktop := PChar('winsta0\default'); 
     end; 

     Result := CreateProcessAsUser(TokenHandle, nil, 
     PChar('"'+FileName+'"'), 
     nil, nil, false, Create_default_error_mode, nil, nil, si, p); 
    end; 
end; 

проблема актуальна в win7,8,10

Я предположил, что все параметры процесса скопированы из explorer.exe (и новый процесс запускается как пользователь в TaskManager), но выглядит как-то из системы ... Пожалуйста, помогите для решения

+0

Предложение: используйте Delphi 'ShellExecute()' и 'Окна runas': http://www.sevenforums.com/tutorials/419-run-different-user.html – paulsm4

+0

Обратите внимание, что использование 'runas' будет вызывать приглашение на повышение UAC, тогда как' CreateProcessAsUser() 'не будет. –

ответ

2

При использовании CreateProcessAsUser() вы должны получить пользовательскую среду, используя CreateEnvironmentBlock():

Извлекает переменные среды для указанного пользователя. Затем этот блок можно передать в функцию CreateProcessAsUser.

Передайте это значение параметру lpEnvironmentCreateProcessAsUser(). В противном случае новый процесс наследует среду вызывающего процесса.

Например:

function RunProcessAsCurrentUser(FileName: string): Boolean; 
var 
    ProcessId: Integer; 
    hWindow, hProcess, TokenHandle: THandle; 
    si: Tstartupinfo; 
    p: Tprocessinformation; 
    lpEnvironment: Pointer; 
begin 
    Result := False; 

    hWindow := FindWindow('Progman', 'Program Manager'); 
    if hWindow = 0 then Exit; 

    GetWindowThreadProcessID(hWindow, @ProcessID); 
    hProcess := OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, ProcessID); 
    if hProcess = 0 then Exit; 

    try 
    if not OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, TokenHandle) then Exit; 

    FillChar(si,SizeOf(si),0); 
    with Si do begin 
     cb := SizeOf(Si); 
     dwFlags := startf_UseShowWindow; 
     wShowWindow := SW_NORMAL; 
     lpDesktop := PChar('winsta0\default'); 
    end; 

    lpEnvironment := nil; 
    CreateEnvironmentBlock(@lpEnvironment, TokenHandle, FALSE); 
    try 
     Result := CreateProcessAsUser(TokenHandle, nil, 
     PChar('"'+FileName+'"'), 
     nil, nil, FALSE, CREATE_DEFAULT_ERROR_MODE, 
     lpEnvironment, nil, si, p); 
    finally 
     DestroyEnvironmentBlock(lpEnvironment); 
    end; 
    finally 
    CloseHandle(hProcess); 
    end; 
end; 
+1

Спасибо! Btw, наши тесты показывают, что вместо CREATE_DEFAULT_ERROR_MODE следует использовать CREATE_UNICODE_ENVIRONMENT. и CreateEnvironmentBlock (lpEnvironment, TokenHandle, FALSE); вместо CreateEnvironmentBlock (@lpEnvironment, TokenHandle, FALSE); –