user-0 提问: 为什么无法捕获控制台的消息？

回复:
user: user-1
content: 学习HOOK不撸WinAPIOverride， 等于没学HOOK！

user: user-0
content: 引用 29 楼 早打大打打核战争 的回复:忘了说了，如果先GetConsoleWindow获取控制台窗口句柄，然后SetWindowsHookEx安装一个WH_CALLWNDPROC、WH_CALLWNDPROCRET、或者WH_GETMESSAGE类型的钩子，然后在HOOK过程中检测传入的MSG结构（hwnd是否是本控制台窗口句柄），是可以获取到全部消息的，但这属于非标准用法 谢谢啊，真的非常谢谢，您的回答简明扼要直中靶心。我正好过些天要学习下HOOK，您给了我不错的思路。

user: user-2
content: 忘了说了，如果先GetConsoleWindow获取控制台窗口句柄，然后SetWindowsHookEx安装一个WH_CALLWNDPROC、WH_CALLWNDPROCRET、或者WH_GETMESSAGE类型的钩子，然后在HOOK过程中检测传入的MSG结构（hwnd是否是本控制台窗口句柄），是可以获取到全部消息的，但这属于非标准用法

user: user-0
content: 引用 27 楼 早打大打打核战争 的回复:[quote=引用 17 楼 六道佩恩 的回复:] [quote=引用 1 楼 早打大打打核战争 的回复:] 不是CreateWindow/CreateWindowEx，而是AllocConsole，console窗口属于系统进程csrss.exe，所以你的程序接收不到窗口消息，如果在控制台应用中调用GetMessage会一直阻塞 那么控制台窗口的消息是完全没有还是只要少部分？[/quote]  简单说，完全没有，因为控制台窗口属于csrss.exe，消息都由它处理了，控制台应用程序获取不到 进一步说，用ReadConsoleInput，PeekConsoleInput可以获取一部分，但是非客户区消息获取不到 [/quote] 谢谢你啊，不过已经结贴了，我不知道怎么加分，，，抱歉哈。。。。

user: user-2
content: 引用 17 楼 六道佩恩 的回复:[quote=引用 1 楼 早打大打打核战争 的回复:] 不是CreateWindow/CreateWindowEx，而是AllocConsole，console窗口属于系统进程csrss.exe，所以你的程序接收不到窗口消息，如果在控制台应用中调用GetMessage会一直阻塞 那么控制台窗口的消息是完全没有还是只要少部分？[/quote]  简单说，完全没有，因为控制台窗口属于csrss.exe，消息都由它处理了，控制台应用程序获取不到 进一步说，用ReadConsoleInput，PeekConsoleInput可以获取一部分，但是非客户区消息获取不到

user: user-3
content: 控制台输入输出是使用的系统缓冲机制，没有消息的事。输出是写入系统输出缓存，输入是读取系统输入缓存，相关调度由系统管理。基本上是这个样子的。

user: user-4
content: 引用 24 楼 六道佩恩 的回复:[quote=引用 23 楼 luj_1768 的回复:] 控制台输入输出是使用的系统缓冲机制，没有消息的事。输出是写入系统输出缓存，输入是读取系统输入缓存，相关调度由系统管理。基本上是这个样子的。 控制台本身也是窗口，那么是不产生消息还是系统得到消息后不作转发？[/quote] 前面六道的回复：the specified window cannot be spied upon. windows will not allow access to the message stream for this window.翻译：指定的窗口不能被窥视，Windows系统不允许获取这个窗口的消息流。 综合前面的大侠回复，理解：控制台的窗口自有按钮的消息是无法被直接获取的。  这样理解对不对？

user: user-0
content: 引用 23 楼 luj_1768 的回复:控制台输入输出是使用的系统缓冲机制，没有消息的事。输出是写入系统输出缓存，输入是读取系统输入缓存，相关调度由系统管理。基本上是这个样子的。 控制台本身也是窗口，那么是不产生消息还是系统得到消息后不作转发？

user: user-0
content: 引用 20 楼 赵4老师 的回复:WinAPIOverride http://jacquelin.potier.free.fr/winapioverride32/ 额，赵老师，我找了一圈，楞是没看到message这个词，获取到窗口句柄后，把上面的按钮都点了一遍也没找到哪里可以捕获message，帮助文档也看不懂，，，，，，要不，赵老师您直接告诉我结论吧，，，就是，我们捕获不到控制台窗口的普通消息，是因为根本没产生消息，还是因为产生的消息没有被系统发送到控制台，还是说发送到了控制台但我们无法接收？

user: user-1
content: WinAPIOverride http://jacquelin.potier.free.fr/winapioverride32/

