ShowWindow User32 не работает, как ожидалось
Я использую метод ShowWindow от User32, чтобы скрыть окно (cmd.exe) от пользователя (главным образом, чтобы предотвратить его закрытие). Когда пользователь открывает форму, процесс запускается и скрывается, затем, когда форма закрывается, процесс уничтожается. Однако, когда форма открывается снова, она не скрывает окно (а иногда и не в первый раз). Может ли кто-нибудь помочь мне с этим?
[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;
}
}
2 ответа
Это было бы намного проще для этого:
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);
}
Вы проверили ли p.MainWindowHandle
является действительным дескриптором? Это должно быть ненулевым, по крайней мере. Попробуйте позвонить IsWindow
подтвердить.
MSDN предлагает позвонить WaitForInputIdle
перед проверкой MainWindowHandle
; возможно, вы обращаетесь к свойству до того, как новый процесс создаст свое окно. Тем не менее, свойство в любом случае ненадежно по своей природе, потому что процессы на самом деле не имеют понятия "главного" окна. Все окна обрабатываются одинаково. Инфраструктура.Net просто определяет первое окно как основное, но сам процесс не должен рассматривать вещи таким образом.
Кроме того, рассматривали ли вы просто сначала скрыть процесс, вместо того, чтобы запустить его, а затем скрыть за фактом? Установите процесс StartInfo
свойства, как демонстрирует Scotty2012.