Win32 APIを用いたVBAによるUAC(ユーザーアカウント制御)設定状態の取得

Tech

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

Win32 APIを用いたVBAによるUAC(ユーザーアカウント制御)設定状態の取得

【背景と目的】

共有ツール配布時、UAC(ユーザーアカウント制御)設定の影響でファイル操作やレジストリ書き込みが失敗する課題を、Win32 APIで高速に検知し、予期せぬエラーを未然に防ぎます。

【処理フロー図】

graph TD
A["開始"] --> B{"HKEY_LOCAL_MACHINEを開く"}
B -->|成功| C["EnableLUA値を取得"]
B -->|失敗| E["権限エラーとして終了"]
C --> D{"値が1か?"}
D -->|Yes| F["UAC有効を通知"]
D -->|No| G["UAC無効を通知"]
F --> H["終了"]
G --> H

【実装:VBAコード】

Option Explicit

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

' --- Win32 API 宣言 (64bit環境対応 PtrSafe) ---
#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, _
        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
#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, _
        ByRef 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, _
        ByRef lpType As Long, _
        ByRef lpData As Any, _
        ByRef lpcbData As Long) As Long

    Private Declare Function RegCloseKey Lib "advapi32.dll" ( _
        ByVal hKey As Long) As Long
#End If

''' <summary>
''' UAC (EnableLUA) の状態を確認するメイン関数
''' </summary>
Public Sub CheckUACStatus()
    Dim hKey As LongPtr
    Dim subKey As String
    Dim valueName As String
    Dim dwValue As Long
    Dim cbData As Long
    Dim result As Long

    ' 高速化設定
    Application.ScreenUpdating = False

    subKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
    valueName = "EnableLUA"
    cbData = 4 ' DWORD (4 bytes)

    ' レジストリキーを読み取り専用で開く
    result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, hKey)

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

        If result = ERROR_SUCCESS Then
            If dwValue = 1 Then
                MsgBox "UACは有効(EnableLUA=1)です。管理者権限が必要な操作に注意してください。", vbInformation, "UAC状態確認"
            Else
                MsgBox "UACは無効(EnableLUA=0)です。", vbInformation, "UAC状態確認"
            End If
        Else
            MsgBox "値の取得に失敗しました。", vbCritical
        End If

        ' ハンドルを閉じる
        RegCloseKey hKey
    Else
        MsgBox "レジストリキーを開けませんでした。権限を確認してください。", vbCritical
    End If

    Application.ScreenUpdating = True
End Sub

【技術解説】

  1. Registry Win32 API: WScript.ShellRegRead よりも高速で、かつ詳細なエラーハンドリングが可能です。実務において、システム設定の変更を検知する際の標準的な手法です。

  2. PtrSafe と LongPtr: 64bit版Officeではメモリアドレスの扱いが異なるため、PtrSafe 宣言と、ハンドルを保持する変数への LongPtr 型の使用は必須です。

  3. EnableLUA: WindowsのUACの核となるレジストリ値です。これが1の場合、管理者権限を持つユーザーでも標準ユーザー権限で動作し、必要に応じて昇格要求が発生します。

【注意点と運用】

  • 読み取り権限: HKEY_LOCAL_MACHINE へのアクセスは、通常読み取りであれば一般権限で可能ですが、環境(グループポリシー等)により制限されている場合があります。

  • 再起動の必要性: ユーザーがレジストリを手動で変更した場合でも、PCを再起動するまで設定が反映されないケースがあるため、取得した値が現時点のOSの「振る舞い」と完全に一致しない場合がある点に注意してください。

  • 例外処理: API呼び出しが ERROR_SUCCESS (0) 以外を返した際、エラーコードに応じたメッセージを表示するように設計することで、デバッグ効率が向上します。

【まとめ】

  • Win32 APIによるレジストリ操作は、WMI等に比べ依存関係が少なく高速。

  • PtrSafeVBA7 定数による条件分岐で、環境を問わない汎用的なコードを実現。

  • UAC状態を事前に把握することで、配布ツールの「動かない」トラブルを劇的に削減可能。

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

コメント

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