对于这种情况,我在 MSDN 上找不到任何有用的东西。使用Dependency Walker,在模块列表中,我看到控制台和 GUI 的混合使用。
这对编译 DLL 有影响吗?
对于这种情况,我在 MSDN 上找不到任何有用的东西。使用Dependency Walker,在模块列表中,我看到控制台和 GUI 的混合使用。
这对编译 DLL 有影响吗?
此选项仅对应用程序 ( exe
) 有效,对库 ( dll
) 无效。
它的文档说:
该
/SUBSYSTEM
选项指定可执行文件的环境。子系统的选择会影响链接器将选择的入口点符号(或入口点函数)。
这不会影响具有自己(可选)入口点的库。
CyberShadow 评论后的附加信息:加载 DLL 时,子系统字段本身似乎被忽略。这篇关于 CSRSS 的文章说(强调我的):
此外,每个进程都与一个特定的子系统相关联;此属性由链接器设置(在编译过程中),并位于以下 PE 结构字段中:[...]
我下面的回复只是一些发现。
我尝试在 VS2015 中创建以下类型的项目:
以下是他们的完整链接选项:
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
域位于0x14C
PE/COFF 文件的文件偏移处。它是Optional Header
.
/DLL /SUBSYESTEM:控制台
/DLL /SUBSYESTEM:WINDOWS
/DLL 并且没有 /SUBSYESTEM 选项(通过在 VS2015 项目属性页面中选择 NOT SET
有趣的是,NOT SET
和WINDOWS
值导致二进制标头中的内容相同。
我比较了 3 个 DLL 的整个二进制文件。除了一些时间戳和调试信息外,其余的二进制文件似乎都是一样的。
这只是我发现的一些事实。选项如何/SUBSYSTEM
影响二进制行为取决于加载器如何解释该字段。
在我参与的一个项目中,/SUBSYSTEM:CONSOLE
和/DLL
一起使用,这与DLL项目的默认组合不同。但似乎没有什么不好的事情发生。所以我同意@Frédéric Hamidi 的观点,即这个标志对 DLL 没有功能影响。