查询硬件信息时替代WMI?

时间:2015-07-17 20:06:49

标签: c# performance wmi

我一直在使用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 ++库来加速这个......

编辑1

有人建议,在创建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并且尝试将其变为字符串正在破坏事情......更多信息我确定......

编辑2

好的,因为我没有实例化枚举器。功能的第三个化身:

MOC.GetEnumerator( )

我认为这是合理的,因为函数GetEnumerator()可能返回实例而不是引用...

0 个答案:

没有答案