【Powershell】複数のWindowsOSのローカルユーザーを一括で削除するツール

スポンサーリンク
powershell
スポンサーリンク

複数のWindowsサーバのローカルユーザーを一括で削除したい

訳あってドメイン参加している複数のWindowsサーバ上のローカルユーザーを一部削除する必要があったので、Powershellを利用して一括削除できるようにした。

搭載機能

  • 指定したユーザリストに存在するWindowsサーバから指定のローカルユーザを削除する。

ユーザリストはフォーマット固定にする
第一カラムをIPaddress、第二カラムをUserNameとする。

みたいな。
ファイルはCSVファイル形式とする。
・今回はドメイン参加しているサーバが対象なので、認証情報はドメインのAdministratorを使用する。(もちろん権限さえあればなんでもいい)
・結果はCSVファイルで出力する。ファイル名に実行年月日時分秒をつける。
・ユーザ数が多いと時間がかかるので、進捗状況が表示されるようにする。
・ユーザリストはテキストボックスで指定できるようにする。
・後からエラーなどを終えるように実行ログを別ファイルとして吐き出す。(別途関数にしたほうが良かった気がする。要改善)

コード

絶対改善余地があるけどこんな感じ。

#
# ローカルユーザーを削除するスクリプト
#
# ファイル名:WinLocalUserDelete.ps1


# 削除対象ユーザ情報の初期化
$UserList = $null

# 連想配列の初期化
$array = @{}

# 日付の取得
$date = Get-Date -Format "yyyyMMdd";

# 時間の取得
$time = Get-Date -Format "HHmmss";

# 調査結果を出力するフォルダ
$scriptPath = $MyInvocation.MyCommand.Path
$scriptPath_split = Split-Path -Parent $scriptPath
$ResultFolder = ($scriptPath_split+"\結果")

# 調査結果出力結果フォルダがなかったら作成
if( -not (Test-Path $ResultFolder) ) {
    New-Item $ResultFolder -Type Directory
}

# 実行結果出力ファイル名
$ExecuteLogFile = ( "\ExecuteLog_"+$date+"_"+$time+".log" )

#実行結果出力フォルダとファイル名のマージ
$ExecuteLog = Join-Path $ResultFolder $ExecuteLogFile

# アセンブリ読み込み
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# フォーム作成
$Form = New-Object System.Windows.Forms.Form
$Form.Size = New-Object System.Drawing.Size(400,130)
$Form.Text = "WindowsServerローカルユーザー削除ツール"

# ラベル作成
$LabelFilePath = New-Object System.Windows.Forms.Label
$LabelFilePath.Location = New-Object System.Drawing.Point(20,10)
$LabelFilePath.Size = New-Object System.Drawing.Size(300,20)
$LabelFilePath.Text = "ユーザリストのファイル(CSVのみ)を入力してください"
$Form.Controls.Add($LabelFilePath)

# 入力用テキストボックス
$TextBoxFilePath = New-Object System.Windows.Forms.TextBox
$TextBoxFilePath.Location = New-Object System.Drawing.Point(20,30)
$TextBoxFilePath.Size = New-Object System.Drawing.Size(300,20)
$Form.Controls.Add($TextBoxFilePath)

# 参照ボタン
$ButtonFilePath = New-Object System.Windows.Forms.Button
$ButtonFilePath.Location = New-Object System.Drawing.Point(320,30)
$ButtonFilePath.Size = New-Object System.Drawing.Size(40,20)
$ButtonFilePath.Text = "参照"
$Form.Controls.Add($ButtonFilePath)

# OKボタン
$ButtonOK = New-Object System.Windows.Forms.Button
$ButtonOK.Location =  New-Object System.Drawing.Point(230,60)
$ButtonOK.Size = New-Object System.Drawing.Size(60,20)
$ButtonOK.Text = "OK"
$Form.Controls.Add($ButtonOK)

