查找使用c#开始的新流程

时间:2010-08-11 03:34:22

标签: c#

我正在使用以下代码来查找已启动的任何新流程。该函数在线程中运行。

我需要登录已启动的进程名称。我使用两个arraylist。在一个arraylist 我在启动线程和其他arraylist之前存储所有进程名称,我填写 线程中的当前进程并比较两个arraylist以找到新进程。

现在的问题是,因为写入日志文件的字符串是针对每个循环的,我看到了 日志文件中重复的进程名称。我希望它只被记录一次。我该如何解决这个问题?

class ProcessMonitor
{
    public static ArrayList ExistingProcess = new ArrayList(); 


    public static void Monitor()
    { 
        existingProcesses = GetExistingProcess();

        while (true)
        {  
            ArrayList currentProcesses = new ArrayList();
            currentProcesses = GetCurrentProcess();

            ArrayList NewApps = new ArrayList(GetCurrentProcess());

            foreach (var p in ExistingProcess)
            {
                NewApps.Remove(p); 
            }
            string str = "";
            foreach (string NewApp in NewApps)
            {
                str += "Launched ProcessName/ID : " + NewApp + "/" + System.Diagnostics.Process.GetProcessesByName(NewApp)[0].Id.ToString() + Environment.NewLine;
            }
             if(str!="")
            {
               Log.Info(str);
            }
        }
    }

    public static ArrayList GetExistingProcess()
    {
        Process[] processlist = Process.GetProcesses();
        foreach (Process Proc in processlist)
        {
            ExistingProcess.Add(Proc.ProcessName);
        }
        return ExistingProcess;
    }
    public static ArrayList GetCurrentProcess()
    {
        ArrayList CurrentProcesses = new ArrayList();
        Process[] processlist =  Process.GetProcesses();
        foreach (Process Proc in processlist)
        {
            CurrentProcesses.Add(Proc.ProcessName);
        }
        return CurrentProcesses;
    }
}

2 个答案:

答案 0 :(得分:4)

在Windows上迭代进程非常昂贵。使用WMI,Win32_ProcessStartTrace类有更好的方法。它还会自动解决您的问题,因为它只会告诉您有关新进程的入门信息。并且不需要线程。

您可以在this answer中找到所需的代码。

答案 1 :(得分:1)

我不确定你在这里做了什么,但是下面摘录的前两行和最后一行基本上做同样的事情,只有最后一行更昂贵(因为你创建了第二个数组列表来自由GetCurrentProcess返回的那个:

ArrayList currentProcesses = new ArrayList();
currentProcesses = GetCurrentProcess();

ArrayList NewApps = new ArrayList(GetCurrentProcess());

其次,就我所知,你似乎永远不会使用currentProcess变量......所以它100%浪费。第三,如果有重复的流程名称,为什么会出现问题?同一个进程可以多次启动,进程的多个实例可以同时运行,进程可以运行,停止,然后再运行等。进程名称不一定“不正确”上市两次。

(更新:您可能在日志中获得“重复”的一个原因是您只获得existingProcesses一次。每次循环(顺便说一下,将以最大速度连续发生),您将再次获取进程列表,并将它们与原始existingProcesses进行比较,因此上一循环中列出的相同进程...如果它们仍在运行,将再次列出。我已更新了我的代码示例演示如何解决此问题。)

您似乎有一些基本的代码错误,并且可能存在缺陷。我将重新审视您的代码,消除无用的代码(如上面的前两行),并通常简化您的代码。 (提示:ArrayList真的错误的选择......我会使用IEnumerable<T>,它不需要任何转换或来自原始数组的填充。如果我用更有效的代码复制上面的代码:

public static void Monitor()
{ 
    var existingProcesses = Process.GetProcesses();

    bool doProcessing = true;
    while (doProcessing)
    {  
        var currentProcesses = Process.GetProcesses();

        var newProcesses = currentProcesses.Except(existingProcesses);

        int capacity = newProcesses.Count() * 60;
        var builder = new StringBuilder(capacity);
        foreach (var newProcess in newProcesses)
        {
            builder.Append("Launched ProcessName/ID : ");
            builder.Append(newProcess.ProcessName);
            builder.Append("/");
            builder.Append(newProcess.Id);
            builder.AppendLine();
        }

        string newProcessLogEntry = builder.ToString();
        if(!String.IsNullOrEmpty(newProcessLogEntry))
        {
           Log.Info(newProcessLogEntry);
        }

        existingProcesses = currentProcesses;  // Update existing processes, so you don't reprocess previously processed running apps and get "duplicate log entries"

        if (requestToStopMonitoring) // do something to kill this loop gracefully at some point
        {
            doProcessing = false;
            continue;
        }

        Thread.Sleep(5000); // Wait about 5 seconds before iterating again
    }
}