关于窗口:从Visual Studio运行时,STARTUPINFO.wShowWindow为0

STARTUPINFO.wShowWindow is 0 when running from Visual Studio

我在调试开源记事本替换中的功能Notepad2时偶然发现了一个问题(更具体地说,是一个名为Notepad2-mod的较新的分支)。

它具有标志/u,该标志使应用程序以管理特权(在ShellExecute中使用runas动词)重新启动。代码如下所示(为简洁起见,略):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
STARTUPINFO si;
SHELLEXECUTEINFO sei;

si.cb = sizeof(STARTUPINFO);
GetStartupInfo(&si);

ZeroMemory(&sei,sizeof(SHELLEXECUTEINFO));
sei.cbSize = sizeof(SHELLEXECUTEINFO);
...
sei.lpVerb = L"runas";
sei.lpFile = lpArg1;
sei.lpParameters = lpArg2;
sei.nShow = si.wShowWindow;

ShellExecuteEx(&sei);

出于某种原因,如果我从Visual Studio(带有或不带有调试器)启动它,则提升的子进程的主窗口将不会显示!它会出现在Process Explorer中,但是没有可见的窗口。

经过调查,我发现从Visual Studio启动时,传递给子进程的WinMainnCmdShow为0(对应于SW_HIDE)!此值随后传递给ShowWindow,这就是为什么它不显示的原因。

当尝试从cmd shell启动此程序时,一切正常。

经过进一步调查,结果发现,在VS中运行时,通过调用GetStartupInfo获得的si.wShowWindow值为0,但从cmd启动时为1:

Launched from a cmd

根据STARTUPINFO MSDN条目,如果dwFlags中包含STARTF_USESHOWWINDOW,则wShowWindow的值应与nCmdShow的值匹配。但是,在两种情况下(从VS和cmd启动),dwFlags的值为0。

那么,这是VS的问题还是我只是认为错误呢?


我会写这个,这是一个非常棒的错误。它特定于VS2015调试引擎,因存在很多错误而臭名昭著。通过禁用它,您可以自己看到一些东西。工具>选项>调试>常规>勾选"使用本机兼容模式"选项。这迫使使用较旧的调试引擎,您现在始终可以获取STARTUPINFO.nCmdShow == SW_SHOWNORMAL。

有一个微不足道的理由可以断言这是故意的,不宜盲从nCmdShow建议。它是一种恶意软件攻击媒介,允许它在不通知用户的情况下启动程序。许多程序故意忽略SW_HIDE,这不是一件很直观的事情,而且很容易忽略。您需要装满一半以上的杯子来进行这种解释,但是,通常使用WinMain()的nCmdShow参数是正确的。

这也是您可以使用的解决方法。当然,在这种特定情况下,您永远不要依赖启动值,而应根据Notepad ++主窗口的当前状态传递SW_SHOWNORMAL或SW_SHOWMAXIMIZED。

因此,我投票给Bug,请使用connect.microsoft.com进行报告。在评论中添加指向反馈文章的链接,我们将对其投票。