Windows和Console应用程序之间的区别

59

Windows应用程序和控制台应用程序有什么区别?

在Visual C++中创建新项目时,会要求选择其中之一。

7个回答

90
唯一的区别在于控制台应用程序总是会生成一个控制台,除非它没有从控制台启动(或者在启动时主动抑制了控制台)。另一方面,Windows应用程序不会生成控制台。它仍然可以使用`AllocConsole`连接到一个现有的控制台或创建一个新的控制台。
这使得Windows应用程序更适合GUI应用程序或后台应用程序,因为通常不希望为这些应用程序创建终端窗口。
技术上讲,控制台和Windows可执行文件之间唯一的区别在于`exe`文件PE头中的一个字节。手动切换此字节(例如使用十六进制编辑器)即可转换应用程序类型。这是一种广为发布的黑客技术,用于在VB6中创建控制台应用程序(在该应用程序类型不被明确支持的情况下)。
要确定并更改应用程序的子系统类型,需要读取PE头的部分内容。子系统数据的地址不固定,因为它是可选文件头的一部分,其位置由存储在DOS文件头中的地址确定(在成员`e_lfanew`中)。该地址实际上指向`_IMAGE_NT_HEADERS`记录,该记录包括`IMAGE_OPTIONAL_HEADER32`结构。该结构具有一个名为`Subsystem`的`int16`成员1)。对于Windows应用程序,该成员的值为2,而对于控制台应用程序,则为3。还存在其他子系统(特别是POSIX和内核)。
我编写了一个小的VB6应用程序来更改应用程序的子系统,可以从ActiveVB下载源代码。
PE格式没有很好地记录,但这个文档可以作为介绍:Peering Inside the PE: A Tour of the Win32 Portable Executable File Format

1) 这并不真正与我的主张相矛盾,即只有一个字节有差异:这个成员的最高位字节始终为0。只有最低有效字节会改变。


1
引用的 DLL 也有差异吗? - David Schmitt
@SoapBox:请查看更新后的答案。地址不是固定的,必须进行计算。我已经发布了一些VB6代码来读取这些数据的链接。MSDN文章也展示了如何实现此操作。 - Konrad Rudolph
我父亲过去常常用自定义程序替换链接器,以更改适当文件中的链接器命令行,然后在其上运行实际的链接器。最终结果当然与在可执行文件中切换字节相同 :) - Joey

20
除了Konrad提到的差异,控制台和Windows应用程序在从命令提示符交互调用时表现不同:
启动控制台应用程序时,命令提示符直到控制台应用程序退出才返回。 启动Windows应用程序时,命令会立即返回。
对于批处理文件,这并不正确。它们将始终等待应用程序退出。(您可以始终使用start命令启动应用程序而不等待。)

5

如果链接失效,引用重要部分会很有用。 - user202729

4

这不是一个可选组件吗?就像你自己编写代码一样,没有任何神奇的东西捆绑到翻译后的二进制文件中... - gavenkoa

4
区别在于应用程序的存根方式。当您使用控制台模板时,您有一个将在控制台中启动的存根。如果您已经在控制台中运行,则忽略对其进行旋转的调用。
同样,Windows应用程序设计有一个默认表单。如果要清除它,请创建一个无窗体Windows Forms应用程序,这是一个没有控制台窗口的控制台应用程序。
就应用程序的实质而言,它们本质上是相同的。主要区别添加在编译阶段。

2

控制台应用程序可以从Windows命令行(开始/运行/cmd)中运行。

窗口应用程序是预设的,您可以编程在Windows环境中运行的GUI应用程序。


2

控制台应用程序的入口点是wmain(自Visual studio 2008以来),如果您选择默认情况下不使用Unicode,则为main。对于桌面应用程序,它是wWinMain/WinMain

这并不意味着这些技术在其他方面是互相排斥的。控制台应用程序仍然可以使用整个Win32 API,而桌面应用程序可以使用控制台I/O(但它们必须显式地创建一个控制台窗口)。


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