2011-09-16 36 views
1

以下是情況:我們有一個構建服務器,它通過套接字爲請求提供服務,並且不會在運行它的計算機上公開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,因爲我迫切需要重定向stdoutstderr,並且在Windows上這是不重要的純粹的Haskell)。

當然,我可以使用構建服務器作爲控制檯應用程序,並將其最小化在服務器上,沒有什麼大不了的,如果我這樣做,它會很好。但我寧願不......有任何想法?

編輯:想到我可能會提到我不會對標準輸入做任何事情。我應該創建一個stdin fd,也許?這些腳本不是交互式的。

回答

0

此問題已在SO上解決了好幾次。例如,看看this question

+0

我已經看到了幾個問題,通常解決了重定向問題,例如您鏈接的問題。那不是我的問題。我可以很好地重定向子控制檯進程的輸出*,假設父進程也是一個控制檯應用程序*特別是,該線程中的建議解決方案基本上都是C++包裝器,這些包裝器已經在使用'_pipe'和'_dup2'。 – 808140

+0

然後我顯然誤解了你的問題。如果不涉及到CreateProcess,我認爲你無法做到自己想做的事。這是您以編程方式控制子進程的std *句柄的唯一方法。 –

1

您可以撥打AllocConsole來創建控制檯,但這與將應用程序創建爲控制檯應用程序並沒有根本的區別。

我認爲一個更好的解決方案是打開你的日誌文件,然後調用SetStdHandle,傳遞它STD_OUTPUT_HANDLE和你剛剛打開的文件的句柄。我認爲應該給你一個其他進程將寫入的標準輸出。

或者,你也許可以找到一個方法來隱藏控制檯窗口完全(從任務欄刪除等)

附加信息:

也許你可以嘗試讓控制檯窗口處理並呼叫ShowWindow(handle, SW_HIDE)。這將從窗口中移除窗口,但是當您寫入標準輸出時,它實際上會寫入該窗口。您應該可以通過調用GetConsoleWindow來獲得控制檯窗口句柄。

如果這不起作用,你可以讓你的程序參數-hide。如果是在命令行上,那麼程序會自動啓動一個新的副本,但是在過程中,啓動信息時會顯示用隱藏窗口啓動進程。

+0

你指向'AllocConsole'的指針是最有用的,因爲它解釋了我看到的行爲。當您啓動一個控制檯應用程序時,它似乎嘗試「AllocConsole」,但每個控制檯進程只能有一個關聯的控制檯,並且默認情況下它會繼承其父級。所以在我的服務器是控制檯應用程序的情況下,'AllocConsole'失敗,但在不是的情況下,它不會。 'AllocConsole'設置所有的I/O文件描述符以指向新的控制檯,因此覆蓋了我的管道。 [這是一個解決方案,但對我來說似乎很瘋狂。](http://www.codeproject.com/KB/threads/RTconsole.aspx) – 808140

+0

@ 808140:是的,該解決方案看起來似乎很瘋狂。看到我的替代方法。這可能會做你想要的。 –

相關問題