# Cancelボタン
$ButtonCancel = New-Object System.Windows.Forms.Button
$ButtonCancel.Location =  New-Object System.Drawing.Point(300,60)
$ButtonCancel.Size = New-Object System.Drawing.Size(60,20)
$ButtonCancel.Text = "キャンセル"
$ButtonCancel.DialogResult = "Cancel"
$Form.Controls.Add($ButtonCancel)

# 参照ボタンをクリック時の動作
$ButtonFilePath.add_click{

    #ダイアログを表示しファイルを選択する
    $Dialog = New-Object System.Windows.Forms.OpenFileDialog
    $Dialog.Filter = "CSVファイル(*.csv) | *.csv"
    if($Dialog.ShowDialog() -eq "OK"){
        $TextBoxFilePath.Text = $Dialog.FileName
    }
}

# OKボタンをクリック時の動作
$ButtonOK.add_click{

    #ファイルパスが入力されていないときは背景を黄色にする
    if($TextBoxFilePath.text -eq ""){
        $TextBoxFilePath.BackColor = "yellow"
    }else{
        $Form.DialogResult = "OK"
    }
}


Start-Transcript $ExecuteLog

# フォームを表示し処理が完了したら結果を返す
$FormResult = $Form.ShowDialog()
if($FormResult -eq "OK"){

$UserList = $TextBoxFilePath.Text

echo $UserList"のローカルユーザーを削除します。この処理は数分ほどかかります。調査中にPowershellのウィンドウのサイズ変更をしないでください。"

echo "認証情報取得のためパスワードを入力してください。"

# 削除実行用の認証情報を取得する(ここではAdministratorをサンプルとする)
$AdminCred = Get-Credential -Credential Administrator


###進捗表示用###
echo "ユーザ数取得中"
$GetUserList = Import-CSV $UserList
$UserCount = $GetUserList.Length
$counter   = 0
echo ("ユーザ数="+$UserCount)
echo "調査開始"
echo ""
$denominator = "/"+[string]$UserCount

ForEach($a in $GetUserList){
    $counter ++;
    Write-Progress -activity "ユーザ配列化-進捗状況" -status $counter$denominator -percentComplete ($counter / $UserCount * 100)
    if ($array.ContainsKey($a.IPaddress)) {
        # 既存に存在するIPアドレス値(つまり重複)
    } else {
        # 新規IPアドレス値なので、要素の追加
        $d = $array.Add($a.IPaddress, (New-Object System.Collections.ArrayList))
    }
    # ハッシュ値に対するファイルパスの格納(重複の場合、Valueが増えていく)
    $d = $array[$a.IPaddress].Add($a.UserName)
}

$counter   = 0

$array.GetEnumerator() | % {
    $IPaddress = $_.Name
    $Users = $_.Value

        # 対象サーバ向けの新規セッションを作成
    $SVsession = New-PSSession $IPaddress -Credential $AdminCred

    $Users | % {
    $counter ++;
    Write-Progress -activity "ユーザ削除-進捗状況" -status $counter$denominator -percentComplete ($counter / $UserCount * 100)

    $User = $_

    echo $IPaddress":"$User" の削除を実行します..."
    # 対象サーバ(リモート)にユーザーIDを変数で渡し、削除(remove)する。
        Invoke-Command -Session $SVSession -ScriptBlock { $UserID = $args[0] } -ArgumentList $User
        Invoke-Command -Session $SVSession -ScriptBlock { Remove-LocalUser -Name $UserID -Confirm }

    }

    # 作成したセッションを閉じる
    Remove-PSSession $SVSession

}

Invoke-item $ExecuteLog

} else {
}
Stop-Transcript

実行イメージ

注意点と補足

・PowerShellが実行可能な環境である必要があります。
・実行環境となるサーバ自身のユーザ削除はできない。(New-PSSessionで取得できないはず)

改版履歴

2021/01/29 初版公開

コメント

タイトルとURLをコピーしました