【问题标题】:Trying to add PSCustomObjects to an ArrayList on a remote machine尝试将 PSCustomObjects 添加到远程计算机上的 ArrayList
【发布时间】:2018-08-07 13:28:21
【问题描述】:

我对 PowerShell 有一些经验,当我有问题时,通常 Google 或类似的搜索论坛会提供答案 - 但这次不是。

我正在尝试收集远程服务器目录中 .log 文件的数量,然后我想将位置(驱动器号和文件夹路径)和计数存储在数组列表中以备后用。到目前为止,一切都按我的预期工作,但我在将 PSCustomObjects 添加到数组列表时遇到了麻烦。我不确定是因为我在远程服务器上执行还是其他原因导致了问题。这是我的代码:

$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),我会避免语法错误,但会收到错误消息,提示我无法在空值表达式上调用方法。

我尝试在 Invoke-Command 中创建 ArrayList,并尝试使用 New-Object 而不是 PSCustomObject 无济于事。

【问题讨论】:

    标签: powershell arraylist powershell-4.0 invoke-command pscustomobject


    【解决方案1】:

    我认为您的混合内容有点多,这样就可以了:

    $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 之外声明。这意味着它在远程机器上的会话中不可用,因此不能在那里使用。

    附带说明,您不能像用数据填充Hashtable 那样填充array

    • 数组填充如$MyArray = @(); $MyArray += 'MyValue'
    • $MyHash=@{}; $MyHash.SomeKey = 'SomeValue' 这样的哈希表或您指出的$MyHash.Add('SomeKey', 'SomeValue')
    • ArrayLists 填充为[System.Collections.ArrayList]$MyArrayList = @(); $MyArrayList.Add('SomeValue')

    我希望这能让它更清楚一点。返回值总是可以在Invoke-Command 之前或什至在简单的foreach () 之前被捕获。例如$result = 0..3 | ForEach-Object {$_} 也是完全有效的。

    【讨论】:

    • 这正是我想要的。我在最后一行添加了一个格式表,以获得所需格式的输出。我认为这是我缺乏经验的地方,因为我不完全了解每个目录的对象是如何存储的。如果您能提供任何见解,我将不胜感激。无论哪种方式,这正是我所需要的,感谢您的帮助!
    • 不客气 :) 黄金法则是始终使用代码中的对象,并且仅在最后格式化数据(用于输出到文件、电子邮件或快速阅读在显示屏上...)
    【解决方案2】:

    您实际上需要将对象从远程系统返回到本地系统,因为您无法在远程会话中使用 $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)
    

    上面的例子缺乏正确的错误处理,因此如果远程系统无法访问但它是一个开始,你会得到一个错误。

    【讨论】:

      猜你喜欢
      • 2013-08-04
      • 1970-01-01
      • 2015-03-01
      • 1970-01-01
      • 2021-06-20
      • 2012-07-09
      • 1970-01-01
      • 2015-04-03
      • 1970-01-01
      相关资源
      最近更新 更多