浅谈Console与Windows子系统

来源:互联网 发布:医院数据集成平台架构 编辑:程序博客网 时间:2024/05/16 05:59

浅谈Console与Windows子系统

因为baidu 空间格式难易调节,富文本粘贴困难,本文停止更新,请访问:Qt Windows下链接子系统与入口函数(终结版)

Windows 下 console 和 gui 程序

刚接触到Visual Studio 时,每次新建工程时,都要选择控制台程序还是Windows程序,当时就误解为:前者就是c/c++的程序,后者是windows下界面程序。

后来开始接触 python,注意到在Windows下的两个后缀 *.py *.pyw 分别注册到 python.exe pythonw.exe两个程序,前者会弹出控制台窗口,后者不会。对Gui程序,pythonw.exe非常的友好。但为什么会这样,仍不了解。

曾经尝试用 gcc 编译 win32 api的简单例子,却发觉总是弹出一个黑色的窗口。感觉很不好,但却以为gcc在windows就这个德行。

接触Qt,注意到在windows下必须添加 CONFIG += console 才能显示出控制台窗口。

由于反复遇到这个问题,才决定要了解究竟是怎么回事:一切都源于链接时subsystem可选择不同的子系统(这是Windows下独有的,linux下似乎简单多了)

subsystem子系统

在windows下,链接时有多个子系统可供选择,最常见的家就是console 和 windows 这两个subsystem。由此,有了下面的故事:一步一步亲自做个试验吧

Gui 程序弹出控制台

#include <windows.h>

int WINAPI
WinMain (HINSTANCE hInstance, HINSTANCE hPrevInst, LPTSTR lpCmdLine, int nShowCmd)
{
MessageBoxW (NULL, L"Hello World!", L"hello", MB_OK | MB_ICONINFORMATION);
return 0;
}

这是一个简单的GUI程序,弹出一个 Hello World 的窗口。但当我直接用 g++ 编译以后,

  • g++ hello.cpp

程序运行时,控制台(黑色的CMD窗口)老是伴随GUI界面出现。

因为上面的等价于

  • g++ hello.cpp -Wl,-subsystem,console

而我们需要的是

  • g++ hello.cpp -Wl,-subsystem,windows

注:

  • 选项 -Wl,-subsystem,... 也可写为 -Wl,--subsystem,...

  • -Wl,-subsystem,console 此处可用 -mconsole 替代

  • -Wl,-subsystem,windows 此处可用 -mwindows 替代

隐藏控制台程序的控制台

#include <iostream>

int main()
{
std::cout<<"hello concole\n";
return 0;
}

该程序编译后,双击运行,会弹出控制台窗口。

  • g++ hello.cpp

如果我们让其链接 windows 子系统,那么程序控制台被隐藏,程序将什么都不显示(有时我们需要这样,比如简单运行一个httpd)。

  • g++ hello.cpp -Wl,-subsystem,windows
对于 msvc

上面的例子是针对 mingw 的,如果我们用的 msvc,情况是类似的。 只不过 msvc 会自动根据 WinMain 和 main 来自动选择链接到windows还是console子系统(哇,看起来这个特性比mingw好多了_,但事情总是两面的)

对第一个程序,我们直接编译(注:函数 MessageBoxW 需要库 user32.lib)

cl /EHsc hello.cpp user32.lib

如前所述,由于自动链接到windows,于是等价于

cl /EHsc hello.cpp /link /subsystem:windows user32.lib

一般情况下这真是我们期望的。

可如果我们想让控制台同时出现怎么办?很容易想到

cl /EHsc hello.cpp /link /subsystem:console user32.lib

可很不幸,它不工作,因为指定子系统后,链接器将会去链接 main 而不是 WinMain。这么一来,我们必须自己通知链接器入口函数是WinMain

cl /EHsc hello.cpp /link /subsystem:console /entry:WinMainCRTStartup user32.lib

对第二个程序,默认链接console子系统,显示控制台。如果我们想隐藏控制台,需要告诉链接器,用windows子系统,入口时main

cl /EHsc hello.cpp /link /subsystem:windows /entry:mainCRTStartup

嘿嘿,挺简单的东西,曾折磨我很长时间

main 和 WinMain

一般控制台程序用 main, GUI 程序用 WinMain,其实事实没这么绝对:它们可以互换的!

#include <windows.h>
int main()
{
MessageBoxW (NULL, L"Hello World!", L"hello", MB_OK | MB_ICONINFORMATION);
return 0;
}

这个一个GUI程序,如果我们想要控制台,那么

cl /EHsc hello.cpp user32.lib
g++ hello.cpp

cl /EHsc hello.cpp /link /subsystem:console /entry:mainCRTStartup user32.lib
g++ hello.cpp -Wl,-subsystem,console

如果不要控制台,那么

cl /EHsc hello.cpp /link /subsystem:windows /entry:mainCRTStartup user32.lib
g++ hello.cpp -Wl,-subsystem,windows

同样,控制台程序也可以用 WinMain 入口。就不再一一列举了。


原创粉丝点击