Powershell 使用Get WmiObject | Where Object将多个对象添加到数组中

Powershell 使用Get WmiObject | Where Object将多个对象添加到数组中,powershell,sccm,Powershell,Sccm,我有下面的工作代码,它在SCCM中用作检测子句,用于检测服务器功能是否作为服务器功能脚本安装程序的一部分安装 $role = Get-WmiObject -Class Win32_ServerFeature | Where-Object {$_.ID -eq 2} if ($role) { Write-Host "Installed" } else { } 问题是,上面只提供了服务器特性中的一个特性,我如何使用数组来添加类中每个相关的服务器特性,从而使detection子句100%准确

我有下面的工作代码,它在SCCM中用作检测子句,用于检测服务器功能是否作为服务器功能脚本安装程序的一部分安装

$role = Get-WmiObject -Class Win32_ServerFeature | Where-Object {$_.ID -eq 2}
if ($role) {
    Write-Host "Installed"
}
else {
}
问题是,上面只提供了服务器特性中的一个特性,我如何使用数组来添加类中每个相关的服务器特性,从而使detection子句100%准确

在这种情况下,相关角色包括:

Web-Server Web-ISAPI-Ext Web-Windows-Auth Web-Metabase Web-WMI RDC
在已安装它们的计算机上,我可以提取此信息以添加到:

Get-WmiObject -Class win32_serverfeature | select Name, ID

Name                                ID
----                                --
Web Server (IIS)                     2
File Services                        6
Windows Deployment Services         19
.NET Framework 3.0 Features         36
Windows Process Activation Service  41
Telnet Client                       44
SNMP Services                       59
Remote Server Administration Tools  67
Web Server                         140
Common HTTP Features               141
Static Content                     142
Default Document                   143
Directory Browsing                 144
HTTP Errors                        145
Application Development            147
ISAPI Extensions                   152
Health and Diagnostics             155
HTTP Logging                       156
Request Monitor                    158
Security                           162
Windows Authentication             164
Request Filtering                  169
Performance                        171
Static Content Compression         172
Management Tools                   174
IIS Management Console             175
IIS 6 Management Compatibility     178
IIS 6 Metabase Compatibility       179
Configuration APIs                 217
.NET Environment                   218
Process Model                      219
.NET Framework 3.0                 220
SNMP Service                       224
SNMP WMI Provider                  225
Deployment Server                  251
Transport Server                   252
File Server                        255
Role Administration Tools          256
Windows Deployment Services Tools  264
Web Server (IIS) Tools             281
注意:这是为运行2008 SP2的旧版服务器设计的,因此,这意味着我可以使用旧的工具集(ServerFeaturecmd.exe-无法使用Install WindowsFeature和Get Windowfeature)


谢谢

我就是这么想的,但是,把对象放入数组而不是单个变量?这似乎不是最简单的方法

$roleID2 = Get-WmiObject -Class Win32_ServerFeature | Where-Object {$_.ID -eq 2}
$roleID140 = Get-WmiObject -Class Win32_ServerFeature | Where-Object {$_.ID -eq 140}
$roleID141 = Get-WmiObject -Class Win32_ServerFeature | Where-Object {$_.ID -eq 141}
$roleID162 = Get-WmiObject -Class Win32_ServerFeature | Where-Object {$_.ID -eq 162}
$roleID164 = Get-WmiObject -Class Win32_ServerFeature | Where-Object {$_.ID -eq 164}
$roleID179 = Get-WmiObject -Class Win32_ServerFeature | Where-Object {$_.ID -eq 179}

If ($roleID2 -and $roleID140 -and $roleID141 -and $roleID162 -and $roleID164 $roleID179) {
    Write-Host "Installed"
}
else {
}
我怀疑我完全误解了你的问题,但这是我的答案

你为什么要反复打电话来创造你已经拥有的东西?[皱眉]您拥有来自该WMI调用的整个属性集的集合。如果只需要其中的一个子集,请创建一个包含所需属性的
[PSCustomObject]

不要重复调用同一个愚蠢的WMI类![咧嘴笑]

在我的win7ps5.1机器上没有像Win32\u ServerFeature这样的类,所以下面的演示是针对其他类的

[注意1]您可以调用多个类,将它们保存到唯一的$Vars,然后使用它们构建整个属性包的子集

[注意2]您可以使用
Invoke Command
在脚本块中调用所有这些命令,以便在远程系统上并行运行它们

#requires -RunAsAdministrator

# fake reading in a list of computer names
#    in real life, use Get-Content or (Get-ADComputer).Name
$ComputerList = @'
Localhost
BetterNotBeThere
127.0.0.1
10.0.0.1
::1
'@.Split("`n").Trim("`r")

