/// <summary>
        /// Perfroms the startup, registration, and shutdown for the given files. Useful if you don't care
        /// about any of the intermediate steps and just want stuff shut down (and are OK with the entire thing failing
        /// if any steps fail)
        /// </summary>
        /// <param name="files"></param>
        public void EasyShutdown(IEnumerable <string> files)
        {
            RestartManager.RM_REBOOT_REASON rebootreason = default(RestartManager.RM_REBOOT_REASON);
            StartSession();
            RegisterResources(files);
            var processesToRestart = RestartManager.RmProcessToNetProcess(GetList(ref rebootreason));

            if (rebootreason != RM_REBOOT_REASON.RmRebootReasonNone)
            {
                string message = "There are processes or services which the RestartManager can't shut down!";
                Logger.Warn("RestartManagerSession.EasyShutdown encountered error: " + message);
                throw new RmSessionException(message);
            }

            Logger.Info("The following processes will be affected by the RestartManager: " + string.Join(", ", processesToRestart.Select(x => x.ProcessName)));

            try
            {
                Shutdown();
            }
            catch (Exception ex)
            {
                EndSession();
                throw ex;
            }

            Logger.Info("RestartManager successfully shut down the above processes");
        }
        /// <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>
        /// Start a restart manager session
        /// </summary>
        /// <param name="dwSessionFlags"></param>
        public void StartSession(int dwSessionFlags = 0)
        {
            Logger.Trace("Starting RMSession " + SessionKey.ToString());
            var result = RestartManager.RmStartSession(out SessionHandle, dwSessionFlags, SessionKey.ToString());

            if (result != RestartManager.ERROR_SUCCESS)
            {
                throw new RmSessionException("Could not start session", result);
            }
            Started = true;
        }
        /// <summary>
        /// Restart the processes and services associated with the registered files.
        /// </summary>
        /// <param name="restartFlags"></param>
        public virtual void Restart(uint restartFlags = 0)
        {
            Logger.Trace("Restarting RMSession " + SessionKey.ToString());
            if (!Started)
            {
                throw new InvalidOperationException("The RM Session has not been started yet!");
            }
            var result = RestartManager.RmRestart(SessionHandle, restartFlags, IntPtr.Zero);

            if (result != RestartManager.ERROR_SUCCESS)
            {
                throw new RmSessionException("Could not restart processes or services!", result);
            }
        }
        /// <summary>
        /// End the restart manager session
        /// </summary>
        public void EndSession()
        {
            Logger.Trace("Ending RMSession " + SessionKey.ToString());
            if (!Started)
            {
                throw new InvalidOperationException("The RM Session has not been started yet!");
            }
            dynamic result = RestartManager.RmEndSession(SessionHandle);

            if (result != RestartManager.ERROR_SUCCESS)
            {
                throw new RmSessionException("Could not end session!", result);
            }
            SessionHandle = 0;
        }
        /// <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>
        /// Register the given resources with the restart manager.
        /// </summary>
        /// <param name="filePaths"></param>
        /// <param name="processes"></param>
        /// <param name="serviceNames"></param>
        public void RegisterResources(IEnumerable <string> filePaths, IEnumerable <RM_UNIQUE_PROCESS> processes = null, IEnumerable <string> serviceNames = null)
        {
            if (processes == null)
            {
                processes = new List <RM_UNIQUE_PROCESS>();
            }
            if (serviceNames == null)
            {
                serviceNames = new List <string>();
            }
            Logger.Trace(string.Format("Registering {0} files, {1} processes, and {2} services with RMSession {3}", filePaths.Count(), processes.Count(), serviceNames.Count(), SessionKey));
            if (!Started)
            {
                throw new InvalidOperationException("The RM Session has not been started yet!");
            }
            var result = RestartManager.RmRegisterResourcesEx(ref SessionHandle, filePaths, processes, serviceNames);

            if (result != RestartManager.ERROR_SUCCESS)
            {
                throw new RmSessionException("Could not register resources", result);
            }
        }
 /// <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)));
 }