以下是情況:我們有一個構建服務器,它通過套接字爲請求提供服務,並且不會在運行它的計算機上公開UI。根據它收到的請求,它啓動構建腳本(通常是MS批處理文件)並提供它們生成的文件。出於診斷目的,構建腳本通過stdout和stderr重定向到管道來啓動,並且此構建服務器應用程序將此輸出保存到緩衝區中,並傳回給請求構建的客戶端。 (這樣,如果構建失敗,請求構建的人可以看到錯誤消息是什麼。)通過非控制檯進程將控制檯輸出重定向到緩衝區
在調試期間,此構建服務器被構建爲控制檯應用程序,主要是爲了便於打印診斷消息(客戶端連接,請求等)。一旦一切正常,我將它重建爲非控制檯應用程序。
突然,應用程序的行爲改變了。由管道捕獲的輸出減少到僅由批處理文件直接生成的輸出(即,在這種情況下命令被回顯,因爲回聲沒有關閉)。批處理文件(如MSBuild,nmake等)啓動的子進程打開了控制檯窗口,並將其輸出導向到窗口而不是管道。
我懷疑發生了什麼事情是,當應用程序是一個控制檯應用程序時,控制檯應用程序不會嘗試管理自己的輸入/輸出,而是從運行控制檯繼承,導致I/O fds上的_dup2
住下來。因此一切正常。但是在父構建服務器沒有創建控制檯窗口的情況下,批處理文件產生的子流程感到需要創建它們自己的並處理它們自己的I/O,搶奪捕獲輸出的構建服務器(而不是提到對連接到服務器桌面的任何人非常惱火)。
所以基本上這個問題很簡單:一個非控制檯如何啓動應用程序並防止這種行爲?我知道大多數控制檯應用程序原則上都是可能的,因爲Emacs shell模式是非控制檯應用程序在Windows上捕獲和重定向命令輸出的示例,但我不知道如何執行此操作。
目前我使用的Win32的POSIX味CRT功能:_pipe
,_dup
,_dup2
,_close
,_spawnvp
和_read
。我知道這些是「真正的」win32函數的簡單包裝,但作爲一名UNIX人員,我認爲通過CreateProcess
和朋友可以節省自己的麻煩。
開發語言需要C語言,因爲構建服務器實際上是用Haskell編寫的,鏈接C更簡單。 (對於你們任何一個Haskellers那裏 - 我推出了我自己的產卵/重定向代碼,並與FFI鏈接,而不是使用System.Process,因爲我迫切需要重定向stdout
和stderr
,並且在Windows上這是不重要的純粹的Haskell)。
當然,我可以使用構建服務器作爲控制檯應用程序,並將其最小化在服務器上,沒有什麼大不了的,如果我這樣做,它會很好。但我寧願不......有任何想法?
編輯:想到我可能會提到我不會對標準輸入做任何事情。我應該創建一個stdin fd,也許?這些腳本不是交互式的。
我已經看到了幾個問題,通常解決了重定向問題,例如您鏈接的問題。那不是我的問題。我可以很好地重定向子控制檯進程的輸出*,假設父進程也是一個控制檯應用程序*特別是,該線程中的建議解決方案基本上都是C++包裝器,這些包裝器已經在使用'_pipe'和'_dup2'。 – 808140
然後我顯然誤解了你的問題。如果不涉及到CreateProcess,我認爲你無法做到自己想做的事。這是您以編程方式控制子進程的std *句柄的唯一方法。 –