PowerShell Export-CSV - 缺少列
PowerShell Export-CSV - Missing Columns
这是
的后续问题
我稍微改变了策略,现在我正在收集所有安装的服务,
45 = Get-WinEvent -FilterHashtable @{ Path="1system.evtx"; Id = 7045 } | select
@{N=’Timestamp’; E={$_.TimeCreated.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')}},
Id,
@{N=’Machine Name’; E={$_.MachineName}},
@{N=’Service Name’; E={$_.Properties[0].Value}},@{N=’Image Path’;E=$_.Properties[1].Value}},
@{N=’RunAsUser’; E={$_.Properties[4].Value}},@{N=’Installed By’; E={$_.UserId}}
现在我匹配每个对象的任何可疑特征,如果找到,我添加一个值为 'Yes' 的列 'Suspicious'。这是因为我想将决定权留给分析师,并且很确定坏人可能会使用我们以前从未见过的东西。
foreach ($Evt in 45)
{
if ($Evt.'Image Path' -match $sus)
{
$Evt | Add-Member -MemberType NoteProperty -Name 'Suspicious' -Value 'Yes'
}
}
现在,我无法让 PowerShell 显示所有列,除非我特别 Select
它们
45 | Format-Table
CSV 导出也是如此。前两个不包括 Suspicious
列,但第三个包括但那是因为我明确要求它。
45 | select * | Export-Csv -Path test.csv -NoTypeInformation
45 | Export-Csv -Path test.csv -NoTypeInformation
45 | Select-Object Timestamp, Id, 'Machine Name', 'Service Name', 'Image Path', 'RunAsUser', 'Installed By', Suspicious | Export-Csv -Path test.csv -NoTypeInformation
我阅读了 MS 上的 Export-CSV 文档。在 Whosebug 上搜索了一些提示,我认为它与 PS 检查第一行然后比较第二行是否存在 属性 等有关。
谢谢
您遇到的问题部分是因为对象在控制台上的显示方式,第一个对象的属性将决定控制台上显示的属性(列)。但是,更大的问题是 Export-Csv
不会导出那些不属于管道上第一个对象的属性,除非您明确使用 Select-Object
正如您在问题中指出的那样。
示例:
$test = @(
[pscustomobject]@{
Col = 'Val'
}
[pscustomobject]@{
Col = 'Val'
Col2 = 'Val2'
}
[pscustomobject]@{
Col3 = 'Val3'
Col4 = 'Val4'
Col5 = 'Val4'
}
)
Format-Table
不会显示 Col2 到 Col5:
PS /> $test | Format-Table
Col
---
Val
Val
Format-List
将按原样显示对象:
PS /> $test | Format-List
Col : Val
Col : Val
Col2 : Val2
Col3 : Val3
Col4 : Val4
Col5 : Val4
Export-Csv
和 ConvertTo-Csv
也会错过 Col2 到 Col5:
PS /> $test | ConvertTo-Csv
"Col"
"Val"
"Val"
您有不同的解决方法,您可以将 Suspicious
属性 添加到 所有对象 以及那些不是怀疑你可以添加 $null
作为 Value。另一种解决方法是使用 Select-Object
显式调用 Suspicious 属性(之所以有效,是因为您知道 属性 在那里并且您知道它是 姓名)。如果您不知道对象有多少属性,另一种解决方法是循环遍历它们并使用 .PSObject.Properties.Name
:
发现它们的属性
$test | ForEach-Object -Begin {
$props = [System.Collections.Generic.HashSet[string]]::new(
[System.StringComparer]::InvariantCultureIgnoreCase
)
} -Process {
foreach($i in $_.PSObject.Properties.Name)
{
$null = $props.Add($i)
}
} -End {
$test | Select-Object ([object[]]$props) | Format-Table
}
继续我的 ,如果您取出 Where-Object
过滤器并简单地将另一个计算的 属性 添加到 Select-Object
命令:
# create a regex for the suspicious executables:
$sus = '(powershell|cmd|psexesvc)\.exe'
# alternatively you can join the array items like this:
# $sus = ('powershell.exe','cmd.exe','psexesvc.exe' | ForEach-Object {[regex]::Escape($_)}) -join '|'
45 = Get-WinEvent -FilterHashtable @{ LogName = 'System';Id = 7045 } |
Select-Object Id,
@{N='Timestamp';E={$_.TimeCreated.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')}},
@{N='Machine Name';E={$_.MachineName}},
@{N='Service Name'; E={$_.Properties[0].Value}},
@{N='Image Path'; E={$_.Properties[1].Value}},
@{N='RunAsUser'; E={$_.Properties[4].Value}},
@{N='Installed By'; E={$_.UserId}},
@{N='Suspicious'; E={
if ($_.Properties[1].Value -match $sus) { 'Yes' } else {'No'}
}}
45 | Export-Csv -Path 'X:\Services.csv' -UseCulture -NoTypeInformation
因为你有很多列,如果你这样做,这将不再适合控制台宽度 45 | Format-Table
,但 CSV 文件将包含你想要的所有列。
我在 Export-Csv cmdlet 中添加了开关 -UseCulture
,确保您只需双击 csv 文件即可在 Excel.
中正确打开它
作为旁注:请不要在代码中使用那些卷曲的所谓 'smart-quotes',因为它们可能会导致无法预料的错误。拉直这些 ’
东西并使用正常的双引号或单引号("
和 '
)
这是
我稍微改变了策略,现在我正在收集所有安装的服务,
45 = Get-WinEvent -FilterHashtable @{ Path="1system.evtx"; Id = 7045 } | select
@{N=’Timestamp’; E={$_.TimeCreated.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')}},
Id,
@{N=’Machine Name’; E={$_.MachineName}},
@{N=’Service Name’; E={$_.Properties[0].Value}},@{N=’Image Path’;E=$_.Properties[1].Value}},
@{N=’RunAsUser’; E={$_.Properties[4].Value}},@{N=’Installed By’; E={$_.UserId}}
现在我匹配每个对象的任何可疑特征,如果找到,我添加一个值为 'Yes' 的列 'Suspicious'。这是因为我想将决定权留给分析师,并且很确定坏人可能会使用我们以前从未见过的东西。
foreach ($Evt in 45)
{
if ($Evt.'Image Path' -match $sus)
{
$Evt | Add-Member -MemberType NoteProperty -Name 'Suspicious' -Value 'Yes'
}
}
现在,我无法让 PowerShell 显示所有列,除非我特别 Select
它们
45 | Format-Table
CSV 导出也是如此。前两个不包括 Suspicious
列,但第三个包括但那是因为我明确要求它。
45 | select * | Export-Csv -Path test.csv -NoTypeInformation
45 | Export-Csv -Path test.csv -NoTypeInformation
45 | Select-Object Timestamp, Id, 'Machine Name', 'Service Name', 'Image Path', 'RunAsUser', 'Installed By', Suspicious | Export-Csv -Path test.csv -NoTypeInformation
我阅读了 MS 上的 Export-CSV 文档。在 Whosebug 上搜索了一些提示,我认为它与 PS 检查第一行然后比较第二行是否存在 属性 等有关。 谢谢
您遇到的问题部分是因为对象在控制台上的显示方式,第一个对象的属性将决定控制台上显示的属性(列)。但是,更大的问题是 Export-Csv
不会导出那些不属于管道上第一个对象的属性,除非您明确使用 Select-Object
正如您在问题中指出的那样。
示例:
$test = @(
[pscustomobject]@{
Col = 'Val'
}
[pscustomobject]@{
Col = 'Val'
Col2 = 'Val2'
}
[pscustomobject]@{
Col3 = 'Val3'
Col4 = 'Val4'
Col5 = 'Val4'
}
)
Format-Table
不会显示 Col2 到 Col5:
PS /> $test | Format-Table
Col
---
Val
Val
Format-List
将按原样显示对象:
PS /> $test | Format-List
Col : Val
Col : Val
Col2 : Val2
Col3 : Val3
Col4 : Val4
Col5 : Val4
Export-Csv
和ConvertTo-Csv
也会错过 Col2 到 Col5:
PS /> $test | ConvertTo-Csv
"Col"
"Val"
"Val"
您有不同的解决方法,您可以将 Suspicious
属性 添加到 所有对象 以及那些不是怀疑你可以添加 $null
作为 Value。另一种解决方法是使用 Select-Object
显式调用 Suspicious 属性(之所以有效,是因为您知道 属性 在那里并且您知道它是 姓名)。如果您不知道对象有多少属性,另一种解决方法是循环遍历它们并使用 .PSObject.Properties.Name
:
$test | ForEach-Object -Begin {
$props = [System.Collections.Generic.HashSet[string]]::new(
[System.StringComparer]::InvariantCultureIgnoreCase
)
} -Process {
foreach($i in $_.PSObject.Properties.Name)
{
$null = $props.Add($i)
}
} -End {
$test | Select-Object ([object[]]$props) | Format-Table
}
继续我的 Where-Object
过滤器并简单地将另一个计算的 属性 添加到 Select-Object
命令:
# create a regex for the suspicious executables:
$sus = '(powershell|cmd|psexesvc)\.exe'
# alternatively you can join the array items like this:
# $sus = ('powershell.exe','cmd.exe','psexesvc.exe' | ForEach-Object {[regex]::Escape($_)}) -join '|'
45 = Get-WinEvent -FilterHashtable @{ LogName = 'System';Id = 7045 } |
Select-Object Id,
@{N='Timestamp';E={$_.TimeCreated.ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')}},
@{N='Machine Name';E={$_.MachineName}},
@{N='Service Name'; E={$_.Properties[0].Value}},
@{N='Image Path'; E={$_.Properties[1].Value}},
@{N='RunAsUser'; E={$_.Properties[4].Value}},
@{N='Installed By'; E={$_.UserId}},
@{N='Suspicious'; E={
if ($_.Properties[1].Value -match $sus) { 'Yes' } else {'No'}
}}
45 | Export-Csv -Path 'X:\Services.csv' -UseCulture -NoTypeInformation
因为你有很多列,如果你这样做,这将不再适合控制台宽度 45 | Format-Table
,但 CSV 文件将包含你想要的所有列。
我在 Export-Csv cmdlet 中添加了开关 -UseCulture
,确保您只需双击 csv 文件即可在 Excel.
作为旁注:请不要在代码中使用那些卷曲的所谓 'smart-quotes',因为它们可能会导致无法预料的错误。拉直这些 ’
东西并使用正常的双引号或单引号("
和 '
)