Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

STARTUPINFO.wShowWindow is 0 when running from Visual Studio

I stumbled upon an issue while debugging a feature in an open-source Notepad replacement called Notepad2 (more specifically, a more recent fork called Notepad2-mod).

It has a flag /u that causes the app to restart itself under Administrative privileges (using runas verb with ShellExecute). The code looks like this (snipped for brevity):

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);

For some reason, if I launched this from Visual Studio (with or without a debugger attached), the elevated child process' main window would just not show! It would appear in Process Explorer, but had no visible windows.

Upon investigation, I realized that the nCmdShow passed to the child process' WinMain was 0 (which corresponds to SW_HIDE) when started from Visual Studio! This value was subsequently passed to ShowWindow, and that's why it didn't show.

When trying to launch this from a cmd shell, everything worked fine.

Upon further investigation, it turned out that the value of si.wShowWindow, obtained by a call to GetStartupInfo was 0 when running in VS, but was 1 when started from a cmd:

Launched from a cmd

According to STARTUPINFO MSDN entry, the value for wShowWindow should match the value of nCmdShow if dwFlags has STARTF_USESHOWWINDOW in it. However, in both cases (launching from VS and cmd), the value for dwFlags was 0.

So, is this an issue with VS or am I just holding it wrong?

like image 432
Igal Tabachnik Avatar asked Apr 30 '16 10:04

Igal Tabachnik


1 Answers

I'll write this one up, it is a pretty awesome bug. It is specific to the VS2015 debugging engine, it is quite notorious for having rather a lot of bugs. Something you can see for yourself by disabling it. Tools > Options > Debugging > General > tick the "Use Native Compatibility Mode" option. That forces an older debugging engine to be used, you now consistently get STARTUPINFO.nCmdShow == SW_SHOWNORMAL.

There is a wee corner-case to reason that this was intentional, blindly following the nCmdShow advice is not advisable. It is a malware attack vector, allowing it to start a program without the user noticing. Many programs intentionally ignore SW_HIDE, not a very intuitive thing to do and very easy to overlook. You need a glass that's well over half-full to make that interpretation however, the nCmdShow argument to WinMain() is what is normally used and it is correct.

Which is also the workaround that you can use. Of course in this specific case you should never rely on the startup value and pass SW_SHOWNORMAL or SW_SHOWMAXIMIZED depending on the current state of Notepad++'s main window.

So I vote bug, use connect.microsoft.com to report it. Put a link to the feedback article in a comment and we'll vote for it.

like image 198
Hans Passant Avatar answered Nov 08 '22 17:11

Hans Passant