Попытка добавить PSCustomObjects в ArrayList на удаленной машине
У меня есть некоторый опыт работы с PowerShell, и обычно Google или поисковые форумы, подобные этим, дают ответы, когда у меня есть вопросы - но не в этот раз.
Я пытаюсь собрать количество файлов.log в каталоге на удаленном сервере, затем я хочу сохранить местоположение (букву диска и путь к папке) и количество в списке массивов для дальнейшего использования. Пока все работает так, как я ожидал, но у меня проблемы с добавлением моих объектов PSCustomObject в список массивов. Я не уверен, что это потому, что я выполняю на удаленном сервере или что-то еще вызывает проблему. Вот мой код:
$server = Read-Host -Prompt 'Please enter the server name'
[System.Collections.ArrayList]$returnObj = @()
Invoke-Command -ComputerName $server {
$drives = Get-PSDrive -PSProvider FileSystem |
Where-Object {$_.Description -like "ExVol*"} |
Select-Object Root
foreach ($d in $drives) {
Set-Location -Path $d.Root
$folders = Get-ChildItem -Path $d.Root |
Where-Object {$_.Name -like "*.log"} |
Select-Object Name
foreach ($f in $folders) {
$count = (Get-ChildItem -Path $f.Name).Count
$obj = [PSCustomObject]@{
LogFolder = $d.Root.Trim() + $f.Name
LogFileCount = $count
}
Write-Host $obj
$returnObj.Add($obj | Select-Object DatabaseFolder,LogFileCount)
}
}
}
$returnObj
В этом формате я получаю синтаксическую ошибку в строке
$returnObj.Add($obj | Select-Object DatabaseFolder,LogFileCount)
Если я изменю вышеуказанную строку на $returnObj.Add($obj)
Я избегаю синтаксической ошибки, но вместо этого получаю сообщение о том, что не могу вызвать метод для выражения с нулевым значением.
Я пытался создать ArrayList внутри Invoke-Command
и я пытался использовать New-Object
вместо PSCustomObject
но безрезультатно.
2 ответа
Я думаю, что ваши вещи немного смешаны, это будет делать:
$returnObj = Invoke-Command -ComputerName $server {
$drives = Get-PSDrive -PSProvider FileSystem |
Where-Object {$_.Description -like "ExVol*"} |
Select-Object Root
foreach ($d in $drives) {
Set-Location -Path $d.Root
$folders = Get-ChildItem -Path $d.Root |
Where-Object {$_.Name -like "*.log"} |
Select-Object Name
foreach ($f in $folders) {
$count = (Get-ChildItem -Path $f.Name).Count
[PSCustomObject]@{
LogFolder = $d.Root.Trim() + $f.Name
LogFileCount = $count
}
}
}
}
$returnObj
Проблема в этой строке:
[System.Collections.ArrayList]$returnObj = @()
объявлен вне Invoke-Command -ScriptBlock
, Это означает, что он не доступен в сеансе на удаленной машине, и поэтому не может использоваться там.
На заметку, вы не можете заполнить array
как вы заполняете Hashtable
с данными.
- Массивы заполнены как
$MyArray = @(); $MyArray += 'MyValue'
- Hashtables, как
$MyHash=@{}; $MyHash.SomeKey = 'SomeValue'
или как вы указали$MyHash.Add('SomeKey', 'SomeValue')
- ArrayLists заполнены как
[System.Collections.ArrayList]$MyArrayList = @(); $MyArrayList.Add('SomeValue')
Я надеюсь, что это делает это немного более ясным. Возвращаемые значения всегда можно отследить до Invoke-Command
или даже перед простым foreach ()
, Например $result = 0..3 | ForEach-Object {$_}
тоже совершенно верно.
Вам действительно нужно вернуть ваш объект из удаленной системы в вашу локальную систему, поскольку вы не можете использовать ваш $ returnObj в удаленном сеансе.
В качестве примера:
$returnValue = Invoke-Command -ComputerName $server {
$obj = [PSCustomObject]@{
LogFolder = $d.Root.Trim() + $f.Name
LogFileCount = $count
}
#return the object via the pipline
$obj
}
$returnObj.Add($returnValue | Select-Object DatabaseFolder,LogFileCount)
В приведенном выше примере отсутствует надлежащая обработка ошибок, поэтому вы получите сообщение об ошибке, если удаленная система недоступна, но это начало.