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终止整个循环 } } }
关键修改点:
- 将
ComputerName参数改为string[]类型,直接支持传入多个计算机名(如Get-UserProfiles -ComputerName Computer1,Computer2)。 - 在
PSCustomObject中添加ComputerName字段,明确标记配置文件所属机器。 - 使用
Out-Host强制即时输出当前计算机的配置对象,确保标题和对应配置文件的显示顺序一致。 - 将
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
相关产品推荐
相关产品推荐

