【Powershell】複数のWindowsOSのローカルユーザーを一括で調べるツール

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

複数のWindowsサーバのローカルユーザーを一括で調べたい

複数のWindowsサーバのローカルユーザーに何がいるのか一括で調べるツール。
訳あってドメイン参加しているWindowsサーバ全てのローカルユーザーを取得する必要があったので、Powershellを利用して作成した。

搭載機能

・指定したサーバリストに存在するWindowsサーバからローカルユーザを取得する。
サーバリストはフォーマット固定にする
第一カラムをName、第二カラムをIPaddressとする。
※処理上は第ニカラムだけでもいいけど一応
Name,IPaddress
サーバホスト名,192.168.1.1
みたいな。
ファイルはCSVファイル形式とする。
・今回はドメイン参加しているサーバが対象なので、認証情報はドメインのAdministratorを使用する。
・取得する情報は
Name=ローカルユーザー名
Domain=サーバ名
Description=ユーザーの説明
PasswordExpires=パスワード期限が無期限かどうか
Disabled=アカウントが有効かどうか
Lockout=アカウントがロックアウトされているかどうか
の6点を取得する
・結果はCSVファイルで出力する。ファイル名に実行年月日時分秒をつける。
・サーバ数が多いと時間がかかるので、進捗状況が表示されるようにする。
・サーバリストはテキストボックスで指定できるようにする。
・後からエラーなどを終えるように実行ログを別ファイルとして吐き出す。
※別途関数にしたほうが良かった気がする。要改善

コード

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

#
# Windowsサーバからローカルユーザ情報を取得するスクリプト
#
# ファイル名:Get-WinLocalUsers.ps1

# 調査対象サーバ情報の初期化
$ServerList = $null
# CSVテーブルの用意
$CSVdatas = @()
# 日付の取得
$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"){

$ServerList = $TextBoxFilePath.Text

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

# 調査結果出力ファイル名
$ResultFile = ( "\WinLocalUsers"+"_"+$date+"_"+$time+".csv" )
# 調査結果出力フォルダとファイル名のマージ
$Result = Join-Path $ResultFolder $ResultFile

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

# ドメインのAdministratorの認証情報を取得する
$AdminCred = Get-Credential -Credential [ドメイン名]\Administrator

###進捗表示用###
echo "サーバ数取得中"
$GetServerList = Import-CSV $ServerList
$ServerCount = $GetServerList.Length
$counter   = 0
echo ("サーバ数="+$ServerCount)
echo "調査開始"
echo ""
$denominator = "/"+[string]$ServerCount

ForEach($a in $GetServerList){ 
    $counter ++;
    Write-Progress -activity "進捗状況" -status $counter$denominator -percentComplete ($counter / $ServerCount * 100)
    if( $a.IPaddress -eq ""){
    } else {

	# 対象サーバ向けの新規セッションを作成
    $SVsession = New-PSSession $a.IPaddress -Credential $AdminCred
    
    # リモートセッション上へローカルユーザー取得コマンドを渡す。結果をCSVに出力する
    $Item = Invoke-Command -Session $SVSession -ScriptBlock { Get-WmiObject Win32_UserAccount | ? { $_.LocalAccount -eq $true } | Select-Object -Property Name,Domain,Description,PasswordExpires,Disabled,Lockout } 
    
    ForEach($b in $Item){

    $CSVdata = New-Object PSObject | Select-Object Server,IPaddress,UserName,Description,PasswordExpires,Disabled,Lockout
    $CSVdata.Server = $b.Domain
    $CSVdata.IPaddress = $b.PSComputerName
    $CSVdata.UserName = $b.Name
    $CSVdata.Description = $b.Description
    $CSVdata.PasswordExpires = $b.PasswordExpires
    $CSVdata.Disabled = $b.Disabled
    $CSVdata.Lockout = $b.Lockout
    $CSVdatas += $CSVdata
    }
        
    # 作成したセッションを閉じる
    Remove-PSSession $SVSession

    } 
            }
}

$CSVdatas | Export-CSV $Result -Encoding Default -NoTypeInformation


# 調査結果ファイルを開く
Invoke-item $Result

else {

echo "操作はキャンセルされました"

}

Stop-Transcript

実行イメージ

どっかで追加します

注意点と補足

・PowerShellが実行可能な環境である必要があります。
・共有フォルダなどで利用する場合は認証済みである必要があります。
・取得したい情報はGet-WmiObject Win32_UserAccountで取れるものなら
追加可能なので取得したい情報に合わせて要素増やす

改版履歴

2020/09/06 初版公開

コメント

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