MatthewKing / DeviceId

A simple library providing functionality to generate a 'device ID' that can be used to uniquely identify a computer.
MIT License
729 stars 118 forks source link

DeviceIdBuilder hangs due to Windows AddSystemSerialDriveNumber() call when using DeviceId.Windows.Mmi #37

Closed AdamCaviness closed 2 years ago

AdamCaviness commented 2 years ago

I updated my nuget package reference(s)to 6.0.0 today and used your new syntax for various platforms. I experienced consistent hanging when adding in the drive serial number AddSystemSerialDriveNumber() for Windows:

var deviceId = new DeviceIdBuilder()
        .AddMachineName()
        .OnWindows(windows => windows
            .AddProcessorId()
            .AddMotherboardSerialNumber()
            .AddSystemSerialDriveNumber())
        .ToString();

Package references:

<PackageReference Include="DeviceId.Mac" Version="6.0.0" />
<PackageReference Include="DeviceId.Windows" Version="6.0.0" />
<PackageReference Include="DeviceId.Windows.Mmi" Version="6.0.0" />

The hang goes away when I use the WMI package instead <PackageReference Include="DeviceId.Windows.Wmi" Version="6.0.0" />. Alternatively, I can keep the MMI package and remove the call to AddSystemSerialDriveNumber().

Might I also ask why the language changed for the the method AddSystemSerialDriveNumber()? It used to be AddSystemDriveSerialNumber() like the other platforms. Lastly, thank you for the excellent work that went into this library.

MatthewKing commented 2 years ago

I can't reproduce this one on my end. Very odd. Can you manually add a copy of this component to your project, use it, and use the debugger to see where it hangs?

As for the naming of the AddSystemDriveSerialNumber extension method - That was a mistake/typo. Will fix it in the next major release. Thanks!

AdamCaviness commented 2 years ago

Interesting, I’ll gladly do that and get back with you. Thanks!

AdamCaviness commented 2 years ago

The "hang" is in reality not a hang. I was cancelling too early. On average it takes a bit over 18 seconds to query via MMI and a bit less than 200ms to query via WMI.

The slowdown in the component is on line 26 when calling session.QueryInstance().

The Microsoft docs on QueryInstance notes that MMI should be quicker than WMI.

System.Management contains the original classes used to access WMI; however, they are considered slower and generally do not scale as well as their Microsoft.Management.Infrastructure counterparts.

Testing out both approaches (sample), I get the following:

Getting disk device id... WMI disk device id: 0025_385A_81B1_1FA6., took 190ms. MMI disk device id: 0025_385A_81B1_1FA6., took 18353ms.

The interesting thing is, this has been mentioned by someone else in regards to using "ASSOCIATORS OF" in a MMI query but isolated to when executing as a local administrator. I tested again without executing administratively:

Getting disk device id... WMI disk device id: 0025_385A_81B1_1FA6., took 187ms. MMI disk device id: 0025_385A_81B1_1FA6., took 229ms.

I'll take a look to see if there are alternative WQL "ASSOCIATORS OF" queries that we could provide that could allow for faster execution when running administratively. Thanks.

AdamCaviness commented 2 years ago

I found that adding WQL criteria to limit the ResultClass to disk partitions seems corrects the perf issue.

$"ASSOCIATORS OF {{Win32_LogicalDisk.DeviceID=\"{systemLogicalDiskDeviceId}\"}} WHERE ResultClass = Win32_DiskPartition"

Getting disk device id... WMI disk device id: 0025_385A_81B1_1FA6., took 187ms. MMI disk device id: 0025_385A_81B1_1FA6., took 141ms.