如何通过PowerShell获取AD对象当前OU并批量移动计算机账户
问题背景
工作任务为将AD中的计算机账户从当前所属的Production类OU移动至对应的Pilot类OU,目前仅持有一份记录所有待操作计算机账户名的文本文件,文件每行对应一个计算机名,格式如下:
computer1 computer2 computer3 ...
当前操作限制:
- 入职时间较短,无相关AD操作经验,不掌握现有完整OU结构,无架构数据库可查询
- 对PowerShell语法不熟悉,精通PowerShell的同事正在休假,无法提供支持
此前尝试编写的脚本逻辑存在语法错误,且未找到获取AD对象当前所属OU的正确方法:
$computers = Get-Content ".\computers.txt" $computers | ForEach-Object { IF object1's OU = Production1 { Move-ADObject -TargetPath "OU=Pilot1" ELSE { IF object1's OU = Production2 { Move-ADObject -TargetPath "OU=Pilot2" ELSE { Move-ADObject -TargetPath "OU=Pilot3" } } } } }
排查过程中尝试查找获取AD对象所属OU的cmdlet,也通过Get-Member排查AD对象属性,但始终无法确定正确的筛选器、参数和调用方式。
实现方法
核心原理
查询AD计算机对象时,默认返回的DistinguishedName(可分辨名称)属性包含对象的完整层级路径,直接从该属性中即可提取计算机当前所属的OU信息,无需调用特殊cmdlet。例如Production1 OU下名为computer1的计算机,其DistinguishedName格式为CN=computer1,OU=Production1,DC=yourdomain,DC=com,拆分字符串即可得到当前OU名称。
前置准备
操作前需安装RSAT Active Directory管理组件,使用具备AD计算机迁移权限的域账号打开PowerShell,执行以下命令加载AD模块:
Import-Module ActiveDirectory
第一步:摸底所有待迁移计算机的当前OU
在正式执行迁移前,先运行以下命令导出所有待操作计算机的当前所属OU清单,避免因OU结构不明确导致迁移错误:
Get-Content ".\computers.txt" | ForEach-Object { try { $adObj = Get-ADComputer -Identity $_ -ErrorAction Stop $currentOu = $adObj.DistinguishedName -split ',' | Where-Object { $_ -like "OU=Production*" } | Select-Object -First 1 [PSCustomObject]@{ ComputerName = $_ CurrentProductionOU = $currentOu -replace 'OU=','' DistinguishedName = $adObj.DistinguishedName } } catch { [PSCustomObject]@{ ComputerName = $_ CurrentProductionOU = "查询失败" DistinguishedName = $_.Exception.Message } } } | Export-Csv -Path ".\待迁移计算机OU清单.csv" -NoTypeInformation -Encoding UTF8
运行完成后打开同目录下生成的CSV文件,即可看到所有待迁移计算机的所属Production OU名称,确认所有OU映射关系。
第二步:执行迁移脚本
根据摸底得到的OU对应关系,修改脚本中$ouMapping的键值对(键为Production OU名称,值为对应Pilot OU的完整可分辨路径),替换脚本中域DN后缀(如域为contoso.com则将DC=yourdomain,DC=com替换为DC=contoso,DC=com),即可运行:
# 读取待迁移计算机列表 $computers = Get-Content ".\computers.txt" # 配置Production OU到目标Pilot OU的映射关系 $ouMapping = @{ "Production1" = "OU=Pilot1,DC=yourdomain,DC=com" "Production2" = "OU=Pilot2,DC=yourdomain,DC=com" "Production3" = "OU=Pilot3,DC=yourdomain,DC=com" } foreach ($pcName in $computers) { try { # 查询AD中的计算机对象 $adComputer = Get-ADComputer -Identity $pcName -ErrorAction Stop # 提取当前所属Production OU名称 $currentOuSeg = $adComputer.DistinguishedName -split ',' | Where-Object { $_ -like "OU=Production*" } | Select-Object -First 1 $currentOuName = $currentOuSeg -replace 'OU=','' # 匹配目标OU并执行迁移 if ($ouMapping.ContainsKey($currentOuName)) { $targetOuPath = $ouMapping[$currentOuName] Move-ADObject -Identity $adComputer.DistinguishedName -TargetPath $targetOuPath -ErrorAction Stop Write-Host "[成功] 计算机 $pcName 已从 $currentOuName 迁移至对应Pilot OU" -ForegroundColor Green } else { Write-Warning "[跳过] 计算机 $pcName 所属OU $currentOuName 未配置映射规则,未执行迁移" } } catch { Write-Error "[失败] 处理计算机 $pcName 时出错:$($_.Exception.Message)" } }
操作提示
- 首次运行脚本时可先将
Move-ADObject行注释掉,先执行一轮模拟运行,确认控制台输出的迁移路径完全符合预期后,再放开注释执行正式迁移 - 若摸底时发现存在未覆盖的Production OU,直接在
$ouMapping哈希表中新增对应键值对即可,无需修改其他逻辑
内容的提问来源于stack exchange,提问作者yckbrd

