【问题标题】:Unable to export custom objects to CSV in powershell无法在 powershell 中将自定义对象导出到 CSV
【发布时间】:2021-08-17 14:36:26
【问题描述】:

我已经编写了 powershell 脚本来生成 IIS 信息到 CSV。

$bindingip = Get-WmiObject -Namespace root\webadministration -Class sslbinding2 | Select-Object - 
Property PSComputerName,IPAddress
$sitedetails = Get-Website | Select-Object -Property Name,ID,State
$report = New-Object psobject
$report | Add-Member -MemberType NoteProperty -Name "Hostname" -Value $bindingip.PSComputerName
$report | Add-Member -MemberType NoteProperty -Name "IPAddress" -Value $bindingip.IPAddress
$report | Add-Member -MemberType NoteProperty -Name "Site Name" -Value $sitedetails.name
$report | Add-Member -MemberType NoteProperty -Name "ID" -Value $sitedetails.id
$report | Add-Member -MemberType NoteProperty -Name "State" -Value $sitedetails.state
$report | Export-Csv C:\content.csv -NoTypeInformation

CSV 的输出:

Hostname         IPAddress        Site Name       ID               State
System.Object[]  System.Object[]  System.Object[] System.Object[]  System.Object[]

我是否需要在代码中添加任何内容才能获得准确的输出,有人可以帮忙吗?

【问题讨论】:

  • 嗯,这很奇怪。将其更改为pscustomobject 有什么不同吗?此外,您应该开始使用 v3 中引入的 Get-Ciminstance cmdlet。尝试添加Out-String
  • @AbrahamZinala 我用 {pscustomobject} 测试过,结果是一样的。
  • 在我看来,$bindingZip$sitedetails 可能包含多个对象。您是否尝试在创建 PSObject 之前将信息打印到控制台?我想你可能打算在两次调用Select-Object 时都使用-ExpandProperty 而不仅仅是-Property
  • @Ash 我的错,是的,我已经相应地更新了脚本。我需要针对多台服务器执行此脚本,因此我在脚本中添加了 Invoke-Command 和几行代码。

标签: powershell powershell-3.0 powershell-4.0 powershell-remoting


【解决方案1】:

正如AbrahamAsh 在他们的cmets 中指出的那样,变量$bindingip$sitedetails 的属性值是一个数组而不是一个字符串。这就是为什么当您导出报告时会得到 object type 而不是它的实际值。

您可以通过以下方式看到这一点:

$bindingip.PSComputerName.GetType()

这会返回如下内容:

IsPublic IsSerial Name        BaseType    
-------- -------- ----        --------    
True     True     Object[]    System.Array

但是,如果您只选择数组 PSComputerName 上的第一个元素

$bindingip.PSComputerName[0].GetType()

你会看到:

IsPublic IsSerial Name        BaseType     
-------- -------- ----        --------     
True     True     String      System.Object

解决方法是通过使用Out-String 或将数组元素与分隔符(即-join '//')连接起来,将值转换为多行字符串。

$bindingip = Get-WmiObject -Namespace root\webadministration -Class sslbinding2
$sitedetails = Get-Website

# Like this (thanks mklement0):
$report = [pscustomobject]@{
    Hostname = "$($bindingip.PSComputerName)"
    IPAddress = "$($bindingip.IPAddress)"
    'Site Name' = "$($sitedetails.name)"
    ID = "$($sitedetails.id)"
    State = "$($sitedetails.state)"
}

# Or like this:
$report = [pscustomobject]@{
    Hostname = ($bindingip.PSComputerName | Out-String).trim()
    IPAddress = ($bindingip.IPAddress | Out-String).trim()
    'Site Name' = ($sitedetails.name | Out-String).trim()
    ID = ($sitedetails.id | Out-String).trim()
    State = ($sitedetails.state | Out-String).trim()
}

# Or like this:
$report = [pscustomobject]@{
    Hostname = $bindingip.PSComputerName -join '//'
    IPAddress = $bindingip.IPAddress -join '//'
    'Site Name' = $sitedetails.name -join '//'
    ID = $sitedetails.id -join '//'
    State = $sitedetails.state -join '//'
}

$report | Export-Csv C:\content.csv -NoTypeInformation

