|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
上一篇提到了 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 是所要監控的應用程序名稱。
此代碼未經過優化,或者邏輯上的紕漏處理,不喜勿噴,謝謝!
最後附上截圖: