Пользовательский PSObject возвращает массив вместо свойств объекта

Мне трудно понять, где этот код ломается и почему Select-Object не возвращает желаемые свойства объекта в качестве вывода. Любой вклад в то, что здесь происходит, или любые возможные исправления приветствуются.

Я собираю все уникальные хэш-значения sha256 из журналов Sysmon с помощью (отдельного) сценария обработчика, затем сценарий обработчика выполняет приведенный ниже сценарий/код для этих хеш-значений. Этот сценарий обработчика запускает приведенный ниже код, а затем передает его выходные данные (script.ps1 | export-csv) в функцию Export-Csv. Однако я получаю массивы каждого объекта в своем выводе csv вместо отформатированного файла CSV с заголовками столбцов и желаемыми свойствами объекта.

Для полноты картины, скрипт-обработчик, запускающий этот файл script.ps1 (код ниже), называется Kansa.

# VirusTotal API Key 
$apikeyVirusTotal = "ABC123MyFreeVirusTotalAPIKey" 

$hashArray = @() #Array to hold multiple objects 

# VirusTotal Function - API/URI 
Function SubmitVirusTotalURL($hash) {
    Write-Host "Sleeping to avoid rate control."
    Start-Sleep -Seconds 16
    Write-Verbose "Checking VirusTotal: $hash"    
    $response = Invoke-WebRequest -Uri "https://www.virustotal.com/vtapi/v2/file/report?apikey=$apikeyVirusTotal&resource=$hash" | ConvertFrom-Json
    return $response
}

# Import the CSV File and assign it to the variable $CSV
$CSV = Import-Csv -Path ".\test.csv"
#For each line in CSV get the column name value   
foreach ($line in $CSV){
    $hashCount = $line.ct 
    $hash = $line.sha256
    IF($hashCount -lt 2 -and (-not ([string]::IsNullOrEmpty($hash)))){
        $httpResponse = SubmitVirusTotalURL($hash)        
        #create a custom object to hold VT data
        $obj = [PSCustomObject]@{
            'hash' = $hash 
            'sha256'   = $httpResponse.sha256
            'Detections' = $httpResponse.positives
            'TotalScanners' = $httpResponse.total
            'VTReport' = $httpResponse.permalink
        }
        $hashArray += $obj
    }
}
$hashArray

Пример входного файла test.csv:

ct, sha256
3, A3CFFBD12ACDB85D24A13E3976B8795C5611DA05C2017755D87B5ECE38D50806
3, 0CD2F3CF62B768F4036605665E6DD888F431B8FEBDA77D07E852F12523072FFC
4, 405F03534BE8B45185695F68DEB47D4DAF04DCD6DF9D351CA6831D3721B1EFC4
1, FAKEHA534BE8B45185695F68DEB47D4DAF04DCD6DF9D351CA6831D3721B1EFC4

В результате получается файл csv, содержащий вывод, например:

