A:增加测试用例;增加统计函数。网络统计已基本可用
This commit is contained in:
1 parent
b48f3368b9
commit
aa6c36655f
8 files changed
+1334
-11
No files matched your search
@@ -20,4 +20,10 @@ public static class SysHelper
|
|||||||
listener.Stop();
|
listener.Stop();
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
public static bool IsAdministrator()
|
||||||
|
{
|
||||||
|
var identity = System.Security.Principal.WindowsIdentity.GetCurrent();
|
||||||
|
var principal = new System.Security.Principal.WindowsPrincipal(identity);
|
||||||
|
return principal.IsInRole(System.Security.Principal.WindowsBuiltInRole.Administrator);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -2,19 +2,24 @@
|
|||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AApplication_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6412d4331611499aab4eb63809a2a83bf60910_003Fd6_003F8ef46f2c_003FApplication_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AApplication_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6412d4331611499aab4eb63809a2a83bf60910_003Fd6_003F8ef46f2c_003FApplication_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AArray_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Fc8_003F8670d075_003FArray_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AArray_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Fc8_003F8670d075_003FArray_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ABoundedChannelOptions_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6c1b38ac9eb24f67b802360dcd86fc07208b0_003Fd0_003Ff86ab164_003FBoundedChannelOptions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ABoundedChannelOptions_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6c1b38ac9eb24f67b802360dcd86fc07208b0_003Fd0_003Ff86ab164_003FBoundedChannelOptions_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACancellationTokenSource_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Facc3e6e5f85e7174c16f6fd86bfc988df4815a736791e6f3d736ed79b8436e_003FCancellationTokenSource_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACancellationToken_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F2565b9d99fdde488bc7801b84387b2cc864959cfb63212e1ff576fc9c6bb7e_003FCancellationToken_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AChannel_00602_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6c1b38ac9eb24f67b802360dcd86fc07208b0_003F10_003F645700ec_003FChannel_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AChannel_00602_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F6c1b38ac9eb24f67b802360dcd86fc07208b0_003F10_003F645700ec_003FChannel_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AConcurrentDictionary_00602_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F4c583240ebf1454eb7477e1b97ab637b43928_003F90_003F523b730a_003FConcurrentDictionary_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AConcurrentDictionary_00602_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F4c583240ebf1454eb7477e1b97ab637b43928_003F90_003F523b730a_003FConcurrentDictionary_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ADefaultInterpolatedStringHandler_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Fe4_003Fdb4307f5_003FDefaultInterpolatedStringHandler_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ADefaultInterpolatedStringHandler_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Fe4_003Fdb4307f5_003FDefaultInterpolatedStringHandler_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ADictionary_00602_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003F38_003Faa4e6832_003FDictionary_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ADictionary_00602_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003F38_003Faa4e6832_003FDictionary_00602_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AEnumerable_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fcca5cfb955e146648d91eb22ffe4627a84930_003Fae_003Fc940e3b4_003FEnumerable_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AEnumerable_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fcca5cfb955e146648d91eb22ffe4627a84930_003Fae_003Fc940e3b4_003FEnumerable_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AETWTraceEventSource_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F25b12134b1124ffbab73641db2e54e5b310830_003F01_003F4bae5ee3_003FETWTraceEventSource_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AETWTraceEventSource_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F25b12134b1124ffbab73641db2e54e5b310830_003F01_003F4bae5ee3_003FETWTraceEventSource_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AETWTraceEventSource_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F25b12134b1124ffbab73641db2e54e5b310830_003F01_003F4bae5ee3_003FETWTraceEventSource_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFileVersionInfo_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F7fad91e527c1434bb313ddbc78144605b8a0_003F3f_003F911bc64d_003FFileVersionInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFileVersionInfo_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F7fad91e527c1434bb313ddbc78144605b8a0_003F3f_003F911bc64d_003FFileVersionInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFile_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003F71_003F40854420_003FFile_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFile_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003F71_003F40854420_003FFile_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AFuture_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F6f90c6c13479b8c2a5be98f3d75dfc3bd885a055652d8a32904ca2448132949e_003FFuture_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIcon_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F946b37ae1f1648b7a334a81e4b6ce11c64330_003F21_003F67e31def_003FIcon_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIcon_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F946b37ae1f1648b7a334a81e4b6ce11c64330_003F21_003F67e31def_003FIcon_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIDisposable_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5aeb6167299d4cfba30c86624130edbcc90938_003F41_003F0f283a8f_003FIDisposable_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIDisposable_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5aeb6167299d4cfba30c86624130edbcc90938_003F41_003F0f283a8f_003FIDisposable_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIPAddress_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5dc54dc133694e6ca1812e5e56e958df388a0_003F68_003F0bc1a452_003FIPAddress_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIPAddress_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F5dc54dc133694e6ca1812e5e56e958df388a0_003F68_003F0bc1a452_003FIPAddress_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIWebSocketConnection_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fa7d96aff8e344c1d9aa8042f229d493cae00_003Fc1_003Fb154f2eb_003FIWebSocketConnection_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AIWebSocketConnection_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fa7d96aff8e344c1d9aa8042f229d493cae00_003Fc1_003Fb154f2eb_003FIWebSocketConnection_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AKernelTraceEventParser_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F25b12134b1124ffbab73641db2e54e5b310830_003F24_003Fd19d02f2_003FKernelTraceEventParser_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AKernelTraceEventParser_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F25b12134b1124ffbab73641db2e54e5b310830_003F24_003Fd19d02f2_003FKernelTraceEventParser_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AKernelTraceEventParser_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F25b12134b1124ffbab73641db2e54e5b310830_003F24_003Fd19d02f2_003FKernelTraceEventParser_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ALazy_00601_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003F74_003F173162e6_003FLazy_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ALazy_00601_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003F74_003F173162e6_003FLazy_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ALogger_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F59d0b425a1244469855c0039f03f864c27e00_003F43_003F8a29b095_003FLogger_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ALogger_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F59d0b425a1244469855c0039f03f864c27e00_003F43_003F8a29b095_003FLogger_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMonitor_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Fb5_003F0c446809_003FMonitor_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AMonitor_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Fb5_003F0c446809_003FMonitor_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
@@ -26,12 +31,14 @@
|
|||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AReadOnlyCollectionBase_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F4c1fd115dbe5414db1b4da1de3e96c5819910_003F04_003Fcae9fe22_003FReadOnlyCollectionBase_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AReadOnlyCollectionBase_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F4c1fd115dbe5414db1b4da1de3e96c5819910_003F04_003Fcae9fe22_003FReadOnlyCollectionBase_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASemaphoreSlim_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Fe9_003F4d4110fd_003FSemaphoreSlim_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ASemaphoreSlim_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Fe9_003F4d4110fd_003FSemaphoreSlim_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AString_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Ff1_003F7b5a67e3_003FString_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AString_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Ff1_003F7b5a67e3_003FString_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATask_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fa77b231cea33ff338c41dc7869d6c493d4dae137ff51e342173efa61d933_003FTask_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATcpIpConnectTraceData_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F25b12134b1124ffbab73641db2e54e5b310830_003F93_003Fd6e6c065_003FTcpIpConnectTraceData_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATcpIpConnectTraceData_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F25b12134b1124ffbab73641db2e54e5b310830_003F93_003Fd6e6c065_003FTcpIpConnectTraceData_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATcpIpSendTraceData_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F25b12134b1124ffbab73641db2e54e5b310830_003F28_003Fce7c9cfa_003FTcpIpSendTraceData_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATcpIpSendTraceData_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F25b12134b1124ffbab73641db2e54e5b310830_003F28_003Fce7c9cfa_003FTcpIpSendTraceData_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATimer_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Fa8_003F04476824_003FTimer_002Ecs_002Fz_003A2_002D1/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATimer_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F211e6f3b24fa438a92f1815153647ce2c8f908_003Fa8_003F04476824_003FTimer_002Ecs_002Fz_003A2_002D1/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATimer_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Ffe2ae574758f4da99bb3bfcba69a0a40b6928_003F7f_003Fb5cb1e21_003FTimer_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATimer_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Ffe2ae574758f4da99bb3bfcba69a0a40b6928_003F7f_003Fb5cb1e21_003FTimer_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATraceEventSession_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F25b12134b1124ffbab73641db2e54e5b310830_003F4e_003F99d3e433_003FTraceEventSession_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATraceEventSession_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F25b12134b1124ffbab73641db2e54e5b310830_003F4e_003F99d3e433_003FTraceEventSession_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATraceEvent_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F25b12134b1124ffbab73641db2e54e5b310830_003F4d_003F09175cdc_003FTraceEvent_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATraceEvent_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F25b12134b1124ffbab73641db2e54e5b310830_003F4d_003F09175cdc_003FTraceEvent_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ATraceEvent_002Ecs_002Fl_003AC_0021_003FUsers_003Fyllyo_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F25b12134b1124ffbab73641db2e54e5b310830_003F4d_003F09175cdc_003FTraceEvent_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AWebView2_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F8aca2f2c90e1454c825fc8b69c53a97e14268_003F06_003F22dc0e77_003FWebView2_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AWebView2_002Ecs_002Fl_003AC_0021_003FUsers_003Fcharlatans_003FAppData_003FRoaming_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F8aca2f2c90e1454c825fc8b69c53a97e14268_003F06_003F22dc0e77_003FWebView2_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=f4a8c497_002D43fb_002D4de1_002D9ffa_002D84076d7db2c5/@EntryIndexedValue"><SessionState ContinuousTestingMode="0" IsActive="True" Name="Test1" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
|
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=f4a8c497_002D43fb_002D4de1_002D9ffa_002D84076d7db2c5/@EntryIndexedValue"><SessionState ContinuousTestingMode="0" IsActive="True" Name="Test1" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session">
|
||||||
<TestAncestor>
|
<TestAncestor>
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ using Common.Net.WebSocketConn;
|
|||||||
using Infrastructure.utils;
|
using Infrastructure.utils;
|
||||||
using Utils.ETW;
|
using Utils.ETW;
|
||||||
using Utils.ETW.Core;
|
using Utils.ETW.Core;
|
||||||
|
using Utils.ETW.Etw;
|
||||||
using WinDivertNet.WinDivertWrapper;
|
using WinDivertNet.WinDivertWrapper;
|
||||||
|
|
||||||
namespace Shell.Views;
|
namespace Shell.Views;
|
||||||
@@ -25,7 +26,31 @@ public partial class WebPanel : UserControl
|
|||||||
InitWebView();
|
InitWebView();
|
||||||
|
|
||||||
// 注册管理 WebSocket 事件
|
// 注册管理 WebSocket 事件
|
||||||
WebSocketManger();
|
// WebSocketManger();
|
||||||
|
|
||||||
|
// ETW 信息获取
|
||||||
|
// 检查管理员权限
|
||||||
|
NewMethod();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task NewMethod()
|
||||||
|
{
|
||||||
|
if (!SysHelper.IsAdministrator())
|
||||||
|
{
|
||||||
|
Console.WriteLine("此程序需要管理员权限才能运行ETW监控!");
|
||||||
|
Console.WriteLine("请以管理员身份重新运行程序。");
|
||||||
|
Console.ReadKey();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var example = new NetworkMonitorUsageExample();
|
||||||
|
example.RunExample();
|
||||||
|
|
||||||
|
// 创建监听实例
|
||||||
|
// var etwNetworkManger = new EtwNetworkManger();
|
||||||
|
// // 设置 ETW 监听
|
||||||
|
// etwNetworkManger.SetupEtwHandlers();
|
||||||
|
// etwNetworkManger.StartCapture();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WebSocketManger()
|
private void WebSocketManger()
|
||||||
@@ -38,13 +63,10 @@ public partial class WebPanel : UserControl
|
|||||||
Console.WriteLine("开始测试");
|
Console.WriteLine("开始测试");
|
||||||
|
|
||||||
// 创建监听实例
|
// 创建监听实例
|
||||||
var etwNetworkManger = new EtwNetworkManger();
|
// var etwNetworkManger = new EtwNetworkManger();
|
||||||
|
|
||||||
// 设置 ETW 监听
|
// 设置 ETW 监听
|
||||||
etwNetworkManger.SetupEtwHandlers();
|
// etwNetworkManger.Initialize();
|
||||||
|
|
||||||
// 开始监听
|
|
||||||
etwNetworkManger.StartCapture();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ namespace Utils.ETW.Core;
|
|||||||
// ETW网络事件处理器
|
// ETW网络事件处理器
|
||||||
public class EtwNetworkCapture(string sessionName = "NetworkETWSession") : IDisposable
|
public class EtwNetworkCapture(string sessionName = "NetworkETWSession") : IDisposable
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 此代码需要管理员权限
|
||||||
|
/// </summary>
|
||||||
private readonly TraceEventSession _session = new(sessionName);
|
private readonly TraceEventSession _session = new(sessionName);
|
||||||
private readonly ETWTraceEventSource _source = new(sessionName, TraceEventSourceType.Session);
|
private readonly ETWTraceEventSource _source = new(sessionName, TraceEventSourceType.Session);
|
||||||
|
|
||||||
@@ -271,11 +274,7 @@ public class EtwNetworkCapture(string sessionName = "NetworkETWSession") : IDisp
|
|||||||
// 缓存进程信息,包括完整路径、命令行等
|
// 缓存进程信息,包括完整路径、命令行等
|
||||||
};
|
};
|
||||||
// 通用事件处理器,用于其他网络事件
|
// 通用事件处理器,用于其他网络事件
|
||||||
_source.Dynamic.All += data =>
|
_source.Dynamic.All += ProcessDynamicEvent;
|
||||||
{
|
|
||||||
// 处理DNS、HTTP等其他网络事件
|
|
||||||
ProcessDynamicEvent(data);
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,200 @@
|
|||||||
|
using System.Net;
|
||||||
|
using Utils.ETW.Models;
|
||||||
|
|
||||||
|
namespace Utils.ETW.Etw;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 应用程序信息
|
||||||
|
/// </summary>
|
||||||
|
public class ApplicationInfo
|
||||||
|
{
|
||||||
|
public int ProcessId { get; set; }
|
||||||
|
public string ApplicationName { get; set; }
|
||||||
|
public string ApplicationPath { get; set; }
|
||||||
|
public string Version { get; set; }
|
||||||
|
public string Company { get; set; }
|
||||||
|
public string Description { get; set; }
|
||||||
|
public DateTime FirstSeenTime { get; set; }
|
||||||
|
public DateTime LastUpdateTime { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 进程网络信息
|
||||||
|
/// </summary>
|
||||||
|
public class ProcessNetworkInfo
|
||||||
|
{
|
||||||
|
public int ProcessId { get; set; }
|
||||||
|
public string ProcessName { get; set; }
|
||||||
|
public DateTime FirstSeenTime { get; set; }
|
||||||
|
public DateTime LastActiveTime { get; set; }
|
||||||
|
public List<string> ActiveConnections { get; set; } = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 连接详细信息
|
||||||
|
/// </summary>
|
||||||
|
public class ConnectionInfo
|
||||||
|
{
|
||||||
|
public string ConnectionKey { get; set; }
|
||||||
|
public int ProcessId { get; set; }
|
||||||
|
public ProtocolType Protocol { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 本地 终结点
|
||||||
|
/// </summary>
|
||||||
|
public IPEndPoint LocalEndpoint { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 目标 终结点
|
||||||
|
/// </summary>
|
||||||
|
public IPEndPoint RemoteEndpoint { get; set; }
|
||||||
|
public ConnectionState State { get; set; }
|
||||||
|
public TrafficDirection Direction { get; set; }
|
||||||
|
public DateTime StartTime { get; set; }
|
||||||
|
public DateTime LastActiveTime { get; set; }
|
||||||
|
public long BytesSent { get; set; }
|
||||||
|
public long BytesReceived { get; set; }
|
||||||
|
public double CurrentSendSpeed { get; set; } // 字节/秒
|
||||||
|
public double CurrentReceiveSpeed { get; set; } // 字节/秒
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
|
||||||
|
// 速率计算辅助字段
|
||||||
|
public long LastBytesSent { get; set; }
|
||||||
|
public long LastBytesReceived { get; set; }
|
||||||
|
public DateTime LastSpeedCalculationTime { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DNS解析信息
|
||||||
|
/// </summary>
|
||||||
|
public class DnsResolveInfo
|
||||||
|
{
|
||||||
|
public string IpAddress { get; set; }
|
||||||
|
public string DomainName { get; set; }
|
||||||
|
public string QueryType { get; set; }
|
||||||
|
public DateTime ResolveTime { get; set; }
|
||||||
|
public DateTime LastUsedTime { get; set; }
|
||||||
|
public List<string> AlternativeDomains { get; set; } = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 端口流量信息
|
||||||
|
/// </summary>
|
||||||
|
public class PortTrafficInfo
|
||||||
|
{
|
||||||
|
public int Port { get; set; }
|
||||||
|
public long BytesSent { get; set; }
|
||||||
|
public long BytesReceived { get; set; }
|
||||||
|
public long TotalBytes => BytesSent + BytesReceived;
|
||||||
|
public DateTime LastUpdateTime { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IP流量信息
|
||||||
|
/// </summary>
|
||||||
|
public class IpTrafficInfo
|
||||||
|
{
|
||||||
|
public string IpAddress { get; set; }
|
||||||
|
public long BytesSent { get; set; }
|
||||||
|
public long BytesReceived { get; set; }
|
||||||
|
public long TotalBytes => BytesSent + BytesReceived;
|
||||||
|
public DateTime LastUpdateTime { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 网络监控数据快照
|
||||||
|
/// </summary>
|
||||||
|
public class NetworkMonitorSnapshot
|
||||||
|
{
|
||||||
|
public DateTime SnapshotTime { get; set; }
|
||||||
|
public List<ApplicationSnapshot> Applications { get; set; }
|
||||||
|
public GlobalNetworkStats GlobalStats { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 应用程序快照
|
||||||
|
/// </summary>
|
||||||
|
public class ApplicationSnapshot
|
||||||
|
{
|
||||||
|
public int ProcessId { get; set; }
|
||||||
|
public string ApplicationName { get; set; }
|
||||||
|
public string ApplicationPath { get; set; }
|
||||||
|
public string Version { get; set; }
|
||||||
|
public string ProcessName { get; set; }
|
||||||
|
public DateTime FirstSeenTime { get; set; }
|
||||||
|
public DateTime LastActiveTime { get; set; }
|
||||||
|
public List<ConnectionSnapshot> Connections { get; set; }
|
||||||
|
|
||||||
|
// 统计信息
|
||||||
|
public int TotalConnections { get; set; }
|
||||||
|
public int ActiveConnections { get; set; }
|
||||||
|
public long TotalBytesSent { get; set; }
|
||||||
|
public long TotalBytesReceived { get; set; }
|
||||||
|
public double TotalSendSpeed { get; set; }
|
||||||
|
public double TotalReceiveSpeed { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 连接快照
|
||||||
|
/// </summary>
|
||||||
|
public class ConnectionSnapshot
|
||||||
|
{
|
||||||
|
public string Protocol { get; set; }
|
||||||
|
public string LocalIp { get; set; }
|
||||||
|
public int LocalPort { get; set; }
|
||||||
|
public string RemoteIp { get; set; }
|
||||||
|
public int RemotePort { get; set; }
|
||||||
|
public string RemoteDomain { get; set; }
|
||||||
|
public string State { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 方向
|
||||||
|
/// </summary>
|
||||||
|
public string Direction { get; set; }
|
||||||
|
public DateTime StartTime { get; set; }
|
||||||
|
public TimeSpan Duration { get; set; }
|
||||||
|
public long BytesSent { get; set; }
|
||||||
|
public long BytesReceived { get; set; }
|
||||||
|
public double CurrentSendSpeed { get; set; }
|
||||||
|
public double CurrentReceiveSpeed { get; set; }
|
||||||
|
public bool IsActive { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 全局网络统计
|
||||||
|
/// </summary>
|
||||||
|
public class GlobalNetworkStats
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 总软件数量
|
||||||
|
/// </summary>
|
||||||
|
public int TotalApplications { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 总连接数量
|
||||||
|
/// </summary>
|
||||||
|
public int TotalConnections { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 活跃连接数
|
||||||
|
/// </summary>
|
||||||
|
public int ActiveConnections { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 端口流量统计
|
||||||
|
/// </summary>
|
||||||
|
public List<PortTrafficInfo> PortTraffic { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IP 流量统计
|
||||||
|
/// </summary>
|
||||||
|
public List<IpTrafficInfo> IpTraffic { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 进程网络详情
|
||||||
|
/// </summary>
|
||||||
|
public class ProcessNetworkDetails
|
||||||
|
{
|
||||||
|
public int ProcessId { get; set; }
|
||||||
|
public string ProcessName { get; set; }
|
||||||
|
public ApplicationInfo ApplicationInfo { get; set; }
|
||||||
|
public List<ConnectionInfo> Connections { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,424 @@
|
|||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Net;
|
||||||
|
using Utils.ETW.Core;
|
||||||
|
using Utils.ETW.Models;
|
||||||
|
|
||||||
|
namespace Utils.ETW.Etw;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 增强的ETW网络管理器 - 负责收集网络数据并更新到GlobalNetworkMonitor
|
||||||
|
/// </summary>
|
||||||
|
public class EnhancedEtwNetworkManager : IDisposable
|
||||||
|
{
|
||||||
|
private readonly EtwNetworkCapture _networkCapture = new();
|
||||||
|
private readonly CancellationTokenSource _cancellationTokenSource = new();
|
||||||
|
|
||||||
|
// 进程信息缓存
|
||||||
|
private readonly ConcurrentDictionary<int, ProcessInfo> _processCache = new();
|
||||||
|
|
||||||
|
// DNS反向查询任务队列
|
||||||
|
private readonly ConcurrentQueue<string> _dnsLookupQueue = new();
|
||||||
|
|
||||||
|
private bool _isRunning = false;
|
||||||
|
|
||||||
|
public EnhancedEtwNetworkManager()
|
||||||
|
{
|
||||||
|
SetupEventHandlers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置事件处理器
|
||||||
|
/// </summary>
|
||||||
|
private void SetupEventHandlers()
|
||||||
|
{
|
||||||
|
// TCP事件处理
|
||||||
|
_networkCapture.OnTcpConnectionEvent += HandleTcpEvent;
|
||||||
|
|
||||||
|
// UDP事件处理
|
||||||
|
_networkCapture.OnUdpPacketEvent += HandleUdpEvent;
|
||||||
|
|
||||||
|
// DNS事件处理
|
||||||
|
_networkCapture.OnDnsEvent += HandleDnsEvent;
|
||||||
|
|
||||||
|
// HTTP事件处理
|
||||||
|
_networkCapture.OnHttpEvent += HandleHttpEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 开始监控
|
||||||
|
/// </summary>
|
||||||
|
public void StartMonitoring()
|
||||||
|
{
|
||||||
|
if (_isRunning) return;
|
||||||
|
|
||||||
|
_isRunning = true;
|
||||||
|
|
||||||
|
// 启动ETW捕获
|
||||||
|
_networkCapture.StartCapture();
|
||||||
|
|
||||||
|
// 启动辅助任务
|
||||||
|
Task.Run(() => ProcessApplicationInfoAsync(_cancellationTokenSource.Token));
|
||||||
|
Task.Run(() => ProcessDnsLookupsAsync(_cancellationTokenSource.Token));
|
||||||
|
Task.Run(() => CleanupExpiredDataAsync(_cancellationTokenSource.Token));
|
||||||
|
|
||||||
|
Console.WriteLine("增强型网络监控已启动");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 停止监控
|
||||||
|
/// </summary>
|
||||||
|
public void StopMonitoring()
|
||||||
|
{
|
||||||
|
if (!_isRunning) return;
|
||||||
|
|
||||||
|
_isRunning = false;
|
||||||
|
_cancellationTokenSource.Cancel();
|
||||||
|
_networkCapture.StopCapture();
|
||||||
|
|
||||||
|
Console.WriteLine("增强型网络监控已停止");
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 事件处理方法
|
||||||
|
|
||||||
|
private void HandleTcpEvent(TcpConnectionEventData tcpEvent)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 更新进程信息
|
||||||
|
UpdateProcessInfo(tcpEvent.ProcessId, tcpEvent.ProcessName, tcpEvent.ThreadId);
|
||||||
|
|
||||||
|
// 创建或更新网络模型
|
||||||
|
var networkModel = new NetworkModel
|
||||||
|
{
|
||||||
|
ConnectType = ProtocolType.TCP,
|
||||||
|
ProcessId = tcpEvent.ProcessId,
|
||||||
|
ThreadId = tcpEvent.ThreadId,
|
||||||
|
ProcessName = tcpEvent.ProcessName,
|
||||||
|
SourceIp = tcpEvent.SourceIp,
|
||||||
|
DestinationIp = tcpEvent.DestinationIp,
|
||||||
|
SourcePort = tcpEvent.SourcePort,
|
||||||
|
DestinationPort = tcpEvent.DestinationPort,
|
||||||
|
LastSeenTime = DateTime.Now,
|
||||||
|
RecordTime = tcpEvent.Timestamp,
|
||||||
|
Direction = tcpEvent.Direction,
|
||||||
|
IsPartialConnection = false,
|
||||||
|
State = ConnectionState.Connecting
|
||||||
|
};
|
||||||
|
|
||||||
|
// 根据事件类型处理
|
||||||
|
switch (tcpEvent.EventType)
|
||||||
|
{
|
||||||
|
case "TcpConnect":
|
||||||
|
networkModel.StartTime = tcpEvent.Timestamp;
|
||||||
|
networkModel.State = ConnectionState.Connecting;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "TcpDisconnect":
|
||||||
|
networkModel.EndTime = tcpEvent.Timestamp;
|
||||||
|
networkModel.State = ConnectionState.Disconnected;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "TcpSend":
|
||||||
|
networkModel.BytesSent = tcpEvent.DataLength;
|
||||||
|
networkModel.State = ConnectionState.Connected;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case "TcpReceive":
|
||||||
|
networkModel.BytesReceived = tcpEvent.DataLength;
|
||||||
|
networkModel.State = ConnectionState.Connected;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新到全局监控器
|
||||||
|
GlobalNetworkMonitor.Instance.UpdateConnectionInfo(networkModel);
|
||||||
|
|
||||||
|
// 添加到DNS查询队列
|
||||||
|
if (!IsPrivateIp(tcpEvent.DestinationIp))
|
||||||
|
{
|
||||||
|
_dnsLookupQueue.Enqueue(tcpEvent.DestinationIp.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"处理TCP事件时出错: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleUdpEvent(UdpPacketEventData udpEvent)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 更新进程信息
|
||||||
|
UpdateProcessInfo(udpEvent.ProcessId, udpEvent.ProcessName, udpEvent.ThreadId);
|
||||||
|
|
||||||
|
var networkModel = new NetworkModel
|
||||||
|
{
|
||||||
|
ConnectType = ProtocolType.UDP,
|
||||||
|
ProcessId = udpEvent.ProcessId,
|
||||||
|
ThreadId = udpEvent.ThreadId,
|
||||||
|
ProcessName = udpEvent.ProcessName,
|
||||||
|
SourceIp = udpEvent.SourceIp,
|
||||||
|
DestinationIp = udpEvent.DestinationIp,
|
||||||
|
SourcePort = udpEvent.SourcePort,
|
||||||
|
DestinationPort = udpEvent.DestinationPort,
|
||||||
|
StartTime = udpEvent.Timestamp,
|
||||||
|
LastSeenTime = DateTime.Now,
|
||||||
|
RecordTime = udpEvent.Timestamp,
|
||||||
|
Direction = udpEvent.Direction,
|
||||||
|
State = ConnectionState.Connected,
|
||||||
|
IsPartialConnection = false
|
||||||
|
};
|
||||||
|
|
||||||
|
if (udpEvent.EventType == "UdpSend")
|
||||||
|
{
|
||||||
|
networkModel.BytesSent = udpEvent.DataLength;
|
||||||
|
}
|
||||||
|
else if (udpEvent.EventType == "UdpReceive")
|
||||||
|
{
|
||||||
|
networkModel.BytesReceived = udpEvent.DataLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新到全局监控器
|
||||||
|
GlobalNetworkMonitor.Instance.UpdateConnectionInfo(networkModel);
|
||||||
|
|
||||||
|
// 添加到DNS查询队列
|
||||||
|
if (!IsPrivateIp(udpEvent.DestinationIp))
|
||||||
|
{
|
||||||
|
_dnsLookupQueue.Enqueue(udpEvent.DestinationIp.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"处理UDP事件时出错: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleDnsEvent(DnsEventData dnsEvent)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 更新DNS缓存
|
||||||
|
if (!string.IsNullOrEmpty(dnsEvent.QueryName) && dnsEvent.ResolvedAddresses?.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (var ip in dnsEvent.ResolvedAddresses)
|
||||||
|
{
|
||||||
|
GlobalNetworkMonitor.Instance.UpdateDnsInfo(ip, dnsEvent.QueryName, dnsEvent.QueryType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"处理DNS事件时出错: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleHttpEvent(HttpEventData httpEvent)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 可以从HTTP事件中提取更多应用层信息
|
||||||
|
Console.WriteLine($"[HTTP] {httpEvent.HttpMethod} {httpEvent.Url}");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"处理HTTP事件时出错: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 辅助方法
|
||||||
|
|
||||||
|
private void UpdateProcessInfo(int processId, string processName, int threadId)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 更新进程网络信息
|
||||||
|
GlobalNetworkMonitor.Instance.UpdateProcessNetworkInfo(processId, processName, threadId);
|
||||||
|
|
||||||
|
// 如果进程信息不在缓存中,添加到缓存并获取详细信息
|
||||||
|
if (!_processCache.ContainsKey(processId))
|
||||||
|
{
|
||||||
|
_processCache.TryAdd(processId, new ProcessInfo
|
||||||
|
{
|
||||||
|
ProcessId = processId,
|
||||||
|
ProcessName = processName,
|
||||||
|
NeedsUpdate = true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"更新进程信息时出错: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步处理应用程序信息
|
||||||
|
/// </summary>
|
||||||
|
private async Task ProcessApplicationInfoAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (var kvp in _processCache.Where(p => p.Value.NeedsUpdate))
|
||||||
|
{
|
||||||
|
var processInfo = kvp.Value;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 获取进程详细信息
|
||||||
|
using (var process = Process.GetProcessById(processInfo.ProcessId))
|
||||||
|
{
|
||||||
|
var mainModule = process.MainModule;
|
||||||
|
if (mainModule != null)
|
||||||
|
{
|
||||||
|
var appPath = mainModule.FileName;
|
||||||
|
var appName = Path.GetFileNameWithoutExtension(appPath);
|
||||||
|
var version = mainModule.FileVersionInfo.FileVersion;
|
||||||
|
var company = mainModule.FileVersionInfo.CompanyName;
|
||||||
|
|
||||||
|
// 更新应用程序信息
|
||||||
|
GlobalNetworkMonitor.Instance.UpdateApplicationInfo(
|
||||||
|
processInfo.ProcessId,
|
||||||
|
appName,
|
||||||
|
appPath,
|
||||||
|
version
|
||||||
|
);
|
||||||
|
|
||||||
|
processInfo.NeedsUpdate = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// 进程可能已经退出
|
||||||
|
Console.WriteLine($"获取进程 {processInfo.ProcessId} 信息失败: {ex.Message}");
|
||||||
|
processInfo.NeedsUpdate = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(1000, cancellationToken);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"处理应用程序信息时出错: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 异步处理DNS查询
|
||||||
|
/// </summary>
|
||||||
|
private async Task ProcessDnsLookupsAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var processedIps = new HashSet<string>();
|
||||||
|
|
||||||
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_dnsLookupQueue.TryDequeue(out var ip))
|
||||||
|
{
|
||||||
|
if (!processedIps.Contains(ip))
|
||||||
|
{
|
||||||
|
processedIps.Add(ip);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 执行反向DNS查询
|
||||||
|
var hostEntry = await Dns.GetHostEntryAsync(ip);
|
||||||
|
if (!string.IsNullOrEmpty(hostEntry.HostName))
|
||||||
|
{
|
||||||
|
GlobalNetworkMonitor.Instance.UpdateDnsInfo(ip, hostEntry.HostName, "PTR");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// DNS查询失败,忽略
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await Task.Delay(100, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"处理DNS查询时出错: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 定期清理过期数据
|
||||||
|
/// </summary>
|
||||||
|
private async Task CleanupExpiredDataAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 清理断开的连接
|
||||||
|
var snapshot = GlobalNetworkMonitor.Instance.GetSnapshot();
|
||||||
|
foreach (var app in snapshot.Applications)
|
||||||
|
{
|
||||||
|
foreach (var conn in app.Connections.Where(c => !c.IsActive && c.Duration > TimeSpan.FromMinutes(5)))
|
||||||
|
{
|
||||||
|
// 这里可以添加清理逻辑
|
||||||
|
Console.WriteLine($"清理过期连接: {app.ProcessName} - {conn.RemoteIp}:{conn.RemotePort}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await Task.Delay(TimeSpan.FromMinutes(1), cancellationToken);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"清理过期数据时出错: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsPrivateIp(IPAddress ip)
|
||||||
|
{
|
||||||
|
if (ip == null) return true;
|
||||||
|
|
||||||
|
var bytes = ip.GetAddressBytes();
|
||||||
|
|
||||||
|
// 10.0.0.0 - 10.255.255.255
|
||||||
|
if (bytes[0] == 10) return true;
|
||||||
|
|
||||||
|
// 172.16.0.0 - 172.31.255.255
|
||||||
|
if (bytes[0] == 172 && bytes[1] >= 16 && bytes[1] <= 31) return true;
|
||||||
|
|
||||||
|
// 192.168.0.0 - 192.168.255.255
|
||||||
|
if (bytes[0] == 192 && bytes[1] == 168) return true;
|
||||||
|
|
||||||
|
// 127.0.0.0 - 127.255.255.255 (loopback)
|
||||||
|
if (bytes[0] == 127) return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
StopMonitoring();
|
||||||
|
_networkCapture?.Dispose();
|
||||||
|
_cancellationTokenSource?.Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 进程信息缓存项
|
||||||
|
/// </summary>
|
||||||
|
private class ProcessInfo
|
||||||
|
{
|
||||||
|
public int ProcessId { get; set; }
|
||||||
|
public string ProcessName { get; set; }
|
||||||
|
public bool NeedsUpdate { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,441 @@
|
|||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Net;
|
||||||
|
using Utils.ETW.Models;
|
||||||
|
|
||||||
|
namespace Utils.ETW.Etw;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 全局网络监控数据管理器 - 单例模式
|
||||||
|
/// 负责收集、整合和管理所有网络监控数据
|
||||||
|
/// </summary>
|
||||||
|
public sealed class GlobalNetworkMonitor
|
||||||
|
{
|
||||||
|
private static readonly Lazy<GlobalNetworkMonitor> _instance = new(() => new GlobalNetworkMonitor());
|
||||||
|
public static GlobalNetworkMonitor Instance => _instance.Value;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 读写锁,保证数据一致性
|
||||||
|
/// </summary>
|
||||||
|
private readonly ReaderWriterLockSlim _lock = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 应用程序信息缓存 (ProcessId -> AppInfo)
|
||||||
|
/// </summary>
|
||||||
|
private readonly ConcurrentDictionary<int, ApplicationInfo> _applications = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 进程信息缓存 (ProcessId -> ProcessInfo)
|
||||||
|
/// </summary>
|
||||||
|
private readonly ConcurrentDictionary<int, ProcessNetworkInfo> _processes = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 连接信息缓存 (ConnectionKey -> ConnectionInfo)
|
||||||
|
/// </summary>
|
||||||
|
private readonly ConcurrentDictionary<string, ConnectionInfo> _connections = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// DNS解析缓存 (IP -> Domain)
|
||||||
|
/// </summary>
|
||||||
|
private readonly ConcurrentDictionary<string, DnsResolveInfo> _dnsCache = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 端口流量统计
|
||||||
|
/// </summary>
|
||||||
|
private readonly ConcurrentDictionary<int, PortTrafficInfo> _portTraffic = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IP流量统计
|
||||||
|
/// </summary>
|
||||||
|
private readonly ConcurrentDictionary<string, IpTrafficInfo> _ipTraffic = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 统计信息更新时间
|
||||||
|
/// </summary>
|
||||||
|
private DateTime _lastUpdateTime = DateTime.Now;
|
||||||
|
|
||||||
|
private GlobalNetworkMonitor()
|
||||||
|
{
|
||||||
|
// 初始化
|
||||||
|
}
|
||||||
|
|
||||||
|
#region 数据更新方法 (只能由ETW模块调用)
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新应用程序信息
|
||||||
|
/// </summary>
|
||||||
|
public void UpdateApplicationInfo(int processId, string appName, string appPath, string version = null)
|
||||||
|
{
|
||||||
|
_lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_applications.AddOrUpdate(processId,
|
||||||
|
new ApplicationInfo
|
||||||
|
{
|
||||||
|
ProcessId = processId,
|
||||||
|
ApplicationName = appName,
|
||||||
|
ApplicationPath = appPath,
|
||||||
|
Version = version,
|
||||||
|
FirstSeenTime = DateTime.Now,
|
||||||
|
LastUpdateTime = DateTime.Now
|
||||||
|
},
|
||||||
|
(key, existing) =>
|
||||||
|
{
|
||||||
|
existing.LastUpdateTime = DateTime.Now;
|
||||||
|
if (!string.IsNullOrEmpty(version))
|
||||||
|
existing.Version = version;
|
||||||
|
return existing;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lock.ExitWriteLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新进程网络信息
|
||||||
|
/// </summary>
|
||||||
|
public void UpdateProcessNetworkInfo(int processId, string processName, int threadId)
|
||||||
|
{
|
||||||
|
_lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_processes.AddOrUpdate(processId,
|
||||||
|
new ProcessNetworkInfo
|
||||||
|
{
|
||||||
|
ProcessId = processId,
|
||||||
|
ProcessName = processName,
|
||||||
|
FirstSeenTime = DateTime.Now,
|
||||||
|
LastActiveTime = DateTime.Now,
|
||||||
|
ActiveConnections = new List<string>()
|
||||||
|
},
|
||||||
|
(key, existing) =>
|
||||||
|
{
|
||||||
|
existing.LastActiveTime = DateTime.Now;
|
||||||
|
return existing;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lock.ExitWriteLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新连接信息
|
||||||
|
/// </summary>
|
||||||
|
public void UpdateConnectionInfo(NetworkModel networkModel)
|
||||||
|
{
|
||||||
|
_lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var connectionKey = networkModel.GetKey();
|
||||||
|
|
||||||
|
_connections.AddOrUpdate(connectionKey,
|
||||||
|
new ConnectionInfo
|
||||||
|
{
|
||||||
|
ConnectionKey = connectionKey,
|
||||||
|
ProcessId = networkModel.ProcessId,
|
||||||
|
Protocol = networkModel.ConnectType,
|
||||||
|
LocalEndpoint = new IPEndPoint(networkModel.SourceIp, networkModel.SourcePort),
|
||||||
|
RemoteEndpoint = new IPEndPoint(networkModel.DestinationIp, networkModel.DestinationPort),
|
||||||
|
State = networkModel.State,
|
||||||
|
Direction = networkModel.Direction,
|
||||||
|
StartTime = networkModel.StartTime ?? DateTime.Now,
|
||||||
|
LastActiveTime = networkModel.LastSeenTime,
|
||||||
|
BytesSent = networkModel.BytesSent,
|
||||||
|
BytesReceived = networkModel.BytesReceived,
|
||||||
|
IsActive = networkModel.State == ConnectionState.Connected
|
||||||
|
},
|
||||||
|
(key, existing) =>
|
||||||
|
{
|
||||||
|
existing.BytesSent = networkModel.BytesSent;
|
||||||
|
existing.BytesReceived = networkModel.BytesReceived;
|
||||||
|
existing.LastActiveTime = networkModel.LastSeenTime;
|
||||||
|
existing.State = networkModel.State;
|
||||||
|
existing.IsActive = networkModel.State == ConnectionState.Connected;
|
||||||
|
|
||||||
|
// 计算速率
|
||||||
|
var timeDiff = (networkModel.LastSeenTime - existing.LastSpeedCalculationTime).TotalSeconds;
|
||||||
|
if (timeDiff > 0)
|
||||||
|
{
|
||||||
|
existing.CurrentSendSpeed = (networkModel.BytesSent - existing.LastBytesSent) / timeDiff;
|
||||||
|
existing.CurrentReceiveSpeed =
|
||||||
|
(networkModel.BytesReceived - existing.LastBytesReceived) / timeDiff;
|
||||||
|
existing.LastBytesSent = networkModel.BytesSent;
|
||||||
|
existing.LastBytesReceived = networkModel.BytesReceived;
|
||||||
|
existing.LastSpeedCalculationTime = networkModel.LastSeenTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
return existing;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 更新进程的活跃连接列表
|
||||||
|
if (_processes.TryGetValue(networkModel.ProcessId, out var process))
|
||||||
|
{
|
||||||
|
if (!process.ActiveConnections.Contains(connectionKey))
|
||||||
|
{
|
||||||
|
process.ActiveConnections.Add(connectionKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 更新端口流量统计
|
||||||
|
UpdatePortTraffic(networkModel.SourcePort, networkModel.BytesSent, networkModel.BytesReceived, true);
|
||||||
|
UpdatePortTraffic(networkModel.DestinationPort, networkModel.BytesSent, networkModel.BytesReceived, false);
|
||||||
|
|
||||||
|
// 更新IP流量统计
|
||||||
|
UpdateIpTraffic(networkModel.SourceIp.ToString(), networkModel.BytesSent, networkModel.BytesReceived, true);
|
||||||
|
UpdateIpTraffic(networkModel.DestinationIp.ToString(), networkModel.BytesSent, networkModel.BytesReceived,
|
||||||
|
false);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lock.ExitWriteLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新DNS解析信息
|
||||||
|
/// </summary>
|
||||||
|
public void UpdateDnsInfo(string ipAddress, string domainName, string queryType = "A")
|
||||||
|
{
|
||||||
|
_lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_dnsCache.AddOrUpdate(ipAddress,
|
||||||
|
new DnsResolveInfo
|
||||||
|
{
|
||||||
|
IpAddress = ipAddress,
|
||||||
|
DomainName = domainName,
|
||||||
|
QueryType = queryType,
|
||||||
|
ResolveTime = DateTime.Now,
|
||||||
|
LastUsedTime = DateTime.Now
|
||||||
|
},
|
||||||
|
(key, existing) =>
|
||||||
|
{
|
||||||
|
existing.LastUsedTime = DateTime.Now;
|
||||||
|
if (!existing.AlternativeDomains.Contains(domainName))
|
||||||
|
{
|
||||||
|
existing.AlternativeDomains.Add(domainName);
|
||||||
|
}
|
||||||
|
|
||||||
|
return existing;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lock.ExitWriteLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 移除连接
|
||||||
|
/// </summary>
|
||||||
|
public void RemoveConnection(string connectionKey)
|
||||||
|
{
|
||||||
|
_lock.EnterWriteLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_connections.TryRemove(connectionKey, out var connection))
|
||||||
|
{
|
||||||
|
// 从进程的活跃连接列表中移除
|
||||||
|
if (_processes.TryGetValue(connection.ProcessId, out var process))
|
||||||
|
{
|
||||||
|
process.ActiveConnections.Remove(connectionKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lock.ExitWriteLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 数据读取方法 (供其他模块调用)
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取完整的网络监控数据快照
|
||||||
|
/// </summary>
|
||||||
|
public NetworkMonitorSnapshot GetSnapshot()
|
||||||
|
{
|
||||||
|
_lock.EnterReadLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var snapshot = new NetworkMonitorSnapshot
|
||||||
|
{
|
||||||
|
SnapshotTime = DateTime.Now,
|
||||||
|
Applications = new List<ApplicationSnapshot>()
|
||||||
|
};
|
||||||
|
|
||||||
|
// 按应用程序组织数据
|
||||||
|
var appGroups = _processes.GroupBy(p => p.Value.ProcessId);
|
||||||
|
|
||||||
|
foreach (var group in appGroups)
|
||||||
|
{
|
||||||
|
var processId = group.Key;
|
||||||
|
var processInfo = _processes[processId];
|
||||||
|
|
||||||
|
// 获取应用程序信息
|
||||||
|
_applications.TryGetValue(processId, out var appInfo);
|
||||||
|
|
||||||
|
var appSnapshot = new ApplicationSnapshot
|
||||||
|
{
|
||||||
|
ProcessId = processId,
|
||||||
|
ApplicationName = appInfo?.ApplicationName ?? processInfo.ProcessName,
|
||||||
|
ApplicationPath = appInfo?.ApplicationPath ?? "Unknown",
|
||||||
|
Version = appInfo?.Version ?? "Unknown",
|
||||||
|
ProcessName = processInfo.ProcessName,
|
||||||
|
FirstSeenTime = processInfo.FirstSeenTime,
|
||||||
|
LastActiveTime = processInfo.LastActiveTime,
|
||||||
|
Connections = new List<ConnectionSnapshot>()
|
||||||
|
};
|
||||||
|
|
||||||
|
// 添加所有连接信息
|
||||||
|
foreach (var connKey in processInfo.ActiveConnections)
|
||||||
|
{
|
||||||
|
if (_connections.TryGetValue(connKey, out var conn))
|
||||||
|
{
|
||||||
|
var connSnapshot = new ConnectionSnapshot
|
||||||
|
{
|
||||||
|
Protocol = conn.Protocol.ToString(),
|
||||||
|
LocalPort = conn.LocalEndpoint.Port,
|
||||||
|
LocalIp = conn.LocalEndpoint.Address.ToString(),
|
||||||
|
RemoteIp = conn.RemoteEndpoint.Address.ToString(),
|
||||||
|
RemotePort = conn.RemoteEndpoint.Port,
|
||||||
|
RemoteDomain = GetDomainForIp(conn.RemoteEndpoint.Address.ToString()),
|
||||||
|
State = conn.State.ToString(),
|
||||||
|
Direction = conn.Direction.ToString(),
|
||||||
|
StartTime = conn.StartTime,
|
||||||
|
Duration = DateTime.Now - conn.StartTime,
|
||||||
|
BytesSent = conn.BytesSent,
|
||||||
|
BytesReceived = conn.BytesReceived,
|
||||||
|
CurrentSendSpeed = conn.CurrentSendSpeed,
|
||||||
|
CurrentReceiveSpeed = conn.CurrentReceiveSpeed,
|
||||||
|
IsActive = conn.IsActive
|
||||||
|
};
|
||||||
|
|
||||||
|
appSnapshot.Connections.Add(connSnapshot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算应用程序级别的统计
|
||||||
|
appSnapshot.TotalConnections = appSnapshot.Connections.Count;
|
||||||
|
appSnapshot.ActiveConnections = appSnapshot.Connections.Count(c => c.IsActive);
|
||||||
|
appSnapshot.TotalBytesSent = appSnapshot.Connections.Sum(c => c.BytesSent);
|
||||||
|
appSnapshot.TotalBytesReceived = appSnapshot.Connections.Sum(c => c.BytesReceived);
|
||||||
|
appSnapshot.TotalSendSpeed = appSnapshot.Connections.Sum(c => c.CurrentSendSpeed);
|
||||||
|
appSnapshot.TotalReceiveSpeed = appSnapshot.Connections.Sum(c => c.CurrentReceiveSpeed);
|
||||||
|
|
||||||
|
snapshot.Applications.Add(appSnapshot);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加全局统计信息
|
||||||
|
snapshot.GlobalStats = new GlobalNetworkStats
|
||||||
|
{
|
||||||
|
TotalApplications = snapshot.Applications.Count,
|
||||||
|
TotalConnections = _connections.Count,
|
||||||
|
ActiveConnections = _connections.Count(c => c.Value.IsActive),
|
||||||
|
PortTraffic = _portTraffic.Values.ToList(),
|
||||||
|
IpTraffic = _ipTraffic.Values.OrderByDescending(i => i.TotalBytes).Take(100).ToList()
|
||||||
|
};
|
||||||
|
|
||||||
|
return snapshot;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lock.ExitReadLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 获取指定进程的网络信息
|
||||||
|
/// </summary>
|
||||||
|
public ProcessNetworkDetails GetProcessDetails(int processId)
|
||||||
|
{
|
||||||
|
_lock.EnterReadLock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (!_processes.TryGetValue(processId, out var processInfo))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
_applications.TryGetValue(processId, out var appInfo);
|
||||||
|
|
||||||
|
var details = new ProcessNetworkDetails
|
||||||
|
{
|
||||||
|
ProcessId = processId,
|
||||||
|
ProcessName = processInfo.ProcessName,
|
||||||
|
ApplicationInfo = appInfo,
|
||||||
|
Connections = new List<ConnectionInfo>()
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var connKey in processInfo.ActiveConnections)
|
||||||
|
{
|
||||||
|
if (_connections.TryGetValue(connKey, out var conn))
|
||||||
|
{
|
||||||
|
details.Connections.Add(conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return details;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
_lock.ExitReadLock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region 私有辅助方法
|
||||||
|
|
||||||
|
private void UpdatePortTraffic(int port, long bytesSent, long bytesReceived, bool isLocal)
|
||||||
|
{
|
||||||
|
_portTraffic.AddOrUpdate(port,
|
||||||
|
new PortTrafficInfo
|
||||||
|
{
|
||||||
|
Port = port,
|
||||||
|
BytesSent = isLocal ? bytesSent : 0,
|
||||||
|
BytesReceived = isLocal ? 0 : bytesReceived,
|
||||||
|
LastUpdateTime = DateTime.Now
|
||||||
|
},
|
||||||
|
(key, existing) =>
|
||||||
|
{
|
||||||
|
if (isLocal)
|
||||||
|
existing.BytesSent = bytesSent;
|
||||||
|
else
|
||||||
|
existing.BytesReceived = bytesReceived;
|
||||||
|
existing.LastUpdateTime = DateTime.Now;
|
||||||
|
return existing;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateIpTraffic(string ip, long bytesSent, long bytesReceived, bool isSource)
|
||||||
|
{
|
||||||
|
_ipTraffic.AddOrUpdate(ip,
|
||||||
|
new IpTrafficInfo
|
||||||
|
{
|
||||||
|
IpAddress = ip,
|
||||||
|
BytesSent = isSource ? bytesSent : 0,
|
||||||
|
BytesReceived = isSource ? 0 : bytesReceived,
|
||||||
|
LastUpdateTime = DateTime.Now
|
||||||
|
},
|
||||||
|
(key, existing) =>
|
||||||
|
{
|
||||||
|
if (isSource)
|
||||||
|
existing.BytesSent = bytesSent;
|
||||||
|
else
|
||||||
|
existing.BytesReceived = bytesReceived;
|
||||||
|
existing.LastUpdateTime = DateTime.Now;
|
||||||
|
return existing;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetDomainForIp(string ip)
|
||||||
|
{
|
||||||
|
return _dnsCache.TryGetValue(ip, out var dnsInfo) ? dnsInfo.DomainName : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@@ -0,0 +1,224 @@
|
|||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Utils.ETW.Core;
|
||||||
|
|
||||||
|
namespace Utils.ETW.Etw;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 网络监控系统使用示例
|
||||||
|
/// </summary>
|
||||||
|
public class NetworkMonitorUsageExample
|
||||||
|
{
|
||||||
|
private EnhancedEtwNetworkManager _networkManager;
|
||||||
|
private CancellationTokenSource _cancellationTokenSource;
|
||||||
|
|
||||||
|
public void RunExample()
|
||||||
|
{
|
||||||
|
Console.WriteLine("启动网络监控系统...");
|
||||||
|
|
||||||
|
// 初始化网络管理器
|
||||||
|
_networkManager = new EnhancedEtwNetworkManager();
|
||||||
|
_cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 启动监控
|
||||||
|
_networkManager.StartMonitoring();
|
||||||
|
|
||||||
|
// 启动定期读取任务
|
||||||
|
var readTask = Task.Run(() => ReadNetworkDataPeriodically(_cancellationTokenSource.Token));
|
||||||
|
|
||||||
|
// 启动WebSocket推送任务(示例)
|
||||||
|
// var websocketTask = Task.Run(() => SimulateWebSocketPush(_cancellationTokenSource.Token));
|
||||||
|
|
||||||
|
// Console.WriteLine("网络监控已启动,按任意键停止...");
|
||||||
|
// Console.ReadKey();
|
||||||
|
//
|
||||||
|
// // 停止监控
|
||||||
|
// _cancellationTokenSource.Cancel();
|
||||||
|
// await Task.WhenAll(readTask, websocketTask);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// _networkManager?.Dispose();
|
||||||
|
// Console.WriteLine("网络监控已停止!!!!!!!!!!!!!11!!!!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 定期读取网络数据
|
||||||
|
/// </summary>
|
||||||
|
private async Task ReadNetworkDataPeriodically(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
while (!cancellationToken.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 获取网络监控快照
|
||||||
|
var snapshot = GlobalNetworkMonitor.Instance.GetSnapshot();
|
||||||
|
|
||||||
|
var serialize = JsonSerializer.Serialize(snapshot);
|
||||||
|
Console.WriteLine("=================================================");
|
||||||
|
Console.WriteLine(serialize);
|
||||||
|
Console.WriteLine("=================================================");
|
||||||
|
// 输出概要信息
|
||||||
|
Console.WriteLine($"\n========== 网络监控快照 {snapshot.SnapshotTime:yyyy-MM-dd HH:mm:ss} ==========");
|
||||||
|
Console.WriteLine($"活跃应用程序: {snapshot.GlobalStats.TotalApplications}");
|
||||||
|
Console.WriteLine(
|
||||||
|
$"总连接数: {snapshot.GlobalStats.TotalConnections} (活跃: {snapshot.GlobalStats.ActiveConnections})");
|
||||||
|
|
||||||
|
// 输出每个应用的详细信息
|
||||||
|
// foreach (var app in snapshot.Applications.OrderByDescending(a =>
|
||||||
|
// a.TotalSendSpeed + a.TotalReceiveSpeed))
|
||||||
|
// {
|
||||||
|
// Console.WriteLine($"\n应用程序: {app.ApplicationName} (PID: {app.ProcessId})");
|
||||||
|
// Console.WriteLine($" 路径: {app.ApplicationPath}");
|
||||||
|
// Console.WriteLine($" 版本: {app.Version}");
|
||||||
|
// Console.WriteLine($" 连接数: {app.ActiveConnections}/{app.TotalConnections}");
|
||||||
|
// Console.WriteLine(
|
||||||
|
// $" 总流量: 发送 {FormatBytes(app.TotalBytesSent)}, 接收 {FormatBytes(app.TotalBytesReceived)}");
|
||||||
|
// Console.WriteLine(
|
||||||
|
// $" 当前速度: ↑{FormatSpeed(app.TotalSendSpeed)} ↓{FormatSpeed(app.TotalReceiveSpeed)}");
|
||||||
|
//
|
||||||
|
// // 显示前5个活跃连接
|
||||||
|
// var topConnections = app.Connections
|
||||||
|
// .Where(c => c.IsActive)
|
||||||
|
// .OrderByDescending(c => c.CurrentSendSpeed + c.CurrentReceiveSpeed)
|
||||||
|
// .Take(5);
|
||||||
|
//
|
||||||
|
// foreach (var conn in topConnections)
|
||||||
|
// {
|
||||||
|
// Console.WriteLine(
|
||||||
|
// $" → {conn.Protocol} {conn.LocalPort} → {conn.RemoteIp}:{conn.RemotePort} " +
|
||||||
|
// $"({conn.RemoteDomain ?? "未解析"}) " +
|
||||||
|
// $"[{conn.State}] " +
|
||||||
|
// $"↑{FormatSpeed(conn.CurrentSendSpeed)} ↓{FormatSpeed(conn.CurrentReceiveSpeed)}");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 输出端口流量TOP 5
|
||||||
|
// Console.WriteLine("\n端口流量 TOP 5:");
|
||||||
|
// var topPorts = snapshot.GlobalStats.PortTraffic
|
||||||
|
// .OrderByDescending(p => p.TotalBytes)
|
||||||
|
// .Take(5);
|
||||||
|
//
|
||||||
|
// foreach (var port in topPorts)
|
||||||
|
// {
|
||||||
|
// Console.WriteLine($" 端口 {port.Port}: {FormatBytes(port.TotalBytes)} " +
|
||||||
|
// $"(发送: {FormatBytes(port.BytesSent)}, 接收: {FormatBytes(port.BytesReceived)})");
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // 输出IP流量TOP 5
|
||||||
|
// Console.WriteLine("\nIP流量 TOP 5:");
|
||||||
|
// var topIps = snapshot.GlobalStats.IpTraffic.Take(5);
|
||||||
|
//
|
||||||
|
// foreach (var ip in topIps)
|
||||||
|
// {
|
||||||
|
// Console.WriteLine($" {ip.IpAddress}: {FormatBytes(ip.TotalBytes)} " +
|
||||||
|
// $"(发送: {FormatBytes(ip.BytesSent)}, 接收: {FormatBytes(ip.BytesReceived)})");
|
||||||
|
// }
|
||||||
|
|
||||||
|
await Task.Delay(5000, cancellationToken); // 每5秒更新一次
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"读取网络数据时出错: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 模拟WebSocket推送
|
||||||
|
/// </summary>
|
||||||
|
// private async Task SimulateWebSocketPush(CancellationToken cancellationToken)
|
||||||
|
// {
|
||||||
|
// while (!cancellationToken.IsCancellationRequested)
|
||||||
|
// {
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// // 获取数据快照
|
||||||
|
// var snapshot = GlobalNetworkMonitor.Instance.GetSnapshot();
|
||||||
|
//
|
||||||
|
// // 构建要推送的数据(根据前端需求定制)
|
||||||
|
// var pushData = new
|
||||||
|
// {
|
||||||
|
// timestamp = snapshot.SnapshotTime,
|
||||||
|
// applications = snapshot.Applications.Select(app => new
|
||||||
|
// {
|
||||||
|
// processId = app.ProcessId,
|
||||||
|
// appName = app.ApplicationName,
|
||||||
|
// appPath = app.ApplicationPath,
|
||||||
|
// version = app.Version,
|
||||||
|
// connections = app.Connections.Select(conn => new
|
||||||
|
// {
|
||||||
|
// protocol = conn.Protocol,
|
||||||
|
// localPort = conn.LocalPort,
|
||||||
|
// remoteIp = conn.RemoteIp,
|
||||||
|
// remotePort = conn.RemotePort,
|
||||||
|
// remoteDomain = conn.RemoteDomain,
|
||||||
|
// state = conn.State,
|
||||||
|
// bytesSent = conn.BytesSent,
|
||||||
|
// bytesReceived = conn.BytesReceived,
|
||||||
|
// sendSpeed = conn.CurrentSendSpeed,
|
||||||
|
// receiveSpeed = conn.CurrentReceiveSpeed,
|
||||||
|
// duration = conn.Duration.TotalSeconds
|
||||||
|
// }),
|
||||||
|
// stats = new
|
||||||
|
// {
|
||||||
|
// totalConnections = app.TotalConnections,
|
||||||
|
// activeConnections = app.ActiveConnections,
|
||||||
|
// totalBytesSent = app.TotalBytesSent,
|
||||||
|
// totalBytesReceived = app.TotalBytesReceived,
|
||||||
|
// totalSendSpeed = app.TotalSendSpeed,
|
||||||
|
// totalReceiveSpeed = app.TotalReceiveSpeed
|
||||||
|
// }
|
||||||
|
// }),
|
||||||
|
// globalStats = new
|
||||||
|
// {
|
||||||
|
// totalApps = snapshot.GlobalStats.TotalApplications,
|
||||||
|
// totalConnections = snapshot.GlobalStats.TotalConnections,
|
||||||
|
// activeConnections = snapshot.GlobalStats.ActiveConnections
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
//
|
||||||
|
// // 序列化为JSON
|
||||||
|
// var json = JsonSerializer.Serialize(pushData);
|
||||||
|
//
|
||||||
|
// // 这里应该通过WebSocket发送数据
|
||||||
|
// // await websocketClient.SendAsync(json);
|
||||||
|
// Console.WriteLine($"\n[WebSocket模拟] 推送数据大小: {json.Length} 字节");
|
||||||
|
// Console.WriteLine(json);
|
||||||
|
// await Task.Delay(1000, cancellationToken); // 每秒推送一次
|
||||||
|
// }
|
||||||
|
// catch (Exception ex)
|
||||||
|
// {
|
||||||
|
// Console.WriteLine($"WebSocket推送时出错: {ex.Message}");
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 格式化字节数
|
||||||
|
/// </summary>
|
||||||
|
private string FormatBytes(long bytes)
|
||||||
|
{
|
||||||
|
string[] sizes = { "B", "KB", "MB", "GB", "TB" };
|
||||||
|
double len = bytes;
|
||||||
|
int order = 0;
|
||||||
|
while (len >= 1024 && order < sizes.Length - 1)
|
||||||
|
{
|
||||||
|
order++;
|
||||||
|
len = len / 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{len:0.##} {sizes[order]}";
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 格式化速度
|
||||||
|
/// </summary>
|
||||||
|
private string FormatSpeed(double bytesPerSecond)
|
||||||
|
{
|
||||||
|
return FormatBytes((long)bytesPerSecond) + "/s";
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user