【入門編】ADO接続文字列の安全な管理:レジストリや外部INIファイルからの動的読み込み – Access VBA解析バイブル

スポンサーリンク
スポンサーリンク

脱・ハードコーディング!プロのAccess VBAが実践する「接続文字列」の動的管理術

こんにちは。開発の現場へようこそ。
マクロの記録や、簡単なVBAの記述ができるようになってきたあなた。今、もし「接続先のパスワードやサーバー名を、VBAのコードの中に直接書き込んでいる」としたら……。

少し耳の痛い話かもしれませんが、それは「いつ爆発するか分からない時限爆弾」を抱えて開発しているのと同じなのです。

今回は、中級者への登竜門とも言える「ADO接続文字列のセキュアな管理」についてお話ししましょう。コードの中に機密情報を隠すのではなく、外部から「設定」として読み込む。このアーキテクチャの考え方をマスターすれば、あなたはもう「ただのマクロ使い」ではなく、一歩先の「エンジニア」へと進化できます。

1. なぜ、コードに接続情報を書いてはいけないのか?

まず、私たちが直面しているリスクを整理しましょう。

セキュリティのリスク

VBAのコードを書き換えられる環境(あるいはVBAプロジェクトのパスワードを突破された環境)では、コード内に書かれたDBのパスワードは丸裸です。

運用の柔軟性の欠如

「開発環境では自分のPCのDBを使うけれど、本番環境ではサーバーのDBを使う」という場面、必ずありますよね?
もし接続文字列をコードに直書きしていたら、環境が変わるたびに「プログラム本体を書き換えて、配布し直す」という、極めてミスの起きやすい作業が発生します。

「ロジック(計算や処理)」と「設定(接続先やパスワード)」を分離する。
これが、世界最高峰のアーキテクチャにおける鉄則です。

2. 二つの管理手法:INIファイル vs レジストリ

設定情報を外部に逃がす方法は、主に2つあります。それぞれの特性を理解しましょう。

手法 メリット デメリット 向いているケース
INIファイル テキスト形式で人間が見やすく、配布やバックアップが容易。 ファイルの置き場所(パス)を管理する必要がある。 設定項目が多く、ユーザーが手動で微調整する場合。
Windowsレジストリ OSが管理するため、ファイルパスを気にする必要がない。比較的セキュア。 誤った書き込みによるOSへの影響。権限の問題。 システム全体で共通の設定を保持したい場合。

今回は、どちらも現場で頻繁に使われるため、両方の実装パターンを伝授します。

3. 【実践】INIファイルから設定を読み込むアーキテクチャ

INIファイルを利用する場合、Windows APIの `GetPrivateProfileString` を呼び出すのが最も標準的で高速な方法です。

ステップ1:INIファイルの準備

メモ帳などで、以下の内容の `config.ini` を作成し、Accessファイルと同じフォルダに置いてください。

[Database]
ConnectionString=Provider=SQLOLEDB;Data Source=ServerName;Initial Catalog=MyDB;User ID=myUser;Password=myPassword;

ステップ2:VBAでの実装

ここからは、プロのコードを見ていきましょう。エラーハンドリングを疎かにしないのが、伝説のエンジニアへの第一歩です。

Option Compare Database
Option Explicit

' Windows APIの宣言:INIファイルから文字列を読み取るために必要
Private Declare PtrSafe Function GetPrivateProfileString Lib "kernel32" Alias "GetPrivateProfileStringA" ( _
    ByVal lpApplicationName As String, _
    ByVal lpKeyName As Any, _
    ByVal lpDefault As String, _
    ByVal lpReturnedString As String, _
    ByVal nSize As Long, _
    ByVal lpFileName As String) As Long

