在前一个技能中,我们使用 UPnP.UPnPDeviceFinder
来发现连入您网络的智能设备。今天,让我们仔细看看返回的对象。
1 2 $UPnPFinder = New-Object -ComObject UPnP.UPnPDeviceFinder$result = $UPnPFinder .FindByType("upnp:rootdevice" , 0 )
当您运行一个搜索(可能需要执行一定的时间),将会获取到许多信息,但是某些属性只是以 System.__ComObject
的形式返回。如何查看它们背后隐藏的信息?
让我们取其中的一个返回对象。在我的例子中,通过查看 $result
,我注意到一个来自 “NetGear” 对象。接下来,我使用 Where-Object
来存取它。
在您的场景中,可用的对象明显不同,这取决于您网络中使用的设备,所以您需要调整过滤器表达式来匹配返回的对象之一。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 PS > $switch = $result | Where-Object ManufacturerName -like *NetGear*PS > $switch IsRootDevice : True RootDevice : System.__ComObject ParentDevice : HasChildren : True Children : System.__ComObject UniqueDeviceName : uuid:4 d696e69-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 : 5 R21945T06DA4 Services : System.__ComObject
大多数属性使用普通的数据类型,例如 string 或者 integer。例如,”UniqueDeviceName” 返回一个设备的唯一名称(稍后会变得很重要)。然而某些属性,只是返回 “System.__ComObject”。让我们看看这些:
每个 PnP 设备可以是一个链条的一部分,并且由一个根设备开始。由于我们一开始搜索的是根设备,所以 “RootDevice” 属性总是对应返回的对象:
1 2 PS > $switch -eq $switch .RootDeviceTrue
要找出那些设备链接到根设备,请查看 “HasChildren” 和 “Children”:”HasChildren” 是一个简单的 Boolean 值。然而 “Children” 是一个 “System.__ComObject” 对象并且包含了我们想了解的信息:
1 2 PS > if ($switch .HasChildren) { $switch .Children.Count } else { 'no children' }1
显然地,”Children” 看起来是某种数组。总之,一个根设备可以有许多子设备。通过存取该属性,PowerShell 自动将 “System.__ComObject” 转换为可读取的 .NET 对象,以下是我的 NetGear 设备的子设备:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 PS > $switch .ChildrenIsRootDevice : False RootDevice : System.__ComObject ParentDevice : System.__ComObject HasChildren : True Children : System.__ComObject UniqueDeviceName : uuid:4 d696e69-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 : 5 R21945T06DA4 Services : System.__ComObject
这个子设备之下还有子设备。但是,继续深挖并列出子设备之下的子设备看起来失败了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 PS > PS > $switch .Children | Select-Object HasChildren, ChildrenHasChildren Children ----------- -------- True System.__ComObject PS > PS > $switch .Children.HasChildrenPS > $switch .Children.ChildrenPS > $switch .Children[0 ].HasChildrenValue does not fall within the expected range. PS > $switch .Children[0 ].ChildrenValue does not fall within the expected range.
失败的原因是 COM 数组的一个特异性。它们使用一个非常规的枚举器,和普通的对象数组不同,所以 PowerShell 无法直接存取数组元素。一个简单的解决方案是使用 ForEach-Object
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 PS > $child = $switch .ChildrenPS > $child | ForEach-Object { $_ .Children }IsRootDevice : False RootDevice : System.__ComObject ParentDevice : System.__ComObject HasChildren : False Children : System.__ComObject UniqueDeviceName : uuid:4 d696e69-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 : 5 R21945T06DA4 Services : System.__ComObject
同样地,也适用于 “ParentDevice” 和 `Services”。我们来查看我的 NetGear 设备的更多服务。这次,我希望直接存取我的 NetGear 设备(这样比枚举所有设备快得多)。不过您需要知道它的唯一设备名。在我的例子中,”UniqueDeviceName” 的值是 “uuid:4d696e69-444c-164e-9d42-3894ed0e1db5”:
1 2 3 4 5 $UPnPFinder = New-Object -ComObject UPnP.UPnPDeviceFinder$myNetgearSwitch = $UPnPFinder .FindByUDN('uuid:4d696e69-444c-164e-9d42-3894ed0e1db5' )$myNetgearSwitch
这次,几乎立即识别出我的设备。要列出它的服务,我只需要获取它的 “Services” 属性,并且 PowerShell 自动将该 COM 对象转为可见的属性:
1 2 3 4 5 PS > $myNetgearSwitch .ServicesServiceTypeIdentifier Id LastTransportStatus --------------------- -- ------------------- urn:schemas-upnp-org :service:Layer3Forwarding:1 urn:upnp-org :serviceId:L3Forwarding1 0