みなさんこんにちは!ヒロポンです!
「新人30人分の AD アカウント、今日中に作っといて」
朝礼でこれ言われた時、業務SE は何を思いますか??
俺なら 血の気が引きます…!! だって GUI でポチポチやると、1人あたり3-4分。30人なら2時間コース。しかも初期パスワード設定とか、OU パス選択とか、毎回ミスる罠が散らばってる。
で、これ PowerShell で書いたら 5分で終わります。マジで。
今回は業務SE が初めて AD バルク登録に挑む時の、CSV → Import-Csv → New-ADUser の実戦パターンをまとめていきます。Docker 検証で実走したターミナルキャプチャも貼ります。
TL;DR
- CSV に30人分の情報を並べて、
Import-Csv | ForEach-Object { New-ADUser @params }で一気に登録できる - GUI なら2時間、PowerShell なら5分。
dsadd.exeという第三の選択肢もあるが、可読性と再実行性で PowerShell に収束する - ハマりポイントは パスワード complexity・OU パス順序・SamAccountName 重複・PowerShell 5.1 vs 7 のエンコーディング差。後半でぜんぶ潰します
3つのバルク登録手段を最初に並べる
業務SE が AD アカウントを大量に作る手段は、ざっくり3つあります。

PowerShell が「コードを残せる・再実行できる・エラーが出た行を追える」で、結局これに収束します。
dsadd.exe はレガシーで CSV を直接食えないため、結局ループを書く時点で PowerShell と差が出ない。GUI は1人なら速いけど、30人やる気力は俺には無い。
で、今回の主役は PowerShell です。
Step 1: CSV を設計する
users.csv をこんな感じで用意します。列は最低限これだけ。
GivenName,Surname,SamAccountName,UPN,OU,Password
太郎,山田,t.yamada,t.yamada@example.local,"OU=営業部,OU=Users,DC=example,DC=local",P@ssw0rd!Init2026
花子,鈴木,h.suzuki,h.suzuki@example.local,"OU=営業部,OU=Users,DC=example,DC=local",P@ssw0rd!Init2026
次郎,佐藤,j.sato,j.sato@example.local,"OU=技術部,OU=Users,DC=example,DC=local",P@ssw0rd!Init2026
ポイントは3つ。
- UPN (UserPrincipalName):
samaccount@ドメイン.localの形。Microsoft 365 と連携する現場ならここがログインIDになる - OU パス:
OU=営業部,OU=Users,DC=example,DC=localの DN 形式。末端から書く のがハマりポイント - Password: ドメインのパスワード複雑性ポリシーを満たすこと。大小英字+数字+記号
CSV は UTF-8 with BOM で保存します。BOM 無しだと PowerShell 5.1 で文字化けする罠があります。
Step 2: Import-Csv + ForEach-Object + New-ADUser
ここが本丸。こんな感じで一気に貼ります。
Import-Csv -Path 'users.csv' -Encoding UTF8 | ForEach-Object {
$params = @{
Name = "$($_.GivenName) $($_.Surname)"
GivenName = $_.GivenName
Surname = $_.Surname
SamAccountName = $_.SamAccountName
UserPrincipalName = $_.UPN
Path = $_.OU
AccountPassword = (ConvertTo-SecureString -AsPlainText $_.Password -Force)
Enabled = $true
ChangePasswordAtLogon = $true
}
try {
New-ADUser @params
Write-Host "OK: $($_.SamAccountName)" -ForegroundColor Green
} catch {
Write-Host "NG: $($_.SamAccountName) - $($_.Exception.Message)" -ForegroundColor Red
}
}
@params の書き方は スプラッティング という PowerShell の技。ハッシュテーブルに引数を全部詰めて、 @ プレフィックスで cmdlet に渡せる。
正直、最初に見た時は「は??」ってなったんですけど、慣れるとめちゃくちゃ便利。引数が10個超える cmdlet を、1行のバックスラッシュ地獄から救ってくれます。
try / catch で 1人失敗しても残り29人は通る ようにしてるのも地味に効きます。業務系のバルク処理は「全件 or ゼロ」じゃなく「成功分は通す・失敗分は後でやり直し」が現場の正解。
Step 3: Docker container で言語仕様部分を動作確認
実環境の AD に流す前に、PowerShell 7 で 言語仕様部分だけ Docker で動かして確認しときます。
ActiveDirectory モジュールは Windows Server の RSAT 抜きだと入らないので、Linux container では New-ADUser 自体は呼べません。
代わりに ConvertFrom-Csv でメモリ上の CSV をパースして、各レコードを PSCustomObject に組み立てる 構造化部分 を検証します。
$csvText = @"
GivenName,Surname,SamAccountName
太郎,山田,t.yamada
花子,鈴木,h.suzuki
次郎,佐藤,j.sato
"@
$csvText | ConvertFrom-Csv | ForEach-Object {
$user = [PSCustomObject]@{
Name = "$($_.GivenName) $($_.Surname)"
SamAccountName = $_.SamAccountName
Status = "Created (mock)"
}
$user | ConvertTo-Json -Compress
}
実行結果:

CSV を3件パースして、各 user オブジェクトが JSON で出てきてます。日本語マルチバイトもそのまま通った。これが Step 2 の New-ADUser @params 直前までの動作を保証する 入力検証層 になります。
続いて、スプラッティング (@params) の引数組み立て部分も検証しときます。
$users = @"
GivenName,Surname,SamAccountName,UPN
太郎,山田,t.yamada,t.yamada@example.local
花子,鈴木,h.suzuki,h.suzuki@example.local
"@ | ConvertFrom-Csv
$users | ForEach-Object {
$params = @{
Name = "$($_.GivenName) $($_.Surname)"
GivenName = $_.GivenName
Surname = $_.Surname
SamAccountName = $_.SamAccountName
UserPrincipalName = $_.UPN
}
Write-Host "Created: $($params.Name) ($($params.SamAccountName)) [$($params.UserPrincipalName)]"
}
実行結果:

