6

I have this loop that runs continuously as a process to check if the mstsc.exe is running.

for (; ; )
{
    System.Diagnostics.Process[] pname = System.Diagnostics.Process.GetProcessesByName("mstsc");

    if (pname.Length != 0)
    {

    }
    else
    {
        System.Diagnostics.Process.Start(@"mstsc.exe");
    }
    System.Threading.Thread.Sleep(3000);
}

The problem is that on logoff, reboot, or shutdown I get this.

enter image description here

I tried to end the process on Form_Closing or with

Microsoft.Win32.SystemEvents.SessionEnded += 
  new Microsoft.Win32.SessionEndedEventHandler(SystemEvents_SessionEnded);

and I still get this...

How could I force this process to kill correctly?

leppie
  • 115,091
  • 17
  • 196
  • 297
Drew Salesse
  • 127
  • 1
  • 3
  • 18
  • Something to try is inserting a bool value that you can change from outside that loop. And when you trigger the form close change it to false. – Nomad101 Apr 30 '13 at 17:08
  • 10
    `How could I force this process to kill correctly.` ...the exact same question Cyberdyne Systems asked when creating SkyNet. – George Johnston Apr 30 '13 at 17:10
  • It's my understanding that Thread.Sleep will not allow any messages to be processed in the current thread while 'sleeping'. You may also be interested in this article: http://www.albahari.com/threading/ – Dan Esparza Apr 30 '13 at 17:12
  • For starters, I wouldn't run this process in a loop like that. I would probably use a `Timer`. For other starters, there's probably a better way to stop mstsc.exe from running. – JosephHirn Apr 30 '13 at 17:30
  • @Ginosaji I don't want to stop it... I want to start if it is stopped... – Drew Salesse Apr 30 '13 at 17:38
  • `Timer` recommendation still applies. – JosephHirn Apr 30 '13 at 17:40
  • also, i would hook into some system event when the system is shutting down to stop the loop, so have some flag there that would not try to start it back up, otherwise you would get some weird behavior – Alex Apr 30 '13 at 18:11

4 Answers4

6

That happends when process has child processes. You have to kill whole process tree.

Kill process tree programmatically in C#

Code from link above (provided by Gravitas):

/// <summary>
/// Kill a process, and all of its children.
/// </summary>
/// <param name="pid">Process ID.</param>
private static void KillProcessAndChildren(int pid)
{
    ManagementObjectSearcher searcher = new ManagementObjectSearcher("Select * From Win32_Process Where ParentProcessID=" + pid);
    ManagementObjectCollection moc = searcher.Get();
    foreach (ManagementObject mo in moc)
    {
        KillProcessAndChildren(Convert.ToInt32(mo["ProcessID"]));
    }
    try
    {
        Process proc = Process.GetProcessById(pid);
        proc.Kill();
    }
    catch (ArgumentException)
    {
        // Process already exited.
    }
}
Community
  • 1
  • 1
Kamil
  • 13,363
  • 24
  • 88
  • 183
2

Timer instead of System.Threading.Thread.Sleep in loop

timer.Tick += new EventHandler(timer_Tick);
timer.Interval = (1000) * (2);             
timer.Enabled = true;                       
timer.Start();

void timer_Tick(object sender, EventArgs e)
    {
        System.Diagnostics.Process[] pname =   System.Diagnostics.Process.GetProcessesByName("mstsc");

        if (pname.Length != 0)
        {

        }
        else
        {
        System.Diagnostics.Process.Start(@"mstsc.exe");
        }
    }
Drew Salesse
  • 127
  • 1
  • 3
  • 18
1

You can move the loop with Thread.Sleep to a separate background thread. That way, it will be silently killed when your process exits.

alex
  • 12,464
  • 3
  • 46
  • 67
  • this is what it is... a seperate process only for the loop, tried closing it from that process or another, it just won't die correctly. – Drew Salesse Apr 30 '13 at 17:30
  • You don't need to create a separate process, create a Thread. `var t = new Thread(your_method_with_loop); t.IsBackground=true; t.Start();` – alex Apr 30 '13 at 18:47
0

1) You could have System.Diagnostic.Process raise an event when the process exits instead of using a loop:

2) Have you tried using Thread.Join instead of Thread.Sleep? This will cause messages to keep pumping; so even in the sleep if you received a SystemEvent it would be able to be processed.

3) What kind of app do you have? Is it a Console app or a Windows Form / WPF app? Do you have anything to pump windows messages in place (Dispatcher, etc..)?

NStuke
  • 1,001
  • 8
  • 11