@{Sha256=0cd2f3cf62b768f4036605665e6dd888f431b8febda77d07e852f12523072ffc    Detections=0    TotalScanners=72    VTReport=https://www.virustotal.com/gui/file/0cd2f3cf62b768f4036605665e6dd888f431b8febda77d07e852f12523072ffc/detection/f-0cd2f3cf62b768f4036605665e6dd888f431b8febda77d07e852f12523072ffc-1589711909}
@{Sha256=7edc950ecfbbb043a62f31f01be2710892bb34455dd7ea435ce1346873d3f36f    Detections=0    TotalScanners=69    VTReport=https://www.virustotal.com/gui/file/7edc950ecfbbb043a62f31f01be2710892bb34455dd7ea435ce1346873d3f36f/detection/f-7edc950ecfbbb043a62f31f01be2710892bb34455dd7ea435ce1346873d3f36f-1572295279}
@{Sha256=8eaa83ed280a3d7d4f8dd3e4f8cbc28cb7fc74947cfca133fb627db0bc767f30    Detections=0    TotalScanners=71    VTReport=https://www.virustotal.com/gui/file/8eaa83ed280a3d7d4f8dd3e4f8cbc28cb7fc74947cfca133fb627db0bc767f30/detection/f-8eaa83ed280a3d7d4f8dd3e4f8cbc28cb7fc74947cfca133fb627db0bc767f30-1569383486}
@{Sha256=e871e48f75b213a51cf13a3a397c1b31b10b516cb4cfb5f0682c85387d3c5ed9    Detections=0    TotalScanners=72    VTReport=https://www.virustotal.com/gui/file/e871e48f75b213a51cf13a3a397c1b31b10b516cb4cfb5f0682c85387d3c5ed9/detection/f-e871e48f75b213a51cf13a3a397c1b31b10b516cb4cfb5f0682c85387d3c5ed9-1587296148}

Чтобы добавить к моему замешательству, я создал тестовый скрипт, который работает почти идентично, за исключением добавления sha256Array @(), и я могу без проблем передать вывод в Format-Table.

Что здесь происходит? Почему я получаю два разных типа вывода с таким похожим кодом и как мне исправить эту проблему?


person Duck    schedule 20.05.2020    source источник
comment
Код в вопросе не объясняет ваш симптом; выходной формат предполагает, что объекты были строчные, как вы могли бы получить, например, с "$($hashArray[0])". Попробуйте опубликовать MCVE (минимальный, полный и проверяемый пример). Кроме того, я предлагаю создать массив, используя цикл foreach в качестве выражения: [array] $hashArray = foreach ($File in $Files){....   -  person mklement0    schedule 20.05.2020
comment
Наконец, лучше избегать PSObject и использовать вместо него PSCustomObject (последнее — это фактически сообщаемое имя типа); используйте синтаксический сахар PSv3+ для создания пользовательских объектов, который более удобочитаем и эффективен: $psCustomObject = [pscustomobject] @{ Sha256 = $hash; ... }   -  person mklement0    schedule 20.05.2020
comment
Вам необходимо dot-source ваш скрипт: . .\script.ps1 | export-csv в противном случае вы просто будете передавать вывод на экран.   -  person iRon    schedule 20.05.2020
comment
Кроме того, вам следует избегать использования оператора увеличения присваивания (+=) для создания коллекции, так как это очень дорого.   -  person iRon    schedule 20.05.2020


Ответы (1)


Как и все комментарии выше, избегайте построения так, как вы это делаете сейчас:

Удалите эту строку:

$hashArray = @() #Array to hold multiple objects 

Теперь используйте:

#For each line in CSV get the column name value   
$CSV | ForEach-Object {
    $hashCount = $_.ct 
    $hash = $_.sha256
    If($hashCount -lt 2 -and (-not ([string]::IsNullOrEmpty($hash)))){
        $httpResponse = SubmitVirusTotalURL($hash)        
        #create a custom object to hold VT data
        [PSCustomObject]@{
            'hash' = $hash 
            'sha256'   = $httpResponse.sha256
            'Detections' = $httpResponse.positives
            'TotalScanners' = $httpResponse.total
            'VTReport' = $httpResponse.permalink
        }
    }
}

Как упоминалось выше, если это превращается в строковые значения, проблема заключается в том, как вы передаете $hasharray в csv. Вы можете передать напрямую в csv или сохранить в переменной для изучения объекта:

$hasharray = $CSV | ForEach-Object {
    $hashCount = $_.ct 
    $hash = $_.sha256
    If($hashCount -lt 2 -and (-not ([string]::IsNullOrEmpty($hash)))){
        $httpResponse = SubmitVirusTotalURL($hash)        
        #create a custom object to hold VT data
        [PSCustomObject]@{
            'hash' = $hash 
            'sha256'   = $httpResponse.sha256
            'Detections' = $httpResponse.positives
            'TotalScanners' = $httpResponse.total
            'VTReport' = $httpResponse.permalink
        }
    }
}
$hasharray | Export-Csv -Path 'pathtocsv\csvname.csv' -NoTypeInformation
person Scepticalist    schedule 20.05.2020
comment
Лучше всего не вообще присваивать его какой-либо переменной (или использовать скобки), так как это остановит конвейер. - person iRon; 21.05.2020