【问题标题】:Powershell - Export Output From Multiple CmdletsPowershell - 从多个 Cmdlet 导出输出
【发布时间】:2014-07-10 08:48:57
【问题描述】:

当数据来自多个 cmdlet 时,我曾多次在导出数据时遇到问题。

例如:我正在尝试使用 WMI 导出打印机列表和其他相关信息,但提取所有信息需要两个 cmdlet:

Get-WmiObject -Class Win32_Printer `
        -ComputerName $Computer -Credential $cred

还有……

Get-WmiObject -Class Win32_PrinterConfiguration `
        -ComputerName $Computer -Credential $cred

我创建了一个对象来将数据导入以便可以导出:

$CSVData = New-Object PSObject
$CSVData | Add-Member -MemberType NoteProperty -Name "Name" -Value ""
$CSVData | Add-Member -MemberType NoteProperty -Name "DriverName" -Value ""
$CSVData | Add-Member -MemberType NoteProperty -Name "Location" -Value ""
$CSVData | Add-Member -MemberType NoteProperty -Name "PrintProcessor" -Value ""
$CSVData | Add-Member -MemberType NoteProperty -Name "PortName" -Value ""
$CSVData | Add-Member -MemberType NoteProperty -Name "Duplex" -Value ""
$CSVData | Add-Member -MemberType NoteProperty -Name "Color" -Value ""
$CSVData | Add-Member -MemberType NoteProperty -Name "PrintQuality" -Value ""

$CSVData.Name = @()
$CSVData.DriverName = @()
$CSVData.Location = @()
$CSVData.PrintProcessor = @()
$CSVData.PortName = @()
$CSVData.Duplex = @()
$CSVData.Color = @()
$CSVData.PrintQuality = @()

我试着把它排成这样:

    $PrinterConfig = Get-WmiObject -Class Win32_PrinterConfiguration `
        -ComputerName $Computer -Credential $cred |
            Select-Object Duplex,
                          Color,
                          PrintQuality

    $CSVData.Duplex += $PrinterConfig.Duplex
    $CSVData.Color += $PrinterConfig.Color
    $CSVData.PrintQuality += $PrinterConfig.PrintQuality

而且,像这样:

        $PrinterInfo = Get-WmiObject -Class Win32_Printer `
        -ComputerName $Computer -Credential $cred | 
            Select-Object Name,
                          DriverName,
                          Location,
                          PrintProcessor,
                          PortName |
                ForEach-Object {
                    $CSVData.Name += $_.Name
                    $CSVData.DriverName += $_.DriverName
                    $CSVData.Location += $_.Location
                    $CSVData.PrintProcessor += $_.PrintProcessor
                    $CSVData.PortName += $_.PortName
                }

然后我像这样导出:

$CSVData | Export-Csv -Path c:\temp\printers.csv $OutDir

问题是实际上没有导出任何有用的数据,我不确定如何正确组合这两个 cmdlet 的输出。

很可能有一种更优雅的方式来做到这一点......

请帮忙!

