CreateProcess成功但生成错误1812(指定的图像文件不包含资源部分)

Pau*_*aul 0 delphi winapi

以下代码

function Run(exePath, cmdLine, currDir: string): Boolean;
var
  si: TStartupInfo;
  pinf: TProcessInformation;
  hStdOut: THandle;
  sa: TSecurityAttributes;
  lastErr: LongWord;
begin
  sa.nLength := SizeOf(TSecurityAttributes);
  sa.bInheritHandle := True;
  sa.lpSecurityDescriptor := nil;

  si := default(TStartupInfo);
  si.cb := SizeOf(si);
  si.dwFlags    := si.dwFlags; // or STARTF_USESTDHANDLES;

  SetLastError(0);
  Result := Createprocess(PWideChar(exePath), PWideChar(cmdLine), nil, nil,
    True, 0 {CREATE_NEW_CONSOLE}, nil, PWideChar(currDir), si, pinf);
  if Result then begin
    WaitForSingleObject(pinf.hProcess, INFINITE);
    lastErr := GetLastError(); // Here error 1812
    if lastErr <> 0 then ShowError(lastErr);
    CloseHandle(pinf.hProcess);
    CloseHandle(pinf.hThread);
  end
  else begin
    lastErr := GetLastError();
    if lastErr <> 0 then ShowError(lastErr);
  end;
end;
Run Code Online (Sandbox Code Playgroud)

在各种可执行文件(git,cgrc,dcc32)上生成错误1812(指定的图像文件不包含资源部分).

它是什么以及如何消除它?

PS这是我想知道的一段提取的代码:

SetLastError(0);
ShowError(GetLastError()); // Here the error code is 0
Result := Createprocess(PWideChar(exePath), PWideChar(cmdLine), nil, nil, False, 0, nil, PWideChar(currDir), si, pinf);
ShowError(GetLastError()); // Here error 1812
Run Code Online (Sandbox Code Playgroud)

我的逻辑如下:如果在CreateProcess调用之前最后一个错误代码是0,并且之后不是0,那么肯定是CreateProcess谁设置了值.如果没有错误发生,为什么要设置错误代码?

这个逻辑似乎是假的,即使函数成功,也可以设置上一个错误代码.

Dav*_*nan 5

您的错误处理代码已损坏.你的功能应该是这样的:

function Run(exePath, cmdLine, currDir: string): Boolean;
var
  si: TStartupInfo;
  pinf: TProcessInformation;
  hStdOut: THandle;
  sa: TSecurityAttributes;
  waitResult: DWORD;
  lastErr: LongWord;
begin
  sa.nLength := SizeOf(TSecurityAttributes);
  sa.bInheritHandle := True;
  sa.lpSecurityDescriptor := nil;

  si := default(TStartupInfo);
  si.cb := SizeOf(si);
  si.dwFlags    := si.dwFlags; // or STARTF_USESTDHANDLES;

  UniqueString(cmdLine);
  Result := CreateProcess(PWideChar(exePath), PWideChar(cmdLine), nil, nil,
    True, 0 {CREATE_NEW_CONSOLE}, nil, PWideChar(currDir), si, pinf);
  if Result then begin
    waitResult := WaitForSingleObject(pinf.hProcess, INFINITE);
    if waitResult = WAIT_FAILED then begin
      lastErr := GetLastError();
      if lastErr <> 0 then ShowError(lastErr);
    end else begin
      Assert(waitResult = WAIT_OBJECT_0);
    end;
    CloseHandle(pinf.hProcess);
    CloseHandle(pinf.hThread);
  end
  else begin
    lastErr := GetLastError();
    if lastErr <> 0 then ShowError(lastErr);
  end;
end;
Run Code Online (Sandbox Code Playgroud)

笔记:

  • 第二个参数CreateProcess必须是可写字符串.因此呼吁UniqueString.
  • 如记录的那样WaitForSingleObject,失败由返回值表示.只应GetLastError在返回值指示失败的情况下调用.
  • 我删除了SetLastError(0)不必要的电话.
  • 如果ShowError引发异常,则此函数将泄漏句柄.

我预计发生的事情是CreateProcess成功的,但没有将最后一个错误设置为零,它没有义务这样做.请记住,返回值表示成功或失败,而不是错误代码.然后WaitForSingleObject也是成功的,并没有将错误代码设置为零,这也是它没有义务做的事情.或者可能WaitForSingleObject是将错误代码设置为非零值.在任何情况下,哪个功能确实没有实际意义.修复错误检查代码后,您将无法查看此无意义的错误代码.

最后,您是否确定要让子进程继承句柄?