|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
上一篇提到了 Process 与 [WMI] ManagementEventWatcher 的相关监控及源码,今天简单使用 TraceEventSession 来做同样的事情。
上篇:https://blog.csdn.net/qq_33538554/article/details/96433844
本人比较赖,不太喜欢打字,所以就简单说下怎么用,然后上代码,其他的自己研究,或者留言。
主要实现的就是监控各种应用程序的启动与退出。
1.首先新建一个 c# 控制台程序(用来可视化监控结果)
新建的项目中,安装 NuGet 程序包:Microsoft.Diagnostics.Tracing.TraceEvent
2.接着新建两个类:MonEventSource.cs :主要处理监控的逻辑,MonitorTrigger.cs:枚举类,定义或者区分回调事件。
① MonEventSource.cs Code
using Microsoft.Diagnostics.Tracing.Parsers;
using Microsoft.Diagnostics.Tracing.Parsers.Kernel;
using Microsoft.Diagnostics.Tracing.Session;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace MonitoringProcessConsole
{
internal class MonEventSource : IDisposable
{
private static readonly Lazy<MonEventSource> InstanceLazy = new Lazy<MonEventSource>(() => new MonEventSource());
public static MonEventSource Instance => InstanceLazy.Value;
private List<App> appList;
public List<App> AppList
{
get
{
if (appList == null)
{
appList = new List<App>
{
new App { ProcessName = "TeamViewer", CurrentState = false },
new App { ProcessName = "wmplayer", CurrentState = false },
};
}
return appList;
}
set
{
appList = value;
}
}
private readonly TraceEventSession _session = new TraceEventSession("TestEventSession", null);
private readonly Thread _traceThread;
private MonEventSource()
{
try
{
_session.StopOnDispose = true;
_session.EnableKernelProvider(KernelTraceEventParser.Keywords.Process);
_session.Source.Kernel.ProcessStart += data => FireAppProcMonEvent(data, MonitorTrigger.Launch);
_session.Source.Kernel.ProcessStop += data => FireAppProcMonEvent(data, MonitorTrigger.Exit);
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
_traceThread = new Thread(() => _session.Source.Process())
{
IsBackground = true,
Name = "TestProcess"
};
}
private void FireAppProcMonEvent(ProcessTraceData data, MonitorTrigger trigger)
{
try
{
uint processId = (uint)data.ProcessID;
string processName = data.ProcessName;
if (trigger == MonitorTrigger.Launch)
{
Console.WriteLine("Launch------" + "processId:" + processId + "-------processName:" + processName + "-------Count:" + AppList.Where(x => x.CurrentState == true).ToList().Count);
App app = AppList?.Where(x => x.ProcessName.ToLower() == processName.ToLower() && x.CurrentState == false)?.LastOrDefault();
if (app != null)
{
app.ProcessId = processId;
app.CurrentState = true;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Launch------" + "processId:" + processId + "-------processName:" + processName + "-------Count:" + AppList.Where(x => x.CurrentState == true).ToList().Count);
Console.ForegroundColor = ConsoleColor.White;
}
}
if (trigger == MonitorTrigger.Exit)
{
Console.WriteLine("Exit-------" + "processId:" + processId + "-------processName:" + processName + "-------Count:" + AppList.Where(x=>x.CurrentState == true).ToList().Count);
App app = AppList?.Where(x => x.ProcessId == processId && x.CurrentState == true)?.LastOrDefault();
if (app != null)
{
app.CurrentState = false;
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("Exit-------" + "processId:" + processId + "-------processName:" + app.ProcessName + "-------Count:" + AppList.Where(x => x.CurrentState == true).ToList().Count);
Console.ForegroundColor = ConsoleColor.White;
}
}
}
catch (Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(e.ToString());
Console.ForegroundColor = ConsoleColor.White;
}
}
public void Dispose()
{
try
{
_session.Dispose();
}
catch (Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(e.ToString());
Console.ForegroundColor = ConsoleColor.White;
}
}
public void Start()
{
try
{
_traceThread.Start();
}
catch (Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(e.ToString());
Console.ForegroundColor = ConsoleColor.White;
}
}
public void Stop()
{
try
{
_session.Stop(true);
}
catch (Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(e.ToString());
Console.ForegroundColor = ConsoleColor.White;
}
}
}
public class App {
public uint ProcessId { get; set; }
public string ProcessName { get; set; }
public bool CurrentState { get; set; }
}
}
② MonitorTrigger.cs Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MonitoringProcessConsole
{
public enum MonitorTrigger
{
Launch = 0,
Exit = 1
}
}
3. 接着在 Program.cs 的Main 函数中,调用监控函数。
① Program.cs Code
using System;
namespace MonitoringProcessConsole
{
class Program
{
static void Main(string[] args)
{
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine($"Please input:(y/n) [y: Start Monitoring n: Stop Monitoring]");
Console.ForegroundColor = ConsoleColor.White;
while (true)
{
string input = Console.ReadLine().ToLower();
if (input == "n")
{
MonEventSource.Instance.Stop();
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine($"------------------------------------------------------------");
Console.WriteLine($"Welcome to use, the program is exiting!");
Environment.Exit(0);
}
else if (input == "y")
{
MonEventSource.Instance.Start();
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine($"Wrong input!Please input :(y/n) [y: Start Monitoring n: Stop Monitoring]");
Console.ForegroundColor = ConsoleColor.White;
}
}
}
}
}
注意:必须以管理员权限运行;代码中的 AppList 是所要监控的应用程序名称。
此代码未经过优化,或者逻辑上的纰漏处理,不喜勿喷,谢谢!
最后附上截图: