PowerShell调用New-ADUser新建AD用户动态传参报错
AD域用户创建脚本动态传参故障排查
问题现象
- 硬编码参数场景:直接给OU变量赋值类似
$OU = 'OU=TESTS,OU=RDS,DC=dism,DC=local'、安全组变量赋值$MembreDuGroupe = "IffendicTest"时,脚本可正常完成用户创建 - 动态传参场景:将硬编码值替换为WinForm列表控件选中的动态值后,执行抛出「参数无效」错误,报错首先触发在
New-ADUser的Path参数传入环节,后续安全组成员添加步骤也存在同类报错风险 - 现有逻辑:已实现OU、安全组列表从AD动态拉取、窗体点选交互,目的是避免操作人员直接接触AD配置,脚本内注释为法语,原始脚本如下:
# Ne surtout pas oublier d'exécuter la commande ci-dessous en mode administrateur # lorsque l'on a un message du genre "Impossible de charger le fichier "ScriptPowerShell.ps1" # Commande à exécuter -> Set-ExecutionPolicy Unrestricted # Import du module de l'AD pour l'exécution de AD cmdlets Import-Module ActiveDirectory # Bibliothèques pour la création de formulaire Add-Type -AssemblyName System.Windows.Forms Add-Type -AssemblyName System.Drawing Add-Type -AssemblyName PresentationFramework # Chargement de l'assemblage permettant d'afficher 1 MessageBox [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") # Saisie des informations générales de l'utilisateur [void][Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') Clear-Host # On définit le "UPN" $UPN = "dism.local" # # Encapsulation en mémoire des données de l'utilisateur dans les # # variables cortrespondantes $msgID = "Saisissez l'identifiant de l'utilisateur : " $identifiant = [Microsoft.VisualBasic.Interaction]::InputBox($msgID,"Identifiant") #, $titreID) if (Get-ADUser -F { SamAccountName -eq $identifiant }) { # Si l'utilisateur existe, afficher un message d'alerte et mettre fin au script $msgBox =[System.Windows.Forms.Messagebox]::Show("Le compte d'utilisateur $identifiant existe déjà dans l'AD.","Oups ! Un doublon...") $msgBox =[System.Windows.Forms.Messagebox]::Show("Fin du script...","Fin du processus") Exit } # Création du formulaire de stockage des groupes de sécurité de l'AD $frmGRP = New-Object System.Windows.Forms.Form $frmGRP.Text = 'Selection de groupes' $frmGRP.Size = New-Object System.Drawing.Size(300,500) $frmGRP.StartPosition = 'CenterScreen' $OKButton = New-Object System.Windows.Forms.Button $OKButton.Location = New-Object System.Drawing.Point(75,430) $OKButton.Size = New-Object System.Drawing.Size(75,23) $OKButton.Text = 'OK' $OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK $frmGRP.AcceptButton = $OKButton $frmGRP.Controls.Add($OKButton) $CancelButton = New-Object System.Windows.Forms.Button $CancelButton.Location = New-Object System.Drawing.Point(150,430) $CancelButton.Size = New-Object System.Drawing.Size(75,23) $CancelButton.Text = 'Abandonner' $CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel $frmGRP.CancelButton = $CancelButton $frmGRP.Controls.Add($CancelButton) $lblGRP = New-Object System.Windows.Forms.Label $lblGRP.Location = New-Object System.Drawing.Point(10,20) $lblGRP.Size = New-Object System.Drawing.Size(480,20) # New-Object System.Drawing.Size(280,20) $lblGRP.Text = 'Veuillez selectionner un ou plusieurs groupes...' $frmGRP.Controls.Add($lblGRP) $lstbGRP = New-Object System.Windows.Forms.Listbox $lstbGRP.Location = New-Object System.Drawing.Point(10,40) $lstbGRP.Size = New-Object System.Drawing.Size(260,20) # Activation de la sélection multiples de groupes de sécurité $lstbGRP.SelectionMode = 'MultiExtended' # Nom du fichier .csv des groupes de sécurité de l'AD $fichierGRP = ".\ExportedGRP.csv" if (Test-Path $fichierGRP) { Remove-Item $fichierGRP } # Création dynamique de la liste des groupes de sécurité Get-ADGroup -Filter '*' | Where-Object{ $_.objectclass -eq 'Group' } ` | Select-Object name ` | Sort-Object name ` | Export-Csv -encoding utf8 -Path $fichierGRP (Get-Content $fichierGRP) -Replace '"', '' | Set-Content $fichierGRP Get-Content $fichierGRP | ForEach-Object {[void] $lstbGRP.Items.Add($_)} # Taille du champs d'affichage de la liste des groupes de sécurité $lstbGRP.Height = 390 $frmGRP.Controls.Add($lstbGRP) $frmGRP.Topmost = true # Affichage du formulaire des groupes de sécurité $resultGRP = $frmGRP.ShowDialog() # Sélection d'un groupe de sécurité pour l'utilisateur if ($resultGRP -eq [System.Windows.Forms.DialogResult]::OK) { $MembreDuGroupe = $lstbGRP.SelectedItems # Lignes ci-dessous à supprimer, par la suite. $msgBox =[System.Windows.Forms.Messagebox]::Show("Groupe de sécurité sélectionné = $MembreDuGroupe","Contrôle sélection Groupe de sécurité") } else { $msgBox =[System.Windows.Forms.Messagebox]::Show("Fin du script...","Fin du processus") Exit } # Création du formulaires des OU $frmOU = New-Object System.Windows.Forms.Form $frmOU.Text = 'Uniés Organisationnelles' $frmOU.Size = New-Object System.Drawing.Size(300,210) $frmOU.StartPosition = 'CenterScreen' $lblOU = New-Object System.Windows.Forms.Label $lblOU.Location = New-Object System.Drawing.Point(10,20) $lblOU.Size = New-Object System.Drawing.Size(280,20) $lblOU.Text = 'Veuillez selectionner une ou plusieurs OU...' $frmOU.Controls.Add($lblOU) $lstbOU = New-Object System.Windows.Forms.Listbox $lstbOU.Location = New-Object System.Drawing.Point(10,40) $lstbOU.Size = New-Object System.Drawing.Size(260,20) #$lstbOU.SelectionMode = 'MultiExtended' $btnOU_OK = New-Object System.Windows.Forms.Button $btnOU_OK.Location = New-Object System.Drawing.Point(75,140) $btnOU_OK.Size = New-Object System.Drawing.Size(75,23) $btnOU_OK.Text = 'OK' $btnOU_OK.DialogResult = [System.Windows.Forms.DialogResult]::OK $btnOU_Cancel = New-Object System.Windows.Forms.Button $btnOU_Cancel.Location = New-Object System.Drawing.Point(150,140) $btnOU_Cancel.Size = New-Object System.Drawing.Size(75,23) $btnOU_Cancel.Text = 'Abandonner' $btnOU_Cancel.DialogResult = [System.Windows.Forms.DialogResult]::Cancel $frmOU.CancelButton = $btnOU_Cancel $frmOU.Controls.Add($btnOU_Cancel) $frmOU.AcceptButton = $btnOU_OK $frmOU.Controls.Add($btnOU_OK) # Nom du fichier des OU au format .csv $fichierOU = ".\ExportedOUs.csv" # Remise à neuf du fichier -> Suppression du fichier, s'il existe if (Test-Path $fichierOU) { Remove-Item $fichierOU } # Creation d'un fichier CSV pour stocker les OU Get-ADOrganizationalUnit -Filter * ` -Properties Name | Sort-Object Name ` | Select-Object -Property DistinguishedName ` | Export-Csv -encoding utf8 -Path $fichierOU (Get-Content $fichierOU) -Replace '"', "'" | Set-Content $fichierOU Get-Content $fichierOU | ForEach-Object {[void] $lstbOU.Items.Add($_)} # Taille du champs d'affichage de la liste $lstbOU.Height = 100 $frmOU.Controls.Add($lstbOU) $frmOU.Topmost = $true $resultOU = $frmOU.ShowDialog() # Sélection d'un OU pour l'utilisateur if ($resultOU -eq [System.Windows.Forms.DialogResult]::OK) { $OU = $lstbOU.SelectedItems # Ligne ci-dessous à supprimer, par la suite. $msgBox =[System.Windows.Forms.Messagebox]::Show("OU sélectionnée = $OU","Contrôle sélection OU") } else { $msgBox =[System.Windows.Forms.Messagebox]::Show("Fin du script...","Fin du processus") Exit } # Enregistrement des données try { New-ADUser -Name $identifiant -Path $OU # 'OU=TESTS,OU=RDS,DC=dism,DC=local' -Path $OU -SamAccountName $identifiant ` # #Affecter l'utilisateur à un groupe Add-ADGroupMember -Identity $MembreDuGroupe -Members $identifiant #'IffendicTest' # A la création de l'utilisateur, afficher un message d'information $msgBox =[System.Windows.Forms.Messagebox]::Show("L'utilisateur $identifiant a été créé avec succès.","Création d'un utilisateur") } Catch { # Affichage du message d'erreur # Récupération et affichage du message d'erreur dans son intégralité $formatstring = "{0} : {1}`n{2}`n" + " + CategoryInfo : {3}`n" + " + FullyQualifiedErrorId : {4}`n" $fields = $_.InvocationInfo.MyCommand.Name, $_.ErrorDetails.Message, $_.InvocationInfo.PositionMessage, $_.CategoryInfo.ToString(), $_.FullyQualifiedErrorId # Pour afficher le message d'erreur dale la fenêtre PowerShell ISE # Supprimer le '#' avec la cmdlets ci-dessous : '$formatstring -f $fields' # $formatstring -f $fields $msgBox =[System.Windows.Forms.Messagebox]::Show("Une erreur est survenue lors de la création de l'utilisateur " + $identifiant + " " + $fields,"Oups ! Erreur lors du processus") } # Fin des traitements... $msgBox =[System.Windows.Forms.Messagebox]::Show("Fin de traitements...","Fin du processus")
故障根因
- 字符处理错误:导出OU的CSV文件时,脚本将CSV原生包裹字段的双引号全局替换为单引号,最终选中的OU路径值前后会带上多余的单引号,不符合AD可分辨名称的格式要求;导出安全组CSV时全局删除所有双引号,还会将CSV表头行作为可选项加载到列表,选中时会传入无效值。
- 参数类型不匹配:WinForm列表控件的
SelectedItems属性返回的是对象集合,不是单个字符串,直接传入要求接收单字符串值的-Path、-Identity参数时,会触发类型校验失败。 - 命令语法错误:
New-ADUser调用段第一行结尾未加换行反引号,还重复定义了两次-Path $OU,导致PowerShell将后续参数识别为独立命令,解析失败。 - 逻辑冗余:通过导出CSV再读回内存的方式加载列表选项,额外引入文件IO异常风险,无实际必要。
修复方案
- 移除CSV中转逻辑:直接将AD查询返回的结果加载到窗体列表项,不需要落地为临时文件,从根源避免字符替换、表头误入选项的问题
- 修正取值逻辑:单选OU场景下,取选中集合的第一个元素转为字符串;多选安全组场景下,直接传递选中集合数组给
Add-ADGroupMember即可 - 修正cmdlet语法:删除重复的
-Path参数,调整换行反引号位置保证参数连续,补全启用账号、设置初始密码、UPN等必要参数 - 增加前置校验:在调用AD cmdlet前判断选中值是否为空,提前拦截无效输入
修正后核心代码片段
# 安全组列表加载逻辑:移除CSV中转,直接加载AD组到列表 Get-ADGroup -Filter '*' | Where-Object{ $_.objectclass -eq 'Group' } ` | Select-Object -ExpandProperty Name ` | Sort-Object | ForEach-Object {[void] $lstbGRP.Items.Add($_)} # 安全组选中值校验 if ($resultGRP -eq [System.Windows.Forms.DialogResult]::OK) { $MembreDuGroupe = $lstbGRP.SelectedItems if (-not $MembreDuGroupe) { [System.Windows.Forms.Messagebox]::Show("未选择任何安全组,脚本退出","错误") Exit } } # OU列表加载逻辑:移除CSV中转、移除错误的引号替换逻辑,直接加载OU可分辨名称到列表 Get-ADOrganizationalUnit -Filter * -Properties Name ` | Sort-Object Name ` | Select-Object -ExpandProperty DistinguishedName ` | ForEach-Object {[void] $lstbOU.Items.Add($_)} # OU选中值校验、类型转换 if ($resultOU -eq [System.Windows.Forms.DialogResult]::OK) { $OU = $lstbOU.SelectedItem.ToString() if (-not $OU) { [System.Windows.Forms.Messagebox]::Show("未选择任何OU,脚本退出","错误") Exit } } # AD用户创建逻辑语法修正 try { # 替换为实际需要的初始密码规则 $defaultPass = ConvertTo-SecureString "P@ssw0rd2024!" -AsPlainText -Force New-ADUser -Name $identifiant ` -Path $OU ` -SamAccountName $identifiant ` -UserPrincipalName "$identifiant@$UPN" ` -AccountPassword $defaultPass ` -Enabled $true ` -ErrorAction Stop # 批量添加用户到选中的安全组 foreach ($grp in $MembreDuGroupe) { Add-ADGroupMember -Identity $grp -Members $identifiant -ErrorAction Stop } [System.Windows.Forms.Messagebox]::Show("L'utilisateur $identifiant a été créé avec succès.","Création d'un utilisateur") } Catch { $formatstring = "{0} : {1}`n{2}`n" + " + CategoryInfo : {3}`n" + " + FullyQualifiedErrorId : {4}`n" $fields = $_.InvocationInfo.MyCommand.Name, $_.ErrorDetails.Message, $_.InvocationInfo.PositionMessage, $_.CategoryInfo.ToString(), $_.FullyQualifiedErrorId [System.Windows.Forms.Messagebox]::Show("Une erreur est survenue lors de la création de l'utilisateur " + $identifiant + " " + $fields,"Oups ! Erreur lors du processus") }
内容的提问来源于stack exchange,提问作者Moumouni
相关产品推荐
相关产品推荐

