我在调试名为 Notepad2 的开源记事本替代品中的功能时偶然发现了一个问题(更具体地说,是一个名为 Notepad2 的更新版本)Notepad2-mod https://github.com/XhmikosR/notepad2-mod).
它有一面旗帜/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 中,但没有可见的窗口。
经过调查,我意识到nCmdShow
传递给子进程'WinMain
为 0(对应于SW_HIDE
)当从 Visual Studio 启动时!该值随后被传递给ShowWindow
,这就是它没有显示的原因。
当尝试从 cmd shell 启动它时,一切正常。
经过进一步调查发现,其价值si.wShowWindow
,通过调用获得GetStartupInfo
在 VS 中运行时为 0,但从 cmd 启动时为 1:
根据STARTUPINFO MSDN 条目 https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx,值wShowWindow
应该匹配的值nCmdShow
if dwFlags
has STARTF_USESHOWWINDOW
在里面。但是,在这两种情况下(从 VS 和 cmd 启动),值dwFlags
was 0.
那么,这是 VS 的问题还是我只是认为错误?
我会把这个写下来,这是一个非常棒的错误。它是针对 VS2015 调试引擎的,因存在大量错误而臭名昭著。您可以通过禁用它来亲自看到一些东西。工具>选项>调试>常规>勾选“使用本机兼容模式”选项。这会强制使用较旧的调试引擎,您现在始终会得到 STARTUPINFO.nCmdShow == SW_SHOWNORMAL。
有一个小极端情况可以证明这是故意的,盲目遵循 nCmdShow 建议是不可取的。它是一种恶意软件攻击媒介,可以在用户不注意的情况下启动程序。许多程序故意忽略 SW_HIDE,这不是一件非常直观的事情,而且很容易被忽视。您需要一个超过半满的玻璃杯才能做出这种解释,但是,WinMain() 的 nCmdShow 参数是通常使用的参数,并且它是正确的。
这也是您可以使用的解决方法。当然,在这种特定情况下,您永远不应该依赖启动值并根据 Notepad++ 主窗口的当前状态传递 SW_SHOWNORMAL 或 SW_SHOWMAXIMIZED 。
所以我投票错误,使用 connect.microsoft.com 来报告它。在评论中添加反馈文章的链接,我们将对其投票。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)