Microsoft Network Monitor 可以用来监测本地网络活动 , 除了功能丰富的 GUI 界面 , 它还提供了一些 API 供程序员在自己的代码里使用 Network Monitor 的功能 . 程序安装完成后 , 在 API 文件夹里可以找到一个 .cs 文件 , 该文件包含了 Network Monitor API 的托管签名 , 直接将此文件加入到 .NET 工程中即可 .
下面是一个简单的例子 :
CaputureAndSave方法显示了如何捕获和解析 frame, 并且把捕获到的一系列 frame 保存到 test.cap 文件中 .
ReadExistingCapFile方法显示了如何读取已有的 .cap 文件 .
class NetmonDemo { const UInt32 ERROR_SUCCESS = 0; private static CaptureCallbackDelegate pCaptureCallBack = new CaptureCallbackDelegate(CaptureCallback); private static ParserCallbackDelegate pParserCallback = new ParserCallbackDelegate(ParserCallback); private static IntPtr hCaptureEngine = IntPtr.Zero; private static IntPtr myFrameParser = IntPtr.Zero; [STAThread] public static void Run() { CaputureAndSave(); } static void CaputureAndSave() { UInt32 ret = 0; String capFileName = @"D:/test.cap"; IntPtr capFileHandle = IntPtr.Zero; UInt32 size = 0; ret = NetmonAPI.NmCreateCaptureFile(capFileName, 1000000, NmCaptureFileFlag.Chain, out capFileHandle, out size); if (ret != ERROR_SUCCESS) { Console.WriteLine("Failed to create capture file: {0}", capFileName); return; } myFrameParser = CreateFrameParser(); if (NetmonAPI.NmOpenCaptureEngine(out hCaptureEngine) == ERROR_SUCCESS) { uint adapterCount; NetmonAPI.NmGetAdapterCount(hCaptureEngine, out adapterCount); Console.WriteLine("there are {0} adapters.", adapterCount); // Retrieves information of the second adapter. UInt32 adapterIndex = 1 ; NM_NIC_ADAPTER_INFO adapterInfo = new NM_NIC_ADAPTER_INFO(); adapterInfo.Size = (UInt16)System.Runtime.InteropServices.Marshal.SizeOf(adapterInfo); UInt32 status = NetmonAPI.NmGetAdapter(hCaptureEngine, adapterIndex, ref adapterInfo); // Configures adapter 1. if (NetmonAPI.NmConfigAdapter(hCaptureEngine, adapterIndex, pCaptureCallBack, capFileHandle, NmCaptureCallbackExitMode.ReturnRemainFrames) == ERROR_SUCCESS) { NetmonAPI.NmStartCapture(hCaptureEngine, adapterIndex, NmCaptureMode.LocalOnly); Console.WriteLine("Tracing begins, press any key to stop"); Console.Read(); NetmonAPI.NmStopCapture(hCaptureEngine, adapterIndex); NetmonAPI.NmCloseHandle(hCaptureEngine); hCaptureEngine = IntPtr.Zero; NetmonAPI.NmCloseHandle(capFileHandle); capFileHandle = IntPtr.Zero; } } } static void ReadExistingCapFile() { myFrameParser = CreateFrameParser(); IntPtr capFile; UInt32 ret = NetmonAPI.NmOpenCaptureFile("D://myfile.cap", out capFile); UInt32 frameCount = 0; ret = NetmonAPI.NmGetFrameCount(capFile, out frameCount); for (UInt32 i = 0; i < frameCount; i++) { IntPtr pframe; ret = NetmonAPI.NmGetFrame(capFile, i, out pframe); IntPtr parsedFrame, insFrame; ret = NetmonAPI.NmParseFrame(myFrameParser, pframe, i, NmFrameParsingOption.FrameConversationInfoRequired, out parsedFrame, out insFrame); unsafe { IntPtr buff = Marshal.AllocHGlobal(1000); uint returnLen = 0; NmPropertyValueType value; ret = NetmonAPI.NmGetPropertyById(myFrameParser, 0, 1000, (byte*)buff, out returnLen, out value, 0, new CNmPropertyStorageKey[1]); Console.WriteLine(Marshal.PtrToStringUni(buff)); Console.WriteLine("-"); } } } static void CaptureCallback(IntPtr hCaptureEngine, UInt32 ulAdapterIndex, IntPtr pCallerContext, IntPtr hFrame) { uint length = 0; unsafe { IntPtr buff = Marshal.AllocHGlobal(100); NetmonAPI.NmGetRawFrame(hFrame, 100, (byte*)buff, out length); } NetmonAPI.NmAddFrame(pCallerContext, hFrame); Console.WriteLine(length); //if (pCallerContext != IntPtr.Zero) //{ // NetmonAPI.NmAddFrame(pCallerContext, hFrame); //} DumpProcessName(hFrame); } static void ParserCallback(IntPtr pCallerContext, UInt32 ulStatusCode, String lpDescription, NmCallbackMsgType ulType) { Console.WriteLine(lpDescription); } static IntPtr CreateFrameParser() { UInt32 ret = 0; IntPtr pCallerContext = IntPtr.Zero; IntPtr nplParser = IntPtr.Zero; ret = NetmonAPI.NmLoadNplParser(null, NmNplParserLoadingOption.NmAppendRegisteredNplSets, pParserCallback, pCallerContext, out nplParser); if (ret != ERROR_SUCCESS) { Console.WriteLine("Failed to load NPL Parser"); return myFrameParser; } IntPtr frameParserConfig = IntPtr.Zero; ret = NetmonAPI.NmCreateFrameParserConfiguration(nplParser, pParserCallback, pCallerContext, out frameParserConfig); if (ret != ERROR_SUCCESS) { Console.WriteLine("Failed to load frame parser configuration."); return myFrameParser; } ret = NetmonAPI.NmConfigConversation(frameParserConfig, NmConversationConfigOption.None, true); if (ret != ERROR_SUCCESS) { Console.WriteLine("Failed to config conversation."); return myFrameParser; } ret = NetmonAPI.NmConfigReassembly(frameParserConfig, NmReassemblyConfigOption.None, true); if (ret != ERROR_SUCCESS) { Console.WriteLine("Failed to config reassembly."); return myFrameParser; } UInt32 propertyId = 0; string propertyName = "Conversation.ProcessName"; ret = NetmonAPI.NmAddProperty(frameParserConfig, propertyName, out propertyId); if (ret != ERROR_SUCCESS) { Console.WriteLine("Failed to add property: {0}", propertyName); return myFrameParser; } //propertyName = "Conversation.ProcessName"; //ret = NetmonAPI.NmAddProperty(frameParserConfig, propertyName, out propertyId); //if (ret != ERROR_SUCCESS) //{ // Console.WriteLine("Failed to add property: {0}", propertyName); // return myFrameParser; //} ret = NetmonAPI.NmCreateFrameParser(frameParserConfig, out myFrameParser, NmFrameParserOptimizeOption.ParserOptimizeNone); if (ret != ERROR_SUCCESS) { Console.WriteLine("Failed to create parser."); NetmonAPI.NmCloseHandle(frameParserConfig); return myFrameParser; } return myFrameParser; } static void DumpProcessName(IntPtr hFrame) { IntPtr parsedFrame, insertedRawFrame; uint ret = NetmonAPI.NmParseFrame(myFrameParser, hFrame, 0, NmFrameParsingOption.FrameConversationInfoRequired, out parsedFrame, out insertedRawFrame); uint propertyID = 0; //NM_NPL_PROPERTY_INFO pInfo = new NM_NPL_PROPERTY_INFO(); //ret = NetmonAPI.NmGetPropertyInfo(myFrameParser, propertyID, ref pInfo); unsafe { IntPtr buff = Marshal.AllocHGlobal(1000); uint returnLen = 0; NmPropertyValueType value; ret = NetmonAPI.NmGetPropertyById(myFrameParser, propertyID, 1000, (byte*)buff, out returnLen, out value, 0, new CNmPropertyStorageKey[1]); //Console.Write("-"); Console.WriteLine(Marshal.PtrToStringUni(buff)); } } }