[英]Windows console app stops printing when I switch to Edge
我必须编写一个控制台应用程序来记录活动窗口的 PID、文本长度和文本。
除非我切换到 Edge,否则它可以工作。 执行不会停止,但只有 PID 和文本长度会打印到屏幕上。
请帮忙,我不知道还能尝试什么。
#include <iostream>
#include <Windows.h>
#include <WinUser.h>
int main()
{
// Use environment's default locale for char type
setlocale(LC_CTYPE, "");
std::cout << "Hello é World!\n";
while (1)
{
// Get foreground window
HWND hwnd = GetForegroundWindow();
if (!hwnd) continue;
// Get window process ID
DWORD pid = 0;
GetWindowThreadProcessId(hwnd, &pid);
if (pid) std::cout << "pid " << pid << " ";
// Get window text length
int len = GetWindowTextLength(hwnd);
// Get window text
WCHAR* text = new WCHAR[len + 1];
std::cout << "len " << GetWindowText(hwnd, text, len + 1) << " ";
//if (!text) continue; // not skipping! so text NOT null
std::wcout << "text " << text;
std::cout << std::endl;
text = NULL;
Sleep(1000);
}
return 0;
}
如果你从未来读到这篇文章,我会发现:
TL;DR :Unicode 字符 8203 在控制台代码页中无法表示,这导致std::wcout
失败。 解决方案是检查std::wcout.fail()
,如果为true
调用std::wcout.clear()
。
这是我深入了解它的方法。
我开始怀疑它与std::wcout
因为即使我切换到 Microsoft Edge(并切换其中的选项卡),以下代码也会继续打印:
#include <iostream>
#include <Windows.h>
#include <WinUser.h>
int main()
{
// Use environment's default locale for char type
setlocale(LC_CTYPE, "");
while (1)
{
// Get foreground window
HWND hwnd = GetForegroundWindow();
if (!hwnd) continue;
// Get window process ID
DWORD pid = 0;
GetWindowThreadProcessId(hwnd, &pid);
std::cout << "pid " << pid << " ";
// Get window text length
int len = GetWindowTextLength(hwnd);
// Get window text
WCHAR* text = new WCHAR[len + 1];
GetWindowText(hwnd, text, len + 1);
std::cout << "text " << text << std::endl;
text = NULL;
Sleep(1000);
}
return 0;
}
在哪里:
3892
- ConsoleApplication1.exe3144
- Visual Studio 代码9812
- 松弛8772
- Microsoft Edge - 在执行期间切换选项卡(相同的 PID) 但是,以下代码将停止打印text ...
行,但在我切换到 Edge 时继续打印pid ...
行(并在其中切换选项卡):
// ...
std::wcout << "text " << text << std::endl; // switched 'cout' with 'wcout'
// ...
在哪里:
424
- ConsoleApplication1.exe3144
、 9812
和8772
与以前相同另外,如果我将pid ...
和text ...
行都切换到wcout
,那么一旦我切换到 Edge 控制台输出就会完全挂起,清楚地表明wcout
流已经失败:
// ...
std::wcout << "pid " << pid << " "; // switched 'cout' with 'wcout'
// ...
std::wcout << "text " << text << std::endl; // same
// ...
在哪里:
13584
- ConsoleApplication1.exe3144
、 9812
和8772
与以前相同现在我需要知道是什么导致wcout
失败。 根据上面的控制台输出, wcout
似乎在“Microsoft”中的t
之后立即失败。 看不见的错误字符,也许? 所以我再次调整代码以打印字符及其代码:
// ...
// std::wcout << "text " << text << std::endl;
for (int i = 0; i < wcslen(text); i++) std::cout << (char)text[i] << " (" << (int)text[i] << ")\n";
正如预期的那样,Microsoft 中的t
之后有一个不可见的字符: Unicode 字符 8203 。 现在,终于知道在 Google 上扔什么(又名“wcout fail unicode 8203”),我找到了这个和这个关键的答案。
具体来说, @dev7060 评论中的代码是我需要的试金石(此处修改):
std::wcout << "abc " << L'\u200b' << " defg" << std::endl; // L'\u200b' is unicode char 8203
if (std::wcout.fail()) {
std::cout << "\nConversion didn't succeed\n";
std::wcout << "This statement has no effect on the console";
std::wcout.clear();
std::wcout << "hello world from wcout! \n";
}
std::cout << "hello world from cout! \n";
std::wcout << "hello world from wcout again! \n";
解决方案(到目前为止)是下面的一个。
// std::wcout << "text " << text << std::endl;
std::wcout << "text " << text;
if (std::wcout.fail()) std::wcout.clear();
std::cout << std::endl;
编辑:找到了一个新的(更好?)解决方案,它不涉及检查std::wcout.fail()
和调用std::wcout.clear()
:
TL;DR :使用setlocale(LC_CTYPE, "en_US.UTF8")
或(在我的情况下) setlocale(LC_CTYPE, "pt_BR.UTF8")
。
我想弄清楚为什么默认环境语言环境( setlocale(LC_CTYPE, "")
)不起作用,所以我设计了以下小实验:
std::cout << "default locale " << setlocale(LC_CTYPE, NULL) << std::endl;
std::cout << "default console output code page " << GetConsoleOutputCP() << std::endl;
setlocale(LC_CTYPE, "pt_BR.UTF8"); // 'method' column from table below
// SetConsoleOutputCP(850)
std::cout << "new locale " << setlocale(LC_CTYPE, NULL) << std::endl;
std::cout << "new console output code page " << GetConsoleOutputCP() << std::endl;
方法 | 默认语言环境 | 默认CP | 新语言环境 | 新CP | wcout 失败? |
---|---|---|---|---|---|
setlocale(LC_CTYPE, "") |
C | 850 | 葡萄牙语_巴西.1252 | 850 | 是的 |
setlocale(LC_CTYPE, "en_US.UTF8") |
C | 850 | en_US.UTF8 | 850 | 不 |
setlocale(LC_CTYPE, "pt_BR.UTF8") |
C | 850 | pt_BR.UTF8 | 850 | 不 |
SetConsoleOutputCP(850) OEM 多语言拉丁语 1; 西欧 (DOS) |
C | 850 | C | 850 | 是的 |
SetConsoleOutputCP(1252) ANSI 拉丁语 1; 西欧 (Windows) |
C | 850 | C | 1252 | 是的 |
SetConsoleOutputCP(65001) Unicode (UTF-8) |
C | 850 | C | 65001 | 是的 |
在我的计算机(Windows 10 x86-64)中,常量CP_WINANSI
和CP_WINUNICODE
映射到850
, CP_UTF8
到65001
。
推荐阅读:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.