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

时间:2018-03-08 09:52:28

标签: 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;

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

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

P.S。这是我想知道的一段代码:

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

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

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

1 个答案:

答案 0 :(得分: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;

注意:

  • CreateProcess的第二个参数必须是可写字符串。因此呼叫UniqueString
  • WaitForSingleObject中所述,失败由返回值表示。如果返回值指示失败,您应该只调用GetLastError
  • 我删除了对SetLastError(0)的调用,这是不必要的。
  • 如果ShowError引发异常,则此函数将泄漏句柄。

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

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