启动远程桌面客户端。无法控制 PID Kill。启动后PID变化...WTF?

Tha*_*ORD 1 c# remote-desktop process c#-4.0

我正在编写一个程序(C# Windows 窗体中的 Visual Studio 2010),它跟踪远程桌面客户端的多个实例(mstsc.exe - 用 Windows 7 版本测试)。我一直在尝试启动该程序并使用以下代码获取其 PID:

Process mstsc = Process.Start(mstscLocation, mstscConString);
int mstscProcessId = mstsc.Id;
DataRow row = openConn.NewRow();
row["RDP ID"] = mstscID;
openConn.Rows.Add(row);
Run Code Online (Sandbox Code Playgroud)

这将启动客户端并返回它应该的 ID。问题是,如果我尝试使用以下代码终止 PID,则无法这样做:

int rdpID = Convert.ToInt32(dgvOpenConnections.Rows[selectedIndex].Cells["RDP ID"].Value.ToString());

try
{
    // kill off mstsc
    Process mstsc = Process.GetProcessById(rdpID);
    mstsc.Kill();
}
Run Code Online (Sandbox Code Playgroud)

我已验证从 Process.Start 记录的 PID 与从 DataGridView (dgvOpenConnections) 检索并放入 rpdID 的 PID 相同(尝试失败并命中捕获,因为原始 PID 不再存在)。此外,在启动 MSTSC.EXE 的一个实例后,我在命令提示符处发出了一个“任务列表”,并且可以验证它是否更改了 PID(在此测试中,C# 记录了 4288,但任务列表显示它运行为 8172)。

我无法杀死所有 MSTSC 进程,因为我试图控制多个进程。有没有办法追踪似乎使用的第二个 PID MSTSC?我的猜测是它要么启动第二个进程并摆脱第一个进程,或者这可能是一个子进程(尽管启动后返回的 PID 不再存在)。

如何在 C# 中确保我有正确的进程 ID 以便以后监视或终止远程桌面客户端的特定实例?

Tom*_*cat 5

如果您尝试从 64 位 Windows 中的 32 位应用程序运行 mstsc,就会发生这种情况。

(来源:http : //social.msdn.microsoft.com/Forums/en-US/wpf/thread/22c10140-a502-4aa1-98d3-3607b8b573e8/

在64 位 Windows 上有两个版本的 mstsc

  1. c:\windows\system32\mstsc.exe64 位版本
  2. c:\windows\syswow64\mstsc.exe或多或少是一个“重定向”,它将c:\windows\system32\mstsc.exe从与您的应用程序不同的进程打开。

我有同样的问题。我的应用程序启动了 mstsc,该进程立即退出,并且 mstsc 以不同的父进程和不同的 PID 重新出现。

发生这种情况是因为 64 位 Windows 使用文件系统重定向来将对 64 位c:\windows\system32可执行文件的调用重定向到c:\windows\syswow64.

有两种解决方案:

  1. 将您的应用程序重新编译为 64 位。那么您的应用程序也将使用 64 位 mstsc。
  2. 禁用文件系统重定向(请参阅http://blog.tonycamilli.com/2005/07/disabling-wow64-file-system.html)并从 32 位应用程序访问 64 位 mstsc。

我只试过重新编译,它奏效了。:-)

编辑: 如果您不希望您的用户使用正确的版本(我们正在使用 ClickOnce 部署,所以我们宁愿向所有人发送一个链接),这里有一个解决方法:

如果您将 .RDP 文件用于 mstsc,只需在您的文件名中添加一个唯一标记。mstsc 将使用像mstsc host_user_token.rdp.

现在,在您调用 之后Process.Start,进行Process.WaitForExit短暂的超时(5 秒)。如果进程没有退出,则您拥有正确的对象。

如果进程确实退出,请执行一个小的轮询循环(100 毫秒间隔,5 秒超时),以使用您的令牌检查进程:

var timeout = AppSettings.GetIntValue(
            Constants.SettingsKeyProcessFinderTimeout, Constants.ProcessFinderTimeoutDefault);
int elapsedTime = 0;
Process process = null;
while (elapsedTime <= timeout)
{
    process =
        Process.GetProcessesByName("mstsc").FirstOrDefault(p => p.StartInfo.Arguments.Contains(guid));
    Logger.TraceVerbose(
        string.Format(
            "Elapsed time: {0}; Found process with PID {1}", elapsedTime, process == null ? -1 : process.Id));
    if (process != null)
    {
        break;
    }

    Thread.Sleep(SleepInterval);
    elapsedTime += SleepInterval;
}
Run Code Online (Sandbox Code Playgroud)

在该循环之后,如果您仍然有process == null,则存在一些错误(未找到进程或根本从未执行过)。如果您有进程引用,那就是“新”mstsc 进程。