移除Glut/FreeGlut/GLFW的控制台窗口?

14
在Visual C++中,我尝试了Glut/FreeGlut/GLFW。似乎每个项目都默认添加了CMD窗口。我尝试通过以下方法删除它:

在“属性” -> “C / C ++” -> “预处理器” -> “预处理器定义”下,删除_CONSOLE并替换为_WINDOWS。

然后我进入:

在“属性” -> “链接器” -> “系统” -> “子系统”下,将选项设置为Windows (/SUBSYSTEM:WINDOWS)。

但是,当我尝试在GLFW下编译时,我会得到以下构建错误:

错误1:无法解析的外部符号_WinMain@16 MSVCRT.lib
错误2:致命错误LNK1120:1个未解决的外部glfwWindow.exe

是否可能删除控制台窗口?
9个回答

22

在链接器选项下,将你的入口点设置为 mainCRTStartup。这个函数会执行必要的 MS libc 设置,然后调用 main 函数。


2
与@Emre的答案结合使用,效果非常好。谢谢。 - Sergey.quixoticaxis.Ivanov
严重程度 代码 描述 项目 文件 行 抑制状态 错误 LNK2019 无法解析的外部符号 _main,在函数 "int __cdecl invoke_main(void)" 中引用 (?invoke_main@@YAHXZ) - user4196492

13

我的项目只有一个main函数,没有WinMain,为了禁用控制台窗口,我将链接器(Linker)->系统(System)->子系统(SubSystem)设置为"Windows(/SUBSYSTEM:WINDOWS)",而不是"Console(/SUBSYSTEM:CONSOLE)",这样就可以去除控制台了。

你不需要修改预处理器定义(Preprocessor Definitions)来移除控制台窗口。

我知道我的回答有点晚了,但希望它对你有所帮助。


5
我尝试了这个操作,但在 VS2015 中,它报链接器错误:未解析的外部符号 WinMain,在函数 "int __cdecl invoke_main(void)" 中引用。 - Nathan Reed
为了解决链接错误:未解析的外部符号WinMain...,您需要添加'mainCRTStartup'入口点:链接器->所有选项->入口点(VS2019社区版)。 - Dmitry Babich

12

大多数链接器支持自动删除控制台启动代码的选项。

我认为在GCC上它被称为-mwindows。


+1 因为我有 WinMain,但控制台一直在打开。 - scones

7
为了通过cmake去除控制台,可以将链接标志设置如下:
set_target_properties(exe_name PROPERTIES 
    LINK_FLAGS "/ENTRY:mainCRTStartup /SUBSYSTEM:WINDOWS")

这很棒,将其包装成IF(WIN32)以使应用程序跨平台。 - michael g
在Visual Studio下,它在链接器->全部选项中起作用。 - Dmitry Babich

5

这个方法可行,我一定会记下来的,但是有一个跨平台的方法会更好。再次感谢! - Johnathan
2
嗯,在其他平台上你并没有同样的问题,所以我建议只需在 #ifdef WIN32 / #endif 块中包装 FreeConsole() 即可。 - Sean Edwards
你是说在Linux和Mac中,默认情况下没有控制台窗口吗? - Johnathan
1
我不了解Mac。在Linux上,如果你从Ubuntu桌面启动一个应用程序,控制台窗口将不会弹出显示标准输出。程序输出将只是消失到无处。如果你在终端中运行它,那么它将像正常一样在那里转储标准输出。没有Linux等效的FreeConsole()函数。 - Sean Edwards
谢谢告诉我。我会按照Sean Edwards在评论中写的添加#ifdef WIN32。这样应该就可以了。 - Johnathan
值得注意的是,使用FreeConsole()函数时,控制台窗口仍会在消失前短暂地弹出。 - Nathan Reed

1
你需要编写一个 WinMain 入口点,并复制你现有的代码(从 main):
int CALLBACK WinMain(
  __in  HINSTANCE hInstance,
  __in  HINSTANCE hPrevInstance,
  __in  LPSTR lpCmdLine,
  __in  int nCmdShow
){
    // ...
}

好的,我明白你的意思,但我需要一种跨平台的方法来实现这个。我可能得按照onteria_所说的去做。我会尝试一下的。不过还是谢谢你的好答案。 - Johnathan
1
我曾经使用过一个WinMain到main的转换器。这样,你的应用程序就提供了两个入口点。你只需要将命令行从lpCmdLine转换为argcargv即可。 - tibur
我不太确定你的意思。这是我必须提供给函数的东西,还是Visual Studio的标志? - Johnathan

0
如果您将新项目创建为控制台应用程序,则它将始终作为此类应用程序运行。如果要在实际窗口中运行它,则必须创建新的GUI项目,否则将不包括正确的头文件和库。
此外,所需的WinMain函数将在生成的模板文件中为您包含。

0

当我遇到这样的错误时,我能够通过在链接器高级选项中输入以下入口点文本来解决它:

main


那确实解决了错误警告,但是现在它崩溃了并将我带到了atonexit.c。 - Johnathan
我很惊讶它居然能工作。据我所知,该设置只是指入口方法的名称,但并不改变签名。你基本上是将 ()(HINSTANCE, HINSTANCE, LPSTR, int) 作为 ()(char **,int) 调用,这几乎肯定会在该方法返回时对调用堆栈造成严重影响。 - Sean Edwards

0
以下是在Visual Studio下解决此问题的详细说明,无需重写代码:
  1. 打开项目的属性窗口
  2. 保持Debug配置不变,控制台对于调试很好
  3. Release配置下,转到链接器->所有选项
  4. 入口点设置为mainCRTStartup
  5. 子系统设置为Windows: /SUBSYSTEM:WINDOWS
  6. 点击应用保存设置
现在,当您在Debug配置下编译项目时,控制台窗口将出现;而在Release配置下,它永远不会打开。您可以在任何常见窗体中使用入口点函数。
int main() {}

int main(int argc, char** argv) {}

我个人更喜欢第二个。感谢Chaoelmindreda,我给你们点赞!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接