VBAとWin32 APIで実現するUAC(ユーザーアカウント制御)設定の自動判定

Tech

  • 専門家としての威厳と、実務家としての具体性を両立。

  • 簡潔な解説と、コピー&ペーストで即戦力となるコードを提供。

  • セキュリティとエラーハンドリングを重視。

本記事はGeminiの出力をプロンプト工学で整理した業務ドラフト(未検証)です。

VBAとWin32 APIで実現するUAC(ユーザーアカウント制御)設定の自動判定

【背景と目的】

UAC設定が不明な環境での自動化は、予期せぬ権限エラーを招きます。Win32 APIを用い、OSのセキュリティレベルを正確に検知する手法を解説します。

【処理フロー図】

graph TD
A["開始"] --> B["Win32 APIによるレジストリキーのオープン"]
B --> C{"キー取得成功?"}
C -- No --> D["エラー終了"]
C -- Yes --> E["EnableLUA値を取得"]
E --> F["ConsentPromptBehaviorAdmin値を取得"]
F --> G["取得値を判定しUACレベルを特定"]
G --> H["判定結果を返却"]
H --> I["終了"]

【実装:VBAコード】

Option Explicit

' --- Win32 API 宣言 (64bit環境を考慮した PtrSafe 形式) ---
Private Declare PtrSafe Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" ( _
    ByVal hKey As LongPtr, _
    ByVal lpSubKey As String, _
    ByVal ulOptions As Long, _
    ByVal samDesired As Long, _
    ByRef phkResult As LongPtr) As Long

Private Declare PtrSafe Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" ( _
    ByVal hKey As LongPtr, _
    ByVal lpValueName As String, _
    ByVal lpReserved As Long, _
    ByRef lpType As Long, _
    ByRef lpData As Any, _
    ByRef lpcbData As Long) As Long

Private Declare PtrSafe Function RegCloseKey Lib "advapi32.dll" ( _
    ByVal hKey As LongPtr) As Long

' --- 定数定義 ---
Private Const HKEY_LOCAL_MACHINE As LongPtr = &H80000002
Private Const KEY_READ As Long = &H20019
Private Const REG_DWORD As Long = 4
Private Const UAC_REG_PATH As String = "SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"

''' <summary>
''' UACの状態を取得し、判定結果を文字列で返却する
''' </summary>
Public Function GetUACLevel() As String
    On Error GoTo ErrorHandler

    ' 高速化のため画面更新を停止(本処理では短時間だが慣習として適用)
    Application.ScreenUpdating = False

    Dim hKey As LongPtr
    Dim enableLUA As Long
    Dim promptBehavior As Long
    Dim result As String

    ' レジストリキーをオープン
    If RegOpenKeyEx(HKEY_LOCAL_MACHINE, UAC_REG_PATH, 0, KEY_READ, hKey) = 0 Then
        ' 必要なフラグを取得
        enableLUA = GetRegDWORD(hKey, "EnableLUA")
        promptBehavior = GetRegDWORD(hKey, "ConsentPromptBehaviorAdmin")

        ' UACレベルの判定ロジック
        If enableLUA = 0 Then
            result = "無効 (通知しない)"
        Else
            Select Case promptBehavior
                Case 0: result = "有効 (昇格の通知のみ行わない)"
                Case 5: result = "有効 (既定: アプリが変更を試みる場合のみ通知)"
                Case 2: result = "有効 (常に通知する)"
                Case Else: result = "不明な設定"
            End Select
        End If

        RegCloseKey hKey
    Else
        result = "レジストリへのアクセスに失敗しました"
    End If

    GetUACLevel = result

CleanUp:
    Application.ScreenUpdating = True
    Exit Function

ErrorHandler:
    GetUACLevel = "エラー発生: " & Err.Description
    Resume CleanUp
End Function

''' <summary>
''' レジストリからDWORD値を取得するヘルパー関数
''' </summary>
Private Function GetRegDWORD(ByVal hKey As LongPtr, ByVal valueName As String) As Long
    Dim lValue As Long
    Dim lSize As Long
    lSize = 4
    If RegQueryValueEx(hKey, valueName, 0, REG_DWORD, lValue, lSize) = 0 Then
        GetRegDWORD = lValue
    Else
        GetRegDWORD = -1 ' 取得失敗時
    End If
End Function

''' <summary>
''' 実行用プロシージャ
''' </summary>
Sub CheckUACStatus()
    MsgBox "現在のUAC設定状態: " & GetUACLevel(), vbInformation, "システム診断"
End Sub

【技術解説】

  1. Registry APIの活用: WScript.Shellでもレジストリ操作は可能ですが、Win32 API(advapi32.dll)を直接叩くことで、権限不足時の詳細な戻り値を取得でき、より堅牢な実装が可能になります。

  2. PtrSafeとLongPtr: Officeの32bit/64bit両環境で動作させるため、ハンドル(hKey)には LongPtr を、API宣言には PtrSafe を適用しています。

  3. UACレベルの判定ロジック: WindowsのUACレベルは、レジストリの EnableLUA(有効/無効)と ConsentPromptBehaviorAdmin(通知の厳格さ)の組み合わせで決定されます。これらを個別に取得してマッピングしています。

【注意点と運用】

  • アクセス権限: HKEY_LOCAL_MACHINE は読み取り専用(KEY_READ)で開く必要があります。書き込み権限を要求すると、一般ユーザー権限で実行した際にAPIがエラー(Access Denied)を返します。

  • 例外処理: レジストリ値が存在しないケースや、OSのバージョンによるキーパスの相違に備え、戻り値のチェック(If RegOpenKeyEx ... = 0)を省略しないでください。

  • WOW64の考慮: 64bit OS上の32bit Officeで実行する場合、レジストリリダイレクト(KEY_WOW64_64KEY 等)が必要になる場合がありますが、今回のシステムポリシーパスに関しては通常共通で参照可能です。

【まとめ】

  • 安全性の確保: APIの戻り値を厳密にチェックし、実行時エラーを回避する。

  • 環境適合: PtrSafeLongPtr を用いて、モダンなOffice環境へ完全対応させる。

  • 事前診断: ファイル操作やレジストリ書き換えを行う処理の冒頭に組み込み、UACによる「予期せぬ停止」を未然に防ぐ。

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

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