1

我当前的 Powershell 脚本会输出计算机名称的 .txt 文档,以及我希望能够导入 csv 文件的软件,每个计算机名称都是一个新列。

目前输出如下所示:

PC1=

产品名称

软件A

软件B

PC2=

产品名称

软件A

软件B

我如何编写脚本以适当地对这些数据进行排序?直接导入到 csv 将在一个列中包含所有这些信息。有什么我可以在 foreach 循环上扔的东西让它写到下一列吗?或者我可以让每个循环写入它自己的 .txt,然后抓取每个 .csv 并将它们导入新工作表

这是源代码:

 $ComputerNames = get-content ".\Computers.txt"


foreach ($Computer in $ComputerNames)
 {$arryStandardSoftware = get-content -path ".\StandardSoftware.txt"| Foreach-Object{$_.trim()}
 $AuditResult = (Get-WMIObject -namespace "root\cimv2\sms" -class sms_installedsoftware -computername "$computer"|
               Select-Object productname|Where-Object{$arryStandardSoftware -notcontains "$($_.productname)"})
 echo "$Computer ="$AuditResult | out-file ".\SoftwareAudit.txt" -append}
4

2 回答 2

1

powershell 的强大之处在于对象(PsCustomObject)。为了将每台计算机输出为一列,您可以构建自定义对象并为其添加新属性,使用计算机名称作为属性名称(只要计算机名称不包含空格或特殊字符)。以下脚本应输出如下内容:

ProductName,  PC1,  PC2
SoftwareA,    true, false
SoftwareB,    false, true

没有测试过,但你应该得到基本的想法。

$ComputerNames = get-content ".\Computers.txt"
$arryStandardSoftware = get-content -path ".\StandardSoftware.txt"| Foreach-Object{$_.trim()}
$reports = $arryStandardSoftware | select @{N="ProductName";E={$_}}

foreach ($Computer in $ComputerNames)
{
    $installed = Get-WMIObject -namespace "root\cimv2\sms" -class sms_installedsoftware -computername "$computer" | select ProductName

    foreach ($r in $reports)
    {
        Add-Member -InputObject $r -MemberType NoteProperty -Name $Computer -Value ($installed -contains $r.ProductName)
    }
}

$reports | export-csv .\SoftwareAudit.txt -NoTypeInformation
于 2013-10-12T00:54:25.283 回答
0

你想要的是一个数组数组。

ComputerA      ComputerB      ComputerC
SoftwareX      SoftwareX      SoftwareY
SoftwareY      SoftwareZ      SoftwareZ
SoftwareZ                     SoftwareA
                              SoftwareB

要获得此结果,您需要在遍历 WMI 结果时编译每个数组。找出最长数组的长度,然后写出每一行。

这是一种蛮力的方法:

$ComputerNames = get-content ".\Computers.txt"
$ComputerIndex = 0
$MasterArray = New-Object object[] $ComputerNames.Count

#collect the list in an array of arrays
foreach ($Computer in $ComputerNames) {
    $arryStandardSoftware = get-content -path ".\StandardSoftware.txt"| Foreach-Object{$_.trim()}
    $AuditResult = (Get-WMIObject -namespace "root\cimv2\sms" -class sms_installedsoftware -computername "$computer"|
               Select-Object productname|Where-Object{$arryStandardSoftware -notcontains "$($_.productname)"})  

    $SoftwareArray = @()
    $SoftwareArray += $Computer

    $AuditResult | % { $SoftwareArray += $_.productname }
    $MasterArray[$ComputerIndex] = $SoftwareArray
    $ComputerIndex += 1
 }

在上一个循环中,为每台计算机构建了一个数组。第一个元素是计算机名称,数组的其余部分是软件列表。

现在找出哪个数组最长。

$longest = 0
for ($i=0;$i -lt $MasterArray.Count; $i++) {
    if ($MasterArray[$i].Count -gt $longest){
        $longest = $MasterArray[$i].Count
    }
}

一旦我们知道最大列长度,我们就可以遍历所有数组,构建将输出到 CSV 文件的行。

$MyOutput = $null

for ($i=0;$i -lt $longest; $i++) {
    $row = ""
    for ($j=0;$j -lt $MasterArray.Count; $j++) {
        if ($i -lt $MasterArray[$j].Count){
            $row += $MasterArray[$j][$i]
        }         
        if ($j -lt ($MasterArray.Count - 1) ){
            $row += "`t"
        }
    }    
   $MyOutput += ($row + "`r`n")
} 

$MyOutput > 'My.csv'

就像我说的,这是一种蛮力方法,但是将每台计算机的软件列表作为一列的要求限制了可用的输出选项。

于 2013-10-12T02:45:49.973 回答