当我切换到 Edge 时,Windows 控制台应用程序停止打印 [英] Windows console app stops printing when I switch to Edge
问题描述
我必须编写一个控制台应用程序来记录活动窗口的 PID、文本长度和文本.
它可以工作,除非我切换到 Edge.执行不会停止,但只有 PID 和文本长度会打印到屏幕上.
请帮忙,我不知道还能尝试什么.
#include #include #include int main(){//使用环境的默认语言环境作为字符类型setlocale(LC_CTYPE,");std::cout <<Hello é World!\n";而 (1){//获取前景窗口HWND hwnd = GetForegroundWindow();如果(!hwnd)继续;//获取窗口进程ID双字 pid = 0;GetWindowThreadProcessId(hwnd, &pid);if (pid) std::cout <<pid"<<pid<<"";//获取窗口文本长度int len = GetWindowTextLength(hwnd);//获取窗口文本WCHAR* text = new WCHAR[len + 1];std::cout <<连"<<GetWindowText(hwnd, text, len + 1) <<"";//如果(!文本)继续;//不跳过!所以文本不为空std::wcout <<文字"<<文本;std::cout <<std::endl;文本 = NULL;睡眠(1000);}返回0;}
如果您是从未来开始阅读本文,我会发现以下内容:
TL;DR:Unicode 字符 8203 无法在控制台代码页中表示,这导致 std::wcout
失败.解决方案是检查 std::wcout.fail()
和如果 true
调用 std::wcout.clear()
.>
以下是我深入了解它的方法.
我开始怀疑它与 std::wcout
有关,因为即使我切换到 Microsoft Edge(并在其中切换标签),以下代码仍会继续打印:
#include #include #include int main(){//使用环境的默认语言环境作为字符类型setlocale(LC_CTYPE,");而 (1){//获取前景窗口HWND hwnd = GetForegroundWindow();如果(!hwnd)继续;//获取窗口进程ID双字 pid = 0;GetWindowThreadProcessId(hwnd, &pid);std::cout <<pid"<<pid<<"";//获取窗口文本长度int len = GetWindowTextLength(hwnd);//获取窗口文本WCHAR* text = new WCHAR[len + 1];GetWindowText(hwnd, text, len + 1);std::cout <<文字"<<文本<
地点:
- PID
3892
- ConsoleApplication1.exe - PID
3144
- Visual Studio 代码 - PID
9812
- Slack - PID
8772
- Microsoft Edge - 在执行期间切换选项卡(相同的 PID)
然而,以下代码将停止打印 text ...
行,但 保持 打印 pid ...
行,当我切换到 Edge(并切换其中的选项卡):
//...std::wcout <<文字"<<文本<
地点:
- PID
424
- ConsoleApplication1.exe - PID
3144
、9812
和8772
与之前相同
此外,如果我将 pid ...
和 text ...
行都切换为 wcout
,那么控制台输出将完全挂起我一切换到 Edge,就清楚地表明 wcout
流失败了:
//...std::wcout <<pid"<<pid<<""//用 'wcout' 切换 'cout'//...std::wcout <<文字"<<文本<
地点:
- PID
13584
- ConsoleApplication1.exe - PID
3144
、9812
和8772
与之前相同
现在我需要知道 是什么导致 wcout
失败.根据上面的控制台输出,wcout
似乎在Microsoft"中的 t
之后立即失败.看不见的错误字符,也许?所以我再次调整代码以打印字符及其代码:
//...//std::wcout <<文字"<<文本<
正如预期的那样,Microsoft 中的 t
之后有一个不可见的字符:
解决方案(到目前为止)如下所示.
//std::wcout <<文字"<<文本<
EDIT:找到了一个新的(更好?)解决方案,它不涉及检查 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 <<默认语言环境"<<setlocale(LC_CTYPE,NULL)<
方法 | 默认语言环境 | 默认CP | 新语言环境 | 新CP | wcout 失败? |
---|---|---|---|---|---|
setlocale(LC_CTYPE, "") | C | 850 | Portuguese_Brazil.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代码>.
推荐阅读:
I have to write a console app to log the active window PID, text length and text.
It works except when I switch to Edge. The execution doesn't stop, but only the PID and text length get printed to the screen.
Please help, I don't know what else to try.
#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;
}
If you're reading this from the future, here's what I found out:
TL;DR: Unicode char 8203 wasn't representable in the console codepage, which caused std::wcout
to fail. The solution is to check for std::wcout.fail()
and if true
call std::wcout.clear()
.
Here's how I got to the bottom of it.
I started suspecting it had something to do with std::wcout
because the following code would keep printing even when I switched to Microsoft Edge (and switched tabs within it):
#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;
}
Where:
- PID
3892
- ConsoleApplication1.exe - PID
3144
- Visual Studio Code - PID
9812
- Slack - PID
8772
- Microsoft Edge - with tabs switched during execution (same PID)
The following code, however, would stop printing the text ...
line but keep printing the pid ...
line when I switched to Edge (and switched tabs within it):
// ...
std::wcout << "text " << text << std::endl; // switched 'cout' with 'wcout'
// ...
Where:
- PID
424
- ConsoleApplication1.exe - PIDs
3144
,9812
and8772
same as before
Also, if I switched both pid ...
and text ...
lines to wcout
, then the console output would completely hang as soon as I switched to Edge, clearly showing that the wcout
stream had failed:
// ...
std::wcout << "pid " << pid << " "; // switched 'cout' with 'wcout'
// ...
std::wcout << "text " << text << std::endl; // same
// ...
Where:
- PID
13584
- ConsoleApplication1.exe - PIDs
3144
,9812
and8772
same as before
Now I needed to know what was causing wcout
to fail. Per the console outputs above, wcout
seemed to fail right after the t
in "Microsoft". Invisible faulty char, maybe? So I tweaked the code once more to print both the char and its code:
// ...
// std::wcout << "text " << text << std::endl;
for (int i = 0; i < wcslen(text); i++) std::cout << (char)text[i] << " (" << (int)text[i] << ")\n";
As expected, there was an invisible char right after the t
in Microsoft: Unicode character 8203. Now, finally knowing what to throw on Google (a.k.a. "wcout fail unicode 8203"), I found this and this pivotal answers.
Specifically, the code from @dev7060's comment was the litmus test I needed (here modified):
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";
The solution (so far) is the one below.
// std::wcout << "text " << text << std::endl;
std::wcout << "text " << text;
if (std::wcout.fail()) std::wcout.clear();
std::cout << std::endl;
EDIT: found a new (better?) solution that doesn't involve checking std::wcout.fail()
and calling std::wcout.clear()
:
TL;DR: use setlocale(LC_CTYPE, "en_US.UTF8")
or (in my case) setlocale(LC_CTYPE, "pt_BR.UTF8")
.
I wanted to figure out why the default environment locale (setlocale(LC_CTYPE, "")
) wasn't working, so I devised the following little experiment:
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;
Method | Default locale | Default CP | New locale | New CP | wcout fail? |
---|---|---|---|---|---|
setlocale(LC_CTYPE, "") |
C | 850 | Portuguese_Brazil.1252 | 850 | Yes |
setlocale(LC_CTYPE, "en_US.UTF8") |
C | 850 | en_US.UTF8 | 850 | No |
setlocale(LC_CTYPE, "pt_BR.UTF8") |
C | 850 | pt_BR.UTF8 | 850 | No |
SetConsoleOutputCP(850) OEM Multilingual Latin 1; Western European (DOS) |
C | 850 | C | 850 | Yes |
SetConsoleOutputCP(1252) ANSI Latin 1; Western European (Windows) |
C | 850 | C | 1252 | Yes |
SetConsoleOutputCP(65001) Unicode (UTF-8) |
C | 850 | C | 65001 | Yes |
In my computer (Windows 10 x86-64), the constants CP_WINANSI
and CP_WINUNICODE
map to 850
and CP_UTF8
to 65001
.
Recommended reading:
这篇关于当我切换到 Edge 时,Windows 控制台应用程序停止打印的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!