【问题讨论】:

    标签: object powershell formatting output cmdlet


    【解决方案1】:

    首先,您可能希望以稍微不同的方式进行查询。这种方式只会返回你真正关心的数据(也快一点):

    $printers = Get-WmiObject -Query "Select Name,DriverName,Location,PrintProcessor,PortName from Win32_Printer" -ComputerName $ComputerName -Credential $cred
    $printerCfgs = Get-WmiObject -Query "select Name,Duplex,Color,PrintQuality from Win32_PrinterConfiguration" -ComputerName $ComputerName -Credential $cred
    

    现在你有两个数组,你必须找到一些方法来连接来自类的数据(有很多方法,大多数比这个例子更复杂)。您需要遍历每个打印机对象并找到相关的打印机配置对象。两个数组都有“名称”属性:

        foreach ( $printer in $printers ) {
            $printerCfg = $printerCfgs | where { $_.Name -eq $printer.Name }
    

    这样您就可以为每个打印机和打印机配置对象创建一个对象。

            $printerInfo = New-Object PSObject -Property @{
                ComputerName = $ComputerName
                Name = $printer.Name
                DriverName = $printer.DriverName
                Location = $printer.Location
                PrintProcessor = $printer.PrintProcessor
                PortName = $printer.PortName
                Duplex = $printerCfg.Duplex
                Color = $printerCfg.Color
                PrintQuality = $printerCfg.PrintQuality
            }
    

    接下来您要以正确的顺序返回数据,以便您的 csv 可读(选择后的 } 关闭了上面的 foreach 循环,您将需要它;)):

        $printerInfo | Select ComputerName,Name,DriverName,Location,PrintProcessor,PortName,Duplex,Color,PrintQuality
    }
    

    最后,您可能希望从不止一台计算机上获取此信息,并且您希望将其全部保存在一个 csv 文件中。有几种方法,您可以使用上面的代码并将其放入 ps1 文件中,或者您可以创建一个函数,将计算机名称作为参数和单个 cred 对象,这样您就不必每次都重新验证WMI 查询。我自己更喜欢函数,我将它们放在我的 ps 配置文件中(更容易跟踪 IMO):

    function get-printerinfo {
    param ( $ComputerName, $cred = (Get-Credential) )
        $printers = Get-WmiObject -Query "Select Name,DriverName,Location,PrintProcessor,PortName from Win32_Printer" -ComputerName $ComputerName -Credential $cred
        $printerCfgs = Get-WmiObject -Query "select Name,Duplex,Color,PrintQuality from Win32_PrinterConfiguration" -ComputerName $ComputerName -Credential $cred
        foreach ( $printer in $printers ) {
            $printerCfg = $printerCfgs | where { $_.Name -eq $printer.Name }
            $printerInfo = New-Object PSObject -Property @{
                ComputerName = $ComputerName
                Name = $printer.Name
                DriverName = $printer.DriverName
                Location = $printer.Location
                PrintProcessor = $printer.PrintProcessor
                PortName = $printer.PortName
                Duplex = $printerCfg.Duplex
                Color = $printerCfg.Color
                PrintQuality = $printerCfg.PrintQuality
            }
            $printerInfo | Select ComputerName,Name,DriverName,Location,PrintProcessor,PortName,Duplex,Color,PrintQuality
        }
    }
    

    对单台电脑使用此功能

    get-printerinfo myComputer
    

    提示我输入用户/密码,然后返回如下内容:

    ComputerName   : myComputer
    Name           : Microsoft XPS Document Writer
    DriverName     : Microsoft XPS Document Writer
    Location       :
    PrintProcessor : winprint
    PortName       : XPSPort:
    Duplex         : False
    Color          : 2
    PrintQuality   : 600
    

    要对当前工作目录中名为 list.txt 的文件中的计算机列表使用它:

    $cred = Get-Credential
    cat .\list.txt | %{ get-printerinfo -ComputerName $_ -cred $cred }  
    

    使用 list.txt 并将输出放在 csv 中:

    $cred = Get-Credential
    cat .\list.txt | %{ get-printerinfo -ComputerName $_ -cred $cred } | Export-Csv .\myPrinterData.csv -NoTypeInformation
    

    更新(新脚本):

    Function Get-Printers {
    
    [CmdletBinding()]
    Param(
        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)][String[]]$ComputerName,
        [Parameter()][string]$OutputDir = 'C:\Temp'
    )
    
    Begin { 
        $Cred = Get-Credential 
        $OutputFile = Join-Path $OutputDir "BCMPrinterAudit - $(Get-Date -Format yyyy-MM-dd--HH-mm-ss).csv"
    }
    
    Process {
        Foreach ($Computer in $ComputerName) {
    
            $Printers = Get-WmiObject -Query "Select Name,DriverName,Location,PrintProcessor,PortName from Win32_Printer" `
                -ComputerName $Computer -Credential $Cred
            $PrinterCfgs = Get-WmiObject -Query "select Name,Duplex,Color,PrintQuality from Win32_PrinterConfiguration" `
                -ComputerName $Computer -Credential $Cred
    
            Foreach ( $Printer in $Printers ) {
                $PrinterCfg = $PrinterCfgs | Where { $_.Name -eq $Printer.Name }
                $PrinterInfo = New-Object PSObject -Property @{
                    ComputerName = $Computer
                    Name = $Printer.Name
                    DriverName = $Printer.DriverName
                    Location = $Printer.Location
                    PrintProcessor = $Printer.PrintProcessor
                    PortName = $Printer.PortName
                    Duplex = $PrinterCfg.Duplex
                    Color = $PrinterCfg.Color
                    PrintQuality = $PrinterCfg.PrintQuality
                }
            }
        }
    }
    
    End {
    
        Write-Output $PrinterInfo     
    
        }
    }
    

    【讨论】:

    • 我应该补充一点,如果您有多个同名打印机,“名称”属性可能会返回不准确的结果,不过还有其他方法可以加入这两个类。
    • 工作愉快!谢谢布伦丹。
    • 我发现需要对此进行扩展...我想针对脚本中的计算机列表运行 foreach 循环。我已将我提出的脚本附加到我原来的问题中。知道我错过了什么吗?
    • 你是如何生成你的列表的?我会从高级参数中删除 [string[]]。
    • 另外,您可能不想写入输出 $PrinterInfo 或执行 $PrinterInfo |脚本/函数中的格式表(或格式列表、ft、fl 等),因为如果有这些输出数据,您将无法使用 export-csv。
    猜你喜欢
    • 2016-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多