从Service,CreateProcessAsUser运行应用程序失败

时间:2015-11-30 00:05:53

标签: delphi winapi windows-services

我知道!我不应该从Windows服务运行GUI应用程序,但这是我应该完成的要求。将不同的代码放在Web上,我有以下过程。作为CreateProcessAsUser的结果,我在日志中看到了Access Violation错误。我尝试了不同的设置而没有运气。知道这个代码有什么问题吗?

procedure TMyService.RunApp;
var
  SessionID: DWORD;
  UserToken: THandle;
  CmdLine: PChar;
  si: _STARTUPINFOW;
  pi: _PROCESS_INFORMATION;
begin
  SessionId:= WtsGetActiveConsoleSessionID;
  if SessionID = $FFFFFFFF then Exit;
  if WTSQueryUserToken(SessionID, UserToken) then begin
    CmdLine:= 'notepad.exe';
    ZeroMemory(@si, SizeOf(si));
    si.cb := SizeOf(si);
    SI.lpDesktop := PChar('winsta0\Default');
    SI.dwFlags := STARTF_USESHOWWINDOW;
    SI.wShowWindow := SW_SHOWNORMAL;
    ZeroMemory(@pi, SizeOf(pi));
    try
      CreateProcessAsUser(UserToken, nil, CmdLine, nil, nil, False,
      0, nil, nil, si, pi);
    except on E: Exception do
      // Log exception ...
    end;
    CloseHandle(UserToken);
  end else begin
    // Log GetLastError ...
  end;
end;

BTW,WTSQueryUserToken用于JEDI API库,定义为:

function WTSQueryUserToken(SessionId: ULONG; var phToken: THandle): BOOL; stdcall;

1 个答案:

答案 0 :(得分:3)

第三个参数必须是指向可修改字符串的指针,如MSDN中所述:

  

此函数的Unicode版本CreateProcessAsUserW可以修改此字符串的内容。因此,此参数不能是只读内存的指针(例如const变量或文字字符串)。如果此参数是常量字符串,则该函数可能会导致访问冲突。

字符串文字存储在只读存储器中。试试这个:

var
  CmdLine: string;
....
CmdLine := 'notepad.exe';
UniqueString(CmdLine); // make modifiable;
....
if not CreateProcessAsUser(..., PChar(CmdLine), ...) then
  // handle error