【问题标题】:DuplicateHandle(), use in first or second process?DuplicateHandle(),在第一个或第二个过程中使用?
【发布时间】:2010-10-23 14:42:09
【问题描述】:

Windows API DuplicateHandle() http://msdn.microsoft.com/en-us/library/ms724251(VS.85).aspx 需要复制对象句柄以及原始进程和要在其中使用复制句柄的其他进程的句柄。

我假设如果我有两个 UNRELATED 进程,只要我有所需的可用句柄,我就可以在其中一个中调用 DuplicateHandle()?

我的问题是关于使用管道在两个进程之间进行通信以通过事件实现这一点。

在第一个过程中我 CreateEvent()。现在我想在第二个进程中使用 WaitForSingleObject()。

如果我尝试在第一个进程中复制句柄,我需要先通过管道将第二个进程句柄发送给第一个进程,复制句柄然后将句柄发送给第二个进程?

或者,我可以先将第一个进程句柄和事件句柄发送到第二个进程,然后在那里复制它。

我有理由选择其中一个吗?

要添加一个皱纹,事件句柄实际上是从实际调用第一个进程(这是一个 CGI 应用程序)的父进程继承的。如果该事件句柄是使用 HANDLE_DO_NOT_DUPLICATE(类似的东西)创建的,那么我实际上可以使用 DuplicateHandle() 为第二个进程复制它吗?

回复:

好吧,我可以在第一个进程中创建一个新的 NAMED 事件,并按照建议在第二个进程中找到它,但是我正在尝试复制在第一个进程的父进程中创建的事件并将其转发给第二个进程.此事件不是命名事件,因此我需要使用 DuplicateHandle()。

我正在为 IPC 使用管道。我意识到 DuplicateHandle() 必须在第一个进程中调用,因为事件句柄在发送到第二个进程时脱离了上下文。

        hProcPseudo  = GetCurrentProcess() 

    //Then call either:
        lpRealHandle = OpenProcess( PROCESS_DUP_HANDLE, 0, hProcPseudo ) 
//This fails with GetLastError= 87 - The parameter is incorrect ???
// same thing with PROCESS_ALL_ACCESS ??


    //OR
        lRet = DuplicateHandle( hProcPseudo, hProcPseudo, hProcPseudo, lpRealHandle, DUPLICATE_SAME_ACCESS, 0, 0 )

    //then I can Duplicate my Event Handle in the first thread with:
        lRet = DuplicateHandle( hLocalProcess, hEvent, lpRealHandle, hDupEvent, DUPLICATE_SAME_ACCESS, 0, 0)

第二个进程用上面详细描述的 DuplicateHandle() 转换它的句柄

hProcPseudo=4294967295

到

hProcess= 152

然后我通过命名管道将此进程句柄传递给第一个进程。 在第一个进程(事件句柄有效)中,我调用 Duplicate handle:

DuplicateHandle( hFirstProcess, hEvent, hSecondProc, hDupEvent, DUPLICATE_SAME_ACCESS, 0, 0)

不幸的是我得到了错误:

DuplicateHandle hPipeFCGI GetLastError= 6 - 句柄无效。

进一步测试(替换 hFirstProcess)显示无效的是 hSecondProc!??

大谜。

【问题讨论】:

  • 我不知道你的布局,但你想考虑使用命名事件吗?这可能比尝试复制句柄更容易。

标签: c++ winapi ipc


【解决方案1】:

为 IPC 使用 named pipe 或 mailslots,这应该可以可靠地用于您的目的。如果您需要等待,请使用命名的等待句柄。

否则,我会选择在第二个过程中执行 DuplicateHandle 以正确设置句柄所有权。

【讨论】:

  • 我正在为 IPC 成功使用 NamedPipe 是的。我无法在第二个进程中复制句柄,因为第一个进程的句柄在第二个进程中没有上下文。我还对 GetCurrentProcess() 在两个进程中返回相同的值这一事实感到困惑......
  • 那是因为 GetCurrentProcess() 首先返回一个常量伪句柄给进程,你需要在通过 RPC 将它传递给另一个进程之前解决这个伪句柄。请参阅此处的文档:msdn.microsoft.com/en-us/library/ms683179(VS.85).aspx
  • 啊,好吧,所以上面的代码看起来还可以吗?使用伪句柄作为前三个参数调用 DuplicateHandle() 似乎很奇怪!
  • 解析的句柄在其他进程中仍然无效(详见上文)
  • 是的,那是因为句柄仍然属于另一个进程。所以在目标进程上,需要再复制一次进程句柄: DuplicateHandle( hFirstProcessFromPipe, hFirstProcessFromPipe, GetCurrentProcess(), hFirstProcess, DUPLICATE_SAME_ACCESS, 0, 0)
【解决方案2】:

进程句柄与进程 ID 不同。 OpenProcess 采用进程 ID。使用类似...

HANDLE hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, GetCurrentProcessId());

【讨论】:

    【解决方案3】:

    如果我理解正确的话,你想通过同一个事件来同步两个不相关的进程。如果是这样,您可以使用命名事件。

    使用CreateEvent API 函数创建一个,为其提供名称,然后从第二个进程使用OpenEvent API 函数,指定事件的名称。

    您对其他同步对象也有类似的功能,例如互斥锁 (OpenMutex) 或信号量 (OpenSemaphore)。

    【讨论】:

    • 见上文。我看到 GetCurrentProcess() 的值相同 - 在 DuplicateHandle() 中使用 - 在两个进程中。这似乎不对?这是为什么呢?
    • 您尝试使用 DuplicateHandle 复制哪种句柄? AFAIK,创建句柄的进程(使用 CreateXXXX 函数)是该创建对象的所有者。
    【解决方案4】:
    1. 不知何故,第二个进程需要将其进程 ID 获取给第一个进程。这个可以通过GetCurrentProcessId()获取
    2. 第一个进程现在需要使用这个 ID 来获取一个HANDLE 给第二个进程:hProcess = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwProcessId);
    3. 现在您可以复制第一个进程中的句柄,使用第二个进程的 REAL 进程句柄和第一个进程的伪句柄:DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &hDupEvent, 0, FALSE, DUPLICATE_SAME_ACCESS);
    4. 记得最终释放您使用OpenProcess 创建的句柄(我不知道它会有什么不同,但您应该...)。此外,释放事件的两个句柄:赋予第二个进程的句柄和初始句柄。

    【讨论】:

      猜你喜欢
      • 2019-01-07
      • 2015-10-11
      • 1970-01-01
      • 1970-01-01
      • 2021-05-04
      • 2016-10-20
      • 1970-01-01
      • 2018-11-02
      • 1970-01-01
      相关资源
      最近更新 更多