繁体   English   中英

当我切换到 Edge 时,Windows 控制台应用程序停止打印

[英]Windows console app stops printing when I switch to Edge

我必须编写一个控制台应用程序来记录活动窗口的 PID、文本长度和文本。

除非我切换到 Edge,否则它可以工作。 执行不会停止,但只有 PID 和文本长度会打印到屏幕上。

请帮忙,我不知道还能尝试什么。

控制台应用程序输出显示 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;
}

使用 std::cout 作为文本行的控制台应用程序输出

在哪里:

  • PID 3892 - ConsoleApplication1.exe
  • PID 3144 - Visual Studio 代码
  • PID 9812 - 松弛
  • PID 8772 - Microsoft Edge - 在执行期间切换选项卡(相同的 PID)

但是,以下代码将停止打印text ...行,但在我切换到 Edge 时继续打印pid ...行(并在其中切换选项卡):

// ...
std::wcout << "text " << text << std::endl; // switched 'cout' with 'wcout'
// ...

使用 std::wcout 作为文本行的控制台应用程序输出

在哪里:

  • PID 424 - ConsoleApplication1.exe
  • PID 314498128772与以前相同

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

// ...
std::wcout << "pid " << pid << " "; // switched 'cout' with 'wcout'
// ...
std::wcout << "text " << text << std::endl; // same
// ...

对 PID 和文本行使用 std::wcout 的控制台输出

在哪里:

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

现在我需要知道是什么导致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";

控制台输出显示隐藏的 Unicode 字符 8203

正如预期的那样,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";

显示 wcout 失败的控制台输出

解决方案(到目前为止)是下面的一个。

// 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_WINANSICP_WINUNICODE映射到850CP_UTF865001

推荐阅读:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM