awtk icon indicating copy to clipboard operation
awtk copied to clipboard

Windows下如何才能不显示控制台(终端)窗口?

Open ufbycd opened this issue 3 years ago • 4 comments

点击编译好的exe文件,显示GUI程序窗口的同时会显示一个显示标准输出的终端窗口。我的程序是要打包给客户使用的,显示一个终端窗口肯定是不行的! 如何才能不显示这个终端窗口?我把编译配置里的 “-D_CONSOLE”选项都去掉了,还是有个终端窗口。

ufbycd avatar Aug 06 '22 16:08 ufbycd

定义宏NDEBUG即可。

#if defined(WIN32) && !defined(NDEBUG)
#define TK_ENABLE_CONSOLE()                   \
  {                                           \
    AllocConsole();                           \
    FILE* fp = NULL;                          \
    freopen_s(&fp, "CONOUT$", "w+t", stdout); \
  }
#else
#define TK_ENABLE_CONSOLE()
#endif /*WIN32 && !NDEBUG*/

xianjimli avatar Aug 06 '22 23:08 xianjimli

定义宏NDEBUG即可。

#if defined(WIN32) && !defined(NDEBUG)
#define TK_ENABLE_CONSOLE()                   \
  {                                           \
    AllocConsole();                           \
    FILE* fp = NULL;                          \
    freopen_s(&fp, "CONOUT$", "w+t", stdout); \
  }
#else
#define TK_ENABLE_CONSOLE()
#endif /*WIN32 && !NDEBUG*/

我是用msys2里的mingw来编译的,加了NDEBUG宏发现还是一样有终端窗口。

ufbycd avatar Aug 07 '22 04:08 ufbycd

应该是在自己的应用程序里定义。

xianjimli avatar Aug 07 '22 23:08 xianjimli

应该是在自己的应用程序里定义。

我现在使用的是awtk_main.inc里的application_init函数作为入口。看了下awtk_main.inc源码,如果编译器是mingw的话程序的入口是main函数而非GUI程序的WinMain之类,所以必定会有控制台窗口。 我没什么win32 api的编程经验,搞这个还要花点时间,建议官方在awtk_main.inc里就做好WinMain入口。

这其实算是一个BUG,我的APP类型都已经定成 APP_DESKTOP了,但实际编译出来的却是console类型程序。

ufbycd avatar Aug 08 '22 04:08 ufbycd

确实有一个BUG:如果编译器是msys2(MSYS2)里的mingw,即使程序的入口是WinMain(或wWinMain),编译出来的GUI程序在双击运行时依然会显示一个控制台(console)窗口;只有添加链接器选项 -Wl,-subsystem,windows显式指定windows子系统后才不会显示控制台窗口。

PS:AWTK到这个阶段了还有这种BUG,说明用AWTK的人真的不多……

ufbycd avatar Aug 15 '22 10:08 ufbycd

好的,谢谢。用mingw编译的人比较少。

xianjimli avatar Aug 17 '22 00:08 xianjimli

mingw 是不能用 WinMain(或wWinMain) 作为程序入口的,只能使用 main 函数作为入口的,而原来的 main 部分的逻辑,是没有处理控制台窗口的,最新的代码会统一了 windows 下的控制台窗口的处理逻辑,可以通过 _CONSOLE 和 NDEBUG 以及程序第 3 个传参来开关控制台窗口。

WNsACE avatar Aug 17 '22 03:08 WNsACE

mingw 是不能用 WinMain(或wWinMain) 作为程序入口的,只能使用 main 函数作为入口的,而原来的 main 部分的逻辑,是没有处理控制台窗口的,最新的代码会统一了 windows 下的控制台窗口的处理逻辑,可以通过 _CONSOLE 和 NDEBUG 以及程序第 3 个传参来开关控制台窗口。

你的mingw跟我的不一样么?我用的是MSYS2里的mingw-w64-x86_64。在windows下如果入口为main必定会有控制台窗口。我修改了awtk_main.inc源码来使用WinMain作为入口、不执行TK_ENABLE_CONSOLE()函数,并且必须加-Wl,-subsystem,windows链接选项才不会有控制台窗口。

ufbycd avatar Aug 18 '22 01:08 ufbycd

好的,谢谢。用mingw编译的人比较少。

我最初也是尝试用MSVC编译的,但编译失败,似乎MSVC这东西不同版本间有差异,所以才换成mingw

ufbycd avatar Aug 18 '22 01:08 ufbycd

哦,重新测试了下,发现我之前的说法有误。修改awtk_main.inc源码,所有测试用例都不执行TK_ENABLE_CONSOLE()函数,mingw为MSYS2里的mingw-w64-x86_64:

  • 入口函数WinMain、无-Wl,-subsystem,windows链接器选项:有控制台窗口
  • 入口函数WinMain、有-Wl,-subsystem,windows链接器选项:无控制台窗口
  • 入口函数main、无-Wl,-subsystem,windows链接器选项:有控制台窗口
  • 入口函数main、有-Wl,-subsystem,windows链接器选项:无控制台窗口

看来有无控制台与入口函数无关而与-Wl,-subsystem,windows链接器选项有关。

ufbycd avatar Aug 18 '22 02:08 ufbycd

我昨天测试了在 MSYS2 里的 mingw-w64-x86_64 或者直接使用 mingw64 编译入口函数为 WinMain,会在链接的时候都会出错,找不到 WinMain 函数。 我的理解在 mingw 上面就不应该有 WinMain 函数,因为 WinMain 函数是属于 windows 的东西来的。 正常来说用 vs 来编译应该可以正常编译才对的,不应该出现问题的把。

WNsACE avatar Aug 18 '22 02:08 WNsACE

我昨天测试了在 MSYS2 里的 mingw-w64-x86_64 或者直接使用 mingw64 编译入口函数为 WinMain,会在链接的时候都会出错,找不到 WinMain 函数。 我的理解在 mingw 上面就不应该有 WinMain 函数,因为 WinMain 函数是属于 windows 的东西来的。 正常来说用 vs 来编译应该可以正常编译才对的,不应该出现问题的把。

找不到WinMain是因为awtk_main.inc里没有这个函数而有unicode版的wWinMain,改下原型即可。

int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) {
  str_t str;
  int argc = 1;
  char* argv[MAX_ARGV];
#ifdef _CONSOLE
  bool_t enable_console = TRUE;
#else
  bool_t enable_console = FALSE;
#endif
  int32_t lcd_w = LCD_WIDTH;
  int32_t lcd_h = LCD_HEIGHT;
  
  str_init(&str, 0);
  str_set(&str, lpcmdline);
  command_line_to_argv(str.str, argv, &argc);

要深入研究入口函数的话最好要看下编译器所使用的启动代码了,似乎Qt在用mingw编译GUI程序时也会指明使用WinMain入口。 今天测了下,即使入口函数是main,只要在链接时指定windows子系统也没有控制台窗口,所以mingw用main是要稳妥点。

ufbycd avatar Aug 18 '22 02:08 ufbycd

你的意思是 mingw 是有 wWinMain 函数,没有 WinMain 函数?

WNsACE avatar Aug 18 '22 03:08 WNsACE

不是。mingw想链接WinMain,但你源码里没有这个函数,awtk/src/awtk_main.inc文件里有wWinMain。可以将wWinMain原型改为WinMain对应的原型。

ufbycd avatar Aug 18 '22 03:08 ufbycd

嗯嗯,明白了,谢谢

WNsACE avatar Aug 18 '22 05:08 WNsACE