我想做的最终目标是将 MMC(Microsoft 管理控制台)计算机管理管理单元 (compmgmt.msc) 进程嵌入到 Windows 窗体中,或者将其视为模态弹出窗口的解决方法上菜单。
现在,我只是想让 mmc.exe 本身正常工作,然后再尝试加载管理单元。问题的第一部分是 mmc.exe 进程几乎退出立即地.
Edit:仅当应用程序构建为 32 位(我的机器是 64 位)时,mmc.exe 才会立即退出。如果应用程序构建为 64 位,则第一个进程将保留,这是预期的行为。
但是,我仍然很好奇为什么会发生奇怪的临时进程行为。请注意,启动的临时 mmc.exe 进程是 32 位,但最终启动的 mmc.exe 进程是 64 位。奇怪的。
以下代码将成功地将 iexplore.exe 嵌入到 Windows 窗体中,但它无法嵌入mmc.exe。
失败的原因是调用 p.WaitForInputIdle(); 时发生异常。
“System.InvalidOperationException”类型的未处理异常
发生在System.dll中
附加信息:无法处理请求,因为该进程已
exited.
正如您从错误消息中看到的,该进程在几毫秒内退出,但从用户的角度来看,MMC 的 GUI 仍然作为一个单独的、与我启动的原始进程无关的进程弹出。
这意味着正在创建另一个 mmc.exe 进程,该进程似乎与创建的原始进程没有连接。
所以问题是:为什么MMC进程立即关闭,而另一个MMC进程几乎立即打开?
相关Windows Form代码,类似这个问题 https://stackoverflow.com/questions/45066532/run-an-executable-from-inside-a-windows-form-in-windows-10.
[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
private void Form1_KeyPress(object sender, EventArgs e)
{
/// Uncomment *one* of these:
//Process p = Process.Start("mmc.exe");
//Process p = Process.Start("iexplore.exe");
Thread.Sleep(500);
p.WaitForInputIdle();
Console.WriteLine("MainWindowHandle: " + p.MainWindowHandle);
Console.WriteLine("Handle: " + p.Handle);
Thread.Sleep(5000);
SetParent(p.MainWindowHandle, this.Handle);
}
相关,但问题似乎更多是关于控制台 GUI 本身关闭,不允许编辑,而不是某些底层进程关闭。https://superuser.com/questions/194252/mmc-exe-starts-and-then-immediately-stops https://superuser.com/questions/194252/mmc-exe-starts-and-then-immediately-stops
随后的问题是,即使我找到弹出的新mmc进程 https://stackoverflow.com/questions/17505032/waiting-till-process-end,它似乎已将 MainWindowHandle 设置为 null,可能意味着 Windows 无法将其识别为具有 GUI https://stackoverflow.com/questions/16185217/c-sharp-process-mainwindowhandle-always-returns-intptr-zero.
解决方法是在创建“临时”mmc 进程和等待新进程实际准备好之间添加睡眠(暂停)。请注意 process.WaitForInputIdle();做过not充当足够长的等待。
对于可能遇到与我相同问题的人:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = Environment.SystemDirectory + "\\" + "mmc.exe";
startInfo.Arguments = "\"" + Environment.SystemDirectory + "\\compmgmt.msc\" /s";
Process tempProcess = Process.Start(startInfo);
tempProcess.WaitForExit();
Thread.Sleep(500); // Added pause!
// Better alternative is to use a while loop on (MainWindowHandle == null)
// with some sort of timeout
Process[] processes = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(startInfo.FileName));
foreach (Process process in processes)
{
// do what you want with the process
Console.WriteLine("MainWindowHandle: " + process.MainWindowHandle);
// Set Computer Management window on top
SetWindowPos(process.MainWindowHandle, HWND_TOPMOST, 0, 0, 0, 0, TOPMOST_FLAGS);
SetParent(process.MainWindowHandle, this.Handle);
SetWindowLong(process.MainWindowHandle, GWL_STYLE, WS_VISIBLE);
process.WaitForExit();
}
但主要问题是弄清楚为什么第一个 MMC 进程会退出。