Delphi Tokyo Service createprocess仅在引导时

时间:2019-06-22 16:03:19

标签: delphi windows-10 windows-services createprocess

我在Delphi Tokyo中有Windows的服务脚本。该服务在系统启动时启动,并正确创建进程x。启动一个计时器,该计时器周期性地检查该进程是否启动,如果没有启动,它将尝试启动该进程,但失败,错误代码为1008。

function TMyservice.CreaProcessoComeUtenteX(const FileName, Params: string;
  WindowState: Word): Boolean;
var
  SessionID: DWORD;
  UserToken: THandle;
  CmdLine: PChar;
  si: _STARTUPINFOW;
  pi: _PROCESS_INFORMATION;
  ExitCode: Cardinal;
begin
  SessionId:= WtsGetActiveConsoleSessionID;
  if SessionID = $FFFFFFFF then
  begin
    ADDLOG('Exit from CreaProcessoComeUtenteX '+IntToStr(SessionID));
    Result := false;
    Exit;
  end;
  if WTSQueryUserToken(SessionID, UserToken) then
  begin    
    CmdLine:= PWideChar(FileName+Params);
    ZeroMemory(@si, SizeOf(si));
    si.cb := SizeOf(si);
    SI.lpDesktop := PChar('winsta0\Default');
    SI.dwFlags := STARTF_USESHOWWINDOW;
    if WindowState = 1 then
      SI.wShowWindow := SW_SHOWNORMAL;
    if WindowState = 0 then
      SI.wShowWindow := SW_MINIMIZE;
    ZeroMemory(@pi, SizeOf(pi));
    try

      CreateProcessAsUser(UserToken, nil, CmdLine, nil, nil, False,
      0, nil, nil, si, pi);

      ADDLOG(' Create process Ok');
      result := true;
    except on E: Exception do
      begin
        // Log exception ...
        result := false;
        ADDLOG('Err proc: '+ E.Message);
      end;
    end;
    CloseHandle(UserToken);
  end else
  begin
    // Log GetLastError ...
    Result := false;
    ADDLOG('QToken: '+IntToStr(GetLastError));
  end;
end;

此代码可模拟当前用户

function TInfBabeleDS.ConnectAs(const lpszUsername,
  lpszPassword: string): Boolean;
var
  hToken       : THandle;
begin
  Result := LogonUser(PChar(lpszUsername), nil, PChar(lpszPassword), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hToken);
  if Result then
    Result := ImpersonateLoggedOnUser(hToken)
  else
  RaiseLastOSError;
end;

1 个答案:

答案 0 :(得分:0)

错误代码1008为ERROR_NO_TOKEN,这意味着在没有用户登录的会话ID上调用了WTSQueryUserToken()

WTSGetActiveConsoleSessionID()并不总是最好的会话,尤其是在系统启动时,如果您的服务尝试在尚未有任何用户登录之前启动该进程。不能保证附加到本地物理监视器/键盘/鼠标的会话ID(如果有的话)可以在任何给定时间使用户登录。

在这种情况下,请使用WTSEnumerateSessions()来查找实际已登录用户的会话。

此外,您没有对CreateProcessAsUser()进行任何错误处理。它不会引发错误异常,就像您的代码所期望的那样。您的try..except没用。