如何检查句柄是否应该关闭?

How to check if an handle should be closed?

如果 ShellExecuteEx returns false,是否应该关闭句柄?:

function EditAndWait(const AFileName : string) : boolean;
var
  Info: TShellExecuteInfo;
begin
  FillChar(Info, SizeOf(Info), 0);
  Info.cbSize := SizeOf(Info);
  Info.lpVerb := 'edit';
  Info.lpFile := PAnsiChar(AFileName);
  Info.nShow := SW_SHOW;
  Info.fMask := SEE_MASK_NOCLOSEPROCESS;
  Result := ShellExecuteEx(@Info);
  if(Result) then 
  begin
    WaitForSingleObject(Info.hProcess, Infinite);
    CloseHandle(Info.hProcess);
  end else
  begin
     //should I close the process handle?
  end;
end;

更一般地说,我如何检查句柄是否应该关闭?

只有在以下情况下才会向您返回进程句柄:

  1. 您包括了 SEE_MASK_NOCLOSEPROCESS
  2. 函数调用成功,并且
  3. 该操作已通过创建新进程解决。

如果满足前两个条件,但不满足第三个条件,那么您将返回一个值为零的进程句柄。所以你的代码应该是:

Result := ShellExecuteEx(@Info);
if Result and (Info.hProcess<>0) then 
begin
  WaitForSingleObject(Info.hProcess, Infinite);
  CloseHandle(Info.hProcess);
end;

如果我们非常迂腐,我们可能会在 WaitForSingleObjectCloseHandle 上寻找错误检查。坦率地说,在这种情况下,我很难对此感到兴奋。可以从哪些可能的故障模式中恢复?


你可能会问我的意思:

The action was resolved by creating a new process.

好吧,shell 操作完全有可能通过重新循环现有流程来解决。在这种情况下,您可能不会返回进程句柄。这会让您的代码陷入困境,因为您没有什么可等待的,更不用说没有句柄可以关闭了。你只需要接受这样的场景超出你的范围。

文档是这样说的:

SEE_MASK_NOCLOSEPROCESS

Use to indicate that the hProcess member receives the process handle. This handle is typically used to allow an application to find out when a process created with ShellExecuteEx terminates. In some cases, such as when execution is satisfied through a DDE conversation, no handle will be returned. The calling application is responsible for closing the handle when it is no longer needed.


最后,祝贺您认真对待错误检查和泄漏避免问题。如此多的开发人员似乎忽略了这个问题,不管他们被告知多少次。很高兴您听取了对最近问题的评论并努力改进您的代码。做得好!