简体   繁体   English

从服务运行应用程序,CreateProcessAsUser失败

[英]Run Application from Service, CreateProcessAsUser Fails

I know! 我知道! I shouldn't run a GUI application from a Windows service, but this is what I should accomplish as a requirement. 我不应该从Windows服务运行GUI应用程序,但这是我应完成的。 Putting different codes from around the Web together, I have the following procedure. 将来自Web的不同代码放在一起,我有以下过程。 I see Access Violation error in log, as a result of CreateProcessAsUser. 由于CreateProcessAsUser,我在日志中看到访问冲突错误。 I have tries different settings with no luck. 我尝试了其他设置,但是没有运气。 Any idea what is wrong with this code? 知道此代码有什么问题吗?

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 is used from JEDI API Library and is defined as: 顺便说一句,JEDI API库使用了WTSQueryUserToken,它的定义为:

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

The third parameter must be a pointer to a modifiable string, as documented on MSDN: 第三个参数必须是指向可修改字符串的指针,如MSDN上所述:

The Unicode version of this function, CreateProcessAsUserW, can modify the contents of this string. 此函数的Unicode版本CreateProcessAsUserW可以修改此字符串的内容。 Therefore, this parameter cannot be a pointer to read-only memory (such as a const variable or a literal string). 因此,该参数不能是指向只读存储器的指针(例如const变量或文字字符串)。 If this parameter is a constant string, the function may cause an access violation. 如果此参数是常量字符串,则该函数可能会导致访问冲突。

A string literal is stored in read only memory. 字符串文字存储在只读存储器中。 Try this instead: 尝试以下方法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM