作業中のメモ

よく「計算機」を使って作業をする.知らなかったことを中心にまとめるつもり.

WSF を用いた Windows メニューの操作

どうも,筆者です.

最近,Windows メニューの操作をする必要が出てきたので,その方法についてまとめておく.

Power Shell 等を利用した方が良いと思うが,時間がなかった為,知っている方法でまとめる.

<job id="chkUser">
    <script language="VBScript">
       ' InputBox
        function vbsInputBox(prompt)
            vbsInputBox = InputBox(prompt)
        end function
    </script>

    <script language="JScript">
        var winFS = WScript.CreateObject('Scripting.FileSystemObject');
        var winShell = WScript.CreateObject("WScript.Shell");
        // 待機時間
        var waitTime = 200;
        // 表示時間
        var displayTime = 3000;

        // InputBox の利用(VBScript の定義を呼び出す)
        function inputBox(prompt_) {
            return vbsInputBox(prompt_);
        }

        // ファイル名を指定して実行の起動
        function openExecutionWindow() {
            // 日本語を使うため、クリップボードにコピー
            winShell.Run("cmd.exe /c echo ファイル名を指定して実行 | clip", 0, true);
            winShell.SendKeys("^{ESC}");
            WScript.Sleep(waitTime);
            winShell.SendKeys("^v");
            winShell.SendKeys("{ENTER}");
            WScript.Sleep(waitTime);
        }

        // タブの移動
        function moveTab(count) {
            for (var i = 0; i < count; i++) {
                winShell.SendKeys("^{TAB}");
                WScript.Sleep(waitTime);
            }
        }

        // セキュリティウィンドウの表示
        function openSecurityWindow() {
            // === フォルダのプロパティメニューが開いている前提 ===
            // 1. 「セキュリティ」タブに移動
            moveTab(2);
            // 2. 「詳細設定」を押下
            winShell.SendKeys("%V");
            WScript.Sleep(waitTime);
            // 3. 「有効なアクセス許可」タブに移動
            moveTab(3);
        }

        // ユーザ名の確認
        function chkUserName(username) {
            // === 「有効なアクセス許可」タブが開いている前提 ===
            // 1. 「選択」を押下
            winShell.SendKeys("%S");
            WScript.Sleep(waitTime);
            // 2. 「ユーザ名」を入力
            winShell.SendKeys(username);
            WScript.Sleep(waitTime);
            // 3. 「名前の確認」を押下
            winShell.SendKeys("%C");
            WScript.Sleep(waitTime);
            // 4. 「OK」を押下
            winShell.SendKeys("{ENTER}");
            WScript.Sleep(waitTime);
        }

        // メイン処理
        var usePath = inputBox("対象フォルダまでの絶対パスを入力");
        var useUserNames = inputBox("ユーザ名の一覧を入力[要 セミコロン区切り]");
        // 引数確認
        if ((usePath != null) && winFS.FolderExists(usePath) && (useUserNames != null)) {
            var fullPath = winFS.GetAbsolutePathName(usePath);
            winShell.Run(fullPath);
            WScript.Sleep(waitTime);
            winShell.SendKeys("%{UP}");
            WScript.Sleep(waitTime);
            winShell.SendKeys("%{ENTER}");
            WScript.Sleep(waitTime);
            openSecurityWindow();

            var userList = useUserNames.replace(/;$/, "").split(";");
            for (var i = 0; i < userList.length; i++) {
                chkUserName(userList[i]);
                WScript.Sleep(displayTime);
            }
            WScript.Echo("Complete");
        }
    </script>
</job>

取り敢えず,プログラムだけ載せておく.

追記

【追記】2018 年 6 月 1 日 Power Shell 使えば楽なことに気付いた.

参考サイト

【Script】AD/File/Reg のアクセス権リストは Get-ACL にお任せ~その1 – Junichi Anno's blog

ユーザー設定の入力ボックスを作成する | Microsoft Docs