user: user-0
content: 引用 18 楼 赵4老师 的回复:难道用Spy++也捕获不到控制台窗口的消息？ 我刚刚去试了一下，我不太确定我的使用方法有没有错，在左边的“Find Window”里选中“Message”，将圆环拖放到目标窗口，其中有些窗口获取到了消息，有些没有，但放到控制台窗口的时候提示“the specified window cannot be spied upon. windows will not allow access to the message stream for this window.”，意思就是的确是捕获不到控制台消息，是吧？

user: user-1
content: 难道用Spy++也捕获不到控制台窗口的消息？

user: user-0
content: 引用 1 楼 早打大打打核战争 的回复:不是CreateWindow/CreateWindowEx，而是AllocConsole，console窗口属于系统进程csrss.exe，所以你的程序接收不到窗口消息，如果在控制台应用中调用GetMessage会一直阻塞 那么控制台窗口的消息是完全没有还是只要少部分？

user: user-5
content: 引用 7 楼 六道佩恩 的回复:[quote=引用 4 楼 ForgetTomorrow 的回复:] 哈哈哈哈哈哈哈哈中 嘲笑别人有意思？[/quote] 兄弟我没有嘲笑你，我只是来看下我的github勋章有没有显示出来，乱打了几个字。 你这内心也太脆弱了吧

user: user-2
content: 引用 13 楼 六道佩恩 的回复:[quote=引用 11 楼 早打大打打核战争 的回复:] [quote=引用 10 楼 六道佩恩 的回复:] [quote=引用 1 楼 早打大打打核战争 的回复:] 不是CreateWindow/CreateWindowEx，而是AllocConsole，console窗口属于系统进程csrss.exe，所以你的程序接收不到窗口消息，如果在控制台应用中调用GetMessage会一直阻塞 3楼的第二个链接里，在控制台窗口创建按钮，是可以捕获到按钮消息的呀[/quote]  那是因为他调用了CreateWindow创建按钮，实际上已经是GUI程序，只是按钮的parent设置为console窗口而已   [/quote] 那么，对于这个例子，消息传送的过程是不是这样：按下按钮——系统获知——传送消息给按钮窗口所在的线程——我们捕获消息。所以这相当于我们的线程捕获的子窗口的消息，而不是捕获的控制台窗口的消息，是这样吗？[/quote]  是的，console窗口属于csrss.exe，按钮属于自己的APP

user: user-6
content: 有试过SetWindowsHookEx  来捕获消息么？

user: user-0
content: 引用 11 楼 早打大打打核战争 的回复:[quote=引用 10 楼 六道佩恩 的回复:] [quote=引用 1 楼 早打大打打核战争 的回复:] 不是CreateWindow/CreateWindowEx，而是AllocConsole，console窗口属于系统进程csrss.exe，所以你的程序接收不到窗口消息，如果在控制台应用中调用GetMessage会一直阻塞 3楼的第二个链接里，在控制台窗口创建按钮，是可以捕获到按钮消息的呀[/quote]  那是因为他调用了CreateWindow创建按钮，实际上已经是GUI程序，只是按钮的parent设置为console窗口而已   [/quote] 那么，对于这个例子，消息传送的过程是不是这样：按下按钮——系统获知——传送消息给按钮窗口所在的线程——我们捕获消息。所以这相当于我们的线程捕获的子窗口的消息，而不是捕获的控制台窗口的消息，是这样吗？

