Exemplo n.º 1
0
        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);
        }
Exemplo n.º 5
0
        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();
        }
Exemplo n.º 6
0
        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());
        }
Exemplo n.º 7
0
        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);
        }
Exemplo n.º 8
0
 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);
Exemplo n.º 9
0
 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);
        }
Exemplo n.º 12
0
 /// <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);
Exemplo n.º 13
0
 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);