ハッシュテーブルに詰め込んだ引数が、そのまま Write-Host 側に展開されてるのが確認できる。本番では Write-Host の代わりに New-ADUser @params を置けば、 そのまま実環境に流せます。
実環境への流し込みは Domain Controller 側でしかできないので、残りは Get-ADUser で事後確認すれば OK です。
ハマりポイント4選 (現場で踏みがちなやつ)
ここからが今回の本題かもしれない。業務SE が踏みがちな罠を4つ。
① パスワード complexity 要件で全件失敗
ドメインのデフォルトポリシーは以下のいずれかを満たす必要があります。
- 8文字以上
- 大文字・小文字・数字・記号のうち3種類以上を含む
P@ssw0rd! みたいなテンプレならOK。 でも Pass2026 みたいな 記号無し で投げると、全件 The password does not meet the password policy requirements で死にます。
俺もこれで、ある日のバルク登録30件が全部 NG になって、軽く絶望した記憶があります。CSV の Password 列、 投入前にざっと目で見るだけで防げる事故です。
② OU パスを逆順で書く
OU パスは DN 形式で、末端から書きます。
OU=営業部,OU=Users,DC=example,DC=local # ✅ 正しい
DC=example,DC=local,OU=Users,OU=営業部 # ❌ 順序が逆
逆に書くと The object name has bad syntax で失敗。「DC=local が一番うしろ」と覚えると間違えにくい。
ちなみに OU 名に日本語使ってる現場は普通にあって、その場合 CSV ダブルクオート囲み必須です。
③ SamAccountName が20文字を超えてる
SamAccountName は 20文字制限 があります。taro.yamada.from.sales みたいに長い名前を投げると、cmdlet が黙って切り捨てたり、失敗したりする。
新人の名簿が長い場合は、CSV 投入前に検証しときましょう。
Import-Csv users.csv | Where-Object { $_.SamAccountName.Length -gt 20 }
ヒット行があればそこだけ修正。これで投入後の事故が半分は減ります。
④ PowerShell 5.1 と 7 のエンコーディング差
Import-Csv -Encoding UTF8 の挙動は 5.1 と 7 で微妙に違います。
- 5.1:
-Encoding UTF8は BOM 付き UTF-8 前提。BOM 無し CSV だと文字化け - 7: BOM 有無を自動判定してくれる
ドメインコントローラが Windows Server 2016 で PowerShell 5.1 のまま、ってのは業務系の現場で普通にあるパターン。 ここを踏んで「文字化けでユーザー名が ??? になった」 のはあるあるです。
CSV は BOM 付きで保存する習慣 をつけときましょう。VS Code なら右下のエンコーディング表示クリックで UTF-8 with BOM に切り替えできます。
まとめ
GUI で 30人 = 2時間。PowerShell なら 5分。CSV を整える時間を入れても 30分以内です。
書いたスクリプトは同じドメインなら使い回せるし、翌年の新人受け入れでも users.csv を差し替えるだけで動く。これがコード資産化のうま味なんですよね。
業務SE 1人運用で AD 触る現場って、 そんなにベテランがいないことが多くて、 「PowerShell? あの黒い画面でしょ?」 で止まってる人が多い。 でも1個書き上げると、 俺の業務時間が 明らかに浮きます!!
ぶっちゃけ、 月1の定例登録作業は ぜんぶスクリプト化して、 「実行して結果見るだけ」 に変えるのがゴール。 そこまで持っていけば、 翌月以降の俺が いい感じに 楽できます。
動作確認メモ: 今回のスクリプトは PowerShell 7 言語仕様レベルで Linux container 検証済。 ただし
New-ADUser本体は Windows RSAT (ActiveDirectory モジュール) が前提のため、 実際の登録は Windows ドメインコントローラ または RSAT 入り運用端末 で実行してください。 CSV パース・スプラッティング部分はそのままコピペで動きます。
よくある質問
Q1. PowerShell ISE と Visual Studio Code、どっちで書くべき?
A. VS Code 一択 です。 ISE は新規開発が止まっていて、 PowerShell 7 に対応してない。 VS Code + PowerShell 拡張機能で、 IntelliSense もデバッグも一通り揃います。 業務系の現場でも VS Code は普及してきてるので、入れて損は無いです。
Q2. ActiveDirectory モジュールが入ってないサーバーでは?
A. RSAT (Remote Server Administration Tools) を追加する必要があります。 Windows Server なら役割追加から、 Windows 10/11 クライアントなら設定 > オプション機能 から RSAT をインストール。 これ無いと New-ADUser が無い世界です。 普段使い PC で AD 管理する場合も RSAT を入れます。
Q3. CSV じゃなくて Excel から直接やりたいんですが
A. ImportExcel モジュールを使えば xlsx をそのまま読めます。 Install-Module ImportExcel -Scope CurrentUser で入る。 ただ業務的には CSV 経由が監査ログ的に楽 で、 差分が見やすい・テキスト diff が効く・Git で履歴管理もできる、 という利点があります。 一度 CSV に落とす運用を推奨します。
関連記事
- 業務イントラの認証 — Windows認証 / Forms認証 / Cookie の使い分けで業務SE が踏む選択 — AD と絡む業務系認証パターンの整理
以上!


コメント