2016-04-30 4 views
8

Я наткнулся на проблему при отладке функции в замене Notepad с открытым исходным кодом под названием Notepad2 (более конкретно, более поздняя версия с именем Notepad2-mod).STARTUPINFO.wShowWindow 0 при запуске из Visual Studio

У этого есть флаг /u, который заставляет приложение перезапускаться в соответствии с Административными привилегиями (с использованием командыс помощью 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, и поэтому оно не показывалось.

При попытке запустить это из командной оболочки, все работает нормально.

После дальнейшего исследования, оказались, что величина si.wShowWindow, полученная с помощью вызова GetStartupInfo 0 при работе в VS, но был 1 при запуске из CMD:

Launched from a cmd

Согласно STARTUPINFO MSDN entry, значение для wShowWindow должно соответствовать значению nCmdShow, если dwFlags имеет STARTF_USESHOWWINDOW. Однако в обоих случаях (запуск из VS и cmd) значение для dwFlags было 0.

Итак, это проблема с VS или я просто держу его неправильно?

+0

Кстати, я не знаю, почему даже имеет значение, какие значения передаются через аргумент 'STARTUPINFO' или' wShowWindow'. Он игнорируется при первом вызове приложения [ShowWindow] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548.aspx). Я полагаю, что Notepad2 делает что-то «необычное», т. Е.вызывая 'ShowWindow' более одного раза для основного окна приложения. – IInspectable

+0

Значение 'wShowWindow' было передано в' sei.nShow', а затем в WinMain дочернего процесса. Поскольку значение равно 0, параметр 'nCmdShow' WinMain также был равен 0. Этот параметр затем передавался в CreateWindow, поэтому он был эффективно вызван с помощью SW_HIDE. Учитывая то, что сказал @HansPassant ниже, возможно, плохая практика напрямую использовать nCmdShow, но это то, что сделал Notepad2. –

+1

Поскольку нет прямого сопоставления между [Стили окна] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms632600.aspx), а значения для * nCmdShow * доступны для [ShowWindow] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548.aspx), я бы сказал, что ошибка действительно находится в Notepad2 (и Visual Studio, но это несколько неуместно). Если только Notepad2 не использует флаг для того, что он не должен использоваться, я бы предложил изменить его. – IInspectable

ответ

8

Я напишу это, это довольно устрашающая ошибка. Он специфичен для механизма отладки VS2015, он довольно известен тем, что имеет довольно много ошибок. Что-то вы можете увидеть сами, отключив его. Инструменты> Параметры> Отладка> Общие> установите флажок «Использовать режим основной совместимости». Это заставляет использовать более старый механизм отладки, теперь вы последовательно получаете STARTUPINFO.nCmdShow == SW_SHOWNORMAL.

Существует краеугольный камень, чтобы понять, что это было намеренно, слепо следовать совету nCmdShow не рекомендуется. Это вектор атаки вредоносного ПО, позволяющий запускать программу без уведомления пользователя. Многие программы намеренно игнорируют SW_HIDE, а не очень интуитивную вещь и очень легко упускать из виду. Вам нужен стакан, который лучше половины, чтобы сделать эту интерпретацию, аргумент nCmdShow для WinMain() - это то, что обычно используется, и это правильно.

Это также обходной путь, который вы можете использовать. Конечно, в этом конкретном случае вы никогда не должны полагаться на значение запуска и передавать SW_SHOWNORMAL или SW_SHOWMAXIMIZED в зависимости от текущего состояния главного окна Notepad ++.

Так что я голосую за ошибку, используйте сообщение connect.microsoft.com, чтобы сообщить об этом. Поместите ссылку на статью обратной связи в комментарии, и мы проголосуем за нее.

+0

Отличное объяснение! Вы также можете использовать опцию «Отправить отзыв» в VS, на нее регулярно смотрят! –

+0

Подожди, я в замешательстве. Что лучше всего делать? Я думал, что runtime вычислил 'nCmdShow'' 'WinMain()', используя 'STARTUPINFO', по умолчанию« SW_SHOWDEFAULT », если бит соответствующего флага не установлен. Я знаю, что документация 'ShowWindow()' говорит об использовании 'SW_SHOWDEFAULT' или что точное значение игнорируется, поэтому я теперь запутался в том, что действительно нужно делать, как для начального окна, так и для любых других не принадлежащих в программе ... – andlabs

Смежные вопросы