Search code examples
powershelllog4j

redundant results are saved when using Export-CSV


I have a working script for detecting Log4j but trying to export all the result to CSV.

The current script was able to export but is giving me multiple rows of exact result.

$hostnames = "PC1"
foreach ($hostname in $hostnames){

Write-Host "Starting..."

$List = Invoke-Command -ComputerName $hostname  {Get-ChildItem 'C:\' -Recurse -Force -Include *.jar -ea 0 | foreach {select-string "JndiLookup.class" $_} | select -exp Path}
            
if ($List -ne $null) 
{
    $List1 = [system.String]::Join("`r`n", $List)

    $file_location = "C:\Powershell\log4j-test.csv"
    
    $global:name = @{N="Computer Name";E={$hostname}}
    $global:lists = @{N="Affected Location";E={$List1}}
    
    Write-Host "Done.."

    $name, $lists | Export-CSV $file_location -noTypeInformation -Force -Append -Encoding UTF8
    
} 

}


Solution

  • You're probably looking for something like this:

    [pscustomobject] @{
      'Computer Name' = $hostname
      'Affected Location' = $List -join "`r`n"
    } | Export-CSV $file_location -noTypeInformation -Force -Append -Encoding UTF8
    

    Note that each single CSV row created in each iteration will (potentially) span multiple lines, due to using newlines ("`r`n") as separators in the Affected Location column.


    As for what you tried:

    • Your hashtable literals (e.g. @{N="Computer Name";E={$hostname}}) use the syntax of a calculated property, yet you're not using a cmdlet - typically Select-Object - that is capable of creating calculated properties.

    • More generally, Export-Csv and ConvertTo-Csv in Windows PowerShell do not meaningfully support hashtables as input objects - you'll need to provide [pscustomobject] instances instead, which you can easily create by casting[1] a hashtable literal to [pscustomobject], as shown above

      • By contrast, in PowerShell (Core) 7+ you may now use hashtables directly as input, though you'll probably want to use [ordered] hashtables for predictable column ordering.

    [1] Strictly speaking, the form [pscustomobject] @{ ... } isn't a cast, but built-in syntactic sugar for creating [pscustomobject] instances as literals. This is evidenced by the fact that the key-definition order in the hashtable literal is maintained in this case, whereas it isn't in stand-alone hashtable literals.