La ShowWindow di User32 non funziona come previsto
-
22-07-2019 - |
Domanda
Sto usando il metodo ShowWindow da User32 per nascondere una finestra (cmd.exe) all'utente (principalmente per impedire che venga chiusa). Quando l'utente apre il modulo, il processo viene avviato e nascosto, quindi alla chiusura del modulo il processo viene interrotto. Tuttavia, quando il modulo viene aperto di nuovo, non nasconde la finestra (e talvolta non la prima volta) Qualcuno può aiutarmi con questo?
[DllImport("User32")]
private static extern int ShowWindow(int hwnd, int nCmdShow); //this will allow me to hide a window
public ConsoleForm(Process p) {
this.p = p;
p.Start();
ShowWindow((int)p.MainWindowHandle, 0); //0 means to hide the window. See User32.ShowWindow documentation SW_HIDE
this.inStream = p.StandardInput;
this.outStream = p.StandardOutput;
this.errorStream = p.StandardError;
InitializeComponent();
wr = new watcherReader(watchProc);
wr.BeginInvoke(this.outStream, this.txtOut, null, null);
wr.BeginInvoke(this.errorStream, this.txtOut2, null, null);
}
private delegate void watcherReader(StreamReader sr, RichTextBox rtb);
private void watchProc(StreamReader sr, RichTextBox rtb) {
string line = sr.ReadLine();
while (line != null && !stop && !p.WaitForExit(0)) {
//Console.WriteLine(line);
line = stripColors(line);
rtb.Text += line + "\n";
line = sr.ReadLine();
}
}
public void start(string[] folders, string serverPath) {
this.inStream.WriteLine("chdir C:\\cygwin\\bin");
//this.inStream.WriteLine("bash --login -i");
this.inStream.WriteLine("");
}
private void ConsoleForm_FormClosed(object sender, FormClosedEventArgs e) {
this.stop = true;
try {
this.p.Kill();
this.p.CloseMainWindow();
} catch (InvalidOperationException) {
return;
}
}
Soluzione
Sarebbe MOLTO più semplice:
public ConsoleForm(Process p) {
this.p = p;
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.StartInfo.CreateNoWindow = true;
p.Start();
this.inStream = p.StandardInput;
this.outStream = p.StandardOutput;
this.errorStream = p.StandardError;
InitializeComponent();
wr = new watcherReader(watchProc);
wr.BeginInvoke(this.outStream, this.txtOut, null, null);
wr.BeginInvoke(this.errorStream, this.txtOut2, null, null);
}
Altri suggerimenti
Hai verificato se p.MainWindowHandle
è un handle valido? Deve essere diverso da zero, almeno. Prova a chiamare IsWindow
per confermare.
MSDN suggerisce chiamando WaitForInputIdle
prima di controllare MainWindowHandle
; potresti accedere alla proprietà prima che il nuovo processo abbia creato la sua finestra. La proprietà è comunque intrinsecamente precaria, poiché i processi in realtà non hanno una nozione di "main" finestra. Tutte le finestre sono trattate allo stesso modo. Il framework .Net designa semplicemente la prima finestra come quella principale, ma il processo stesso non deve considerare le cose in questo modo.
Inoltre, hai considerato semplicemente di nascondere inizialmente il processo, anziché avviarlo e poi nasconderlo dopo il fatto? Imposta il StartInfo
del processo / a> properties come dimostra Scotty2012 .