【PowerShell】Windowsのローカルユーザー、グループを大量に作成する

#初めに
私の現場ではまれに各Windows Serverでローカルユーザを作成して、グループへ所属させるような業務が発生する。
少数であればGUIでポチポチ設定してもよいけれど大量に作成する必要があったり、少人数の作成でも頻繁に依頼があると面倒なので
PowerShellでCSVからユーザ設定を読み込んで一括作成したい。


#環境

```powershell:powershell
$PSVersionTable

Name                           Value                                                                                  
----                           -----                                                                                  
PSVersion                      5.1.19041.1                                                                            
PSEdition                      Desktop 
...


Get-Module -Name "Microsoft.PowerShell.LocalAccounts"

ModuleType Version    Name                                ExportedCommands                                            
---------- -------    ----                                ----------------                                            
Binary     1.0.0.0    Microsoft.PowerShell.LocalAccounts  {Add-LocalGroupMember, Disable-LocalUser, Enable-LocalUse...

```
Windows Server環境ではなく個人PCのWindows10 Homeで実施していますがWindows Server 2016以降であればデフォルトで動作するはず。


##使用できるコマンドレット一覧

```powershell:powershell
#グループへ追加する
Add-LocalGroupMember

#有効化無効化
Disable-LocalUser
Enable-LocalUser

#情報取得
Get-LocalGroup
Get-LocalGroupMember
Get-LocalUser

#新規作成
New-LocalGroup
New-LocalUser

#削除
Remove-LocalGroup
Remove-LocalGroupMember
Remove-LocalUser

#名前変更
Rename-LocalGroup
Rename-LocalUser

#設定変更
Set-LocalGroup
Set-LocalUser
```
##注意
Get-で始まるコマンドレット以外はすべて管理者権限での実行が必要。

#ユーザ作成
ユーザの作成は``New-LocalUser``コマンドレットを使用する。
オプションでユーザの各種プロパティを設定可能。[公式ドキュメントはこちら](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.localaccounts/new-localuser?view=powershell-5.1)

```powershell:powershell
New-LocalUser
   [-AccountExpires <DateTime>]	#有効期限
   [-AccountNeverExpires]		#有効期限なし
   [-Description <String>]		#説明
   [-Disabled]					#無効化
   [-FullName <String>]			#フルネーム
   [-Name] <String>				#ユーザ名
   [-Password] <SecureString>	#パスワード
   [-NoPassword]				#パスワードなし
   [-PasswordNeverExpires]		#パスワードを無期限
   [-UserMayNotChangePassword]	#ユーザによってパスワードを変更させない
   [-WhatIf]					#実行せずに結果を確認する
   [-Confirm]					#確認を要求する
   [<CommonParameters>]			
```
``New-LocalUser``で作成されたユーザはどのグループにも所属していない。（Usersグループにも所属していない）
また、``-password``にプレーンテキストを渡すと下記エラーとなるのでコマンドでSystem.Security.SecureString型へ変換する必要がある。


```:実行例
> New-LocalUser -Name 'TEST_USER' -Password 'P@ssw0rd'

New-LocalUser : パラメーター 'Password' をバインドできません。"P@ssw0rd" の値を "System.String" 型から "System.Security.SecureString" 型に変換できま
せん。
発生場所 行:1 文字:43
+ New-LocalUser -Name 'TEST_USER' -Password 'P@ssw0rd'
+                                           ~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [New-LocalUser]、ParameterBindingException
    + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.NewLocalUserCommand
 
```

###System.String型をSystem.Security.SecureString型へ変換するコマンド

```powershell:powershell
convertto-securestring  'P@ssw0rd' -AsPlainText -Force
```

###使用例
```powershell:powershell
#プレーンテキストを暗号化
$password = convertto-securestring 'PASSWORD' -AsPlainText -Force

#ユーザ名TEST_USERを作成
New-LocalUser -Name 'TEST_USER' `
    -Password $password `
    -Description 'テスト用のユーザです' `
    -AccountNeverExpires
```
#ユーザ設定変更
```powershell:powershell
Set-LocalUser -Name TEST_USER -Description 'テスト用のユーザです2020/10/01に破棄'
```

#グループを作成する
```powershell:powershell
#グループ名TEST_GROUPを作成
New-LocalGroup -Name 'TEST_GROUP'
```

#グループへ追加する
```powershell:powershell
#TEST_GROUPグループへTEST_USERを追加
Add-LocalGroupMember -Group 'TEST_GROUP' -Member 'TEST_USER'
```

#CSVからユーザ設定を読み込んで一括で作成するスクリプト(例)

##CSV
作成するユーザの各種設定を記載したCSVを用意する。※文字コードはSJIS
ファイル名は「作成するユーザ設定.csv」としています。

```:見出し
"ユーザ名","パスワード","説明","無期限(TRUE/FALSE)"
```



##スクリプト
下記を実行するとCSVをもとにユーザを一括で作成します。
スクリプトと同一フォルダにある「作成するユーザ設定.csv」を読み込みます。

```powershell:まとめてローカルユーザ作成.ps1
#$PSScriptRootはカレントファルダパス
$csv = Import-Csv -Encoding Default -Path (Join-Path $PSScriptRoot "作成するユーザ設定.csv")

for($i=0; $i -lt $csv.Length; $i++){
    #ユーザー作成
    $Name = $csv.'ユーザ名'[$i]
    New-LocalUser -Name $Name `
        -Password (convertto-securestring $csv.'パスワード'[$i] -AsPlainText -Force) `
        -Description $csv.'説明'[$i]
    
    #CSVの「無期限(TRUE/FALSE)」列にTRUEと記載されている場合実行
    if($csv.'無期限(TRUE/FALSE)'[$i] -eq 'TRUE'){
        Set-LocalUser -Name $Name -AccountNeverExpires
    }

    #Usersグループへ追加する
    Add-LocalGroupMember -Group Users -Member $Name
}
```

##試しに1000ユーザ作成してみる
###コマンドでCSVを作成する

```powershell:powershell
[String[]]$array = @('"ユーザ名","パスワード","説明","無期限(TRUE/FALSE)"')
1..1000 | %{ $array += '"TEST_USER' + $_ + '","P@ssw0rd",,' }

$csvPath = Join-Path $PSScriptRoot "作成するユーザ設定.csv"
Add-Content -Encoding Default -Value $array -Path $csvPath
```

###実行結果
1000ユーザ作成までにかかった時間はこんな感じ。
グループ追加もしてるとはいえ、そこそこかかる・・。

```powershell:powershell
Measure-Command { .\まとめてローカルユーザ作成.ps1 }

Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 56
Milliseconds      : 63
Ticks             : 560634428
TotalDays         : 0.000648882439814815
TotalHours        : 0.0155731785555556
TotalMinutes      : 0.934390713333333
TotalSeconds      : 56.0634428
TotalMilliseconds : 56063.4428
```
以上です。


#参考
* [Microsoft Docs 公式ドキュメント](https://docs.microsoft.com/ja-jp/powershell/module/microsoft.powershell.localaccounts/?view=powershell-5.1)
* [PowerShellでローカルユーザー(アカウント)やグループの追加・変更・削除を行う方法](https://www.haruru29.net/blog/how-to-configure-local-users-using-powershell/)
* [powershellでローカルユーザを追加 - Qiita](https://qiita.com/isyt/items/dcbc9aecf23147506a46)