Search code examples
c#windows-10background-processsleep-mode

C# Kill process before computer enters sleep mode


In Windows 10, I have a process I've created to run in the background that is initialized at Startup. When the computer goes to sleep, it crashes windows and gives me a BSOD.

I'm open to any solution, however I'm currently attempting to kill the process when the 'Suspend' PowerModeChanged Event occurs. It doesn't appear as though this is sufficient to kill the process before the machine enters a hibernation state, and the machine is still crashing. My PowerModeChanged listener is definitely working, and it's definitely the secondary process that causing the machine to crash.

I'm a little new to background process development, and I've been trying different approaches all day with marginal progress. Surely someone must have experience with this and knows a fix.

// Application path and command line arguments
    static string ApplicationPath = @"C:\path\to\program.exe";
    static Process ProcessObj = new Process();

    static void Main(string[] args)
    {
        SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(SystemEvents_PowerModeChanged);

        startProcess(); 
        Console.ReadKey(); 
    }

    static void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
    {
        Console.WriteLine(e.Mode.ToString());
        if (e.Mode == PowerModes.Suspend)
        {
            ProcessObj.Kill(); 
        }

        if (e.Mode == PowerModes.Resume)
        {
            startProcess();
        }
    }

    static void startProcess()
    {

        // Create a new process object
        try
        {
            // StartInfo contains the startup information of the new process
            ProcessObj.StartInfo.FileName = ApplicationPath;

            // These two optional flags ensure that no DOS window appears
            ProcessObj.StartInfo.UseShellExecute = false;
            ProcessObj.StartInfo.CreateNoWindow = true;

            // This ensures that you get the output from the DOS application
            ProcessObj.StartInfo.RedirectStandardOutput = true;

            // Start the process
            ProcessObj.Start();

            // Wait that the process exits
            ProcessObj.WaitForExit();

            // Now read the output of the DOS application
            string Result = ProcessObj.StandardOutput.ReadToEnd();
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

Solution

  • On the Windows OS platform, when one truly wants to run a "background process" for the entirety of the machine running, and to have that process survive across power events, such as hibernation, they typically architect their process as a Windows service.

    Many popular applications are implemented as Windows services, such as Microsoft SQL Server, or Window's own web server (W3SVC).

    Windows services can be built in Visual Studio by choosing to create a new project of type "Windows Service".

    Using this technique, you'd have the ability to respond to multiple events, including the following (which are defined in System.ServiceProcess.ServiceBase):

    • OnStart(string[] args)
    • OnStop()
    • OnPause()
    • OnContinue()
    • OnPowerEvent(PowerBroadcastStatus powerStatus)
    • OnShutdown()

    You can find loads more information on building a .NET Windows service here: https://learn.microsoft.com/en-us/dotnet/framework/windows-services/