2016-04-30 43 views
8

Mi sono imbattuto in un problema mentre eseguivo il debug di una funzionalità in una sostituzione Notepad open-source denominata Notepad2 (in particolare, un fork più recente chiamato Notepad2-mod).STARTUPINFO.wShowWindow è 0 quando è in esecuzione da Visual Studio

Ha una bandiera /u che provoca il riavvio dell'app in Privilegi amministrativi (utilizzando runas con ShellExecute). Il codice è simile al seguente (ottenuto per brevità):

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

Per qualche ragione, se ho lanciato questo da Visual Studio (con o senza un debugger), il processo figlio elevata la finestra principale sarebbe semplicemente non vedere! Apparirebbe in Process Explorer, ma non aveva finestre visibili.

Dopo alcune indagini, ho capito che la nCmdShow passato al processo figlio WinMain era di 0 (che corrisponde al SW_HIDE), quando ha iniziato da Visual Studio! Questo valore è stato successivamente passato a ShowWindow ed è per questo che non è stato mostrato.

Quando si prova a lanciare questo da una shell cmd, tutto ha funzionato correttamente.

ulteriori indagini, si è scoperto che il valore di si.wShowWindow, ottenuto da una chiamata a GetStartupInfo era 0 quando viene eseguito in VS, ma era 1 quando lanciato da un cmd:

Launched from a cmd

Secondo STARTUPINFO MSDN entry, il valore per wShowWindow deve corrispondere al valore di nCmdShow se contiene STARTF_USESHOWWINDOW. Tuttavia, in entrambi i casi (avvio da VS e cmd), il valore per dwFlags era 0.

Quindi, si tratta di un problema con VS o sto semplicemente sbagliando?

+0

Per inciso, non lo so, perché fa anche la differenza quali valori vengono passati attraverso l'argomento 'STARTUPINFO' o' wShowWindow'. Viene ignorato, la prima volta che un'applicazione chiama [ShowWindow] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548.aspx). Suppongo che Notepad2 faccia qualcosa di "insolito", ad es.chiamare 'ShowWindow' più di una volta per la sua finestra principale dell'applicazione. – IInspectable

+0

Il valore di 'wShowWindow' è stato passato in' sei.nShow' e successivamente nel WinMain del processo figlio. Poiché il valore era 0, anche il parametro 'nCmdShow' di WinMain era 0. Questo parametro è stato quindi passato a CreateWindow, quindi è stato effettivamente chiamato con SW_HIDE. Dato quello che @HansPassant ha detto di seguito, è probabilmente una cattiva pratica usare direttamente nCmdShow, ma è quello che ha fatto Notepad2. –

+1

Poiché non esiste alcuna mappatura diretta tra [Stile finestra] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms632600.aspx) e i valori per * nCmdShow * sono disponibili per [ShowWindow] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms633548.aspx), direi che il bug si trova davvero in Notepad2 (e Visual Studio, ma è in qualche modo irrilevante). A meno che non ci sia un motivo sorprendente per Notepad2 per usare la bandiera per quello che non dovrebbe essere usato, suggerirei di cambiarlo. – IInspectable

risposta

8

Scriverò questo, è un baco molto bello. È specifico del motore di debug VS2015, è piuttosto noto per avere un sacco di bug. Qualcosa che puoi vedere da solo disabilitandolo. Strumenti> Opzioni> Debug> Generale> selezionare l'opzione "Usa modalità di compatibilità nativa". Ciò impone l'utilizzo di un motore di debug più vecchio, ora ottieni sempre STARTUPINFO.nCmdShow == SW_SHOWNORMAL.

C'è un caso d'angolo per ragionare che questo è stato intenzionale, seguendo ciecamente il consiglio nCmdShow non è consigliabile. È un vettore di attacco malware che consente di avviare un programma senza che l'utente se ne accorga. Molti programmi ignorano intenzionalmente SW_HIDE, non una cosa molto intuitiva da fare e molto facile da trascurare. Hai bisogno di un vetro che sia ben più di mezzo pieno per fare questa interpretazione, tuttavia l'argomento nCmdShow per WinMain() è quello che viene normalmente utilizzato ed è corretto.

Quale è anche la soluzione alternativa che è possibile utilizzare. Ovviamente in questo caso specifico non dovresti mai fare affidamento sul valore di avvio e passare SW_SHOWNORMAL o SW_SHOWMAXIMIZED a seconda dello stato corrente della finestra principale di Notepad ++.

Quindi io voto bug, usa connect.microsoft.com per segnalarlo. Metti un link all'articolo di feedback in un commento e voteremo per esso.

+0

Ottima spiegazione! Puoi anche usare l'opzione Invia commenti in VS, è regolarmente controllata! –

+0

Aspetta, sono confuso. Qual'è la miglior cosa da fare? Ho pensato che il runtime computasse 'nCmdShow' in' WinMain() 'usando' STARTUPINFO', facendo default a 'SW_SHOWDEFAULT' se il rispettivo flag bit non è impostato. So che la documentazione di 'ShowWindow()' parla dell'uso di 'SW_SHOWDEFAULT' o che il valore esatto viene ignorato, quindi ora sono confuso quale sia la cosa giusta da fare, sia per la finestra iniziale che per tutti gli altri toplevel non di proprietà nel programma ... – andlabs