ShowWindow do User32 não agir como esperado
-
22-07-2019 - |
Pergunta
Eu estou usando o método ShowWindow de User32 para ocultar uma janela (cmd.exe) do usuário (principalmente para os impedir de fechá-lo). Quando o usuário abre o formulário, o processo é iniciado, e se escondeu, em seguida, quando o formulário está fechando o processo é morto. No entanto, quando o formulário é aberto novamente, ele não esconde a janela (e, por vezes, não pela primeira vez) alguém pode me ajudar com isso?
[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;
}
}
Solução
Seria muito mais fácil para isso:
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);
}
Outras dicas
Você verificou se p.MainWindowHandle
é um identificador válido? Ele deve ser diferente de zero, no mínimo. Tente chamar IsWindow
para confirmar.
MSDN sugere chamada WaitForInputIdle
antes de verificar MainWindowHandle
; você pode estar acessando a propriedade antes do novo processo criou sua janela. A propriedade é inerentemente qualquer maneira precária, porém, porque os processos não têm realmente uma noção do "main" janela. Todas as janelas são tratados igualmente. O framework .Net designa simplesmente a primeira janela como a principal, mas o próprio processo não precisa considerar as coisas dessa forma.
Além disso, você já pensou em simplesmente escondendo o processo inicialmente, em vez de iniciá-lo e, em seguida, se escondendo após o fato? Definir StartInfo
propriedades do processo como Scotty2012 demonstra .