''' <summary>
''' INIファイルから指定されたセクションのキーの値を取得する
''' </summary>
Public Function GetConfigValue(section As String, key As String) As String
    Dim iniPath As String
    Dim buffer As String
    Dim retLen As Long
    
    ' Accessファイルと同じフォルダにある config.ini を指定
    iniPath = CurrentProject.Path & "\config.ini"
    
    ' 読み込み用のバッファ(十分な大きさを確保)
    buffer = String(255, vbNullChar)
    
    ' APIの呼び出し
    retLen = GetPrivateProfileString(section, key, "", buffer, Len(buffer), iniPath)
    
    If retLen > 0 Then
        ' 取得した文字列から余分なNull文字を取り除く
        GetConfigValue = Left(buffer, retLen)
    Else
        ' 取得失敗時はエラーを返す(実務ではログ出力などを検討)
        GetConfigValue = ""
    End If
End Function

''' <summary>
''' ADOを使用して安全にデータベースへ接続するメインロジック
''' </summary>
Public Sub ExecuteSecureQuery()
    Dim conn As Object ' ADODB.Connection
    Dim strConn As String
    
    ' 1. 設定ファイルから接続文字列を動的に取得
    strConn = GetConfigValue("Database", "ConnectionString")
    
    ' 2. 取得失敗時のチェック
    If strConn = "" Then
        MsgBox "接続設定の読み込みに失敗しました。config.iniを確認してください。", vbCritical
        Exit Sub
    End If
    
    ' 3. ADOオブジェクトの生成と接続
    On Error GoTo ErrorHandler
    Set conn = CreateObject("ADODB.Connection")
    
    ' 接続開始
    conn.Open strConn
    
    MsgBox "接続に成功しました!これで安全な運用が可能です。", vbInformation

CleanUp:
    ' 4. オブジェクトの解放(リソースリークを防ぐための極めて重要な工程)
    If Not conn Is Nothing Then
        If conn.State = 1 Then conn.Close ' 1 = adStateOpen
        Set conn = Nothing
    End If
    Exit Sub

ErrorHandler:
    MsgBox "接続エラーが発生しました。" & vbCrLf & _
           "Error No: " & Err.Number & vbCrLf & _
           "Description: " & Err.Description, vbCritical
    Resume CleanUp
End Sub

4. 【実践】レジストリから設定を読み込むアーキテクチャ

レジストリを使う場合は、`WScript.Shell` オブジェクトを利用するのがスマートです。

''' <summary>
''' レジストリから接続文字列を取得する
''' </summary>
Public Function GetRegistryConnString() As String
    Dim shell As Object
    Dim regPath As String
    Dim val As Variant
    
    Set shell = CreateObject("WScript.Shell")
    ' ユーザー個別の設定領域(HKEY_CURRENT_USER)を使用
    regPath = "HKEY_CURRENT_USER\Software\MyAccessApp\Settings\"
    
    On Error Resume Next
    ' レジストリから値を取得
    val = shell.RegRead(regPath & "ConnectionString")
    On Error GoTo 0
    
    If IsEmpty(val) Then
        GetRegistryConnString = ""
    Else
        GetRegistryConnString = CStr(val)
    End If
End Function

5. 陥りやすいエラーと、プロの回避術

ここまで学んだあなたが、次にぶつかる壁をあらかじめ教えておきましょう。

① 「パスが見つかりません」エラー

INIファイル方式で最も多いのが、`CurrentProject.Path` の使い方の誤りです。
Accessをネットワークドライブから開いている場合、パスの形式(`\\Server\Folder` か `Z:\Folder` か)によって挙動が変わることがあります。必ず、「実行時に実際に存在するか」を `Dir()` 関数などでチェックする癖をつけましょう。

② 「オブジェクトが閉じられていません」エラー

ADOの接続(Connection)は、使い終わったら必ず `Close` し、`Nothing` を代入してメモリから解放しなければなりません。これを忘れると、データベース側に「幽霊接続」が残り続け、サーバーの負荷を高め、最悪の場合、データベースがロックされて動かなくなります。
上記のコードにある `CleanUp` セクションのような、「必ず通る終了処理」を書くことが、プロの作法です。

③ 権限(Permission)エラー

レジストリの `HKEY_LOCAL_MACHINE`(マシン全体の設定)に書き込もうとすると、管理者権限がないためエラーになります。個人設定であれば `HKEY_CURRENT_USER` を使う、という使い分けを徹底してください。

最後に:ここをクリアすれば、あなたはもう一歩先へ

「コードに直接書けば動く。でも、あえて外に出す。」

この一見遠回りに見えるプロセスこそが、システムを堅牢にし、保守性を高め、あなたの信頼を築くのです。

今回紹介したコードは、そのまま実務のベースとして使えます。まずは、小さなプロジェクトで「設定ファイルからパスワードを読み込む」という実験から始めてみてください。

「動けばいい」のその先へ。
あなたの素晴らしいエンジニアライフを応援しています!

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