我正在编写一个程序(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);
这会启动客户端并返回一个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();
}
我已经验证从Process.Start记录的PID与从DataGridView(dgvOpenConnections)检索到的PID相同并放入rpdID(尝试失败并因原始PID不再存在而命中catch)。此外,我在启动MSTSC.EXE的一个实例后在命令提示符下发出了“任务列表”,并且可以验证它是否更改了PID(在此测试中,C#记录了4288但是任务列表显示它运行为8172)。
我无法杀死所有MSTSC进程,因为我试图控制多个进程。有没有办法追查第二个PID MSTSC似乎使用?我的猜测是要么启动第二个进程并取消第一个进程,要么这可能是一个子进程(尽管启动后返回的PID不再存在)。
如何在C#中确保我拥有正确的进程ID以便以后监视或终止远程桌面客户端的特定实例?
答案 0 :(得分:4)
如果您尝试在64位Windows中从32位应用程序运行mstsc,则会发生这种情况。
(资料来源:http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/22c10140-a502-4aa1-98d3-3607b8b573e8/)
在64位Windows上有两个版本的mstsc :
c:\windows\system32\mstsc.exe
是 64位版本c:\windows\syswow64\mstsc.exe
或多或少是一个“重定向”,它将从与您的应用程序不同的进程中打开c:\windows\system32\mstsc.exe
。我遇到了同样的问题。我的应用程序启动了mstsc,该进程立即退出,并且mstsc重新出现,具有不同的父进程和不同的PID。
这是因为64位Windows使用文件系统重定向将对64位c:\windows\system32
可执行文件的调用重定向到c:\windows\syswow64
。
有两种解决方案:
我只尝试过重新编译,但它确实有效。 : - )
修改强> 如果您不希望您的用户使用正确的版本(我们正在使用ClickOnce部署,所以我们宁愿向所有人发送一个链接),这是一个解决方法:
如果您正在为.sts文件使用.RDP文件,只需在文件名中添加一个唯一标记即可。 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;
}
在该循环之后,如果您仍然有process == null
,则会出现一些错误(未找到进程或从未执行过程)。如果你有一个Process引用,那就是“new”mstsc进程。
答案 1 :(得分:0)
我使用Process Explorer尝试了您的示例,但我看不到正在创建的第二个或子进程。从头到尾远程桌面进程是同一个,并且在创建之后我能够使用我在开始时看到的相同PID来终止进程。