So I’ve discovered that WMI is going to be deprecated so I’m trying to convert my old uses of Get-WMIObject to Get-CimInstance. The issue is, for example, if I try this:

$usbDrive = Get-WMIObject win32_diskdrive | Where-Object {$_.interfacetype -eq "USB"} | ForEach-Object {Get-WmiObject -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"} |  ForEach-Object {Get-WmiObject -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} | ForEach-Object {$_.deviceid}

This basically just gets the drive letter of any USB device connected and if I were to swap out every “WmiObject” with “CimInstance”, it will still work. I really am not sure if I should rely on it just working or if there is anything else I need to change. Having flashbacks to when PHP changed mysql to mysqli. Whilst it seemed like just adding an “i” on the end, there were loads more parameters needed for a bunch of things so the whole thing had to be gone over.

If I look at this win32_diskdrive thing with Wmi, I get three objects formatted like this…

Partitions : 1
DeviceID : \.\PHYSICALDRIVE0
Model : SanDisk SDSSDHP128G
Size : 128034708480
Caption : SanDisk SDSSDHP128G

If I do the same with CimInstance, I get this…

\.\PHYSICALDRIVE0 SanDisk SDSSDHP128G 1 128034708480 SanDisk SDSSDHP128G

So, I can see this is the better format for objects but I’m really just asking to check there isn’t anything else I need to do in my example or any others if there are some common ones.

Thanks!

3 Spice ups

If it were me, I’d take this one step at a time.

The WMI cmdlets are not cross-platform however, the CIM cmdlets are and they provide better coverage too. But ultimately, they both return the same data. However, the wrapper objects are different, and the way you invoke method differs too.

That is quite a complex one-liner that you are asking about. If it were me, I’d decompose it and convert it bit by bit. So start with :

$USBDisks = Get-CIMInstance -ClassName Win32_DiskDrive | Where-Object InterfaceType -eq 'USB'

Then go from there.

The WMI coding you are doing seems complex What are you trying to discover?

Also, To figure out what is being returned = pipe the output to Get-Member like this:

$USBDisks | Get-Member
1 Spice up

Like I said, just changing WmiObject to CimInstance actually works but I just wanted to check I wasn’t missing something. And the purpose is to just list USB Drives. So the result of both the Wmi and Cim versions of that one liner end up just putting a list of drive letters with a colon on the end. So it just says

N:

for me.

$USBDisks = Get-CIMInstance -ClassName Win32_DiskDrive | Where-Object InterfaceType -eq 'USB'

Would do much the same thing…

And to get the drive letters…

$USBDisks = Get-CIMInstance -ClassName Win32_DiskDrive | 
  Where-Object InterfaceType -eq 'USB'

Not really, this just finds the disks but I need the result of this to just be the drive letter.

Is there something I can do like this…

$arrDrives = Get-CimInstance Win32_DiskDrive|Where-Object InterfaceType -eq ‘USB’

$driveLetter = $arrDrives[0].DriveLetter

or something?

how about this:

(Get-Disk | where bustype -eq 'usb' | get-partition).driveletter 
1 Spice up

Ah ha! Near perfect for what I currently had. I’ll just do a += “:” on the end of it.

I got the original one when searching forums desperately when I started out but now it all makes much more sense to keep things minimal.

In general, if you can do so - avoid WMI - it’s slow and (IMHO) cumbersome. This is because WMI itself is a huge set of COM objects, and when you use Get-WMIobject or Get-CImInstance. PowerShell has to do some nasty things to cross the interop barrier!

In general, I always recommend using native cmdlets where you can and use WMI where you have to. And in both cases, for production scripting avoid long complex one liners!

Glad you got an answer.

2 Spice ups

Just so I can give you the best answer, could you give me an answer to the original question? I was just wondering if old scripts using WmiObject could simply be changed to CimInstance by a [ctrl + h].

In general, Get-WMIObject can be replaced with Get-CimInstance.

Both commands return the same identical class data, but

  1. Get-WMIObject returns system properties and methods. Get-CimInstance doesn’t. This is more efficient in most cases.

  2. The wrapper classes are different (PowerShell wraps the data returned from WMI via COM in a .NET object which is what you see if you use Get-Member etc. You probably don’t care much about wrapper classes in most cases.

  3. If you want to get an object from WMI and want to invoke a method on it, the mechanism is quite different. With the WMI cmdlets, you get the WMI object, then call the method from the instantiated object. With CIM cmdlets, you use Invoke-CimMethod specifying the WMI object, the method name, and a hash table of parameter values.

tl:dr: for simple things, you can replace "Get-WmiObject’ with ‘Get-Ciminstance’.

1 Spice up