2

应用程序在哪里决定/导致生成新的控制台窗口(动态链接时)?是否有一些我可能忽略的定义或编译指示或默认运行时 dll 中的标准行为发生了一些变化?我不太确定这些是要问的正确问题,请阅读下面的背景并耐心等待。我很高兴每一次朝着正确的方向轻推。

背景:控制台应用程序 (/SUBSYSTEM:CONSOLE) 在启动时会产生一个新的子控制台。使用相同源和配置设置的其他应用程序不会。唯一的区别(似乎)是提供的 3rd-party-dll。由于新的子控制台,我无法再重定向输出(app.exe > dump.txt)。重定向对于此应用程序至关重要。

我正在 MS Visual Studio 2008 上构建该 c/c++ 控制台应用程序。该应用程序动态链接到大量混乱的 dll。整个库包由一个第 3 方作为发布版本提供,没有调试信息。dll 包包括 msvcr90.dll (9.0.30729.1) msvcp90.dll (9.0.30729.1) 和 msvcr80.dll (8.0.50727.42)。

无论导致这似乎是非常全局的,因为第一个 fprintf 到 stdout 或 main() 中的 stderr 进入新的控制台窗口,而不是启动应用程序的 shell。

在我的第一次尝试中,我在 Visual Studio 2005(我们一直使用到最新版本的库包)和 2010(由 dll 提供者推荐)上构建了应用程序。这些构建没有产生控制台,但在释放可能在不同版本的运行时中分配的内存时确实崩溃了。使用 Dependency Walker,我可以找到链接 dll 的“主”运行时。

PS:Afaik 链接到 2 个不同的运行时已经足够危险了。但它是对先前版本的 dll-pack 的改进,其中包括 71、80、90 运行时 dll 的 r、c 和 m 变体。

PPS:我之前主要在linux上开发,所以我可能会犯一些非常基本的错误。请提前接受我对我的无知的歉意。

更新1:

按照 Anton Kovalenko 的建议,我削减了越来越多的库。然后我删除了更多代码。最后我结束了:

#include <stdio.h>
#include <Windows.h>

int main(int _argc, char **_argv)
{
printf("application running ...\n");
fflush(stdout);
Sleep(2000);
exit(0);
}

配置属性 > c/c++ > 命令行:

/Od /Ob2 /D "_MBCS" /FD /EHsc /MD /Fo"a4input_interface_6.12_1.dir\Release\\" /Fd"a4input_interface_6.12_1.dir\Release\vc90.pdb" /W3 /nologo /c /TC /errorReport:prompt

配置属性 > 链接器 > 命令行:

/OUT:"D:\sascha\svn\a4_devel\cmakebuild\build\win32_release\inputinterfaces\.inter_612_1_32.exe" /VERSION:0.0 /INCREMENTAL:NO /NOLOGO /MANIFEST /MANIFESTFILE:"a4input_interface_6.12_1.dir\Release\.inter_612_1_32.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /SUBSYSTEM:CONSOLE /DYNAMICBASE:NO /ERRORREPORT:PROMPT kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib

配置属性 > 清单工具 > 命令行

/nologo /outputresource:"..\..\..\build\win32_release\inputinterfaces\.inter_612_1_32.exe;#1"

我仍然有一个问题,即生成了一个 shell 并且无法使用(即 app.exe > test.txt)重定向标准输出。所以文本“应用程序正在运行......”不会打印在启动 exe 的同一个 shell 上。

我仍然一无所知,仍然感谢每一个提示。

更新 2:

我为命令行创建了一个批处理文件。如果我用它编译它,则 exe 按预期工作。

cl.exe /Od /Ob2 /D "_MBCS" /FD /EHsc /MD /Fo"a4input_interface_6.12_1.dir\Release\\" /Fd"a4input_interface_6.12_1.dir\Release\vc90.pdb" /W3 /nologo /c /TC /errorReport:prompt main.c

link.exe /OUT:"D:\sascha\svn\a4_devel\cmakebuild\build\win32_release\inputinterfaces\.inter_612_1_32.exe" /VERSION:0.0 /INCREMENTAL:NO /NOLOGO /MANIFEST /MANIFESTFILE:"a4input_interface_6.12_1.dir\Release\.inter_612_1_32.exe.intermediate.manifest" /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /SUBSYSTEM:CONSOLE /DYNAMICBASE:NO /ERRORREPORT:PROMPT kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib a4input_interface_6.12_1.dir\Release\main.obj

mt.exe /manifest a4input_interface_6.12_1.dir\Release\.inter_612_1_32.exe.intermediate.manifest /nologo /outputresource:"D:\sascha\svn\a4_devel\cmakebuild\build\win32_release\inputinterfaces\.inter_612_1_32.exe";#1"

因此,Visual Studio 所做的某些事情并未反映在它提供的命令行中。什么和为什么?我仍然一无所知,仍然感谢每一个提示。

解决方案: 为这个名称的可执行文件配置了一个调试器。这就是为什么我有这种行为:

  • inter_612_2_32.exe 没有子外壳
  • intes_612_2_32.exe 没有子外壳
  • inter_612_1_32.exe 生成子外壳
  • intes_612_1_32.exe 没有子外壳

使用 ProcessExplorer 我发现 inter_612_1_32.exe 是 DbgHost.exe 的子进程。不幸的是,我没有遵循那个领导并忘记了它。

加载的 Dll 实际上并不重要。问题是注册表中的一个条目:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\inter_612_1_32.exe

我猜该条目是由 DebugDiag、Application Verifier 或其他工具创建的,但在工具的 GUI 中删除时并未删除。

感谢所有考虑过的人。

4

1 回答 1

1

一些第三方dll可能正在调用FreeConsoleand AllocConsole,有你描述的效果。如果它在DllMainfor中完成DLL_PROCESS_ATTACH,它将在输入main()作为您的项目依赖项的库之前发生。

似乎没有与您的构建环境相关的替代解释。

如果您创建一个将LoadLibrary用于可疑 dll 而不是链接到其导入库的项目,您可以了解更多信息:如果其中一些(或它们的依赖项)确实FreeConsoleAllocConsolein DllMain,它将在LoadLibrary调用期间发生。

于 2013-01-17T12:47:51.690 回答