查找使用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; } } 

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

您将在此答案中找到所需的代码。

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

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

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

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

您似乎有一些基本的代码错误,并可能存在您的期望缺陷。 我会重新审视您的代码,消除无用的代码(如上面的前两行),并通常简化您的代码。 (提示: ArrayList是一个非常糟糕的选择……我会使用IEnumerable ,它不需要从原始数组进行任何转换或填充)。 如果我用更有效的代码复制上面的代码:

 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 } }