我在调试开源记事本替换中的功能Notepad2时偶然发现了一个问题(更具体地说,是一个名为Notepad2-mod的较新的fork )。
它具有一个标志/u
,该标志使应用程序在“管理”特权下(使用runas
带有ShellExecute的动词)重新启动。代码看起来像这样(为简洁起见,略):
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条目,该值wShowWindow
应该匹配的值nCmdShow
,如果dwFlags
有STARTF_USESHOWWINDOW
在里面。但是,在这两种情况下(从VS和cmd启动),其值dwFlags
均为0。
那么,这是VS的问题还是我只是认为错误呢?
我将其写出来,这是一个非常棒的错误。它特定于VS2015调试引擎,因存在很多错误而臭名昭著。通过禁用它,您可以自己看到一些东西。工具>选项>调试>常规>勾选“使用本机兼容模式”选项。这迫使使用较旧的调试引擎,您现在始终可以获取STARTUPINFO.nCmdShow == SW_SHOWNORMAL。
有一个微不足道的理由可以断言这是故意的,不宜盲目地遵循nCmdShow建议。它是一种恶意软件攻击媒介,允许它在不通知用户的情况下启动程序。许多程序故意忽略SW_HIDE,这不是一件很直观的事情,而且很容易忽略。您需要装满一半以上的杯子来进行这种解释,但是,通常使用WinMain()的nCmdShow参数,它是正确的。
这也是您可以使用的解决方法。当然,在这种特定情况下,您永远不要依赖启动值,而应根据Notepad ++主窗口的当前状态传递SW_SHOWNORMAL或SW_SHOWMAXIMIZED。
因此,我投票给Bug,请使用connect.microsoft.com进行报告。在评论中添加指向反馈文章的链接,我们将对其投票。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句