Суть этой проблемы будет заключаться в следующем: как скопировать данные из одного CSV в другой без знания / перечисления заголовков исходного CSV. Командлет, который я создаю, предназначен для преобразования отчета из CSV в электронную таблицу. И если я напишу заголовки столбцов в код, то каждый раз, когда кто-то изменяет отчет, код будет нарушаться, и его придется обновлять.
Шаги, которые я сейчас предприму:
# Import the Source CSV. Gonna pull data from this later.
$SourceCSV = Import-Csv -Path $reportSourceCSV -Delimiter ";"
# Remove NULL characters, white spaces and change comma separator to semicolon.
(Get-Content -Path $reportSourceCSV | Where-Object {-not [string]::IsNullOrWhiteSpace($PSItem)}).Replace('","',";") | Out-File -FilePath $TMP1
# Import the modified new temp CSV.
$Input = Import-Csv -Path $TMP1 -Delimiter ";"
# Take existing CSV file headers and append some new ones. Rename a long column name.
((($GetHeaders = foreach ($Header in $SourceCSV[0].PSObject.Properties.Name) {
"`"$Header`""
}) + '"column4"','"column5"','"column6"') -join ";").Replace("VerylongOldColumnName","ShortName") | Out-File -FilePath $TMP2
foreach ($Item in $Input) {
"`"$($Item.column1)`";`"$($Item.'column2')`";`"$($Item.column3)`"" | Out-File -FilePath $TMP2 -Append
}
$exportToXLSX = Import-Csv -Path $TMP2 -Delimiter ";" | Export-Excel -Path $Target -WorkSheetname "reportname" -TableName "tablename" -TableStyle Medium2 -FreezeTopRow -AutoSize -PassThru
$exportToXLSX.Save()
$exportToXLSX.Dispose()
Remove-Item -Path $TMP1, $TMP2
Это работает! Но я не хочу создавать бесконечное количество различных отчетов и столько же различных логических блоков для обработки всех этих отчетов.
Так что это насколько я смог попробовать более динамичный способ обработкиCSV отчета:
(Get-Content -Path $reportSourceCSV | Where-Object {-not [string]::IsNullOrWhiteSpace($PSItem)}).Replace('","',";") | Out-File -FilePath $TMP1
$import = Import-Csv -Path $TMP1 -Delimiter ";"
$headers = ($import[0].PSObject.Properties.Name).Replace("VerylongOldColumnName","ShortName")
$headers | Out-File -FilePath "C:\TEMP\test.csv"
foreach ($item in $import) {
for ($h = 0; $h -le ($headers).Count; $h++) {
$($item.$($headers[$h]))
}
}
Теперь, это работает ... вроде. Если я запускаю скрипт, как это, он показывает вывод, который я хочу, но я НЕ смог экспортировать его в CSV. Я добавил Export-Csv
к этой строке: $($item.$($headers[$h]))
, чтобы эта конкретная строка выглядела следующим образом:
$($item.$($headers[$h])) | Export-Csv -Path $Output -Delimiter ";" -Append -NoTypeInformation
И вот такая ошибка:
Export-Csv : Cannot append CSV content to the following file: C:\TEMP\test.csv.
The appended object does not have a property that corresponds to the following
column: column1. To continue with mismatched properties, add the -Force parameter,
and then retry the command.
At line:11 char:36
+ ... ers[$h])) | Export-Csv -Path $Output -Delimiter ";" -Append -NoTypeIn ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (column1:String) [Export-Csv], InvalidOperationException
+ FullyQualifiedErrorId : CannotAppendCsvWithMismatchedPropertyNames,Microsoft.PowerShell.Commands.ExportCsvCommand
Если я добавлю-Force
, на выходе будут заголовки и куча пустых строк.
Насколько я понимаю, вывод по какой-то причине является строкой? Насколько мне известно, все должно быть объектом в PS, если не преобразовано в строку (командлет Write-Host является исключением). И я на самом деле не знаю, как заставить выходные данные быть объектами.
Редактировать: Добавлен пример источника CSV
"Plugin","Plugin Name","Family","Severity","IP Address","Protocol","Port","Exploit?","Repository","DNS Name","NetBIOS Name","Plugin Text","Synopsis","Description","Solution","See Also","Vulnerability Priority Rating","CVSS V3 Base Score","CVSS V3 Temporal Score","CVSS V3 Vector","CPE","CVE","Cross References","First Discovered","Last Observed","Vuln Publication Date","Patch Publication Date","Exploit Ease","Exploit Frameworks"
"65057","Insecure Windows Service Permissions","Windows","High","127.0.0.1","TCP","445","No","Individual Scan","computer.domain.tld","NetBIOS Name","Plugin Output:
Path : c:\program files (x86)\application\folder\service.exe
Used by services : application
File write allowed for groups : Users, Authenticated Users
Full control of directory allowed for groups : Users, Authenticated Users","At least one improperly configured Windows service may have a privilege escalation vulnerability.","At least one Windows service executable with insecure permissions was detected on the remote host. Services configured to use an executable with weak permissions are vulnerable to privilege escalation attacks.
An unprivileged user could modify or overwrite the executable with arbitrary code, which would be executed the next time the service is started. Depending on the user that the service runs as, this could result in privilege escalation.
This plugin checks if any of the following groups have permissions to modify executable files that are started by Windows services :
- Everyone
- Users
- Domain Users
- Authenticated Users","Ensure the groups listed above do not have permissions to modify or write service executables. Additionally, ensure these groups do not have Full Control permission to any directories that contain service executables.","http://www.nessus.org/u?e4e766b2","","8.4","","AV:L/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H","cpe:/o:microsoft:windows","","","Jul 11, 2029 06:48:20 CEST","Jul 11, 2029 06:48:20 CEST","N/A","N/A","",""
Редактировать: я думаю, что нашелИными словами, как это сделать, и, глядя на это, похоже, я пытался переусердствовать.
# Doing cleanup, changing delimiters, renaming that one known column. All in one line.
$importCSV = 'C:\TEMP\sourceReport.csv'
(Get-Content -Path $importCSV | Where-Object {-not [string]::IsNullOrWhiteSpace($PSItem)}).Replace('","','";"').Replace"VerylongOldColumnName","ShortName") | Out-File -FilePath C:\TEMP\tmp1.csv
# Adding additional columns and exporting it all to result CSV.
Import-Csv -Path C:\TEMP\tmp1.csv -Delimiter ";" | Select-Object *, "Column1", "Column2" | Export-Csv -Path C:\TEMP\result.csv -NoTypeInformation -Delimiter ";"