業務SE が初めて触る AD バルクユーザー作成 — PowerShell で30人を5分で登録するスクリプト

みなさんこんにちは!ヒロポンです!

「新人30人分のADアカウント、今日中に作っといて」

朝礼でこれ言われた時、業務SEは何を思いますか??

俺なら血の気が引きます…!!だってGUIでポチポチやると、1人あたり3-4分。30人なら2時間コース。しかも初期パスワード設定とか、OUパス選択とか、毎回ミスる罠が散らばってる。

で、これPowerShellで書いたら5分で終わります。マジで。

今回は業務SEが初めてADバルク登録に挑む時の、CSV → Import-CsvNew-ADUserの実戦パターンをまとめていきます。Docker検証で実走したターミナルキャプチャも貼ります。

目次

忙しい人向けに最初にまとめ

  • 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つあります。

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 / catch1人失敗しても残り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
}

実行結果:

ConvertFrom-Csv + PSCustomObject の実行結果 (verify-pwsh container)

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)]"
}

実行結果:

スプラッティング (@params) の引数組み立て検証

ハッシュテーブルに詰め込んだ引数が、そのまま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 UTF8BOM付き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に落とす運用を推奨します。

関連記事

以上!

執筆者

バイブス父さん — 業務 SE 7 年 (正社員 2 / フリーランス 5)。 現職は SEO 直轄部の AI アドバイザー兼 PL、 副業で中小 SIer の CTO。 SES 複数社・フリーランスエージェント複数経由の経験ベースで「業務 SE 視点」 の技術 + キャリア記事を書いています。

🐦 X: @hiro_progra0524 (日々の現場メモ更新中)
📝 About Me で経歴詳細を見る

この記事が気に入ったら
いいねしてね!

どんどんシェア待ってるぜ!!
  • URLをコピーしました!

コメント

コメントする

CAPTCHA


目次