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

Foreach循环异常:多计算机用户Profile合并至同一PSCustomObject输出问题

问题分析

你的代码存在两个核心问题:

  • 缺少计算机标识:生成的PSCustomObject没有包含ComputerName字段,导致无法区分配置文件所属的计算机,看起来所有配置文件都归属于最后一台机器。
  • 参数类型与输出顺序问题:ComputerName参数为string类型,需要手动分割处理;同时Write-Host的即时输出与管道对象的延迟输出顺序不一致,造成标题和对应配置文件显示错位。
解决方案

方案1:每个配置文件生成独立对象(带计算机标识)

这个方案修正参数类型,给每个配置文件对象添加所属计算机名称,同时确保输出顺序符合预期:

Function Get-UserProfiles {
    [CmdletBinding()]
    Param(
        [string[]]$ComputerName = "localhost",  # 改为数组类型,直接支持多个计算机名
        [array]$ExcludedProfiles = @()
    )
    foreach ($Computer in $ComputerName) {
        Write-Host "`n== All profiles on $($Computer) ==`n"
        try {
            # 获取非特殊用户配置文件,排除指定名称的配置文件
            Get-CimInstance -ComputerName $Computer -className Win32_UserProfile | 
                Where-Object { -not $_.Special } | 
                Foreach-Object {
                    $profileName = $_.LocalPath.Split('\')[-1]
                    if ($profileName -notin $ExcludedProfiles) {
                        [PSCustomObject]@{
                            'ComputerName'          = $Computer  # 添加计算机名称字段
                            'UserName'              = $profileName
                            'Profile path'          = $_.LocalPath
                            'Last used'             = ($_.LastUseTime -as [DateTime]).ToString("yyyy-MM-dd HH:mm")
                            'Is the profile active?'= $_.Loaded
                        }
                    }
                } | Out-Host  # 强制即时输出当前计算机的配置对象,避免延迟
        }
        catch {
            Write-Warning "获取$Computer的配置文件失败:$($PSItem.Exception.Message)"
            continue  # 使用continue跳过当前计算机,继续处理下一台,而非break终止整个循环
        }
    }
}

关键修改点:

  1. 将ComputerName参数改为string[]类型,直接支持传入多个计算机名(如Get-UserProfiles -ComputerName Computer1,Computer2)。
  2. 在PSCustomObject中添加ComputerName字段,明确标记配置文件所属机器。
  3. 使用Out-Host强制即时输出当前计算机的配置对象,确保标题和对应配置文件的显示顺序一致。
  4. 将break改为continue,避免一台机器出错导致整个函数终止。

方案2:每台计算机生成一个包含所有配置文件的对象

如果你确实需要每台计算机对应一个对象(包含该机器的所有配置文件集合),可以使用以下代码:

Function Get-UserProfiles {
    [CmdletBinding()]
    Param(
        [string[]]$ComputerName = "localhost",
        [array]$ExcludedProfiles = @()
    )
    foreach ($Computer in $ComputerName) {
        try {
            # 收集当前计算机的所有符合条件的配置文件
            $profiles = Get-CimInstance -ComputerName $Computer -className Win32_UserProfile | 
                Where-Object { -not $_.Special } | 
                Foreach-Object {
                    $profileName = $_.LocalPath.Split('\')[-1]
                    if ($profileName -notin $ExcludedProfiles) {
                        [PSCustomObject]@{
                            'UserName'              = $profileName
                            'Profile path'          = $_.LocalPath
                            'Last used'             = ($_.LastUseTime -as [DateTime]).ToString("yyyy-MM-dd HH:mm")
                            'Is the profile active?'= $_.Loaded
                        }
                    }
                }
            
            # 生成包含当前计算机和所有配置文件的对象
            [PSCustomObject]@{
                'ComputerName' = $Computer
                'UserProfiles' = $profiles
            }
        }
        catch {
            Write-Warning "获取$Computer的配置文件失败:$($PSItem.Exception.Message)"
            continue
        }
    }
}

使用示例:

调用函数后,每台计算机会返回一个对象,其中UserProfiles属性是该机器的所有用户配置文件集合:

Get-UserProfiles -ComputerName Computer1,Computer2 -ExcludedProfiles "Administrator","DefaultUser"

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 21:33:23