Win32 APIでセキュアに取得するUAC(ユーザーアカウント制御)設定状態の確認手法

Tech

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

Win32 APIでセキュアに取得するUAC(ユーザーアカウント制御)設定状態の確認手法

【背景と目的】

VBAによるファイル操作やシステム連携時、UAC(ユーザーアカウント制御)の制限による書き込みエラーが頻発します。事前にレジストリからUACの状態を判定し、適切な警告を出すことで実行時エラーを未然に防ぎます。

【処理フロー図】

graph TD
A["開始"] --> B["Win32 APIでレジストリキーを開く"]
B --> C{"キーの展開に成功?"}
C -->|Yes| D["EnableLUAの値を読み取り"]
C -->|No| E["エラー処理: 権限不足等"]
D --> F{"値が 1 か?"}
F -->|Yes| G["UAC 有効と判定"]
F -->|No| H["UAC 無効と判定"]
G --> I["レジストリハンドルを閉じて終了"]
H --> I
E --> I

【実装:VBAコード】

Option Explicit

' --- Win32 API 宣言 (64bit/32bit 両対応) ---
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_QUERY_VALUE As Long = &H1
Private Const ERROR_SUCCESS As Long = 0&
Private Const REG_DWORD As Long = 4

''' <summary>
''' UAC (EnableLUA) の状態を確認するメイン関数
''' </summary>
''' <returns>True: 有効, False: 無効または取得失敗</returns>
Public Function IsUACEnabled() As Boolean
    Dim hKey As LongPtr
    Dim subKey As String
    Dim valueName As String
    Dim dwValue As Long
    Dim cbData As Long
    Dim lngRet As Long

    ' 高速化設定(本処理はUI非依存だが、慣例として定義)
    Application.ScreenUpdating = False

    ' UAC設定が格納されているレジストリパス
    subKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
    valueName = "EnableLUA"
    cbData = 4 ' DWORDのサイズ

    ' 1. レジストリキーを開く
    lngRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, KEY_QUERY_VALUE, hKey)

    If lngRet = ERROR_SUCCESS Then
        ' 2. 値を取得
        lngRet = RegQueryValueEx(hKey, valueName, 0, REG_DWORD, dwValue, cbData)

        ' 3. ハンドルを閉じる
        RegCloseKey hKey

        If lngRet = ERROR_SUCCESS Then
            ' EnableLUA = 1 ならば UAC 有効
            IsUACEnabled = (dwValue = 1)
        End If
    Else
        ' キーが開けない場合は権限不足またはパス不在
        IsUACEnabled = False
    End If

    Application.ScreenUpdating = True
End Function

''' <summary>
''' 動作確認用プロシージャ
''' </summary>
Sub CheckUACStatus()
    If IsUACEnabled() Then
        MsgBox "UAC(ユーザーアカウント制御)は【有効】です。" & vbCrLf & _
               "管理者権限が必要な操作でエラーが出る可能性があります。", vbInformation
    Else
        MsgBox "UAC(ユーザーアカウント制御)は【無効】です。", vbExclamation
    End If
End Sub

【技術解説】

  1. Win32 APIの使用: 標準の WScript.Shell (RegRead) でも取得可能ですが、Win32 API を使用することで、参照設定を不要にしつつ、動作速度の向上とエラーハンドリングの厳密化(戻り値による判定)を実現しています。

  2. PtrSafe と LongPtr: 64bit版のExcelでも安全に動作するよう、ポインタ(ハンドル)を扱う変数には LongPtr を使用し、宣言には PtrSafe を付与しています。

  3. レジストリパス: UACの核となる EnableLUA 値を HKEY_LOCAL_MACHINE から参照しています。ここはOS全体のセキュリティ設定を司る場所です。

【注意点と運用】

  • 読み取り権限: 通常、このレジストリキーの読み取りには管理者権限は不要(一般ユーザーでOK)ですが、環境によってはセキュリティソフトがAPIによるレジストリアクセスをブロックする可能性があります。

  • レジストリ操作のリスク: 本コードは「読み取り」のみを行いますが、誤って RegSetValue 等を実行しないよう注意してください。

  • 反映タイミング: UACの設定を変更した場合、OSを再起動するまでレジストリ上の値と実際の動作が乖離するケースがあります。

【まとめ】

  • Win32 API(advapi32.dll)を活用し、高速かつ参照設定不要で情報を取得。

  • EnableLUA の値を参照することで、プログラムの動作環境を事前に把握。

  • エラーハンドリングをAPIの戻り値 ERROR_SUCCESS で判定し、堅牢なツール設計に。

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

コメント

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