Arrays 如何将cmdlet的输出添加到数组?

Arrays 如何将cmdlet的输出添加到数组?,arrays,powershell,Arrays,Powershell,我正在尝试确定我们的Windows服务器上是否安装了特定的Windows修补程序。我对PowerShell脚本非常陌生,到目前为止,我已经掌握了以下内容: $servers = Get-ADComputer -Filter {(OperatingSystem -like "Windows Server 2019*") -and (enabled -ne $false)} -Property * $result = @() ForEach ($item in $servers) { $te

我正在尝试确定我们的Windows服务器上是否安装了特定的Windows修补程序。我对PowerShell脚本非常陌生,到目前为止,我已经掌握了以下内容:

$servers = Get-ADComputer -Filter {(OperatingSystem -like "Windows Server 2019*") -and (enabled -ne $false)} -Property *
$result = @()
ForEach ($item in $servers) {
    $testhotfix = Get-HotFix -Id KB4534310,KB4534314,KB4534283,KB4534288,KB4534297,KB4534309,KB4534271,KB4534273 -ComputerName $item.Name | `
    select $item.Name,$item.CanonicalName,$item.OperatingSystem
    $result += $testhotfix
}
$result | Export-Csv -Path C:\Users\user1\Desktop\Servers.csv -NoTypeInformation
创建的CSV文件包含一行我要查找的信息,后面是几行逗号,如下所示:

“SERVER1”、“somedomain.com/Servers/Non-Prod/New\u Server\u Staging/SERVER1”、“Windows Server 2019标准” ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,, ,

我们有几个服务器,其中至少安装了一个修补程序。如何将每个服务器添加到$result数组中

谢谢

总的来说:

选择$item.Name、$item.CanonicalName、$item.OperatingSystem

应该是:

选择名称、规范名称、操作系统

也就是说,您需要传递属性名称(例如,
名称
),而不是当前输入对象的属性值(例如,
$item.Name
选择
(cmdlet)

净效果是,
Select Object
创建自定义对象,这些对象的属性(错误地)以属性值命名,并且它们本身没有值,因为输入对象没有此类属性。 这解释了您看到的输出

然而,更大的问题是,即使这样也不行,因为属性名称与
$item
对象相关,而不是与
获取修补程序输出的对象相关,这些对象是
选择
操作的对象。

事实证明,您真正需要的是使用
Get HotFix
调用作为条件,以便仅在至少安装了一个指定的修补程序时为手头的计算机写入CSV行

$hotfixIds = 'KB4534310', 'KB4534314', 'KB4534283', 'KB4534288', 'KB4534297', 'KB4534309', 'KB4534271', 'KB4534273'

if (0 -ne (Get-HotFix -ErrorAction SilentlyContinue -Id $hotfixIds -ComputerName $item.Name).Count)  {
  $result += $item | select Name, CanonicalName, OperatingSystem
}
注:

  • 请注意它现在是如何通过管道输送到
    选择
    ,以确保提取其属性(以具有这些属性的自定义对象的形式)的
    $item
    (手头的计算机)

  • 您可以完全省略
    0-eq
    ,并依赖于PowerShell的隐式到布尔转换,其中任何非零数的计算结果都是
    $true
    (有关所有规则的摘要,请参阅的底部部分)

    • 如果您想测试正在安装的所有指定修补程序,请将
      0-ne
      替换为
      $hotfixIds.Count-eq
  • -ErrorAction SilentlyContinue
    可使未安装任何指定修补程序的计算机的错误静音;您可以随后检查自动
    $Error
    集合,或使用
    -ErrorVariable err
    收集变量
    $err
    中的所有命令特定错误

此外,您的总体命令可以大大简化-请参阅底部部分


针对不同场景的解决方案,也可能会引起兴趣:

如果希望
获取修补程序的属性
输出对象与
$item
对象的属性
组合(表示手头的计算机): 以下命令:

  • 获取修补程序
    输出对象中选择所有属性(
    -Property*
  • 使用添加当前
    $item
    中感兴趣的属性
请注意,
-Exclude Name
Name
属性从输入对象中排除(
Get HotFix
具有此属性但为空的输出对象),因此可以将
Name
添加为包含计算机名称的属性


至于你尝试了什么: 除了上面提到的
Select Object
属性名问题外,您的主要问题是希望管道段作为条件,而不是管道的工作方式:

Get HotFix…|选择…

上述操作只是将
Get HotFix
的输出对象发送到
select
select Object
),然后无条件地处理它们(如上所述,在这些对象上查找具有给定名称的属性)

现在,如果
Get HotFix
没有生成任何输出,那么条件逻辑将隐式应用:
select
命令将不会被调用

相反,如果
Get HotFix
生成多个输出,则会对每个输出调用
select

也就是说,如果我们天真地试图纠正您的命令:

Get HotFix…|选择…

致:

Get HotFix…| ForEach对象{$item | select…}

您可能会在每台计算机上创建多个输出对象,也就是说,当一台给定的计算机碰巧安装了多个热修复程序时


简化版的(已更正)命令: 您的命令可以简化为仅使用单个管道,而不需要辅助变量:

Get-ADComputer -Filter '(OperatingSystem -like "Windows Server 2019*") -and (enabled -ne $false)' -Property * |
  ForEach-Object {
    if (0 -ne (Get-HotFix -ErrorAction SilentlyContinue -ComputerName $item.Name -Id KB4534310,KB4534314,KB4534283,KB4534288,KB4534297,KB4534309,KB4534271,KB4534273).Count) {
      $item | select Name, CanonicalName, OperatingSystem
    }
  } | Export-Csv -Path C:\Users\user1\Desktop\Servers.csv -NoTypeInformation
注:

  • 如果以
    |
    结束一行,则不需要尾随
    `
    来表示行继续

    • PowerShell[Core]v7.0+现在还允许将
      |
      放在下一行的开头
  • 使用单引号字符串(
    “…”
    )而不是脚本块(
    {…}
    )来传递
    -Filter
    参数,因为tt最好使用

  • 使用
    $item | select Name、CanonicalName、OperatingSystem
    创建的输出自定义对象实例直接发送到管道

一般来说:

选择$item.Name、$item.CanonicalName、$item.OperatingSystem

应该是:

选择名称、规范名称、操作系统

也就是说,您需要传递属性名称(例如,
Name
),而不是当前输入对象的属性
Get-ADComputer -Filter '(OperatingSystem -like "Windows Server 2019*") -and (enabled -ne $false)' -Property * |
  ForEach-Object {
    if (0 -ne (Get-HotFix -ErrorAction SilentlyContinue -ComputerName $item.Name -Id KB4534310,KB4534314,KB4534283,KB4534288,KB4534297,KB4534309,KB4534271,KB4534273).Count) {
      $item | select Name, CanonicalName, OperatingSystem
    }
  } | Export-Csv -Path C:\Users\user1\Desktop\Servers.csv -NoTypeInformation
    $array = foreach($item in $obj)
    {
        [PSCustomObject]@{
            Name = $item.Name
            CanonicalName = $item.CanonicalName
            OS = $item.OperatingSystem
        }
    }