internal ProcessInfo(NativeMethods.RM_PROCESS_INFO processInfo) { ProcessId = (int)processInfo.Process.dwProcessId; // ProcessStartTime is returned as local time, not UTC. StartTime = DateTime.FromFileTime((((long)processInfo.Process.ProcessStartTime.dwHighDateTime) << 32) | processInfo.Process.ProcessStartTime.dwLowDateTime); ApplicationName = processInfo.strAppName; ServiceShortName = processInfo.strServiceShortName; ApplicationType = (ApplicationType)processInfo.ApplicationType; ApplicationStatus = (ApplicationStatus)processInfo.AppStatus; Restartable = processInfo.bRestartable; TerminalServicesSessionId = (int)processInfo.TSSessionId; try { var process = Process.GetProcessById(ProcessId); if (string.IsNullOrWhiteSpace(ApplicationName)) { ApplicationName = process.ProcessName; } FilePath = process.MainModule.FileName; UserName = NativeMethods.GetProcessOwner(process.SafeHandle); } catch { } }
internal ProcessInfo(NativeMethods.RM_PROCESS_INFO processInfo) { ProcessId = (int)processInfo.Process.dwProcessId; // ProcessStartTime is returned as local time, not UTC. StartTime = DateTime.FromFileTime((((long)processInfo.Process.ProcessStartTime.dwHighDateTime) << 32) | processInfo.Process.ProcessStartTime.dwLowDateTime); ApplicationName = processInfo.strAppName; ServiceShortName = processInfo.strServiceShortName; ApplicationType = (ApplicationType)processInfo.ApplicationType; ApplicationStatus = (ApplicationStatus)processInfo.AppStatus; Restartable = processInfo.bRestartable; TerminalServicesSessionId = (int)processInfo.TSSessionId; }
public static IEnumerable<ProcessInfo> GetLockingProcessInfos(params string[] paths) { if (paths == null) throw new ArgumentNullException("paths"); const int maxRetries = 6; // See http://blogs.msdn.com/b/oldnewthing/archive/2012/02/17/10268840.aspx. var key = new StringBuilder(new string('\0', NativeMethods.CCH_RM_SESSION_KEY + 1)); uint handle; int res = NativeMethods.RmStartSession(out handle, 0, key); if (res != 0) throw GetException(res, "RmStartSession", "Failed to begin restart manager session."); try { string[] resources = paths; res = NativeMethods.RmRegisterResources(handle, (uint)resources.Length, resources, 0, null, 0, null); if (res != 0) throw GetException(res, "RmRegisterResources", "Could not register resources."); // // Obtain the list of affected applications/services. // // NOTE: Restart Manager returns the results into the buffer allocated by the caller. The first call to // RmGetList() will return the size of the buffer (i.e. nProcInfoNeeded) the caller needs to allocate. // The caller then needs to allocate the buffer (i.e. rgAffectedApps) and make another RmGetList() // call to ask Restart Manager to write the results into the buffer. However, since Restart Manager // refreshes the list every time RmGetList()is called, it is possible that the size returned by the first // RmGetList()call is not sufficient to hold the results discovered by the second RmGetList() call. Therefore, // it is recommended that the caller follows the following practice to handle this race condition: // // Use a loop to call RmGetList() in case the buffer allocated according to the size returned in previous // call is not enough. // uint pnProcInfo = 0; NativeMethods.RM_PROCESS_INFO[] rgAffectedApps = null; int retry = 0; do { uint lpdwRebootReasons = (uint)NativeMethods.RM_REBOOT_REASON.RmRebootReasonNone; uint pnProcInfoNeeded; res = NativeMethods.RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, rgAffectedApps, ref lpdwRebootReasons); if (res == 0) { // If pnProcInfo == 0, then there is simply no locking process (found), in this case rgAffectedApps is "null". if (pnProcInfo == 0) return Enumerable.Empty<ProcessInfo>(); Debug.Assert(rgAffectedApps != null, "rgAffectedApps != null"); var lockInfos = new List<ProcessInfo>((int)pnProcInfo); for (int i = 0; i < pnProcInfo; i++) { lockInfos.Add(new ProcessInfo(rgAffectedApps[i])); } return lockInfos; } if (res != NativeMethods.ERROR_MORE_DATA) throw GetException(res, "RmGetList", string.Format("Failed to get entries (retry {0}).", retry)); pnProcInfo = pnProcInfoNeeded; rgAffectedApps = new NativeMethods.RM_PROCESS_INFO[pnProcInfo]; } while ((res == NativeMethods.ERROR_MORE_DATA) && (retry++ < maxRetries)); } finally { res = NativeMethods.RmEndSession(handle); if (res != 0) throw GetException(res, "RmEndSession", "Failed to end the restart manager session."); } return Enumerable.Empty<ProcessInfo>(); }
public static IEnumerable <ProcessInfo> GetLockingProcessInfos(params string[] paths) { if (paths == null) { throw new ArgumentNullException("paths"); } const int maxRetries = 6; // See http://blogs.msdn.com/b/oldnewthing/archive/2012/02/17/10268840.aspx. var key = new StringBuilder(new string('\0', NativeMethods.CCH_RM_SESSION_KEY + 1)); uint handle; int res = NativeMethods.RmStartSession(out handle, 0, key); if (res != 0) { throw GetException(res, "RmStartSession", "Failed to begin restart manager session."); } try { string[] resources = paths; res = NativeMethods.RmRegisterResources(handle, (uint)resources.Length, resources, 0, null, 0, null); if (res != 0) { throw GetException(res, "RmRegisterResources", "Could not register resources."); } // // Obtain the list of affected applications/services. // // NOTE: Restart Manager returns the results into the buffer allocated by the caller. The first call to // RmGetList() will return the size of the buffer (i.e. nProcInfoNeeded) the caller needs to allocate. // The caller then needs to allocate the buffer (i.e. rgAffectedApps) and make another RmGetList() // call to ask Restart Manager to write the results into the buffer. However, since Restart Manager // refreshes the list every time RmGetList()is called, it is possible that the size returned by the first // RmGetList()call is not sufficient to hold the results discovered by the second RmGetList() call. Therefore, // it is recommended that the caller follows the following practice to handle this race condition: // // Use a loop to call RmGetList() in case the buffer allocated according to the size returned in previous // call is not enough. // uint pnProcInfo = 0; NativeMethods.RM_PROCESS_INFO[] rgAffectedApps = null; int retry = 0; do { uint lpdwRebootReasons = (uint)NativeMethods.RM_REBOOT_REASON.RmRebootReasonNone; uint pnProcInfoNeeded; res = NativeMethods.RmGetList(handle, out pnProcInfoNeeded, ref pnProcInfo, rgAffectedApps, ref lpdwRebootReasons); if (res == 0) { // If pnProcInfo == 0, then there is simply no locking process (found), in this case rgAffectedApps is "null". if (pnProcInfo == 0) { return(Enumerable.Empty <ProcessInfo>()); } Debug.Assert(rgAffectedApps != null, "rgAffectedApps != null"); var lockInfos = new List <ProcessInfo>((int)pnProcInfo); for (int i = 0; i < pnProcInfo; i++) { lockInfos.Add(new ProcessInfo(rgAffectedApps[i])); } return(lockInfos); } if (res != NativeMethods.ERROR_MORE_DATA) { throw GetException(res, "RmGetList", string.Format("Failed to get entries (retry {0}).", retry)); } pnProcInfo = pnProcInfoNeeded; rgAffectedApps = new NativeMethods.RM_PROCESS_INFO[pnProcInfo]; } while ((res == NativeMethods.ERROR_MORE_DATA) && (retry++ < maxRetries)); } finally { res = NativeMethods.RmEndSession(handle); if (res != 0) { throw GetException(res, "RmEndSession", "Failed to end the restart manager session."); } } return(Enumerable.Empty <ProcessInfo>()); }