当我切换到 Edge 时,Windows 控制台应用程序停止打印 [英] Windows console app stops printing when I switch to Edge

查看:29
本文介绍了当我切换到 Edge 时,Windows 控制台应用程序停止打印的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须编写一个控制台应用程序来记录活动窗口的 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 314498128772 与之前相同

此外,如果我将 pid ...text ... 行都切换为 wcout,那么控制台输出将完全挂起我一切换到 Edge,就清楚地表明 wcout 流失败了:

//...std::wcout <<pid"<<pid<<""//用 'wcout' 切换 'cout'//...std::wcout <<文字"<<文本<

地点:

  • PID 13584 - ConsoleApplication1.exe
  • PID 314498128772 与之前相同

现在我需要知道 是什么导致 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新语言环境新CPwcout 失败?
setlocale(LC_CTYPE, "")C850Portuguese_Brazil.1252850
setlocale(LC_CTYPE, "en_US.UTF8")C850en_US.UTF8850没有
setlocale(LC_CTYPE, "pt_BR.UTF8")C850pt_BR.UTF8850没有
SetConsoleOutputCP(850)
OEM 多语言拉丁语 1;西欧 (DOS)
C850C850
SetConsoleOutputCP(1252)
ANSI 拉丁语 1;西欧 (Windows)
C850C1252
SetConsoleOutputCP(65001)
Unicode (UTF-8)
C850C65001

在我的计算机 (Windows 10 x86-64) 中,常量 CP_WINANSICP_WINUNICODE 映射到 850CP_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 and 8772 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 and 8772 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