2
0

FileHandleHelper.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Runtime.InteropServices;
  5. namespace Optimizer {
  6. public static class FileHandleHelper {
  7. public static List<Process> GetProcessesLockingFile(string path) {
  8. uint handle;
  9. string key = Guid.NewGuid().ToString();
  10. int res = RmStartSession(out handle, 0, key);
  11. if (res != 0) return null;
  12. try {
  13. const int MORE_DATA = 234;
  14. uint pnProcInfoNeeded, pnProcInfo = 0, lpdwRebootReasons = RmRebootReasonNone;
  15. string[] resources = { path };
  16. res = RmRegisterResources(handle, (uint)resources.Length, resources, 0, null, 0, null);
  17. if (res != 0) return null;
  18. res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, null, ref lpdwRebootReasons);
  19. if (res == MORE_DATA) {
  20. return EnumerateProcesses(pnProcInfoNeeded, handle, lpdwRebootReasons);
  21. }
  22. else if (res != 0) return null;
  23. }
  24. finally {
  25. RmEndSession(handle);
  26. }
  27. return new List<Process>();
  28. }
  29. [StructLayout(LayoutKind.Sequential)]
  30. public struct RM_UNIQUE_PROCESS {
  31. public int dwProcessId;
  32. public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime;
  33. }
  34. const int RmRebootReasonNone = 0;
  35. const int CCH_RM_MAX_APP_NAME = 255;
  36. const int CCH_RM_MAX_SVC_NAME = 63;
  37. public enum RM_APP_TYPE {
  38. RmUnknownApp = 0,
  39. RmMainWindow = 1,
  40. RmOtherWindow = 2,
  41. RmService = 3,
  42. RmExplorer = 4,
  43. RmConsole = 5,
  44. RmCritical = 1000
  45. }
  46. [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
  47. public struct RM_PROCESS_INFO {
  48. public RM_UNIQUE_PROCESS Process;
  49. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_APP_NAME + 1)] public string strAppName;
  50. [MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_SVC_NAME + 1)] public string strServiceShortName;
  51. public RM_APP_TYPE ApplicationType;
  52. public uint AppStatus;
  53. public uint TSSessionId;
  54. [MarshalAs(UnmanagedType.Bool)] public bool bRestartable;
  55. }
  56. [DllImport("rstrtmgr.dll", CharSet = CharSet.Unicode)]
  57. static extern int RmRegisterResources(uint pSessionHandle, uint nFiles, string[] rgsFilenames,
  58. uint nApplications, [In] RM_UNIQUE_PROCESS[] rgApplications, uint nServices,
  59. string[] rgsServiceNames);
  60. [DllImport("rstrtmgr.dll", CharSet = CharSet.Auto)]
  61. static extern int RmStartSession(out uint pSessionHandle, int dwSessionFlags, string strSessionKey);
  62. [DllImport("rstrtmgr.dll")]
  63. static extern int RmEndSession(uint pSessionHandle);
  64. [DllImport("rstrtmgr.dll")]
  65. static extern int RmGetList(uint dwSessionHandle, out uint pnProcInfoNeeded,
  66. ref uint pnProcInfo, [In, Out] RM_PROCESS_INFO[] rgAffectedApps,
  67. ref uint lpdwRebootReasons);
  68. private static List<Process> EnumerateProcesses(uint pnProcInfoNeeded, uint handle, uint lpdwRebootReasons) {
  69. var processes = new List<Process>(10);
  70. var processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded];
  71. var pnProcInfo = pnProcInfoNeeded;
  72. // Get the list
  73. var res = RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, ref lpdwRebootReasons);
  74. if (res != 0) return null;
  75. for (int i = 0; i < pnProcInfo; i++) {
  76. try {
  77. processes.Add(Process.GetProcessById(processInfo[i].Process.dwProcessId));
  78. }
  79. catch { }
  80. }
  81. return processes;
  82. }
  83. }
  84. }