CreateProcess .. WaitForSingleObject .. CloseHandle 调用的最佳 try..finally 位置

Posted

技术标签:

【中文标题】CreateProcess .. WaitForSingleObject .. CloseHandle 调用的最佳 try..finally 位置【英文标题】:Optimal try..finally placement for CreateProcess .. WaitForSingleObject .. CloseHandle calls 【发布时间】:2015-05-02 13:57:09 【问题描述】:

我想在调用 CreateProcess ..WaitForSingleObject 后调用 CloseHandle,并希望将 CloseHandle 调用包含在 try..finally 块中,但不确定将不同调用放在哪里 w.r.t。试试..最后。

这是我当前的代码:

var
  p, f, a: String;
  pi: TProcessInformation;
  si: TStartupInfo;
begin
  Log('Starting backup..');

  if (not FileExists(FMYPROG)) then
  begin
    Log('Error: ' + STR_ERRMSG_1);
    MessageDlg(STR_ERRMSG_1, mtError, [mbOK], 0);
    Exit;
  end;

  // start process up
  FillChar(si, SizeOf(si), 0);
  si.cb := SizeOf(si);
  si.dwFlags := STARTF_USESHOWWINDOW;
  si.wShowWindow := SW_NORMAL;

  f := IncludeTrailingPathDelimiter(FBAKFILEPATH) + 'output.bak';
  p := '/changesonly "' + f + '"';

  try   // is this the optimal placement for this line? or should it be after CreateProcess? 
    if CreateProcess(PChar(FMYPROG), PChar(p), nil, nil, False,
      CREATE_NEW_PROCESS_GROUP + NORMAL_PRIORITY_CLASS, nil, PChar(ExtractFilePath(FMYPROG)), si, pi) then
      WaitForSingleObject(pi.hProcess, INFINITE)
    else
      RaiseLastOSError;

  finally
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
  end;

寻求导致德尔福启蒙的建议和批评。谢谢。

【问题讨论】:

if not CreateProcess(...) then RaiseLastOSError; try..finally CloseHandles; end; 因为即使CreateProcess 失败,您也会关闭这些句柄。 顺序始终相同:AcquireResource; try UseResource; finally ReleaseResource; end。这适用于您拥有的任何类型的资源(在您的情况下,进程和线程句柄)。您只需决定获取、使用和释放它们意味着什么。 【参考方案1】:

只有在CreateProcess 成功时才调用CloseHandle。因此它是这样的:

if CreateProcess(...) then
  try
    ....
  finally
    // calls to CloseHandle
  end
else
  RaiseLastOSError;

或者,如果您更愿意预先处理错误情况:

if not CreateProcess(...) then
  RaiseLastOSError;
try
  ....
finally
  // calls to CloseHandle
end

这在语义上是相同的,因为您知道RaiseLastOSError 会引发异常。

或者我更喜欢:

Win32Check(CreateProcess(...));
try 
  ....
finally
  // calls to CloseHandle
end;

Win32Check 便利函数只是简单地封装了逻辑

if not Succeeded then
  RaiseLastOSError;

【讨论】:

这与 TLama 对该问题的评论不同。等着看他的理由。 不,本质上是一样的。要点是在CreateProcess 失败时跳过try..finally 块。在这篇文章中使用else 来引发异常。但是,即使您只是在输入异常之前引发异常,您也会跳过该块(这就是第二个 sn-p 所做的)。我已经放弃了我的答案草稿... @Steve 是的,它是一样的。关键是只有在 CreateProcess 成功时才会执行 try。我将添加第三个选项。

以上是关于CreateProcess .. WaitForSingleObject .. CloseHandle 调用的最佳 try..finally 位置的主要内容,如果未能解决你的问题,请参考以下文章

CreateProcess() C++ 文件未找到

CreateProcess() 无法正常工作

CreateProcess 和命令行参数

forking() 和 CreateProcess()

无法识别 C++ CreateProcess 'telnet'

createprocess默认暂停[关闭]