Powershell 将值追加到数组中,只需添加一个值

Sam*_*shi 2 powershell

我想要获取进程的 CPU 和内存统计信息,并希望定期将其添加到 CSV 中。以下是我为此编写的 powershell 脚本:

# Specify the process names
$process1Name = "abcd"
$csvFilePath = "C:\Users\johndoe\Stats.csv"
# Create an array to store process stats
$processStats = @()
# Loop to monitor processes every second
$exportIntervalInSeconds = 60  # Set the desired export interval
$iterationCount = 0
# Function to get CPU and Memory usage of a process
function Get-ProcessStats {
    param (
        [string]$processName
    )
    
    $process = Get-Process -Name $processName -ErrorAction SilentlyContinue
    
    if ($process -ne $null) {
        $cpuUsage = $process.CPU
        $memoryUsage = $process.WorkingSet64
        Write-Output "$processName - CPU Usage: $cpuUsage%, Memory Usage: $memoryUsage bytes"
        # Create an object with process stats
        $statsObject = [PSCustomObject]@{
            ProcessName = $processName
            CPUUsage = $cpuUsage
            MemoryUsage = $memoryUsage
        }
        Write-Output "Stats: $statsObject"
        # Add the stats object to the array
        $processStats += $statsObject       
        Write-Output "ProcessStats:"
        $processStats | Format-Table
        $processStats.Count
    } else {
        Write-Output "$processName not found."
    }
}

# Loop to monitor processes every second
while ($true) {
    Get-ProcessStats -processName $process1Name
    Start-Sleep -Seconds 1
    $iterationCount++
    # Clear-Host  # Optional: Clear the console for better readability
    if ($iterationCount -ge $exportIntervalInSeconds) {
        # Export the process stats to CSV
        Write-Output "Reached the iteration count greater than export interval"
        Write-Output "Exporting process stats to CSV:"
        $processStats | Format-Table
        Write-Output "Exporting..."
        $processStats | Export-Csv -Force -Path $csvFilePath -NoTypeInformation

        # Reset iteration count
        $iterationCount = 0
        $processStats = @()
    }
}
Run Code Online (Sandbox Code Playgroud)

在定期间隔后,我没有看到 Stats.csv 中添加任何内容。事实上,processStats 不包含任何内容。有趣的是,statsObject 的值被打印,函数 Get-ProcessStats 中的 processStats 值也被打印,但此时仅包含 1 个值。不确定出了什么问题以及为什么所有值都没有打印并存储在 CSV 文件中。

mkl*_*nt0 5

  • 您无法从function$processStats填充在脚本作用域中初始化的数组,因为函数在调用者的子作用域中运行(除非dot-sourced)。

  • 要使其正常工作,您必须直接在调用者的作用域中引用该变量,在您的情况下这意味着:$script:processStats += $statsObject

  • 但是,从代码维护的角度来看,最好不要跨范围边界修改变量,PowerShell 惯用的解决方案是使函数输出要添加为数组元素的对象。


至于为什么你的方法不起作用:

  • 虽然您的函数可以获取调用者的$processStats变量(值), 但设置它会创建一个同名的局部变量,该变量独立于调用者的变量而存在,并在函数退出时超出范围。
    因此,调用者看不到对函数内的(意外的本地)变量进行的任何修改。[1]

  • 这种行为有点违反直觉,特别是对于诸如 之类的运算符+=,其中新的局部变量值是基于原始变量的值创建的。

  • 有关 PowerShell 范围界定的简明概述,请参阅此答案


[1] 请注意,在某些情况下可以修改祖先作用域中的变量引用的对象,但这与变量作用域无关。具体来说,如果祖先变量碰巧 (a) 包含 .NET引用类型的实例,并且 (b) 该类型碰巧具有改变实例状态的方法。 一个示例是在脚本作用域中创建一个实例,然后在函数内部使用其方法来添加到该实例。 尽管数组( 的实例)也是 .NET 引用类型,但它们是固定大小的,因此这种方法不起作用;当“增长”数组时, PowerShell 的运算符所做的是在幕后创建一个新数组,该数组由原始元素加上“追加”的元素组成。正是由于这个原因,通常最好避免使用数组- 请参阅此答案
[System.Collections.Generic.List[object]].Add()
System.Array+=+=