You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell Invoke-Command为何未触发完整Foreach循环?

排查PowerShell脚本获取IIS应用池回收时间的问题

现有IIS应用池列表文件apppools.txt和服务器列表文件servers.txt,运行以下PowerShell脚本后,仅能获取每台服务器的单个应用池回收时间,无法输出预期的约10个应用池对应数据,需排查脚本错误:

$apppools = gc c:\temp\apppools.txt
$servers = Get-Content C:\temp\servers.txt
foreach ($server in $servers){
Invoke-Command -ComputerName $server -argumentlist @($apppools) -scriptblock {

param($apppools)
$servername = hostname
$infoObject = New-Object PSObject

import-module webadministration

foreach ($a in $apppools){

$recycle = (Get-ItemProperty -Path "IIS:\AppPools\$a" -Name recycling.periodicRestart.schedule.collection).value.tostring()}


Add-Member -inputObject $infoObject -memberType NoteProperty -name "ServerName" -value $Servername
Add-Member -inputObject $infoObject -memberType NoteProperty -name "AppPool" -value $a
Add-Member -inputObject $infoObject -memberType NoteProperty -name "RecycleTime" -value $recycle

$infoObject
} | Select-Object * -ExcludeProperty PSComputerName, RunspaceId, PSShowComputerName | Export-Csv -append -path  "C:\temp\recycling.csv" -NoTypeInformation 

}

问题根源

脚本核心错误在于对象创建与输出逻辑的位置错误:

  1. 仅在循环外创建了一个$infoObject对象,循环内仅更新$recycle和$a变量,循环结束后才执行属性添加与输出,最终只会生成一条数据(若中途无报错,会保留最后一个应用池的信息;若某应用池不存在导致脚本中断,则仅输出第一个有效应用池的数据)。
  2. 缺少错误处理,单个应用池的异常会直接终止整个服务器的脚本执行,导致后续应用池数据无法获取。

修正后的脚本

$apppools = Get-Content C:\temp\apppools.txt
$servers = Get-Content C:\temp\servers.txt

foreach ($server in $servers) {
    Invoke-Command -ComputerName $server -ArgumentList $apppools -ScriptBlock {
        param($apppools)
        $serverName = $env:COMPUTERNAME
        
        # 确保WebAdministration模块加载成功
        try {
            Import-Module WebAdministration -ErrorAction Stop
        }
        catch {
            Write-Error "无法加载WebAdministration模块: $_"
            return
        }

        foreach ($a in $apppools) {
            try {
                # 获取应用池回收计划时间
                $recycleSchedule = Get-ItemProperty -Path "IIS:\AppPools\$a" -Name recycling.periodicRestart.schedule.collection -ErrorAction Stop
                $recycleTime = $recycleSchedule.Value.ToString()

                # 为每个应用池创建独立输出对象
                [PSCustomObject]@{
                    ServerName  = $serverName
                    AppPool     = $a
                    RecycleTime = $recycleTime
                }
            }
            catch {
                # 捕获异常并标记,不中断后续执行
                [PSCustomObject]@{
                    ServerName  = $serverName
                    AppPool     = $a
                    RecycleTime = "获取失败: $_"
                }
            }
        }
    } | Select-Object * -ExcludeProperty PSComputerName, RunspaceId, PSShowComputerName | 
        Export-Csv -Append -Path "C:\temp\recycling.csv" -NoTypeInformation
}

关键优化说明

  • 将对象创建逻辑移至应用池循环内部,确保每个应用池生成独立的输出条目。
  • 增加try/catch错误处理,单个应用池的异常不会影响其他应用池或服务器的执行。
  • 使用[PSCustomObject]直接构造对象,替代New-Object+Add-Member的繁琐写法,提升效率与可读性。
  • 用$env:COMPUTERNAME替代hostname,符合PowerShell最佳实践。

内容的提问来源于stack exchange,提问作者dbutts

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 15:03:17