当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 将系统路径添加到 CIMInstance 对象

作者:精品下载站 日期:2024-12-14 07:39:09 浏览:13 分类:玩电脑

将系统路径添加到 CIMInstance 对象


有一天晚上,当我在密西西比州 PowerShell 用户组演讲时,其中一位成员展示了一些使用 CIM cmdlet 的 PowerShell 3.0 代码。问题在于 CIM cmdlet 如何处理 WMI 系统属性(例如 __SERVER 和 __RELPATH)。默认情况下,不会显示这些属性,但它们会在 CimSystemProperties 属性中捕获。

[玩转系统] 将系统路径添加到 CIMInstance 对象

问题是使用 Get-CIMInstance 时未捕获 __PATH 属性,如屏幕截图中所示。这显然是一个已知问题。使用 Get-WMIObject 仍然有效。

PS C:\> get-wmiobject win32_service -filter "name='bits'" | Select -expand __PATH
\SERENITY\root\cimv2:Win32_Service.Name="BITS"

大多数时候这可能没什么大不了的。但也许在某些情况下您需要 __PATH 属性。那天晚上我看到了一些构建 __PATH 属性的代码。我很感兴趣并决定自己解决这个问题。该路径需要计算机名称、命名空间类路径、类名称、类键和该键的值。我已经从

PS C:\> $c.CimSystemProperties.ServerName
SERENITY
PS C:\> $c.CimSystemProperties.Namespace.Replace("/","\")
root\cimv2
PS C:\> $c.CimSystemProperties.ClassName
Win32_Service

我改变了命名空间中斜杠的方向。我唯一缺少的部分是关键属性。但我可以通过查看类属性的限定符来找到它。将限定符视为表示特殊用途的标签。 CIMInstance 真正酷的地方在于它包含了类信息。这意味着我可以从对象本身查看类。

PS C:\> $c.cimclass.CimClassProperties | select name,qualifiers

[玩转系统] 将系统路径添加到 CIMInstance 对象

我需要做的就是找到带有 KEY 限定符的属性。

PS C:\> $c.cimclass.CimClassProperties | where {$_.qualifiers.name -contains 'key'}

Name               : Name
Value              :
CimType            : String
Flags              : Property, Key, ReadOnly, NullValue
Qualifiers         : {read, key}
ReferenceClassName :

现在我知道 Name 属性是关键,我可以完成路径的构建。

PS C:\> $Key = $c[0].CimClass.CimClassProperties |
>> where {$_.qualifiers.name -contains "key"} |
>> select -ExpandProperty Name
>>
PS C:\> $c | Select @{Name="__PATH";Expression={
>>   '\{0}\{1}:{2}{3}' -f $_.CimSystemProperties.ServerName,
>>   $_.CimSystemProperties.Namespace.Replace("/","\"),
>>   $_.CimSystemProperties.ClassName,
>>   ".$($key)=""$($_.$key)"""
>>   }}
>>

__PATH
------
\SERENITY\root\cimv2:Win32_Service.Name="BITS"

这就是我使用 Get-WMIObject 获得的确切路径。

PS C:\> Get-WmiObject win32_service -filter "name='bits'" | select __Path

__PATH
------
\SERENITY\root\cimv2:Win32_Service.Name="BITS"

当然,我不想做所有这些输入工作,所以我创建了一个函数来为我完成这些工作。

#requires -version 3.0

Function Add-CIMPath {
<#
.Synopsis
Add the __PATH property to a CIMInstance object
.Description
The Get-CIMInstance cmdlet by default doesn't display the WMI system properties
like __SERVER. The properties are available in the CimSystemProperties property
except for __PATH. This function will construct the __PATH property and add it
to a CIMInstance object.
.Example
PS C:\> get-ciminstance win32_memorydevice | add-cimpath | select __Path

__PATH
------
\SERVER01\root\cimv2:Win32_MemoryDevice.DeviceID="Memory Device 0"
\SERVER01\root\cimv2:Win32_MemoryDevice.DeviceID="Memory Device 1"
.Example
PS C:\> get-ciminstance win32_bios -computer netbk8 | add-cimpath | format-list __Path,PSComputername

__PATH         : \NETBK8\root\cimv2:Win32_BIOS.Name="Rev 1.0
                 ",SoftwareElementID="Rev 1.0
                 ",SoftwareElementState="3",TargetOperatingSystem="0",Version="LENOVO - 6040000"
PSComputerName : netbk8
.Inputs
CIMInstance
.Outputs
CIMInstance
.Link
Get-CIMInstance
#>

[cmdletbinding()]
Param (
[Parameter(Position=0,ValueFromPipeline=$True)]
[ValidateNotNullorEmpty()]
[ciminstance]$Inputobject
)

Begin {
    Write-Verbose -Message "Starting $($MyInvocation.Mycommand)"  
} #begin

Process {
#get the key class property
Write-Verbose "Processing $($Inputobject.CimClass.CimClassName)"

$Key = $Inputobject.CimClass.CimClassProperties | 
where {$_.qualifiers.name -contains "key"} | 
select -ExpandProperty Name

Write-Verbose "Creating __PATH Using key property $key"

$Inputobject | Add-Member -PassThru -MemberType NoteProperty -Name __PATH -Value ( 
 '\{0}\{1}:{2}{3}' -f $_.CimSystemProperties.ServerName.ToUpper(),
  $_.CimSystemProperties.Namespace.Replace("/","\"),
  $_.CimSystemProperties.ClassName,
  $(
   if ($key -is [array]) {
     #create a string with the array of key names and values
     [string]$s = ".$($key[0])=""$($_.($key[0]))"""
     #add each additional key separated by comma
     for ($i=1;$i -lt $key.count;$i++) {
       $s+= ",$($key[$i])=""$($_.($key[$i]))"""
     }
     $s
   }
   elseif ($Key) {
    #just a single key
    ".$($key)=""$($_.$key)"""
   }
   else {
    #no key
    '=@'
   })
 ) #value
} #process

End {
    Write-Verbose -Message "Ending $($MyInvocation.Mycommand)"
} #end

} #end Add-CIMPath

该函数的主要部分本质上就是我刚才演示的内容。但是,在某些特殊情况下,没有键属性或有多个键,因此我必须添加一些逻辑来考虑到这一点。我编写该函数时假设您要将 CIMInstance 对象通过管道传递给它,并且您想要添加 __PATH。

PS C:\> get-ciminstance win32_logicaldisk | Add-CIMPath | select __Path

__PATH
------
\SERENITY\root\cimv2:Win32_LogicalDisk.DeviceID="C:"
\SERENITY\root\cimv2:Win32_LogicalDisk.DeviceID="D:"
\SERENITY\root\cimv2:Win32_LogicalDisk.DeviceID="E:"
\SERENITY\root\cimv2:Win32_LogicalDisk.DeviceID="F:"
\SERENITY\root\cimv2:Win32_LogicalDisk.DeviceID="G:"
\SERENITY\root\cimv2:Win32_LogicalDisk.DeviceID="Z:"

这是特殊情况的样子。

[玩转系统] 将系统路径添加到 CIMInstance 对象

我将是第一个承认这有点暴力破解的人,我不能保证我已经涵盖了每一个奇怪的用例。因此,如果您尝试此操作并遇到一个未提供正确 __PATH 的类,我希望您能让我知道。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