public void TestBasicRestartManager() { //Start up all the little dandies StartService(TestHelpers.TestService); RestartManagerSession manager = new RestartManagerSession(); manager.StartSession(); System.Threading.Thread.Sleep(1000); manager.RegisterResources(new List <string>() { ReplacementFileServicePath }); //Look for the processes locking on our poor file RM_REBOOT_REASON rebootReason = default(RM_REBOOT_REASON); var processes = RestartManager.RmProcessToNetProcess(manager.GetList(ref rebootReason)); //Make sure it's the service we expect. var serviceExecutable = GetServiceExecutablePath(TestHelpers.TestService); Assert.IsTrue(processes.Count > 0 && processes.Any(x => x.MainModule.FileName.ToLower() == serviceExecutable.ToLower())); manager.EndSession(); StopService(TestHelpers.TestService); }
/// <summary> /// Retrieve the list of processes that are holding onto registered resources. ALSO internally sets /// the list of processes to manually restart /// </summary> /// <param name="lpdwRebootReasons"></param> /// <returns></returns> public override List <RM_PROCESS_INFO> GetList(ref RM_REBOOT_REASON lpdwRebootReasons) { Logger.Trace(string.Format("Getting RMSession {0} process list with {1} manual processes to restart", SessionKey, ManualRestartProcesses.Count)); var processes = base.GetList(ref lpdwRebootReasons); var netProcesses = RestartManager.RmProcessToNetProcess(processes); ProcessesToManuallyShutdown = netProcesses.Where(x => ManualRestartProcesses.Select(y => y.Replace(".exe", "")).Contains(x.ProcessName)).ToList(); return(processes); }
/// <summary> /// Try to get the list of processes affected by the registered resources /// </summary> /// <param name="lpdwRebootReasons"></param> /// <returns></returns> public virtual List <RM_PROCESS_INFO> GetList(ref RM_REBOOT_REASON lpdwRebootReasons) { Logger.Trace("Getting list of processes for RMSession " + SessionKey.ToString()); if (!Started) { throw new InvalidOperationException("The RM Session has not been started yet!"); } List <RM_PROCESS_INFO> processes = new List <RM_PROCESS_INFO>(); var result = RestartManager.RmGetListEx(SessionHandle, ref processes, ref lpdwRebootReasons); if (result != RestartManager.ERROR_SUCCESS) { throw new RmSessionException("Could not retrieve process list", result); } return(processes); }
/// <summary> /// Find out what process(es) have a lock on the given files. /// </summary> /// <param name="paths">Paths of the files.</param> /// <returns>Processes locking the files</returns> public static List <Process> WhoIsLocking(IEnumerable <string> paths) { RestartManagerSession restartSession = new RestartManagerSession(); RM_REBOOT_REASON rebootReasons = default(RM_REBOOT_REASON); //All this crap can throw an exception. Let's hope the caller handles these exceptions at some point. restartSession.StartSession(); restartSession.RegisterResources(paths); var rmProcesses = restartSession.GetList(ref rebootReasons); var realProcesses = RmProcessToNetProcess(rmProcesses); restartSession.EndSession(); return(realProcesses); }
public void TestRestartManagerFakeFiles() { RestartManagerSession manager = new RestartManagerSession(); manager.StartSession(); manager.RegisterResources(new List <string>() { "REALLYNOTAFILE" }); RM_REBOOT_REASON rebootReason = default(RM_REBOOT_REASON); var processes = RestartManager.RmProcessToNetProcess(manager.GetList(ref rebootReason)); Assert.IsTrue(processes.Count == 0); manager.EndSession(); }
public void TestRestartManagerManualShutdown() { var ReplacementProcessCopy = ReplacementProcess + "2"; File.Copy(ReplacementProcess, ReplacementProcessCopy, true); //Start up the service and TRY to move the file. It should fail Process proc = Process.Start(ReplacementProcess); //We're hoping this will fail, as the process SHOULD be holding onto this guy MyAssert.ThrowsException(() => File.Copy(ReplacementProcessCopy, ReplacementProcess, true)); //Now startup the restart manager and lets hope the process will be restarted. RestartManagerExtendedSession manager = new RestartManagerExtendedSession(); manager.ManualRestartProcesses.Add(ReplacementProcess); manager.StartSession(); manager.RegisterResources(new List <string>() { ReplacementProcess }); RM_REBOOT_REASON rebootReason = default(RM_REBOOT_REASON); var processes = RestartManager.RmProcessToNetProcess(manager.GetList(ref rebootReason)); Assert.IsTrue(rebootReason == RM_REBOOT_REASON.RmRebootReasonNone); Assert.IsTrue(processes.Count > 0); //After shutdown, the file should be copyable manager.Shutdown(); ThreadingServices.WaitOnAction(() => File.Copy(ReplacementProcessCopy, ReplacementProcess, true), TimeSpan.FromSeconds(3)); //Now try to restart everything manager.Restart(); //We're hoping this will fail, as the service SHOULD be holding onto this guy again MyAssert.ThrowsException(() => ThreadingServices.WaitOnAction(() => File.Copy(ReplacementProcessCopy, ReplacementProcess, true), TimeSpan.FromSeconds(2))); manager.EndSession(); System.Diagnostics.Process.GetProcessesByName(ReplacementProcess.Replace(".exe", "")).ToList().ForEach(x => x.Kill()); }
public void TestRestartManagerServiceFileMove() { //Start up the service and TRY to move the file. It should fail StartService(TestHelpers.TestService); //We're hoping this will fail, as the service SHOULD be holding onto this guy MyAssert.ThrowsException(() => File.Copy(ReplacementFile, ReplacementFileServicePath, true)); //Now startup the restart manager and lets hope the service will be restarted. RestartManagerSession manager = new RestartManagerSession(); manager.StartSession(); manager.RegisterResources(new List <string>() { ReplacementFileServicePath }); RM_REBOOT_REASON rebootReason = default(RM_REBOOT_REASON); var processes = RestartManager.RmProcessToNetProcess(manager.GetList(ref rebootReason)); Assert.IsTrue(rebootReason == RM_REBOOT_REASON.RmRebootReasonNone); Assert.IsTrue(processes.Count > 0); //After shutdown, the file should be copyable manager.Shutdown(); ThreadingServices.WaitOnAction(() => File.Copy(ReplacementFile, ReplacementFileServicePath, true), TimeSpan.FromSeconds(3)); //Now try to restart everything manager.Restart(); //We're hoping this will fail, as the service SHOULD be holding onto this guy again MyAssert.ThrowsException(() => File.Copy(ReplacementFile, ReplacementFileServicePath, true)); manager.EndSession(); StopService(TestHelpers.TestService); }
public static extern uint RmGetList([In, MarshalAs(UnmanagedType.U4)] uint dwSessionHandle, [Out, MarshalAs(UnmanagedType.U4)] out uint pnProcInfoNeeded, [In, Out, MarshalAs(UnmanagedType.U4)] ref uint pnProcInfo, [In, Out] RM_PROCESS_INFO[] rgAffectedApps, [Out, MarshalAs(UnmanagedType.U4)] out RM_REBOOT_REASON lpdwRebootReasons);
public static extern RmResult RmGetList( int dwSessionHandle, out uint pnProcInfoNeeded, ref uint pnProcInfo, [In, Out] RM_PROCESS_INFO[] rgAffectedApps, out RM_REBOOT_REASON lpdwRebootReasons);
/// <summary> /// Try to get the list of processes affected by the registered resources AS .net processes /// </summary> /// <param name="lpdwRebootReasons"></param> /// <returns></returns> public virtual List <Process> GetListAsProcesses(ref RM_REBOOT_REASON lpdwRebootReasons) { return(RestartManager.RmProcessToNetProcess(GetList(ref lpdwRebootReasons))); }
/// <summary> /// Wraps the raw RmGetList in an easier to use function. Gets the list of affected apps and stores it into rgAffectedApps. /// Attempts to retrieve processes up to maxAttempts times (due to inherent race condition present in restart manager) /// </summary> /// <param name="dwSessionHandle"></param> /// <param name="rgAffectedApps"></param> /// <param name="lpdwRebootReasons"></param> /// <returns></returns> public static int RmGetListEx(uint dwSessionHandle, ref List <RM_PROCESS_INFO> rgAffectedApps, ref RM_REBOOT_REASON lpdwRebootReasons, int maxAttempts = 5) { int attempts = 0; RM_PROCESS_INFO[] rawAffectedApps = null; uint affectedApps = 0; uint rawAffectedAppsSize = 0; int result = 0; //Only attempt to pull processes until we reach the maximum attempts. There is an inherent race condition: RmGetList returns //ERROR_MORE_DATA if you did not supply an array large enough to hold all the processes. HOWEVER, if the number of processes //increases before you call RmGetList again with the larger array, it will no longer be large enough to hold it. This can repeat //forever if processes keep increasing (for some reason). Thus, we only retry a set amount of times. do { uint lpdwInt = (uint)lpdwRebootReasons; result = RmGetList(dwSessionHandle, out affectedApps, ref rawAffectedAppsSize, rawAffectedApps, out lpdwInt); if (result == ERROR_MORE_DATA) { //If we didn't make a big enough array to hold all the processes, increase the size of the array. rawAffectedApps = new RM_PROCESS_INFO[Convert.ToInt32(affectedApps) + 1]; rawAffectedAppsSize = Convert.ToUInt32(rawAffectedApps.Length); } else if (result == ERROR_SUCCESS) { //Otherwise, if everything is fine, fill the provided list with the affected apps and be on our way if (rawAffectedApps != null) { rgAffectedApps = new List <RM_PROCESS_INFO>(rawAffectedApps.Take(Convert.ToInt32(affectedApps))); } break; } else { //Oof, something we don't recognize? It's probably an error; just exit so the user knows the results. break; } attempts += 1; } while (attempts < maxAttempts); return(result); }
/// <summary> /// Gets a list of all applications and services that are currently using resources that have been registered with the Restart Manager session. /// </summary> /// <param name="dwSessionHandle">A handle to an existing Restart Manager session.</param> /// <param name="pnProcInfoNeeded"> /// A pointer to an array size necessary to receive RM_PROCESS_INFO structures required to return information for all affected applications and services. /// </param> /// <param name="pnProcInfo">A pointer to the total number of RM_PROCESS_INFO structures in an array and number of structures filled.</param> /// <param name="rgAffectedApps"> /// An array of RM_PROCESS_INFO structures that list the applications and services using resources that have been registered with the session. /// </param> /// <param name="lpdwRebootReasons"> /// Pointer to location that receives a value of the RM_REBOOT_REASON enumeration that describes the reason a system restart is needed. /// </param> /// <returns>This is the most recent error received. The function can return one of the system error codes that are defined in Winerror.h.</returns> public static RmResult GetList(int dwSessionHandle, out uint pnProcInfoNeeded, ref uint pnProcInfo, RM_PROCESS_INFO[] rgAffectedApps, out RM_REBOOT_REASON lpdwRebootReasons) => RmGetList(dwSessionHandle, out pnProcInfoNeeded, ref pnProcInfo, rgAffectedApps, out lpdwRebootReasons);
public static extern int RmGetList(SafeRestartSessionHandle dwSessionHandle, out int pnProcInfoNeeded, ref int pnProcInfo, [In, Out] RM_PROCESS_INFO[] rgAffectedApps, ref RM_REBOOT_REASON lpdwRebootReasons);
public static extern int RmGetList(IntPtr dwSessionHandle, out uint pnProcInfoNeeded, ref uint pnProcInfo, [In, Out] RM_PROCESS_INFO[] rgAffectedApps, out RM_REBOOT_REASON lpdwRebootReasons);