无法在powershell中将自定义对象导出为CSV
我编写了powershell scirpt以将IIS信息生成到CSV无法在powershell中将自定义对象导出为CSV,powershell,powershell-3.0,powershell-4.0,powershell-remoting,Powershell,Powershell 3.0,Powershell 4.0,Powershell Remoting,我编写了powershell scirpt以将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-O
$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[]
我是否需要向代码中添加任何内容以获得准确的输出,有人可以提供帮助。正如他们在评论中指出的,变量$bindingip
和$sitedetails
上的属性值是数组而不是字符串。这就是为什么导出报告时会得到对象类型
,而不是它的实际值
您可以通过执行以下操作来了解这一点:
$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
编辑
这也是我所建议的。它将为属性值上的每个元素创建一个新对象:
$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
和$sitedetails
上的属性值是数组而不是字符串。这就是为什么导出报告时会得到对象类型
,而不是它的实际值
您可以通过执行以下操作来了解这一点:
$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
编辑
这也是我所建议的。它将为属性值上的每个元素创建一个新对象:
$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 = @(
[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
}
}
}
除了圣地亚哥的,在我看来,我们只是将一个数组的对象与另一个数组的对象组合起来,以产生所有可能的组合。为了实现这一点,我可能会执行以下操作
$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
}
}
}
嗯,真奇怪。将其更改为
pscustomobject
,有什么区别吗?此外,您应该开始使用v3中引入的Get-Ciminstance cmdlet。尝试添加Out字符串
@AbrahamZinala,我已经用{pscustomobject}测试过了,结果是一样的。看起来像$bindingZip
和$sitedetails
对我来说可能包含多个对象。在创建PSObject之前,您是否尝试将信息打印到console?我想您可能想在调用选择对象
的两次调用中都使用-ExpandProperty
,而不仅仅是-Property
@Ash My bad,是的,我已经相应地更新了脚本。我需要在多个服务器上执行这个脚本,所以我添加了Invoke命令和几行代码。将其更改为pscustomobject
,有什么区别吗?此外,您应该开始使用v3中引入的Get-Ciminstance cmdlet。尝试添加Out字符串
@AbrahamZinala,我已经用{pscustomobject}测试过了,结果是一样的。看起来像$bindingZip
和$sitedetails
对我来说可能包含多个对象。在创建PSObject之前,您是否尝试将信息打印到console?我想您可能想在调用选择对象
的两次调用中都使用-ExpandProperty
,而不仅仅是-Property
@Ash My bad,是的,我已经相应地更新了脚本。我需要对多台服务器执行此脚本,因此我在脚本中添加了Invoke命令和几行代码。更有效的方法是让字符串插值处理数组字符串化,例如,“$($bindingip.PSComputerName)”
。至于通过列表构建集合:这是可行的,当然比使用+=
将数组“追加”更可取,但请注意,将整个for
循环作为一个表达式来处理更简洁、更有效($report=for(…){…}
)-请参阅。(但是+1)。@mklement0谢谢你的洞察力,先生,你的反馈总是正确的。我编辑了我的答案。@SantiagoSquarzon谢谢。我对脚本做了一些相应的修改,我的脚本面临两个问题。当我将内容导出到CSC时,整个输出存储在脚本的一个单元格中。是否有任何方法可以将输出格式化为CSV中的每个单元格。@DKU上次编辑我的答案的代码应该可以做到这一点。@SantiagoSquarzon谢谢,我将在我的实验室进行相应的测试,我已经修改了脚本,以便在多个服务器上运行,为此我添加了Invoke命令。我考虑的新要求是解析绑定IP地址并添加相同的CSV。为此,我使用resolve DNSName$ipadd | select object-property NameHost,无法将数据从IP地址添加到CSV每个解析主机名。更有效的方法是简单地让字符串插值处理数组字符串化,例如,“$($bindingip.PSComputerName)”
。至于通过列表构建集合:这是可行的,当然比使用+=
将数组“追加”更可取,但请注意,将整个for
循环作为一个表达式来处理更简洁、更有效($report=for(…){…}
)-请参阅。(但是+1)。@mklement0谢谢你的洞察力,先生,你的反馈总是正确的。我编辑了我的答案。@SantiagoSqua