我一直在使用WMI来构建系统指纹,但它......工作......但只有只是。它需要永远,而最糟糕的部分是它在应用程序启动时,所以在其他任何事情发生之前几分钟就会过去。
以下是我构建系统指纹的方法:
private static async Task<string> GetHash( string s ) {
byte[ ] b = await Task.Run( ( ) => IdLib.AscEnc.GetBytes( s ) );
return await IdLib.GetHexString( IdLib.CSP.ComputeHash( b ) );
}
private static async Task<string> GetHexString( byte[ ] b ) {
string s = string.Empty;
await Task.Run( ( ) => {
b.ToList( ).ForEach( by => {
int[ ] n = new int[ ] { 0, 0, 0 };
n[0] = ( int )by;
n[1] = n[0] & 15;
n[2] = ( n[0] >> 4 ) & 15;
s += n[1] > 9
? ( ( char )( n[1] - 10 + ( int )'A' ) ).ToString( )
: n[1].ToString( );
s += n[2] > 9
? ( ( char )( n[2] - 10 + ( int )'A' ) ).ToString( )
: n[2].ToString( );
if ( ( s.Length - s.Count( c => c == '-' ) ) % 4 == 0 )
s += '-';
} );
} );
return s.TrimEnd( '-' );
}
private static async Task<string> ID( string wmiClass, string wmiProperty, string wmiMustBeTrue ) {
string result = string.Empty;
List<ManagementObject> MOC = new ManagementClass( wmiClass ).GetInstances( ).Cast<ManagementObject>( ).ToList( );
foreach ( ManagementObject MO in MOC ) {
if ( wmiMustBeTrue.Equals( string.Empty ) || MO[wmiMustBeTrue].ToString( ).Equals( "True" ) )
if ( result.Equals( string.Empty ) )
try {
result = await Task.Run( ( ) => MO[wmiProperty].ToString( ) );
break;
} catch { }
}
return result;
}
private static async Task<string> ID( string wmiClass, string wmiProperty ) {
return await IdLib.ID( wmiClass, wmiProperty, string.Empty );
}
private static async Task<string> GetCPUID( ) {
string r = await IdLib.ID( "Win32_Processor", "UniqueId" );
if ( r.Equals( string.Empty ) )
r = await IdLib.ID( "Win32_Processor", "ProcessorId" );
if ( r.Equals( string.Empty ) )
r = await IdLib.ID( "Win32_Processor", "Name" );
if ( r.Equals( string.Empty ) )
r = await IdLib.ID( "Win32_Processor", "Manufacturer" );
r += IdLib.ID( "Win32_Processor", "MaxClockSpeed" );
return await IdLib.GetHash( r );
}
private static async Task<string> GetBiosID( ) {
return await IdLib.GetHash(
await IdLib.ID( "Win32_BIOS", "Manufacturer" ) +
await IdLib.ID( "Win32_BIOS", "SMBIOSBIOSVersion" ) +
await IdLib.ID( "Win32_BIOS", "IdentificationCode" ) +
await IdLib.ID( "Win32_BIOS", "SerialNumber" ) +
await IdLib.ID( "Win32_BIOS", "ReleaseDate" ) +
await IdLib.ID( "Win32_BIOS", "Version" )
);
}
private static async Task<string> GetHDDID( ) {
return await IdLib.GetHash(
await IdLib.ID( "Win32_DiskDrive", "Model" ) +
await IdLib.ID( "Win32_DiskDrive", "Manufacturer" ) +
await IdLib.ID( "Win32_DiskDrive", "Signature" ) +
await IdLib.ID( "Win32_DiskDrive", "TotalHeads" ) );
}
private static async Task<string> GetMOBOID( ) {
return await IdLib.GetHash(
await IdLib.ID( "Win32_BaseBoard", "Model" ) +
await IdLib.ID( "Win32_BaseBoard", "Manufacturer" ) +
await IdLib.ID( "Win32_BaseBoard", "Name" ) +
await IdLib.ID( "Win32_BaseBoard", "SerialNumber" ) );
}
private static async Task<string> GetVGAID( ) {
return await IdLib.GetHash(
await IdLib.ID( "Win32_VideoController", "DriverVersion" ) +
await IdLib.ID( "Win32_VideoController", "Name" ) );
}
private static async Task<string> GetMACID( ) {
return await IdLib.GetHash( await IdLib.ID( "Win32_NetworkAdapterConfiguration", "MacAddress", "IPEnabled" ) );
}
承认这里可能存在很多错误,我首先关注的是ID(string, string, string)
方法正在执行 ,而且#&# 39;这是不可接受的。是否存在使用WMI获取此类低级别信息的替代方法?如果有必要,我愿意建立一个C / C ++库来加速这个......
有人建议,在创建ManagementClass
对象时会消耗大部分时间。而不是我选择了WqlObjectQuery
:
private static async Task<string> ID( string wmiClass, string wmiProperty, string wmiMustBeTrue ) {
Task<string> T = Task.Run( ( ) => {
Stopwatch SW = new Stopwatch( );
WqlObjectQuery Q = new WqlObjectQuery(
"SELECT " +
wmiProperty +
" FROM "
+ wmiClass +
( string.IsNullOrEmpty( wmiMustBeTrue ) ? "" : "WHERE " + wmiMustBeTrue + " = True" ) );
ManagementObjectSearcher MOS = new ManagementObjectSearcher( Q );
SW.Start( );
ManagementObjectCollection MOC = MOS.Get( );
while ( MOC.GetEnumerator( ).MoveNext( ) )
if ( !string.IsNullOrEmpty( MOC.GetEnumerator( ).Current[wmiProperty].ToString( ) ) ) {
SW.Stop( );
Console.WriteLine( "Querying " + wmiProperty + " of " + wmiClass + " took " + SW.Elapsed.ToString( ) );
return MOC.GetEnumerator( ).Current[wmiProperty].ToString( );
}
return null;
});
await T;
if ( T.Exception == null )
return T.Result;
else {
Console.WriteLine( "Exception in ID Method Function : wmiClass : " + wmiClass + "; wmiPriperty : " + wmiProperty + ";" );
Exception E = T.Exception;
while ( E != null ) {
Console.WriteLine( E.Message );
Console.WriteLine( E.StackTrace );
E = E.InnerException;
}
return null;
}
}
我一直注意到,在观看调试输出时,仍然会抛出这些第一次机会异常,告诉我有一个NullReferenceException ...某处...它非常令人恼火。我启用了对每种异常类型的分解,并且它使我得出的结论是,当我尝试执行以下操作时,它会被抛出:
return new ManagementObjectSearcher(/*Direct String Query*/).Get( ).Cast<ManagementObject>( ).First( )[wmiProperty].ToString( );
这让我觉得我可能做得太多了,所以我把它改为现在的功能,现在又抛出另一个异常(我认为是第一次机会),告诉我MOC.GetEnumerator( ).Current[wmiProperty].ToString( )
是抛出异常是因为某些东西处于无效状态。我认为这是因为我需要让枚举器进入它自己的变量......但这也没有意义,因为它是通过引用传递的,所以变量为{{1应该完全相同(虽然为了简洁不太理想)而不仅仅是调用ManagementObjectEnumerator Foo = MOC.GetEnumerator
...也可能是我正在查询的属性中的对象为null并且尝试将其变为字符串正在破坏事情......更多信息我确定......
好的,因为我没有实例化枚举器。功能的第三个化身:
MOC.GetEnumerator( )
我认为这是合理的,因为函数GetEnumerator()可能返回实例而不是引用...