VBAでWin32 APIを介してUAC(ユーザーアカウント制御)の設定状態を判定する

Tech

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

VBAでWin32 APIを介してUAC(ユーザーアカウント制御)の設定状態を判定する

【背景と目的】

権限不足によるファイル操作や外部連携のエラーを防ぐため、実行前にUACの状態を確認し、予期せぬ実行停止やアクセス拒否トラブルを未然に回避します。

【処理フロー図】

graph TD
A["開始"] --> B["Win32 APIによるレジストリキーのオープン"]
B --> C{"オープン成功?"}
C -- No --> D["エラー終了"]
C -- Yes --> E["EnableLUA値を取得"]
E --> F["レジストリハンドルのクローズ"]
F --> G["UAC有効/無効を判定"]
G --> H["結果を呼び出し元へ返す"]
H --> I["終了"]

【実装:VBAコード】

Option Explicit

' --- Win32 API 宣言 (64bit/32bit両対応) ---
#If VBA7 Then

    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, 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, _
        lpType As Long, lpData As Any, lpcbData As Long) As Long
    Private Declare PtrSafe Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As LongPtr) As Long
#Else

    Private Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" ( _
        ByVal hKey As Long, ByVal lpSubKey As String, ByVal ulOptions As Long, _
        ByVal samDesired As Long, phkResult As Long) As Long
    Private Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" ( _
        ByVal hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, _
        lpType As Long, lpData As Any, lpcbData As Long) As Long
    Private Declare Function RegCloseKey Lib "advapi32.dll" (ByVal hKey As Long) As Long
#End If

' --- 定数定義 ---
Private Const HKEY_LOCAL_MACHINE As Long = &H80000002
Private Const KEY_READ As Long = &H20019
Private Const ERROR_SUCCESS As Long = 0&
Private Const REG_DWORD As Long = 4

''' <summary>
''' UAC(ユーザーアカウント制御)が有効かどうかを確認する
''' </summary>
''' <returns>True: 有効, False: 無効または取得失敗</returns>
Public Function IsUACEnabled() As Boolean
    ' 高速化のための描画停止(本処理ではレジストリ参照のみだが、ルーチンとして組み込み)
    Application.ScreenUpdating = False

    #If VBA7 Then

        Dim hKey As LongPtr
    #Else

        Dim hKey As Long
    #End If

    Dim subKey As String
    Dim valueName As String
    Dim dwValue As Long
    Dim dwSize As Long
    Dim result As Long

    ' UAC設定を司るレジストリパス
    subKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
    valueName = "EnableLUA"
    dwSize = 4 ' DWORDのサイズ

    IsUACEnabled = False

    ' 1. レジストリキーを読み取り専用でオープン
    result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, hKey)

    If result = ERROR_SUCCESS Then
        ' 2. EnableLUA の値を取得
        result = RegQueryValueEx(hKey, valueName, 0, REG_DWORD, dwValue, dwSize)

        If result = ERROR_SUCCESS Then
            ' 1 ならば UAC 有効、0 ならば無効
            If dwValue = 1 Then IsUACEnabled = True
        End If

        ' 3. オープンしたハンドルを閉じる
        RegCloseKey hKey
    Else
        ' レジストリへのアクセス権限がない、またはパスが存在しない場合の処理
        Debug.Print "Registry Open Error: " & result
    End If

    Application.ScreenUpdating = True
End Function

''' <summary>
''' 動作確認用テストルーチン
''' </summary>
Sub Test_UACCheck()
    If IsUACEnabled() Then
        MsgBox "UACは有効です。管理者権限が必要な操作には注意してください。", vbInformation
    Else
        MsgBox "UACは無効です。システム設定を確認してください。", vbExclamation
    End If
End Sub

【技術解説】

  1. Win32 APIの活用: VBA標準の Environ 関数等では取得できない詳細なシステム設定を確認するため、advapi32.dll のレジストリ操作関数群を使用しています。

  2. PtrSafe 宣言: Office 64bit環境でクラッシュを防ぐため、ハンドル型(LongPtr)と条件付きコンパイルを採用し、堅牢性を確保しています。

  3. レジストリ・キー EnableLUA: WindowsのUAC機能を根本から制御するフラグです。これが 1 であれば、管理者として実行していても、昇格プロセス(Consent UI)が介在する状態であることを示します。

  4. 高速化と安全性: RegOpenKeyExKEY_READ(読み取り専用)で開くことにより、書き込み権限がない一般ユーザー環境でもエラーを最小限に抑えています。

【注意点と運用】

  • WOW64の挙動: 64bit OS上で32bit版Officeを実行している場合、レジストリ・リダイレクタによって参照先が変わる可能性があります。本コードのパスは Policies\System であるため通常は共通ですが、環境依存の挙動には留意してください。

  • UACレベルの詳細: EnableLUA は「UACそのものが有効か」を判定します。「通知レベル(スライダーの位置)」までは判定しないため、より詳細な制御が必要な場合は ConsentPromptBehaviorAdmin 値なども併せて確認する必要があります。

  • 例外処理: API呼び出しに失敗した場合(戻り値が ERROR_SUCCESS 以外)、環境特有の権限問題が発生している可能性があるため、ログ出力等のエラーハンドリングを推奨します。

【まとめ】

  • ファイルアクセスエラーの事前診断として、UACの状態確認をルーチンに組み込む。

  • PtrSafe 対応により、配布先(32bit/64bit混在)を選ばないコード構成にする。

  • レジストリ操作は必ず RegCloseKey でハンドルを解放し、リソースリークを防ぐ。

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

コメント

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