Exploring Plug&Play Devices (Part 2)

by Jan 1, 2020

In the previous tip, we used the UPnP.UPnPDeviceFinder to discover smart devices hooked up to your network. Today, let’s take a closer look at the objects returned.

$UPnPFinder = New-Object -ComObject UPnP.UPnPDeviceFinder
$result = $UPnPFinder.FindByType("upnp:rootdevice", 0)

When you run a search (which can take some time to complete), you get back a lot of information, but some properties return just ‘System.__ComObject’. How can you find out what’s hidden in them?

Let’s pick one of the objects returned. In my case, by looking at $result, I noticed an object from “NetGear” which caught my attention. Below, I am using Where-Object to access it.

The objects available in your case obviously vary, depending on the devices you use in your network, so you will have to adjust the filter expression to match one of your returned objects.

 
PS> $switch = $result | Where-Object ManufacturerName -like *NetGear*

PS> $switch


IsRootDevice     : True
RootDevice       : System.__ComObject
ParentDevice     : 
HasChildren      : True
Children         : System.__ComObject
UniqueDeviceName : uuid:4d696e69-444c-164e-9d42-3894ed0e1db5
FriendlyName     : RBR50 (Gateway)
Type             : urn:schemas-upnp-org:device:InternetGatewayDevice:1
PresentationURL  : http://www.orbilogin.net/
ManufacturerName : NETGEAR, Inc.
ManufacturerURL  : http://www.netgear.com/
ModelName        : NETGEAR Orbi Desktop AC3000 Router
ModelNumber      : RBR50
Description      : http://www.netgear.com/home/products/wirelessrouters
ModelURL         : http://www.netgear.com/orbi
UPC              : RBR50
SerialNumber     : 5R21945T06DA4
Services         : System.__ComObject
 

Most properties use regular data types like string or integer. For example, “UniqueDeviceName” returns the unique name of a device (which becomes important in a moment). Some properties, however, simply return “System.__ComObject”. Let’s take a look at these:

Each PnP device can be part of a chain which always starts at a root device. Since we searched for root devices in the first place, the property “RootDevice” is always identical to the returned object:

 
PS> $switch -eq $switch.RootDevice
True 
 

To find out which devices are chained to a root device, look at “HasChildren” and “Children”: “HasChildren” is a simple Boolean value. “Children” however is a “System.__ComObject” and contains the info we are after:

 
PS> if ($switch.HasChildren) { $switch.Children.Count } else { 'no children' }
1 
 

Obviously, “Children” seems to be some sort of array. After all, a root device can have many children. By accessing the property, PowerShell automatically turns the “System.__ComObjects” into readable .NET objects, so here are the children of my NetGear device:

 
PS> $switch.Children


IsRootDevice     : False
RootDevice       : System.__ComObject
ParentDevice     : System.__ComObject
HasChildren      : True
Children         : System.__ComObject
UniqueDeviceName : uuid:4d696e69-444c-164e-9d43-3894ed0e1db5
FriendlyName     : WAN Device
Type             : urn:schemas-upnp-org:device:WANDevice:1
PresentationURL  : 
ManufacturerName : NETGEAR
ManufacturerURL  : http://www.netgear.com/
ModelName        : NETGEAR Orbi Desktop AC3000 Router
ModelNumber      : RBR50
Description      : WAN Device on NETGEAR RBR50 Orbi Router
ModelURL         : http://www.netgear.com/
UPC              : RBR50
SerialNumber     : 5R21945T06DA4
Services         : System.__ComObject  
 

This child in turn has children again. However, digging any deeper and listing the children of a child seems to fail:

 
PS> # works:
PS> $switch.Children | Select-Object HasChildren, Children

HasChildren Children          
----------- --------          
       True System.__ComObject



PS> # fails:
PS> $switch.Children.HasChildren
PS> $switch.Children.Children
PS> $switch.Children[0].HasChildren
Value does not fall within the expected range.
PS> $switch.Children[0].Children
Value does not fall within the expected range.
 

The reason for this is an oddity with COM arrays. They use an unusual enumerator that differs from regular object arrays, so PowerShell cannot directly access the array elements. An easy workaround is to use Foreach-Object:

 
PS> $child = $switch.Children

PS> $child | ForEach-Object { $_.Children }


IsRootDevice     : False
RootDevice       : System.__ComObject
ParentDevice     : System.__ComObject
HasChildren      : False
Children         : System.__ComObject
UniqueDeviceName : uuid:4d696e69-444c-164e-9d44-3894ed0e1db5
FriendlyName     : WAN Connection Device
Type             : urn:schemas-upnp-org:device:WANConnectionDevice:1
PresentationURL  : 
ManufacturerName : NETGEAR
ManufacturerURL  : http://www.netgear.com/
ModelName        : NETGEAR Orbi Desktop AC3000 Router
ModelNumber      : RBR50
Description      : WANConnectionDevice on NETGEAR RBR50 Orbi Router
ModelURL         : http://www.netgear.com/
UPC              : 606449084528
SerialNumber     : 5R21945T06DA4
Services         : System.__ComObject 
 

The same applies to “ParentDevice” and “Services”. Let’s find out more about the services of my NetGear device. This time, I want to access my NetGear device directly (which is much faster than enumerating all devices). You do need to know its unique device name, though. In my case, the property “UniqueDeviceName” exposed “uuid:4d696e69-444c-164e-9d42-3894ed0e1db5”:

$UPnPFinder = New-Object -ComObject UPnP.UPnPDeviceFinder
# the UDN is unique, so you need to find out the UDN for your device first
# you cannot use the UDN I used
$myNetgearSwitch = $UPnPFinder.FindByUDN('uuid:4d696e69-444c-164e-9d42-3894ed0e1db5')
$myNetgearSwitch

This time, my device was identified almost momentarily. To list its services, I simply dump its property “Services”, and Powershell automatically turns the COM object into visible properties:

 
PS> $myNetgearSwitch.Services

ServiceTypeIdentifier                           Id                                   LastTransportStatus
---------------------                           --                                   -------------------
urn:schemas-upnp-org:service:Layer3Forwarding:1 urn:upnp-org:serviceId:L3Forwarding1                   0  
 

Twitter This Tip! ReTweet this Tip!