最後終於找到一個可以解決的辦法,所以記錄一下
//----------------------------------------------------------------------
需求是有一個 MFC 的程式,並經由 cmd line 呼叫
而且在程式執行失敗時,可以顯示訊息到 cmd 當下的視窗中
PS. 接收命令參數使用下面的方法
CString strCommandLine(GetCommandLine());
CommandLineToArgvW(CString(GetCommandLine()), &nArgCount);
處理過程中所遇到的問題
1. 無法在當下的 cmd 中 printf 訊息
2. printf 出來的訊息位置不佳
第一點比較快解決,有兩種方法,我是選用第一個,較簡單
第一種:
AttachConsole(ATTACH_PARENT_PROCESS); //直接取得當下 process
_cprintf("程式執行失敗");
第二種方法是下面這個網址的做法
http://blog.csdn.net/panchunrong/article/details/8930603
第二個問題就真的卡很久了
先說明一下狀況
----------------------------------------------------------------------
C:\>MFC.exe
程式執行失敗 <-目標顯示狀況:在下面的 C:\> 之前顯示
C:\>
----------------------------------------------------------------------
C:\>MFC.exe
C:\>程式執行失敗 <-實際顯示狀況:在 C:\> 之後才顯示
----------------------------------------------------------------------
在思考時主要有兩個方向
- 進程
- Console 緩衝區字元處理
進程的思考就是要在 C:\> 出現之前就將訊息印出
不過似乎不是能夠輕易解決
所以最後是用「Console 緩衝區字元處理」解掉的
再配合一些小技巧 (e.g. 實現 "Enter" 輸入,清空一行緩衝區)
就能完美的解決問題
程式碼如下:
AttachConsole(ATTACH_PARENT_PROCESS); //綁定當下cmd窗口 HANDLE hHandle = GetStdHandle(STD_OUTPUT_HANDLE); //綁定 handle CONSOLE_SCREEN_BUFFER_INFO sbi; //窗口緩衝區信息 GetConsoleScreenBufferInfo(hHandle, &sbi); //讀取console內容 char *szLine; /* buffer to hold the line read from the console */ szLine = (char *) malloc(sbi.dwSize.X); COORD coordLine = {0, 0}; /* coordinates of where to read characters from */ DWORD dwCharsRead(0); SHORT StartLine(0); for(int i=sbi.dwCursorPosition.Y ; true ; i--) { coordLine.X = 0; coordLine.Y = i; // ReadConsoleOutputCharacterA(hHandle, szLine, sbi.dwSize.X, coordLine, &dwCharsRead); //讀取console緩衝區的一行內容 int j = sbi.dwSize.X - 1; szLine[j--] = 0; /* null terminate */ while (szLine[j] == ' ') { szLine[j--] = 0; } if (j==-1) //代表當下的行無任何字元 { StartLine = i; break; } } for (int i=StartLine ; i<=sbi.dwCursorPosition.Y ; i++) //清空每一行(避免命令列路徑大於一行時) { coordLine.Y = i; FillConsoleOutputCharacter(hHandle, _T(' '), sbi.dwSize.X, coordLine, &dwCharsRead); } coordLine.Y = StartLine+1; SetConsoleCursorPosition(hHandle, coordLine); //移動Console游標位置 _cwprintf(L"程式執行失敗\n"); keybd_event(VK_RETURN, 0 , 0, 0); //實現按下 "Enter" 鍵