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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 08:54:22