最後終於找到一個可以解決的辦法,所以記錄一下
//----------------------------------------------------------------------
需求是有一個 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" 鍵