User32のShowWindowが期待どおりに動作しない
-
22-07-2019 - |
質問
User32のShowWindowメソッドを使用して、ユーザーからウィンドウ(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;
}
}
解決
これは非常に簡単です:
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が提案する の呼び出しhref = "http://msdn.microsoft.com/en-us/library/system.diagnostics.process.waitforinputidle.aspx" rel = "nofollow noreferrer"> WaitForInputIdle
を確認する前に MainWindowHandle
;新しいプロセスがウィンドウを作成する前にプロパティにアクセスしている可能性があります。ただし、プロセスには「メイン」という概念がないため、プロパティは本質的に不安定です。窓。すべてのウィンドウは等しく扱われます。 .Netフレームワークは、最初のウィンドウをメインウィンドウとして指定するだけですが、プロセス自体はそのように考慮する必要はありません。
また、プロセスを開始してから事後に隠すのではなく、最初にプロセスを単に隠すことを検討しましたか?プロセスの StartInfo
プロパティ Scotty2012が示すとおり。