为什么,从 c# 执行 mstsc.exe(远程桌面)时,进程 HasExited = true 并且没有 MainWindowHandle

Why ,when executing mstsc.exe (remote desktop) from c# , the process HasExited = true and doesnt have MainWindowHandle

我的主要目标是打开远程桌面并在远程会话结束时将其释放回来。 我正在尝试在 winform 应用程序中托管 Mstsc.exe,因此我将管理进程的关闭并将释放命令发送到远程 PC。 这可以通过批处理文件完成:

for /f "skip=1 tokens=3" %%s in ('query user %USERNAME%') do (  %windir%\System32\tscon.exe %%s /dest:console)

C#代码:

[DllImport("user32.dll")]
static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

添加远程PC的证书

        Process p = Process.Start(Environment.ExpandEnvironmentVariables(@"C:\Windows\system32\cmdkey.exe "), string.Format(" /generic:TERMSRV/{0} /user:{1} /pass:{2}", host, userName, password));

打开远程桌面:

        Process mainP = Process.Start(@"C:\Windows\system32\mstsc.exe ", (" /v " + host));
        mainP.Exited += P_Exited;
        while (mainP.MainWindowHandle ==null || mainP.MainWindowHandle == IntPtr.Zero)
        {
            Thread.Sleep(20);
            //mainP.Refresh();

        }
        Console.WriteLine(mainP.MainWindowHandle);
        SetParent(mainP.MainWindowHandle, panel1.Handle);

MainWindowHandle 始终为零,如果我刷新进程,则会出现异常。 mainP.HasExited 是真的,虽然 mstsc 是开放的。 如何获得 MSTSC.exe 的 MainWindowHandle?

谢谢

远程桌面客户端的实现方式似乎是,当使用命令行参数启动时,它将处理参数,启动一个单独的进程(如果参数有效),然后终止原始进程.

这意味着您将需要一个代表新进程的 Process 实例,以便获取其主进程的句柄 window。

添加到您的原始代码:

Process mainP = Process.Start(@"C:\Windows\system32\mstsc.exe ", (" /v " + "CLSERVER"));
mainP.WaitForExit();
mainP.Dispose();
Process otherP;
while ((otherP = Process.GetProcessesByName("mstsc").FirstOrDefault()) == null) {
    Thread.Sleep(20);
}
otherP.Exited += P_Exited;
while (otherP.MainWindowHandle == IntPtr.Zero) {
    Thread.Sleep(20);
}
Console.WriteLine(otherP.MainWindowHandle);
SetParent(otherP.MainWindowHandle, panel1.Handle);

我在使用上面的代码时能够成功获取句柄,但是它并没有考虑到 mstsc.exe 的多个实例 - 如果您需要区分它们,则需要更多地检查进程仔细(也许看看MainWindowTitle?)。