2013-04-11 74 views
4

我的應用程序是一個GUI應用程序,它通過終端(通過cout)提供有用的信息(儘管是可選的)。在Windows中使用GUI應用程序中的控制檯,僅當它從控制檯運行時

在Windows中,我要麼出現一個控制檯(通過編譯爲控制檯應用程序,或動態分配它),或者我不知道。

我的意圖是使用控制檯,如果它正在從控制檯運行,但是如果它不是完全忽略控制檯。 (基本上在Linux和OS X中會發生什麼)。

我不希望重定向到一個文件(並在使用cin的情況下,這不是一個可行的解決方案)。

有沒有辦法將Windows應用程序中的GUI應用程序附加到它運行的控制檯上,當且僅當它從控制檯運行?

+0

可能重複://計算器.com/questions/447352 /如何知道我們是在一個控制檯還是一個窗口的應用程序) – wallyk 2013-04-11 15:35:47

+1

如果您的應用程序正在運行,您是否只想打印到控制檯?一?你可以使用'cout',如果程序沒有從控制檯啓動,它將被忽略。 – 2013-04-11 15:36:53

+0

@ slavik262我不會在Windows上花太多時間,但是從以前的經驗來看,如果它不是控制檯應用程序,則打印到控制檯時會被忽略。這跟cout,stdout,printf等有關係嗎? – latreides 2013-04-11 15:50:39

回答

9

,並在使用CIN的情況下,這不是一個可行的解決方案無論如何

這是你的問題的殺手細節。這很簡單,首先調用AttachConsole(ATTACH_PARENT_PROCESS)來嘗試附加到現有的控制檯。當您的程序從資源管理器或桌面快捷方式等GUI程序啓動時,這會失敗。所以如果它返回FALSE,那麼調用AllocConsole()來創建你自己的控制檯。

使用cin是一個問題。命令處理器會關注您的EXE並檢查它是否爲控制檯模式應用程序或GUI應用程序。它會檢測到您的案例中的GUI應用程序,然後不會等待該過程完成。它再次顯示提示並等待輸入。然後你也會等待輸入,但是你會失敗,命令處理器首先到達那裏。您的輸出也與命令提示符混合在一起,這是要解決的簡單問題。

有一個簡單的解決方法,你的用戶應該用start /wait yourapp開始你的程序,告訴命令處理器等待該過程完成。問題是:沒有人使用過。用戶不會意識到鍵入輸入時會發生什麼情況,而是希望它進入您的程序,但它實際上是由命令處理器解釋的。產生一個神祕的錯誤信息或格式化硬盤驅動器。

只有兩個很好的方法來解決這個無法解決的問題。您可以將您的程序構建爲控制檯模式應用程序,並在您確定要顯示GUI時調用FreeConsole()。或者總是調用AllocConsole()。這些不是很好的選擇。第一種方法是Windows上的Java JVM使用的方法。其中一個針對JVM提出的最老的錯誤,使Java程序員完全從閃爍的控制檯窗口中跳出來。

第三個選擇是唯一的體面的一個,你不想要的,創建另一個總是使用控制檯的EXE。像Java一樣,javaw.exe vs java.exe。

一個詭計是可能的,您可以將該文件從「yourapp2.exe」重命名爲「yourapp.com」。當用戶在命令行提示符下鍵入「yourapp」時,它將被首先選中,桌面快捷方式仍然可以指向「yourapp.exe」。 Visual Studio使用這個技巧,devenv.com vs devenv.exe。

+0

今天特別起泡。我認爲Java和Python都選擇單獨的可執行文件選項javaw和pythonw。這是保持理智的唯一方法。 – 2013-04-11 21:09:37

+0

雖然不是我所希望的,但這是解決所有問題的最佳,最完整的答案。我希望沒有這種犧牲是可行的。接受,謝謝。 – latreides 2013-04-12 05:26:59

1

您可以在啓動時檢查CONSOLE_SCREEN_BUFFER_INFO(通過GetConsoleScreenBufferInfo)以確定您是否從現有控制檯中運行。如果緩衝區的位置是0,0,則從控制檯外部運行。有關詳細信息,請參閱此處描述該過程的Microsoft Knowledgebase Article

爲了達到此目的,您需要將應用程序編譯爲控制檯應用程序(使用/SUBSYSTEM:CONSOLE),然後在應用程序啓動新控制檯(緩衝區爲0,0)時從控制檯分離自己。這將使程序在從命令行啓動時正確地「附加」到調用控制檯。

+0

雖然這絕對是我需要的答案的一部分,但它不是完整的(當我從內存中回想以前將應用程序移植到Windows)時打印到控制檯,並且我在Windows的控制檯中運行我的GUI應用程序,打印命令只是...消失。 – latreides 2013-04-11 15:54:30

+0

@latreides如果你不需要它,你需要讓你的應用程序成爲一個控制檯應用程序並釋放控制檯 - 編輯我的答案並提供更多細節。 – 2013-04-11 16:03:36

+0

@latreides,恐怕他是對的 - 如果你不是首先將它創建爲控制檯應用程序,那麼將'cin'和'cout'連接到控制檯所需的啓動代碼將被跳過。但要知道是否有控制檯,您應該使用['GetConsoleWindow'](http://msdn.microsoft.com/en-us/library/ms683175(VS.85).aspx)而不是'GetConsoleScreenBufferInfo'。 – 2013-04-11 16:09:29

0

正如其他人指出,你必須創建一個控制檯應用程序和一個窗口應用程序。所以,你最終會得到console.exeapp.exe。爲了讓它在命令行中不太明顯,您可以利用像devenv這樣的PATHEXT技巧。如果其擴展名位於PATHEXT環境變量中,則cmd.exe將文件視爲命令。 COM默認存在,因此您可以將console.exe重命名爲app.com,允許命令app啓動附加到當前控制檯的控制檯應用程序。

注意:當然,如果需要,控制檯應用程序可以顯示GUI。

app.com和app.exe之間的構建差異取決於您的構建系統,但它可能只是設置輸出類型的一個屬性。使用msbuild(對於.vcxproj文件),這只是另一個構建配置的問題。

0

您可以在控制檯中創建一個應用程序,該應用程序使用argc獲取一行並將其打印出來;

//// 
int main(int argc, char *argv[]) 
{ 
    //here print argv....using cout or printf 
} 

將文件保存爲您的應用程序文件夾中的console.exe。 現在在你的應用程序,如果你想看到在控制檯的任何行,您可以調用命令

system("console.exe this is the line i want to print and see in console"); 
[如何知道我們是否是在一個控制檯或窗口的應用程序?(HTTP的
相關問題