PowerShell脚本Get-ADUser抛ContinueException,Catch块失效且脚本终止求助
问题排查:PowerShell处理AD用户特殊字符时Catch块失效及脚本终止问题
问题描述
在Windows Server 2012上使用PowerShell v5编写脚本,用于替换AD用户属性中的特殊字符。已添加Catch块尝试捕获错误,但无法记录错误详情;脚本顶部已设置$ErrorActionPreference = 'Stop',并将错误输出改为$_.Exception.Message,但日志中仍无错误痕迹。控制台报错显示Get-ADUser抛出System.Management.Automation.ContinueException,当遇到displayName为空的用户时,脚本直接停止,无法处理后续用户。
报错信息
Get-ADUser : System error. At C:\Users\test\Documents\Skripts\replace_umlaute.ps1:10 char:1 + Get-ADUser -Filter * -SearchBase $OUpath -properties $paramlist | Sel ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Get-ADUser], ContinueException + FullyQualifiedErrorId : ActiveDirectoryCmdlet:System.Management.Automation.ContinueException,Microsoft.ActiveDirectory.Management.Commands.GetADUser
原脚本代码
Get-ADUser -Filter * -SearchBase $OUpath -properties $paramlist | Select-object $paramlist | foreach{ try{ if([bool]$_.sAMAccountName -And $_.displayName -match "[üäßöÜÄÖ]"){ $aux = [regex]::Replace($_.displayName,'[äöü](?:(?=ß)|\p{L})?',{ param($m) ([string] $m.Value[0]).Normalize('FormD')[0] + $(if ([char]::IsUpper($(if ($m.Value[1]) { $m.Value[1] } else { $m.Value[0] }))) { 'E' } else { 'e' }) + $m.Value[1] },'IgnoreCase' ) $dnp = $aux -creplace '(?<=\p{Ll})ß','ss' -creplace '(?<=\p{Lu})ß','SS' if(!($_.displayNamePrintable -ceq $dnp)) { $dp = $_.displayName try{ Set-ADUser -Identity $_.sAMAccountName -Replace @{displayNamePrintable=$dnp} "`r$(Get-Date -Format "dd.MM.yyyy - HH':'mm':'ss") [$dp] displayNamePrintable of User $($_.cn) updated to $dnp`r" | out-file $log -Append -Encoding UTF8 }catch{ "`r" | out-file $log -Append -Encoding UTF8 $_.Exception.Message | out-file $log -Append -Encoding UTF8 "`r" | out-file $log -Append -Encoding UTF8 continue } } }else{ continue } }catch{ "`r" | out-file $log -Append -Encoding UTF8 $_.Exception.Message | out-file $log -Append -Encoding UTF8 "`r" | out-file $log -Append -Encoding UTF8 } }
问题原因分析
- 错误发生在管道起始阶段,未被当前Catch块捕获:现有脚本的try/catch仅包裹了
foreach内部逻辑,但ContinueException是Get-ADUser执行时抛出的,此时尚未进入foreach循环,后续Catch块无法捕获该错误。 - 空值触发正则匹配异常:当
displayName为空时,执行$_.displayName -match "[üäßöÜÄÖ]"会触发异常;由于$ErrorActionPreference = 'Stop',该异常被升级为终止错误,直接导致管道终止,脚本停止运行。
修复方案
1. 给Get-ADUser添加错误捕获
将Get-ADUser单独处理,使用-ErrorAction SilentlyContinue和-ErrorVariable捕获阶段错误,避免管道终止:
# 获取AD用户并捕获阶段错误 $adUsers = Get-ADUser -Filter * -SearchBase $OUpath -properties $paramlist -ErrorAction SilentlyContinue -ErrorVariable adErrors # 记录Get-ADUser的错误 if ($adErrors) { foreach ($err in $adErrors) { "`r$(Get-Date -Format "dd.MM.yyyy - HH':'mm':'ss") Get-ADUser错误: $($err.Exception.Message)`r" | Out-File $log -Append -Encoding UTF8 } } # 继续处理正常获取到的用户 $adUsers | Select-object $paramlist | ForEach-Object { # 原有foreach逻辑 }
2. 提前判断displayName非空
在正则匹配前,先检查displayName是否存在且非空,避免触发空值异常:
if([bool]$_.sAMAccountName -And $_.displayName -and $_.displayName -match "[üäßöÜÄÖ]"){ # 原有替换逻辑 }
3. 优化错误日志记录
将日志内容补充时间戳和用户标识,便于定位问题:
# 替换原有Catch块中的日志代码 "`r$(Get-Date -Format "dd.MM.yyyy - HH':'mm':'ss") 处理用户$($_.cn)错误: $($_.Exception.Message)`r" | Out-File $log -Append -Encoding UTF8
修复后的完整脚本示例
$ErrorActionPreference = 'Stop' $log = "C:\path\to\your\logfile.log" $OUpath = "OU=Users,DC=domain,DC=com" $paramlist = @("sAMAccountName", "displayName", "displayNamePrintable", "cn") # 获取AD用户并捕获阶段错误 $adUsers = Get-ADUser -Filter * -SearchBase $OUpath -properties $paramlist -ErrorAction SilentlyContinue -ErrorVariable adErrors # 记录Get-ADUser的错误 if ($adErrors) { foreach ($err in $adErrors) { "`r$(Get-Date -Format "dd.MM.yyyy - HH':'mm':'ss") Get-ADUser错误: $($err.Exception.Message)`r" | Out-File $log -Append -Encoding UTF8 } } $adUsers | Select-object $paramlist | ForEach-Object { try { # 提前判断displayName非空再执行匹配 if([bool]$_.sAMAccountName -And $_.displayName -and $_.displayName -match "[üäßöÜÄÖ]"){ $aux = [regex]::Replace($_.displayName,'[äöü](?:(?=ß)|\p{L})?',{ param($m) ([string] $m.Value[0]).Normalize('FormD')[0] + $(if ([char]::IsUpper($(if ($m.Value[1]) { $m.Value[1] } else { $m.Value[0] }))) { 'E' } else { 'e' }) + $m.Value[1] },'IgnoreCase' ) $dnp = $aux -creplace '(?<=\p{Ll})ß','ss' -creplace '(?<=\p{Lu})ß','SS' if(!($_.displayNamePrintable -ceq $dnp)) { $dp = $_.displayName try{ Set-ADUser -Identity $_.sAMAccountName -Replace @{displayNamePrintable=$dnp} "`r$(Get-Date -Format "dd.MM.yyyy - HH':'mm':'ss") [$dp] displayNamePrintable of User $($_.cn) updated to $dnp`r" | Out-File $log -Append -Encoding UTF8 }catch{ "`r$(Get-Date -Format "dd.MM.yyyy - HH':'mm':'ss") 更新用户$($_.cn)错误: $($_.Exception.Message)`r" | Out-File $log -Append -Encoding UTF8 continue } } } }catch{ "`r$(Get-Date -Format "dd.MM.yyyy - HH':'mm':'ss") 处理用户$($_.cn)错误: $($_.Exception.Message)`r" | Out-File $log -Append -Encoding UTF8 } }
内容的提问来源于stack exchange,提问作者Zombievirus
相关产品推荐
相关产品推荐

