Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell and WMI to find a wireless keyboard or mouse attached to a system.

Microsoft Scripting Guy, Ed Wilson, is here. Yesterday, we had a great time at the Windows PowerShell user group meeting at the Microsoft Office in Munich (actually just outside of Munich). It was great to be back—as it had been five years since I was in the building. The Scripting Wife and I got to see a lot of our old friends.

Today, we are supposed to meet with Windows PowerShell Guru Oliver Lipkau. We'll see him in either Munich or in Regensburg—not sure which town yet. We are in our hotel room right now waiting for his email to detail the plans, and I am sipping an excellent cup of Earl Grey tea—Germany has awesome tea because so much comes through the port of Hamburg. It does not matter where we meet him because both towns are absolutely lovely.

Use WMI to detect wireless keyboard and mouse

One of the things I remember from when I was a consultant is that my customers wanted to be able to know who was using a wireless keyboard or a wireless mouse. This was for inventory purposes, audit purposes, or maybe general information. Anyway, at the time, it was not possible to obtain this information because the two WMI classes (Win32_Keyboard and Win32_PointingDevice) could not detect a wireless device back then. It only reported the “primary devices” physically connected to the computers. Bummer.

At some point, WMI started reporting wireless devices. I do not have the resources to test this out right now, so I cannot report when exactly WMI began reporting wireless keyboards and mice. However, I will use both Windows PowerShell 3.0 and Windows PowerShell 2.0 code so you can test this out for yourself. Remember we are in the middle of a three-week trip, and I did not even pack a “winter coat” let alone three different laptops running various versions of Windows. I do know it works on my Windows 8 laptop.

First, the wireless mouse

Ok, it is a mouse, right? Well, WMI calls it a "point device," and therefore, the WMI class name is Win32_PointingDevice. I can get an inventory of the attached mice by querying the class. This is shown here.

Get-WmiObject win32_PointingDevice

With Windows PowerShell 3.0, use the Get-CimInstance cmdlet, as shown here.

Get-CimInstance Win32_PointingDevice

The output displays a lot of stuff—some of which is not populated. Here is a screen shot of the query and some of the output.

Image of command output

A better output appears when I pipe the results to the HasWMIValue filter from my Scripting Guys WMI module. This filter displays only WMI properties from a class that has values. It makes a much cleaner output. This is shown in the following image.

Image of command output

Ok, I found what I was looking for—a caption that says HID-compliant mouse. I could have found this piece of information in Devices and Printers. In fact, I can even launch it through the Show-ControlPanelItem cmdlet as seen here.

Show-ControlPanelItem devices*

Here is an image of the property page for the mouse.

Image of property page for mouse

From a management perspective, the two most important properties are the description and the PNPDeviceID. I use the Get-WmiObject cmdlet to return both mice; then I use the Where-Object to filter out only the HID type; and, lastly, I send the information to a Format-Table command to produce a nice output, as shown here.

Windows PowerShell 2.0 syntax:

Get-WmiObject win32_PointingDevice | Where-Object { $_.Description -match 'hid'} | Format-Table description, pnpDeviceID -AutoSize -Wrap

Windows PowerShell 3.0 syntax:

Get-CimInstance win32_PointingDevice | Where Description -match 'hid' | Format-Table description, pnpDeviceID -AutoSize –Wrap

Here is the result of both commands.

Image of command output

Next, the wireless keyboard

Just like I can use WMI to find the HID wireless mouse, I can also use it to find the HID wireless keyboard. I use the WMI class Win32_Keyboard. Here is the result of piping the class to the HasWMIValue filter—this is everything WMI will tell me.

Image of command output

Once again, the two properties I am interested in are the PNPDeviceID and the description. Here are the commands used to produce my “report.”

Windows PowerShell 2.0 syntax:

Get-WmiObject win32_Keyboard | Where-Object { $_.Description -match 'hid'} | Format-Table description, pnpDeviceID -AutoSize -Wrap

Windows PowerShell 3.0 syntax:

Get-CimInstance win32_keyboard | Where Description -match 'hid' | Format-Table description, pnpDeviceID -AutoSize –Wrap

The results of running these two commands is shown here.

Image of command output

Dude! They are basically the same—combine ‘em

One of the nice things about WMI is that at times it is very consistent. As it turns out, this is one of those occasions. I am filtering by ‘hid’ and selecting the same two properties: description and pnpDeviceID. This way I can create an array of WMI classes and do both queries at the same time, as shown here, where gwmi is an alias for Get-WmiObject, % is an alias for foreach-object, ? is an alias for the Where-Object, and ft is an alias for Format-Table.

$class = "win32_pointingdevice","win32_keyboard"

$class | % {gwmi $_ | ? description -match 'hid'} | ft description, PNPDeviceID -A -Wr

Here is the output from the command.

Image of command output

Well, that is enough for this morning. We need to go hop a train. Join me tomorrow for some more Windows PowerShell fun.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy