2013-07-15 172 views
2

所以我想修改由微軟(here)提供的代碼使用WriteConsoleInput,而不是WriteFile的,但它說的句柄無效(我打賭這是什麼真的很傻),怎麼樣手柄最初創建或者其他的東西。爲什麼一個HANDLE不適用於WriteConsoleInput,但適用於WriteFile?

所以我的問題,什麼是和WriteFile的手柄需要WriteConsoleInput手柄之間的區別,?

WriteConsoleInput

WriteFile

我猜測它有與由CreateProcess的/ CreatePipe/DuplicateHandle過程中創建的繼承手柄通過的CreateFile創建的句柄的權限標誌做。

我決定這將是更容易,如果你能看到的問題,所以這是我的完整的解決方案(使用Visual Studio 2012)兩個孩子和家長的應用程序都包括在內。

ConsoleRedir on GitHub

作爲一個說明,我需要的是兒童應用使用ReadConsoleInput,這是我的沮喪的來源。

原始的方法:

/////////////////////////////////////////////////////////////////////// 
// GetAndSendInputThreadOrig 
// Thread procedure that monitors the console for input and sends input 
// to the child process through the input pipe. 
// This thread ends when the child application exits. 
// Original from http://support.microsoft.com/kb/190351 
/////////////////////////////////////////////////////////////////////// 
DWORD WINAPI GetAndSendInputThreadOrig(LPVOID lpvThreadParam) 
{ 
    CHAR read_buff[256]; 
    DWORD nBytesRead,nBytesWrote; 
    HANDLE hPipeWrite = (HANDLE)lpvThreadParam; 

    // Get input from our console and send it to child through the pipe. 
    while (bRunThread) 
    { 
     if(!ReadConsole(hStdIn,read_buff,1,&nBytesRead,NULL)) 
      DisplayError("ReadConsole"); 

     read_buff[nBytesRead] = '\0'; // Follow input with a NULL. 

     if (!WriteFile(hPipeWrite,read_buff,nBytesRead,&nBytesWrote,NULL)) 
     { 
      if (GetLastError() == ERROR_NO_DATA) 
       break; // Pipe was closed (normal exit path). 
      else 
       DisplayError("WriteFile"); 
     } 
    } 

    return 1; 
} 

我的修改版本(必須建立按鍵):

/////////////////////////////////////////////////////////////////////// 
// GetAndSendInputThread 
// Thread procedure that monitors the console for input and sends input 
// to the child process through the input pipe. 
// This thread ends when the child application exits. 
/////////////////////////////////////////////////////////////////////// 
DWORD WINAPI GetAndSendInputThread(LPVOID lpvThreadParam) 
{ 
    CHAR read_buff[256]; 
    DWORD nBytesWrote; 
    HANDLE hPipeWrite = (HANDLE)lpvThreadParam; 

    // Get input from our console and send it to child through the pipe. 
    while (bRunThread) 
    { 
     INPUT_RECORD inputRecords[4]; 
     // Build a keyboard event, press '?' and then press RETURN 
     inputRecords[0].EventType = KEY_EVENT; 
     inputRecords[0].Event.KeyEvent.bKeyDown = TRUE; 
     inputRecords[0].Event.KeyEvent.uChar.UnicodeChar = '?'; 
     inputRecords[1].EventType = KEY_EVENT; 
     inputRecords[1].Event.KeyEvent.bKeyDown = FALSE; 
     inputRecords[1].Event.KeyEvent.uChar.UnicodeChar = '?'; 
     inputRecords[2].EventType = KEY_EVENT; 
     inputRecords[2].Event.KeyEvent.bKeyDown = TRUE; 
     inputRecords[2].Event.KeyEvent.dwControlKeyState = 0; 
     inputRecords[2].Event.KeyEvent.uChar.UnicodeChar = '\r'; 
     inputRecords[2].Event.KeyEvent.wRepeatCount = 1; 
     inputRecords[2].Event.KeyEvent.wVirtualKeyCode = VK_RETURN; 
     inputRecords[2].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC); 
     inputRecords[3].EventType = KEY_EVENT; 
     inputRecords[3].Event.KeyEvent.bKeyDown = FALSE; 
     inputRecords[3].Event.KeyEvent.dwControlKeyState = 0; 
     inputRecords[3].Event.KeyEvent.uChar.UnicodeChar = '\r'; 
     inputRecords[3].Event.KeyEvent.wRepeatCount = 1; 
     inputRecords[3].Event.KeyEvent.wVirtualKeyCode = VK_RETURN; 
     inputRecords[3].Event.KeyEvent.wVirtualScanCode = MapVirtualKey(VK_RETURN, MAPVK_VK_TO_VSC); 


     if (!WriteConsoleInput(hPipeWrite,inputRecords,sizeof(inputRecords)/sizeof(*inputRecords),&nBytesWrote)) 
     { 
      if (GetLastError() == ERROR_NO_DATA) 
       break; // Pipe was closed (normal exit path). 
      else 
       DisplayError("WriteConsoleInput"); 
     } 
    } 

    return 1; 
} 
+1

認爲一個句柄作爲一個指向一個結構。指針只是一個指針,但是一個結構與另一個結構不可比。 – Twifty

+0

這是我的第一個處理不只是將文件保存到磁盤的項目,所以你所說的話告訴我,我得到一個「無效的句柄」,因爲它不是一個CONSOLE輸入句柄,它只是一個句柄STDIN。不是一回事。是對的嗎? –

回答

2

WriteConsoleInput要求手柄是一個 「句柄到控制檯輸入緩衝區。」 (在問題鏈接頁面中輸入參數handle的描述中的第一句)。

您需要使用手柄從GetStdHandle得到一個合適的手感。

WriteConsoleInput僅適用於直接處理到控制檯,而不是重定向的管道或類似。

+0

看起來像我需要找到另一種方式發送命令到孩子的輸入緩衝區然後,呃? –

+1

出於好奇,因爲子應用程序正在使用ReadConsoleInput,如果我無法獲得孩子的CONIN $句柄,是否有任何方法可以在應用程序之間發送數據?聽起來這是用WriteConsoleInput發送INPUT_RECORD的唯一方法。 –

相關問題