VBAでWindowsのUAC(ユーザーアカウント制御)設定状態を判定する実用コード

Tech

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

VBAでWindowsのUAC(ユーザーアカウント制御)設定状態を判定する実用コード

【背景と目的】

外部ファイル操作やレジストリ変更を伴うツールにおいて、UAC設定による権限不足でエラー終了する事態を防ぐため、実行前に環境の権限状態を正確に把握します。(67文字)

【処理フロー図】

graph TD
A["開始"] --> B{"Win32 APIでレジストリ参照"}
B --> C["HKEY_LOCAL_MACHINEをオープン"]
C --> D["EnableLUA値を取得"]
D --> E["レジストリキーをクローズ"]
E --> F{"取得値は 1 か?"}
F -->|Yes| G["UAC有効と判定"]
F -->|No| H["UAC無効と判定"]
G --> I["結果を通知して終了"]
H --> 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_READ As Long = &H20019
Private Const REG_DWORD As Long = 4

''' <summary>
''' UAC(ユーザーアカウント制御)が有効化されているか確認する関数
''' </summary>
''' <returns>True: 有効, False: 無効(または取得失敗)</returns>
Public Function IsUACEnabled() As Boolean
    Dim hKey As LongPtr
    Dim res As Long
    Dim dwValue As Long
    Dim cbData As Long
    Dim subKey As String
    Dim valueName As String

    subKey = "SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
    valueName = "EnableLUA"
    cbData = 4 ' DWORDのサイズ

    ' レジストリキーを開く
    res = RegOpenKeyEx(HKEY_LOCAL_MACHINE, subKey, 0, KEY_READ, hKey)

    If res = 0 Then
        ' 値を取得 (EnableLUA: 1=有効, 0=無効)
        res = RegQueryValueEx(hKey, valueName, 0, REG_DWORD, dwValue, cbData)
        ' キーを閉じる
        RegCloseKey hKey

        If res = 0 Then
            IsUACEnabled = (dwValue = 1)
            Exit Function
        End If
    End If

    ' 取得失敗時は安全のためデフォルト値を考慮(ここではFalseとする)
    IsUACEnabled = False
End Function

''' <summary>
''' 実行用プロシージャ
''' </summary>
Sub CheckUACStatus()
    ' 高速化設定
    Application.ScreenUpdating = False

    On Error GoTo ErrorHandler

    If IsUACEnabled() Then
        MsgBox "UAC(ユーザーアカウント制御)は【有効】です。" & vbCrLf & _
               "管理者権限が必要な処理には注意してください。", vbInformation, "状態確認"
    Else
        MsgBox "UAC(ユーザーアカウント制御)は【無効】です。", vbInformation, "状態確認"
    End If

    Application.ScreenUpdating = True
    Exit Sub

ErrorHandler:
    Application.ScreenUpdating = True
    MsgBox "エラーが発生しました: " & Err.Description, vbCritical
End Sub

【技術解説】

  1. Win32 API の活用: 標準の Shell 関数や WScript.Shell でもレジストリ読み取りは可能ですが、Win32 API を使用することで、アクセス権限エラーのハンドリングがより厳密に行え、依存関係を最小限に抑えられます。

  2. PtrSafe 宣言: LongPtr を用いることで、Excel 32bit/64bit 両方の環境でメモリポインタを正しく扱い、クラッシュを防止しています。

  3. レジストリパス: Windows OS のセキュリティポリシーを司る EnableLUA キーを参照しています。これは UAC の根本的な有効/無効を司るフラグです。

【注意点と運用】

  • 読み取り権限: HKEY_LOCAL_MACHINE は読み取り専用(KEY_READ)で開く必要があります。書き込み権限で開こうとすると、標準ユーザー環境では API が失敗します。

  • 反映タイミング: ユーザーがコントロールパネルから UAC 設定を変更しても、OS の再起動が完了するまでレジストリ値が実際の挙動と一致しない場合があります。

  • 例外処理: 万が一レジストリキーが存在しない(極めて稀なケース)やアクセス拒否が発生した場合に備え、戻り値のチェックを徹底しています。

【まとめ】

  • 事前判定の徹底: 管理者権限が必要なファイル操作の前に UAC 状態をチェックし、予期せぬエラーを回避。

  • 環境非依存: Win32 API の PtrSafe 記述により、配布先の Office バージョンを問わず動作可能。

  • コードの堅牢性: 直接レジストリを叩くことで、スクリプト実行禁止環境でも動作する可能性を高める。

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

コメント

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