16

对于这种情况,我在 MSDN 上找不到任何有用的东西。使用Dependency Walker,在模块列表中,我看到控制台和 GUI 的混合使用。

这对编译 DLL 有影响吗?

4

2 回答 2

15

此选项仅对应用程序 ( exe) 有效,对库 ( dll) 无效。

它的文档说:

/SUBSYSTEM选项指定可执行文件的环境。

子系统的选择会影响链接器将选择的入口点符号(或入口点函数)。

这不会影响具有自己(可选)入口点的库。

Cyber​​Shadow 评论后的附加信息:加载 DLL 时,子系统字段本身似乎被忽略。这篇关于 CSRSS 的文章说(强调我的):

此外,每个进程都与一个特定的子系统相关联;此属性由链接器设置(在编译过程中),并位于以下 PE 结构字段中:[...]

于 2012-07-30T06:37:00.020 回答
3

我下面的回复只是一些发现。

我尝试在 VS2015 中创建以下类型的项目:

  • Win32 控制台应用程序项目
  • Win32 DLL 项目
  • Win32 Windows 应用项目

以下是他们的完整链接选项:

Win32 控制台应用程序项目

/OUT:"C:\Temp\ConsoleApplication3\Debug\ConsoleApplication3.exe" /MANIFEST /NXCOMPAT /PDB:"C:\Temp\ConsoleApplication3\Debug\ConsoleApplication3.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" “gdi32.lib” “winspool.lib” “comdlg32.lib” “advapi32.lib” “shell32.lib” “ole32.lib” “oleaut32.lib” “uuid.lib” “odbc32.lib” “odbccp32.lib” /DEBUG /MACHINE:X86 /INCREMENTAL /PGD:"C:\Temp\ConsoleApplication3\Debug\ConsoleApplication3.pgd" /SUBSYSTEM:CONSOLE /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"Debug\ ConsoleApplication3.exe.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1

Win32 DLL 项目

/OUT:"C:\Temp\ConsoleApplication3\Debug\Win32DLLProject1.dll" /MANIFEST /NXCOMPAT /PDB:"C:\Temp\ConsoleApplication3\Debug\Win32DLLProject1.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" “gdi32.lib” “winspool.lib” “comdlg32.lib” “advapi32.lib” “shell32.lib” “ole32.lib” “oleaut32.lib” “uuid.lib” “odbc32.lib” “odbccp32.lib” /IMPLIB:"C:\Temp\ConsoleApplication3\Debug\Win32DLLProject1.lib" /DEBUG /DLL /MACHINE:X86 /INCREMENTAL /PGD:"C:\Temp\ConsoleApplication3\Debug\Win32DLLProject1.pgd" /SUBSYSTEM:WINDOWS /MANIFESTUAC :"level='asInvoker' uiAccess='false'" /ManifestFile:"Debug\Win32DLLProject1.dll.intermediate.清单” /ERRORREPORT:PROMPT /NOLOGO /TLBID:1

Win32 Windows 应用项目

/OUT:"C:\Temp\ConsoleApplication3\Debug\Win32WindowsProject1.exe" /MANIFEST /NXCOMPAT /PDB:"C:\Temp\ConsoleApplication3\Debug\Win32WindowsProject1.pdb" /DYNAMICBASE "kernel32.lib" "user32.lib" “gdi32.lib” “winspool.lib” “comdlg32.lib” “advapi32.lib” “shell32.lib” “ole32.lib” “oleaut32.lib” “uuid.lib” “odbc32.lib” “odbccp32.lib” /DEBUG /MACHINE:X86 /INCREMENTAL /PGD:"C:\Temp\ConsoleApplication3\Debug\Win32WindowsProject1.pgd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /ManifestFile:"Debug\ Win32WindowsProject1.exe.intermediate.manifest" /ERRORREPORT:PROMPT /NOLOGO /TLBID:1

所以我们可以看到,对于 a /DLL/SUBSYSTEM:WINDOWS定义了。

然后我尝试用 3 个不同的 SUBSYSTEM 值构建一个 DLL:

  • 安慰
  • 视窗
  • 没有设置

还有其他值,但我只能用上面3个才能成功构建。其他值会导致链接错误,这意味着需要一些外部符号。

可能的 SUBSYSTEM 值的完整列表是:

在此处输入图像描述

您可以使用 CFF Explorer 检查 PE/COFF 二进制文件。

SUBSYSTEM域位于0x14CPE/COFF 文件的文件偏移处。它是Optional Header.

/DLL /SUBSYESTEM:控制台

在此处输入图像描述

/DLL /SUBSYESTEM:WINDOWS

在此处输入图像描述

/DLL 并且没有 /SUBSYESTEM 选项(通过在 VS2015 项目属性页面中选择 NOT SET

在此处输入图像描述

有趣的是,NOT SETWINDOWS值导致二进制标头中的内容相同。

我比较了 3 个 DLL 的整个二进制文件。除了一些时间戳和调试信息外,其余的二进制文件似乎都是一样的。

这只是我发现的一些事实。选项如何/SUBSYSTEM影响二进制行为取决于加载器如何解释该字段。

在我参与的一个项目中,/SUBSYSTEM:CONSOLE/DLL一起使用,这与DLL项目的默认组合不同。但似乎没有什么不好的事情发生。所以我同意@Frédéric Hamidi 的观点,即这个标志对 DLL 没有功能影响。

于 2020-12-11T02:06:51.263 回答