$IC_ScriptBlock = {
    $CIM_ComputerSystem = Get-CimInstance -ClassName CIM_ComputerSystem
    $CIM_BIOSElement = Get-CimInstance -ClassName CIM_BIOSElement
    $CIM_OperatingSystem = Get-CimInstance -ClassName CIM_OperatingSystem
    $CIM_Processor = Get-CimInstance -ClassName CIM_Processor
    $CIM_LogicalDisk = Get-CimInstance -ClassName CIM_LogicalDisk |
        Where-Object {$_.Name -eq $CIM_OperatingSystem.SystemDrive}

    [PSCustomObject]@{
        LocalComputerName = $env:COMPUTERNAME
        Manufacturer = $CIM_ComputerSystem.Manufacturer
        Model = $CIM_ComputerSystem.Model
        SerialNumber = $CIM_BIOSElement.SerialNumber
        CPU = $CIM_Processor.Name
        SysDrive_Capacity_GB = '{0:N2}' -f ($CIM_LogicalDisk.Size / 1GB)
        SysDrive_FreeSpace_GB ='{0:N2}' -f ($CIM_LogicalDisk.FreeSpace / 1GB)
        SysDrive_FreeSpace_Pct = '{0:N0}' -f ($CIM_LogicalDisk.FreeSpace / $CIM_LogicalDisk.Size * 100)
        RAM_GB = '{0:N2}' -f ($CIM_ComputerSystem.TotalPhysicalMemory / 1GB)
        OperatingSystem_Name = $CIM_OperatingSystem.Caption
        OperatingSystem_Version = $CIM_OperatingSystem.Version
        OperatingSystem_BuildNumber = $CIM_OperatingSystem.BuildNumber
        OperatingSystem_ServicePack = $CIM_OperatingSystem.ServicePackMajorVersion
        CurrentUser = $CIM_ComputerSystem.UserName
        LastBootUpTime = $CIM_OperatingSystem.LastBootUpTime
        }
    }

$IC_Params = @{
    ComputerName = $ComputerList
    ScriptBlock = $IC_ScriptBlock
    ErrorAction = 'SilentlyContinue'
    }
$RespondingSystems = Invoke-Command @IC_Params
$NOT_RespondingSystems = $ComputerList.Where({
    # these two variants are needed to deal with an ipv6 localhost address
    "[$_]" -notin $RespondingSystems.PSComputerName -and
    $_ -notin $RespondingSystems.PSComputerName
    })

$RespondingSystems
$NOT_RespondingSystems
来自响应系统的截断输出

LocalComputerName           : [MySystemName]
Manufacturer                : System manufacturer
Model                       : System Product Name
SerialNumber                : System Serial Number
CPU                         : AMD Phenom(tm) II X4 945 Processor
SysDrive_Capacity_GB        : 931.41
SysDrive_FreeSpace_GB       : 750.18
SysDrive_FreeSpace_Pct      : 81
RAM_GB                      : 8.00
OperatingSystem_Name        : Microsoft Windows 7 Professional 
OperatingSystem_Version     : 6.1.7601
OperatingSystem_BuildNumber : 7601
OperatingSystem_ServicePack : 1
CurrentUser                 : [MySystemName]\[MyUserName]
LastBootUpTime              : 2018-10-29 1:48:53 AM
PSComputerName              : Localhost
RunspaceId                  : 367b79f3-dd9a-48c3-8e15-7be4d9134eda
BetterNotBeThere
10.0.0.1
来自无响应系统的输出

LocalComputerName           : [MySystemName]
Manufacturer                : System manufacturer
Model                       : System Product Name
SerialNumber                : System Serial Number
CPU                         : AMD Phenom(tm) II X4 945 Processor
SysDrive_Capacity_GB        : 931.41
SysDrive_FreeSpace_GB       : 750.18
SysDrive_FreeSpace_Pct      : 81
RAM_GB                      : 8.00
OperatingSystem_Name        : Microsoft Windows 7 Professional 
OperatingSystem_Version     : 6.1.7601
OperatingSystem_BuildNumber : 7601
OperatingSystem_ServicePack : 1
CurrentUser                 : [MySystemName]\[MyUserName]
LastBootUpTime              : 2018-10-29 1:48:53 AM
PSComputerName              : Localhost
RunspaceId                  : 367b79f3-dd9a-48c3-8e15-7be4d9134eda
BetterNotBeThere
10.0.0.1

如果您只想减少代码,可以这样编写:

$featureIDs = @(2, 140, 141, 162, 164, 179)
$compliant = $true

foreach($ID in $featureIDs) {
    $compliant = $compliant -and ((Get-WmiObject -Class Win32_ServerFeature | Where-Object {$_.ID -eq $ID}) -ne $null)
}

if ($compliant) {
    Write-Host "Installed"
}
else {
}

但是,这确实会执行大量WMI调用,而不仅仅是您需要的调用。我不确定使用一些WQL语法是否可以做得更好(因为WQL非常有限),但是如果我找到一种更优雅的方法,我会更新它。我现在主要发布这个相当粗糙的解决方案,因为我想我了解您想要实现的目标,希望能够激发出更好的解决方案。

定义“相关”。@AnsgarWiechers-请参阅编辑请再次编辑,因此您提到的角色确实在功能列表中。使用准确的名称,以免混淆。ie.
Windows身份验证
Web Windows身份验证
的功能吗?奇怪的是,我真的不确定你在找什么……无论如何,还是要为我重写它?@ArcSet我想他想要的(从我个人的sccm知识和他发布的内容来看)是一个任意数组,带有ID,他可以在脚本开始时定义,然后是一个查询(或之后的一些代码)检查数组中的ID是否都存在于win32_serverfeature中,并输出“installed”(已安装)仅在这种情况下我还没有这些服务器功能,这就是添加这些功能的全部目的,它们都需要存在,以便语句返回“installed”值这反过来又告诉SCCM,脚本安装程序工作正常并安装了这些特定角色。安装是通过设备集合在一组计算机上完成的,因此,在这种情况下,不需要使用Invoke命令。@Royston-因此,您希望在2的
Name
列中自动生成项目列表nd
win32\u serverfeature
示例?如果是,您可以使用隐藏的
.PSObject
属性获取列表。类似于
(获取日期).PSObject.Properties.Name
的内容将为您提供对象的属性名称列表。