2013-04-21 46 views
1

我有一個類可以讓我關閉給定進程中的進程句柄。我有基礎知識,它在Win7 x64中完美運行,但是當我在WinXP x86中運行它時,它會掛起,我不明白爲什麼。我覺得我錯過了一些相當明顯的東西,在這裏。掛在WinXPx32中的NtQuerySystemInformation,但在Win7x64中工作正常

public static List<handleFinder.SYSTEM_HANDLE_INFORMATION> 
    GetHandles(Process process = null, string IN_strObjectTypeName = null, string IN_strObjectName = null) 
    { 
     int nLength = 0; 
     int nHandleInfoSize = 0x10000; 
     IntPtr ipHandle = IntPtr.Zero; 
     IntPtr ipHandlePointer = Marshal.AllocHGlobal(nHandleInfoSize); 
     uint nStatus; 

     while ((nStatus = handleFinder.NtQuerySystemInformation(CNST_SYSTEM_HANDLE_INFORMATION, ipHandlePointer,nHandleInfoSize, ref nLength)) == STATUS_INFO_LENGTH_MISMATCH) 
     { 
      nHandleInfoSize = nLength; 
      Marshal.FreeHGlobal(ipHandlePointer); 
      ipHandlePointer = Marshal.AllocHGlobal(nLength); 
     } 

     byte[] baTemp = new byte[nLength]; 
     Marshal.Copy(ipHandlePointer, baTemp, 0, nLength); 

     long lHandleCount = 0; 
     if (Is64Bits()) 
     { 
      lHandleCount = Marshal.ReadInt64(ipHandlePointer); 
      ipHandle = new IntPtr(ipHandlePointer.ToInt64() + 8); 
     } 
     else 
     { 
      lHandleCount = Marshal.ReadInt32(ipHandlePointer); 
      ipHandle = new IntPtr(ipHandlePointer.ToInt32() + 4); 
     } 

     handleFinder.SYSTEM_HANDLE_INFORMATION shHandle; 
     List<handleFinder.SYSTEM_HANDLE_INFORMATION> lstHandles = new List<handleFinder.SYSTEM_HANDLE_INFORMATION>(); 

     for (long lIndex = 0; lIndex < lHandleCount; lIndex++) 
     { 
      shHandle = new handleFinder.SYSTEM_HANDLE_INFORMATION(); 
      if (Is64Bits()) 
      { 
       shHandle = (handleFinder.SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ipHandle, shHandle.GetType()); 
       ipHandle = new IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle) + 8); 
      } 
      else 
      { 
       ipHandle = new IntPtr(ipHandle.ToInt64() + Marshal.SizeOf(shHandle)); 
       shHandle = (handleFinder.SYSTEM_HANDLE_INFORMATION)Marshal.PtrToStructure(ipHandle, shHandle.GetType()); 
      } 
      if (process != null) 
      { 
       if (shHandle.ProcessID != process.Id) continue; 
      } 

      string strObjectTypeName = ""; 
      if (IN_strObjectTypeName != null) 
      { 
       strObjectTypeName = getObjectTypeName(shHandle, Process.GetProcessById(shHandle.ProcessID)); 
       if (strObjectTypeName != IN_strObjectTypeName) continue; 
      } 

      string strObjectName = ""; 
      if (IN_strObjectName != null) 
      { 
       strObjectName = getObjectName(shHandle, Process.GetProcessById(shHandle.ProcessID)); 
       if (strObjectName != IN_strObjectName) continue; 
      } 
      lstHandles.Add(shHandle); 

      string strObjectTypeName2 = getObjectTypeName(shHandle, Process.GetProcessById(shHandle.ProcessID)); 
      string strObjectName2 = getObjectName(shHandle, Process.GetProcessById(shHandle.ProcessID)); 
      Console.WriteLine("{0} {1} {2}", shHandle.ProcessID, strObjectTypeName2, strObjectName2); 

     } 
     return lstHandles; 
    } 

    public static bool Is64Bits() 
    { 
     return Marshal.SizeOf(typeof(IntPtr)) == 8 ? true : false; 
    } 
} 

public class HandleKiller 
{ 
    public static void doMurderHandle() 
    { 
     String ProcessName = "xboxstat"; 

     try 
     { 
      Process process = Process.GetProcessesByName(ProcessName)[0]; 
      var handles = Win32Processes.GetHandles(process, "File"); 
      if (handles.Count == 0) throw new System.ArgumentException("No handles found"); 
      foreach (var handle in handles) 
      { 
       IntPtr ipHandle = IntPtr.Zero; 
       if (!handleFinder.DuplicateHandle(Process.GetProcessById(handle.ProcessID).Handle, handle.Handle, handleFinder.GetCurrentProcess(), out ipHandle, 0, false, handleFinder.DUPLICATE_CLOSE_SOURCE)) 
        Console.WriteLine("DuplicateHandle() failed, error = {0}", Marshal.GetLastWin32Error()); 

       Console.WriteLine("Handle Killed!"); 
      } 
     } 
     catch (IndexOutOfRangeException) 
     { 
      Console.WriteLine("The process name '{0}' is not currently running", ProcessName); 
     } 
     catch (ArgumentException) 
     { 
      Console.WriteLine("The Handle '{0}' was not found in the process '{1}'", "", ProcessName); 
     } 
     Console.ReadLine(); 
    } 
} 
} 
+0

你確定這是'NtQuerySystemInformation'把懸,而不是其他像'NtQueryObject'? – Mehrdad 2013-04-21 04:28:03

+0

是否有必要產生掛起的所有代碼?你能把它削減到基本要素嗎? – 2013-04-21 04:35:34

+0

感謝關於刪除額外代碼的提示,我很難弄清楚它是NtQueryObject還是NtQuerySystemInformation。當我在斷點後遍歷它時,WinXP中的循環沒有問題,但是如果我嘗試過快地執行它,則會出現錯誤「無法執行操作,因爲進程正在運行」。 – user2303420 2013-04-21 04:41:36

回答

2

爲了避免僵局掛起等待操作遇到同步命名管道時,在重複處理呼叫的CreateFileMapping()。

如果GetLastError()返回193(ERROR_BAD_EXE_FORMAT),那麼句柄不是文件句柄,您應該跳過查詢文件名。

與其他類型的測試命名管道的調用不同,CreateFileMapping()在內核中不會死鎖。

ERROR_BAD_EXE_FORMAT - ZwCreateSection可能返回映射到該用戶錯誤代碼的STATUS_INVALID_FILE_FOR_SECTION。

看到http://msdn.microsoft.com/en-us/library/windows/hardware/ff566428(v=vs.85).aspxhttp://support.microsoft.com/kb/113996

相關問題