我在调试开源记事本替换中的功能Notepad2时偶然发现了一个问题(更具体地说,是一个名为Notepad2-mod的较新的fork)。
它具有标志/u
,该标志使应用程序以管理特权(在ShellExecute中使用runas
动词)重新启动。代码看起来像这样(为简洁起见,略):
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启动时,传递给子进程的
nCmdShow
的WinMain
为0(对应于SW_HIDE
)!此值随后传递给ShowWindow
,这就是为什么它不显示的原因。尝试从cmd shell启动此程序时,一切正常。
经过进一步调查,结果发现,在VS中运行时,通过调用
si.wShowWindow
获得的GetStartupInfo
的值为0,但从cmd启动时为1:根据STARTUPINFO MSDN entry,如果
wShowWindow
中包含nCmdShow
,则dwFlags
的值应与STARTF_USESHOWWINDOW
的值匹配。但是,在两种情况下(从VS和cmd启动),dwFlags
的值为0。那么,这是VS的问题还是我只是认为错误呢?
最佳答案
我将其写出来,这是一个非常棒的错误。它特定于VS2015调试引擎,因存在很多错误而臭名昭著。通过禁用它,您可以自己看到一些东西。工具>选项>调试>常规>勾选“使用 native 兼容模式”选项。这迫使使用较旧的调试引擎,您现在始终可以获取STARTUPINFO.nCmdShow == SW_SHOWNORMAL。
有一个微不足道的理由可以断言这是故意的,不宜盲目地遵循nCmdShow建议。它是一种恶意软件攻击媒介,允许它在不通知用户的情况下启动程序。许多程序故意忽略SW_HIDE,这不是一件很直观的事情,而且很容易忽略。您需要装满一半以上的杯子来进行这种解释,但是,通常使用WinMain()的nCmdShow参数,它是正确的。
这也是您可以使用的解决方法。当然,在这种特定情况下,您永远不要依赖启动值,而应根据Notepad++主窗口的当前状态传递SW_SHOWNORMAL或SW_SHOWMAXIMIZED。
因此,我投票给Bug,请使用connect.microsoft.com进行报告。在评论中添加指向反馈文章的链接,我们将对其投票。
关于windows - 从Visual Studio运行时,STARTUPINFO.wShowWindow为0,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36953886/