gallery.technet.microsoft.com

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$form = New-Object System.Windows.Forms.Form
$form.Text = 'アクセス権を調べる'
$form.Size = New-Object System.Drawing.Size(300,150)
$form.StartPosition = 'CenterScreen'

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(70,70)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = 'OK'
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $OKButton
$form.Controls.Add($OKButton)

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(155,70)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = 'Cancel'
$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $CancelButton
$form.Controls.Add($CancelButton)

$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(280,20)
$label.Text = 'アクセス権を調査するフォルダの絶対パスを入力'
$form.Controls.Add($label)

$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10,40)
$textBox.Size = New-Object System.Drawing.Size(260,20)
$form.Controls.Add($textBox)

# 最大化ボタンを無効化
$Form.MaximizeBox = $false
# 最小化ボタンを無効化
$Form.MinimizeBox = $false
# ウィンドウサイズを固定
$Form.FormBorderStyle = 'Fixed3D'
# 常に前面に表示
$form.Topmost = $true

$form.Add_Shown({$textBox.Select()})
$result = $form.ShowDialog()

# 出力先
$outputDir = [Environment]::GetFolderPath("Desktop")
# 出力ファイル名
$csvFile = $outputDir + "\accesslist.txt"

if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
    $filePath = $textBox.Text

    # 引数の確認
    if ($filePath) {
        # ファイルパスの確認
        if (Test-Path $filePath) {
            # アクセス権の取得
            $acl = Get-Acl -Path $filePath
            # アクセス権を持つユーザを出力
            $acl.Access | ForEach-Object { 
                $outArray = $_.FileSystemRights, $_.AccessControlType, $_.identityReference.value
                $outString = $outArray -join ","
                Write-Output $outString
            } | Out-File -FilePath $csvFile
        }
    }
}

bat ファイルでも作成できるから,ダブルクリックで起動可能.

参考サイト

reosablo.hatenablog.jp

@setlocal enabledelayedexpansion&set a=%*&(if defined a set a=!a:"=\"!&set a=!a:'=''!)&powershell/c $i=$input;iex ('$i^|^&{$PSCommandPath=\"%~f0\";$PSScriptRoot=\"%~dp0";#'+(${%~f0}^|Out-String)+'} '+('!a!'-replace'[$(),;@`{}]','`$0'))&exit/b

# Power Shell のスクリプト
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

$form = New-Object System.Windows.Forms.Form
$form.Text = 'アクセス権を調べる'
$form.Size = New-Object System.Drawing.Size(300,150)
$form.StartPosition = 'CenterScreen'

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Point(70,70)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = 'OK'
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $OKButton
$form.Controls.Add($OKButton)

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Point(155,70)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = 'Cancel'
$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $CancelButton
$form.Controls.Add($CancelButton)

$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(280,20)
$label.Text = 'アクセス権を調査するフォルダの絶対パスを入力'
$form.Controls.Add($label)

$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10,40)
$textBox.Size = New-Object System.Drawing.Size(260,20)
$form.Controls.Add($textBox)

# 最大化ボタンを無効化
$Form.MaximizeBox = $false
# 最小化ボタンを無効化
$Form.MinimizeBox = $false
# ウィンドウサイズを固定
$Form.FormBorderStyle = 'Fixed3D'
# 常に前面に表示
$form.Topmost = $true

$form.Add_Shown({$textBox.Select()})
$result = $form.ShowDialog()

# 出力先
$outputDir = [Environment]::GetFolderPath('Desktop')
# 出力ファイル名
$csvFile = $outputDir + '\accesslist.txt'

if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
    $filePath = $textBox.Text

    # 引数の確認
    if ($filePath) {
        # ファイルパスの確認
        if (Test-Path $filePath) {
            # アクセス権の取得
            $acl = Get-Acl -Path $filePath
            # アクセス権を持つユーザを出力
            $acl.Access | ForEach-Object { 
                $outArray = $_.FileSystemRights, $_.AccessControlType, $_.identityReference.value
                $outString = $outArray -join ','
                Write-Output $outString
            } | Out-File -FilePath $csvFile
        }
    }
}