2
0

FileHandleHelper.cs 4.0 KB

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