ShowWindow de User32 no actúa como se esperaba
-
22-07-2019 - |
Pregunta
Estoy usando el método ShowWindow de User32 para ocultar una ventana (cmd.exe) del usuario (principalmente para evitar que la cierren). Cuando el usuario abre el formulario, el proceso se inicia y se oculta, luego, cuando el formulario se está cerrando, el proceso finaliza. Sin embargo, cuando el formulario se abre nuevamente, no oculta la ventana (y a veces no lo hace la primera vez) ¿Alguien puede ayudarme con esto?
[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;
}
}
Solución
Sería MUCHO más fácil para esto:
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);
}
Otros consejos
¿Ha verificado si p.MainWindowHandle
es un identificador válido? Debe ser distinto de cero, como mínimo. Intente llamar a IsWindow
para confirmar.
MSDN sugiere llamar a href = "http://msdn.microsoft.com/en-us/library/system.diagnostics.process.waitforinputidle.aspx" rel = "nofollow noreferrer"> WaitForInputIdle
antes de verificar MainWindowHandle
; es posible que esté accediendo a la propiedad antes de que el nuevo proceso haya creado su ventana. Sin embargo, la propiedad es inherentemente precaria porque los procesos realmente no tienen una noción de `` principal '' ventana. Todas las ventanas son tratadas por igual. El marco .Net simplemente designa la primera ventana como la principal, pero el proceso en sí no necesita considerar las cosas de esa manera.
Además, ¿ha considerado simplemente ocultar el proceso inicialmente, en lugar de iniciarlo y luego esconderse después del hecho? Establezca el StartInfo
del proceso
propiedades como demuestra Scotty2012 .