user: user-0
content: 引用 9 楼 赵4老师 的回复:仅供参考：#pragma comment(lib,"user32") #include <stdio.h> #include <string.h> #include <windows.h> int main() {     SECURITY_ATTRIBUTES sa          = {0};     STARTUPINFO         si          = {0};     PROCESS_INFORMATION pi          = {0};     HANDLE              hPipeOutputRead  = NULL;     HANDLE              hPipeOutputWrite = NULL;     HANDLE              hPipeInputRead   = NULL;     HANDLE              hPipeInputWrite  = NULL;     BOOL                bTest = 0;     DWORD               dwNumberOfBytesRead = 0;     DWORD               dwNumberOfBytesWrite = 0;     CHAR                szMsg[100];     CHAR                szBuffer[256];      sa.nLength = sizeof(sa);     sa.bInheritHandle = TRUE;     sa.lpSecurityDescriptor = NULL;      // Create pipe for standard output redirection.     CreatePipe(&hPipeOutputRead,  // read handle             &hPipeOutputWrite, // write handle             &sa,      // security attributes             0      // number of bytes reserved for pipe - 0 default             );      // Create pipe for standard input redirection.     CreatePipe(&hPipeInputRead,  // read handle             &hPipeInputWrite, // write handle             &sa,      // security attributes             0      // number of bytes reserved for pipe - 0 default             );      // Make child process use hPipeOutputWrite as standard out,     // and make sure it does not show on screen.     si.cb = sizeof(si);     si.dwFlags     = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;     si.wShowWindow = SW_HIDE;     si.hStdInput   = hPipeInputRead;     si.hStdOutput  = hPipeOutputWrite;     si.hStdError   = hPipeOutputWrite;      CreateProcess (           NULL, "cmd.exe",           NULL, NULL,           TRUE, 0,           NULL, NULL,           &si, &pi);      // Now that handles have been inherited, close it to be safe.     // You don't want to read or write to them accidentally.     CloseHandle(hPipeOutputWrite);     CloseHandle(hPipeInputRead);      // Now test to capture DOS application output by reading     // hPipeOutputRead.  Could also write to DOS application     // standard input by writing to hPipeInputWrite.     sprintf(szMsg, "ver\n");     WriteFile(           hPipeInputWrite,      // handle of the write end of our pipe           &szMsg,               // address of buffer that send data           strlen(szMsg),        // number of bytes to write           &dwNumberOfBytesWrite,// address of number of bytes read           NULL                  // non-overlapped.           );      while(TRUE)     {        bTest=ReadFile(           hPipeOutputRead,      // handle of the read end of our pipe           &szBuffer,            // address of buffer that receives data           256,                  // number of bytes to read           &dwNumberOfBytesRead, // address of number of bytes read           NULL                  // non-overlapped.           );        if (!bTest){           sprintf(szMsg, "Error #%d reading pipe.",GetLastError());           printf("%s",szMsg);           break;       }        // do something with data.       szBuffer[dwNumberOfBytesRead] = 0;  // null terminate       printf("%s",szBuffer);       if ('>'==szBuffer[dwNumberOfBytesRead-1]) break;     }      sprintf(szMsg, "chcp\nexit\n");     WriteFile(           hPipeInputWrite,      // handle of the write end of our pipe           &szMsg,               // address of buffer that send data           strlen(szMsg),        // number of bytes to write           &dwNumberOfBytesWrite,// address of number of bytes read           NULL                  // non-overlapped.           );      while(TRUE)     {        bTest=ReadFile(           hPipeOutputRead,      // handle of the read end of our pipe           &szBuffer,            // address of buffer that receives data           256,                  // number of bytes to read           &dwNumberOfBytesRead, // address of number of bytes read           NULL                  // non-overlapped.           );        if (!bTest){           sprintf(szMsg, "Error #%d reading pipe.",GetLastError());           printf("%s",szMsg);           break;       }        // do something with data.       szBuffer[dwNumberOfBytesRead] = 0;  // null terminate       printf("%s",szBuffer);     }      // Wait for CONSPAWN to finish.     WaitForSingleObject (pi.hProcess, INFINITE);      // Close all remaining handles     CloseHandle (pi.hProcess);     CloseHandle (hPipeOutputRead);     CloseHandle (hPipeInputWrite);      return 0; } //C:\test>test //Microsoft Windows [版本 5.2.3790] //(C) 版权所有 1985-2003 Microsoft Corp. // //C:\test>ver // //Microsoft Windows [版本 5.2.3790] // //C:\test>chcp //活动的代码页: 936 // //C:\test>exit //Error #109 reading pipe. //C:\test>  赵老师，额，虽然不是很懂这个代码，但大概好像是创建进程、管道，你这个好像是进程间通信吧，，，额，，您是不是误解了我的问题？

user: user-2
content: 引用 10 楼 六道佩恩 的回复:[quote=引用 1 楼 早打大打打核战争 的回复:] 不是CreateWindow/CreateWindowEx，而是AllocConsole，console窗口属于系统进程csrss.exe，所以你的程序接收不到窗口消息，如果在控制台应用中调用GetMessage会一直阻塞 3楼的第二个链接里，在控制台窗口创建按钮，是可以捕获到按钮消息的呀[/quote]  那是因为他调用了CreateWindow创建按钮，实际上已经是GUI程序，只是按钮的parent设置为console窗口而已

user: user-0
content: 引用 1 楼 早打大打打核战争 的回复:不是CreateWindow/CreateWindowEx，而是AllocConsole，console窗口属于系统进程csrss.exe，所以你的程序接收不到窗口消息，如果在控制台应用中调用GetMessage会一直阻塞 3楼的第二个链接里，在控制台窗口创建按钮，是可以捕获到按钮消息的呀