2010-06-23 53 views
1

我正在編寫一個程序(C#Windows窗體中的Visual Studio 2010),用於跟蹤遠程桌面客戶端的多個實例(mstsc.exe - 經過Windows 7版本測試)。我一直在嘗試啓動該程序,並用以下代碼獲取其PID:啓動遠程桌面客戶端。無法控制PID殺死。開始後PID改變... WTF?

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)並放入rpdID中(嘗試失敗並點擊捕獲,因爲原始PID不再存在)。此外,我在啓動MSTSC.EXE的一個實例後,在命令提示符下發出了一個「任務列表」,並且可以驗證它是否改變了PID(在此測試中,C#記錄了4288,但tasklist顯示它運行的是8172)。

我不能殺死所有MSTSC進程,因爲我試圖控制多個進程。有沒有辦法跟蹤第二個PID MSTSC似乎使用?我的猜測是要麼開始第二個進程,擺脫第一個或者這可能是一個子進程(雖然啓動後返回的PID不再存在)。

如何在C#中確保我有正確的進程ID,以便稍後監視或終止遠程桌面客戶端的特定實例?

回答

0

我試着用你的例子使用Process Explorer,我看不到正在創建的第二個或子進程。從開始到結束,遠程桌面進程是同一個,並且在創建之後,我能夠使用我在開始時看到的相同PID來終止進程。

+0

什麼版本的Windows?如果那不是問題,我做錯了什麼?我知道我正在轉換int> string> int,但所有調試看起來都是正確的。我在c:\ windows \ system32版本6.1.7600.16385(日期爲7/13/2009)上的Windows 7(64位操作系統)上使用mstsc.exe。關於複製應用程序+從XP的DLL ...打賭它會工作。我會仔細檢查我的代碼,以確保它! – 2010-06-23 14:53:39

+0

我自己使用Windows 7 x64 6.1.7600,mstsc.exe是版本6.1.7600.16385,日期爲7/14/2009(UTC)。我敢肯定還有其他的錯誤。你的代碼似乎沒有做錯什麼。 – ErikHeemskerk 2010-06-23 15:06:08

3

如果您嘗試從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部署,所以我們寧願送一個鏈接給大家),這裏有一個解決方法:

如果您使用mstsc的.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引用,那就是「新」mstsc進程。