2010-02-26 87 views
6

使用Windows API在C++中創建子進程時,可以允許繼承從父到子的句柄。在Microsoft示例"Creating a Child Process with Redirected Input and Output"中,將子進程的標準輸入/輸出重定向到由父級創建的管道,必須允許重定向管道的繼承可用。我正在開發一個小的演示類,它啓動一個外部可執行文件,讀取輸出,然後將其吐回給調用者(將返回的輸出記錄到文件中)。我試圖建立一個超時功能,它只會在撥打TerminateProcess()關於孩子並繼續生活之前阻塞一段時間。選擇子進程繼承哪些句柄

但是,我發現通過允許句柄繼承,子進程也有一個句柄(可見於Process Explorer)到輸出文件。我不想讓子進程獲得這個句柄,但是在這種情況下(此演示類)的父進程不知道該句柄,所以我當前不能使用SetHandleInformation()來特別取消標記輸出文件以將其排除在繼承之外。

我確定必須有更好的方法來繼承我想要的特定句柄,而不允許通過意外和不需要的句柄的「一攬子」繼承。不幸的是,我一直無法找到解決方案,瀏覽儘可能多的MSDN相關文章,並且讓Google陷入灰心。

至少,我需要做某些東西刪除子句柄,而不必在演示類中有這些句柄(它們被調用類使用,並且此演示類沒有明確的瞭解他們的存在)。

更多選擇性遺傳的解決方案?如果存在這樣的解決方案,我特別感興趣的解決方案可以特別聲明要繼承的句柄,並且所有未指定的句柄都不會被繼承。

謝謝。

回答

3

如果輸出文件句柄是由子進程繼承的,那是因爲父進程中的代碼打開文件明確指出文件句柄應該是可繼承的。它通過了CreateFile參數lpSecurityAttributes的值。默認狀態是的句柄不是是可繼承的。

在我看來,你的進程創建類不應該試圖猜測它的調用者,誰已經打開文件。但是,如果您具體瞭解新進程需要哪些句柄,那麼從Windows Vista開始,有一種機制可以指定應該繼承哪些句柄。當您準備致電CreateProcess時,請使用STARTUPINFOEX結構,而不是通常的STARTUPINFO。它有一個lpAttributeList成員。分配並初始化它,然後使用UpdateProcThreadAttributePROC_THREAD_ATTRIBUTE_HANDLE_LIST來設置要繼承的句柄列表。所有句柄都必須是可繼承的,並且當您致電CreateProcess時,仍然需要指定bInheritHandles = true。您還需要在dwCreationFlags參數中包含EXTENDED_STARTUPINFO_PRESENTRaymond Chen demonstrated the technique in an article in 2011.

如果您沒有添加的功能,那麼您肯定可以嘗試[枚舉所有程序的打開手柄]並將其所有繼承屬性設置爲SetHandleInformation,但這似乎超出了功能的範圍其任務是創建子進程。讓創建句柄的代碼擔心它們是否應該是可繼承的。

+0

儘管對原始擁有者的意圖不加猜測的情緒當然是合理的,但在這種特殊情況下,我很熟悉來電者的工作方式。該文件實際上是一個'ofstream',通常打開一個「streamName.open(」filename「);」雖然這似乎表明此std調用的默認行爲是創建一個可繼承的句柄,但我仍然覺得應該可以明確定義在創建子進程時應該繼承哪些句柄。我仍然希望這是可能的,而且有人知道如何。 – KevenK 2010-02-26 22:06:51

+0

(從上面繼續)。我的空間用完了,但我也想感謝你分享你的時間和知識。我當然非常感謝允許創建者確定句柄的可繼承性的智慧,如果他們特別想分享它的話。我並不反對這種情緒,只是在這種情況下我知道這是一個意想不到的結果。我想相信有一個「直到指定的默認值」來對付目前的「默認所有,除非指定」設置。或許,我的一廂情願的想法!但是,感謝你的時間和智慧。 – KevenK 2010-02-26 22:10:40

+0

創建進程時唯一的選項是讓進程繼承已設置爲可繼承的所有內容,或繼承任何內容。在該規則中,你需要找到句柄並在之後設置它們的可繼承性。如果文件流沒有用你想要的屬性創建文件,那麼你自己調用'CreateFile',然後使用'_open_osfhandle'和* fdstream.hpp *或者Boost.Iostreams類'file_descriptor'來包裝句柄,並且'stream'。 – 2010-02-26 22:49:11

1

您可以使用SetHandleInformation清除輸出句柄上的HANDLE_FLAG_INHERIT位,這將阻止子進程繼承它。

如果設置了此標誌,則CreateProcess的bInheritHandles參數設置爲TRUE創建的子進程將繼承對象句柄。

+1

謝謝你的時間和幫助。然而,正如我試圖在OP中解釋的那樣,這個演示類本身沒有處理副本(它由該方法的調用者擁有),因此我不能使用SetHandleInformation特定地取消標記該特定處理。除非有一個快速的方法來枚舉所有除特別需要的句柄之外都會繼承和取消標記的句柄,否則我不確定它可以用來解決這個問題。我正在尋找更多的「繼承這些顯式句柄」的方法,而不是「繼承除這個之外的所有句柄」。 – KevenK 2010-02-26 21:51:44