Constantly monitor processes

2019-06-14 16:36发布

I've written some code which monitors the running windows processes. I wish to know when a certain process starts and when it ends. The code works just like I want it to.

Now, I wish to implement it in a windows form server application - so it will run in loop as long as the form is alive. I guess I should make it run asynchronously maybe using a BackgroundWorker. I'm just not sure what's the best way to do it and how.

Here is my monitor code:

using System;
using System.Management;
using System.Diagnostics;
using System.Collections.Generic;
using System.ComponentModel;

class ProcessMonitor
{
    public static void Main()
    {
        Dictionary<string, Process> newProcs= new Dictionary<string, Process> ();
        while (true) 
        {
            foreach (Process process in Process.GetProcesses())
            {
                if (process.ProcessName.CompareTo("Someprocess") == 0)
                {
                    if (!searchForProcess(newProcs, process.Id))
                    {
                        ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT CommandLine FROM Win32_Process WHERE ProcessId = " + process.Id);
                        foreach (ManagementObject @object in searcher.Get())
                        {
                            Console.Write("Adding new Process: ");
                            Console.WriteLine(@object["CommandLine"] + " ");
                            newProcs.Add(@object["CommandLine"] + " ", process);
                        }   
                    }
                }
            }
            checkProcesses(newProcs);
        } 
        Console.WriteLine("Done");
    }

    private static bool searchForProcess(Dictionary<string, Process> newProcs, int newKey)
    {
        foreach (Process process in newProcs.Values)
        {
            if (process.Id == newKey)
                return true;
        }

        return false;
    }
    private static void checkProcesses(Dictionary<string, Process> newProcs)
    {
        foreach (string currProc in newProcs.Keys)
        {
            bool processExists = false;
            foreach (Process process in Process.GetProcesses())
            {
                if (process.Id == newProcs[currProc].Id)
                {
                    processExists = true;
                    break;
                }

            }
            if (!processExists)
            {
                Console.Write("Process Finished: ");
                Console.WriteLine(currProc);
                newProcs.Remove(currProc);
                if (newProcs.Count == 0)
                    break;
            }
        }
    }
}

Any ideas?

3条回答
Bombasti
2楼-- · 2019-06-14 17:06

This can be achieved using Subscription or Polling .

Polling (for Process loop)

  • BackgroundWorker

    if you have a single task that runs in the background and needs to interact with the UI.

  • ThreadPool thread

    When efficiency is desired. It avoid the overhead associated with creating, starting, and stopping threads. Not for long running tasks.

  • Thread class

    For long-running tasks and when you require fine-grained control over thread execution,etc.

Subscripton

  • ManagementEventWatcher (what stuartd mentioned)

In this scenario subscription is probably more efficient than polling.

查看更多
ら.Afraid
3楼-- · 2019-06-14 17:11

As you're already using WMI, I would recommend using a temporary event subscription to watch for changes to the processes. The process can be synchronous, asynchronous, or semi-synchronous (usually the recommended choice) and you can specify a polling interval with a WITHIN clause.

This query watches for process creation events:

SELECT TargetInstance FROM __InstanceCreationEvent 
  WHERE TargetInstance ISA "Win32_Process" -- or Win32_ProcessStartTrace

This one watches for process end events:

SELECT TargetInstance FROM __InstanceDeletionEvent 
  WHERE TargetInstance ISA "Win32_Process" -- or Win32_ProcessStopTrace

This question has an example of how to use the ManagementEventWatcher class in C#.

查看更多
The star\"
4楼-- · 2019-06-14 17:17

u can create a method like this

 public static void Thread1() {
           //paste your main code hear
            }

copy and past all your code, written in the main to this new method.

change the main to some like this

 public static void Main() {
            Console.WriteLine("Before start thread");
            Thread tid1 = new Thread(new ThreadStart(Thread1 ) );
            tid1.Start();                
    }
查看更多
登录 后发表回答