编辑

这也可以,这是我认为mklement0 建议的。它将根据属性的值为每个元素创建一个新对象:

$compName = $bindingip.PSComputerName
$ipAddr = $bindingip.IPAddress
$name = $sitedetails.name
$id = $sitedetails.id
$state = $sitedetails.state

$top = ($compName.Count,$ipAddr.Count,$name.Count,$id.Count,$state.Count | Measure-Object -Maximum).Maximum

$report = for($i = 0;$i -lt $top;$i++)
{
    [pscustomobject]@{
        Hostname = $compName[$i]
        IPAddress = $ipAddr[$i]
        'Site Name' = $name[$i]
        ID = $id[$i]
        State = $state[$i]
}

$report | Export-Csv...

【讨论】:

  • 一种更有效的方法是简单地让字符串插值处理数组字符串化,例如"$($bindingip.PSComputerName)"。至于通过列表构建集合:这可行,并且肯定比使用+=“附加”到数组更可取,但请注意,简单地将整个for 循环视为表达式既更简洁也更有效( $report = for (...) { ... }) - 见this answer。 (但 +1)。
  • @mklement0 感谢您的洞察力先生,您的反馈始终是正确的。我编辑了我的答案。
  • @SantiagoSquarzon 谢谢。我相应地对脚本进行了一些更改,我的脚本面临两个问题。当我将内容导出到 CSC 时,整个输出存储在脚本的一个单元格中。有什么方法可以将输出格式化为 CSV 中的每个单元格。
  • @DKU 我的答案上一次编辑的代码应该可以解决问题。
  • @SantiagoSquarzon 谢谢,我将在我的实验室进行相应的测试,我已经修改了脚本以针对多个服务器运行,为此我添加了 Invoke-Command。我正在考虑的新要求是解析绑定 IP 地址并添加相同的 CSV 为此我使用 Resolve-DNSName $ipadd | select-object -property NameHost,我无法将来自 IP 地址的每个解析主机名的数据添加到 CSV。
【解决方案2】:

除了 Santiago 的 very thorough and excellent answer,在我看来,我们只是将一个数组的对象与另一个数组组合以产生所有可能的组合。我可能会执行以下操作来完成此操作。

$bindingip = @(
    [PSCustomObject]@{
        PSComputerName = 'Public1'
        IPAddress      = '192.168.0.1'
    },
    [PSCustomObject]@{
        PSComputerName = 'Public1'
        IPAddress      = '127.0.0.1'
    }
)

$siteDetails = @(
    [PSCustomObject]@{
        Name  = 'site 1'
        Id    = 'site1'
        State = 'up'
    },
    [PSCustomObject]@{
        Name  = 'site 2'
        Id    = 'site2'
        State = 'down'
    }
)    

$combined = foreach ($ip in $bindingip) {
    foreach ($details in $siteDetails) {
        $out = [ordered]@{}
        $ip.psobject.properties | ForEach-Object {
            $out[$_.Name] = $_.Value
        }
        $details.psobject.properties | ForEach-Object {
            $out[$_.Name] = $_.Value
        }

        [pscustomobject]$out
    }
}

$combined | Format-Table

输出

PSComputerName IPAddress   Name   Id    State
-------------- ---------   ----   --    -----
Public1        192.168.0.1 site 1 site1 up
Public1        192.168.0.1 site 2 site2 down
Public1        127.0.0.1   site 1 site1 up
Public1        127.0.0.1   site 2 site2 down

可以将其包装在一个函数中以实现可重用性

function Combine-ObjectsFromTwoArrays {
    param (
        [array]$array1,
        [array]$array2
    )

    foreach ($obj1 in $array1) {
        foreach ($obj2  in $array2) {
            $out = [ordered]@{}
            $obj1.psobject.properties | ForEach-Object {
                $out[$_.Name] = $_.Value
            }
            $obj2.psobject.properties | ForEach-Object {
                $out[$_.Name] = $_.Value
            }

            [pscustomobject]$out
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-11-30
    • 1970-01-01
    • 2018-05-11
    • 1970-01-01
    • 1970-01-01
    • 2016-04-20
    • 2016-11-14
    • 1970-01-01
    相关资源
    最近更新 更多