【VBA】ファイルの拡張子に関連付けられたプログラムのパスを取得する方法 (API)

目次

はじめに

VBAマクロから特定のファイルを開く際、通常は Shell 関数に直接ファイルパスを渡せば、Windowsが自動的に関連付けられたプログラムで開いてくれます。しかし、「.pdf ファイルを開くプログラムが何であるか(Acrobat Readerなのか、ブラウザなのか)を事前に知りたい」という、より高度な要求に応える場面があります。

このような「拡張子とプログラムの関連付け情報」を取得するのが、Windows APIの FindExecutable 関数です。この関数を使えば、指定したファイルの拡張子を開くために設定されている、実行ファイルのフルパスを取得できます。

この記事では、FindExecutable APIを使って、特定の拡張子に関連付けられたプログラムの情報を取得する方法を解説します。


関連付けられたプログラムを取得するVBAサンプルコード

Declareステートメントや Const(定数)は、モジュールの最上部Sub などのプロシージャよりも前)に記述する必要があります。

このマクロは、一時的にダミーの .html ファイルを作成し、その拡張子に関連付けられているプログラム(通常はデフォルトのウェブブラウザ)のパスを取得します。

完成コード

'--- モジュールの最上部にAPI関数と定数を宣言 ---

' 64bit/32bit両対応
#If VBA7 Then
    Private Declare PtrSafe Function FindExecutable Lib "shell32.dll" Alias "FindExecutableA" ( _
        ByVal lpFile As String, _
        ByVal lpDirectory As String, _
        ByVal lpResult As String _
    ) As LongPtr
#Else
    Private Declare Function FindExecutable Lib "shell32.dll" Alias "FindExecutableA" ( _
        ByVal lpFile As String, _
        ByVal lpDirectory As String, _
        ByVal lpResult As String _
    ) As Long
#End If

' パスを格納するためのバッファサイズ
Private Const MAX_PATH As Long = 260


' .html拡張子に関連付けられたプログラムのパスを取得する
Sub GetAssociatedExecutable()
    Dim dummyFileName As String
    Dim resultBuffer As String
    Dim resultCode As LongPtr
    Dim executablePath As String
    
    '--- 1. 存在確認のための一時ファイルを作成 ---
    dummyFileName = ThisWorkbook.Path & "\_temp.html"
    Open dummyFileName For Output As #1: Close #1
    
    '--- 2. 結果を格納するための文字列バッファを準備 ---
    resultBuffer = String(MAX_PATH, vbNullChar)
    
    '--- 3. FindExecutable API関数を実行 ---
    resultCode = FindExecutable(dummyFileName, vbNullString, resultBuffer)
    
    '--- 4. 後片付け ---
    Kill dummyFileName
    
    '--- 5. 結果を判定して表示 ---
    ' 戻り値が32より大きい場合、成功と見なす
    If resultCode > 32 Then
        ' バッファから実際のパス部分だけを切り出す
        executablePath = Left(resultBuffer, InStr(resultBuffer, vbNullChar) - 1)
        MsgBox ".html ファイルは、以下のプログラムに関連付けられています:" & vbCrLf & _
               executablePath, vbInformation, "関連付け情報"
    Else
        MsgBox ".html に関連付けられたプログラムが見つかりませんでした。", vbExclamation
    End If
End Sub

コードの解説

FindExecutable API関数

FindExecutable は、指定したファイルを開くために実行されるプログラムのパスを探し出す関数です。

  • lpFile: 調査したいファイルの名前(フルパスまたはファイル名)を渡します。実際にファイルが存在する必要があるため、一時的なダミーファイルを作成しています。
  • lpDirectory: ファイルのデフォルトディレクトリを指定しますが、lpFile にフルパスを渡す場合は vbNullString で問題ありません。
  • lpResult: 結果(見つかった実行ファイルのパス)を格納するための、あらかじめ領域を確保しておいた文字列変数(バッファ)を渡します。

resultBuffer = String(MAX_PATH, vbNullChar)

FindExecutable は、結果を第3引数 lpResult に書き込みます。そのため、VBA側で、結果を書き込むのに十分な長さの「空の箱」を用意しておく必要があります。

  • String(MAX_PATH, vbNullChar): MAX_PATH(Windowsのパスの最大長である260文字)分の、vbNullChar(ヌル文字)で満たされた文字列を作成し、バッファとして準備しています。

結果の判定と抽出

  • If resultCode > 32 Then: FindExecutable は、成功した場合に 32 より大きい値を返します。これをチェックすることで、処理が成功したかどうかを判定します。
  • Left(resultBuffer, InStr(resultBuffer, vbNullChar) - 1): APIから返される文字列は、実際のパスの後にヌル文字が続いています。InStr で最初のヌル文字の位置を探し、Left でそれより前の部分だけを切り出すことで、純粋な実行ファイルのパスを取得しています。

まとめ

今回は、Windows APIの FindExecutable を使って、ファイルの拡張子に関連付けられたプログラムのパスを取得する方法を解説しました。

  • FindExecutable APIで、ファイルを開くプログラムを特定できる。
  • 事前にダミーファイルと、結果を格納する文字列バッファの準備が必要。
  • 戻り値が 32 より大きいかどうかで成功を判定する。

このテクニックを使えば、「ユーザーのPCでPDFが開けるか(Adobe Readerやブラウザが関連付けられているか)を確認する」といった、より環境に配慮した、堅牢なマクロを作成することが可能になります。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次