● 短いファイル名から長いファイル名に変換する(大仰版) ●

やはり自力で書いてみた。一応、動くようだ。ネットワークのパスが渡されても動くかもしれない。

Private Type FILETIME
        dwLowDateTime As Long
        dwHighDateTime As Long
End Type

Private Const MAX_PATH = 260

Private Type WIN32_FIND_DATA
        dwFileAttributes As Long
        ftCreationTime As FILETIME
        ftLastAccessTime As FILETIME
        ftLastWriteTime As FILETIME
        nFileSizeHigh As Long
        nFileSizeLow As Long
        dwReserved0 As Long
        dwReserved1 As Long
        cFileName As String * MAX_PATH
        cAlternate As String * 14
End Type

Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long

Private Declare Function FindClose Lib "kernel32" (ByVal hFindFile As Long) As Long

Private Const INVALID_HANDLE_VALUE = -1

'-----------------------------------------------------------------------
' 関数名 : CnvShortToLong
' 機能   : 短いファイル名から長いファイル名に変換する
' 引数   : (in) ファイルの短いファイル名
' 戻り値 : 変換された長いファイル名
' 備  考 : ファイル、ディレクトリドンと来い!! ネットワークパスも多分大丈夫
'           引数に ? や * で終わる値が渡された場合、エラーにするとよいかも
'-----------------------------------------------------------------------
Public Function CnvShortToLong(ByVal ShortFileName As String) As String

    Dim udtW32FD As WIN32_FIND_DATA
    Dim hFindFile As Long  'ファイル・ディレクトリのハンドル
    Dim FoundPos As Long
    Dim NameParts() As String
    Dim ArrayIndex As Long
    Dim i As Long
    Dim TargetFileName As String
    Dim IsDirectory As Boolean

    '存在チェック
    hFindFile = FindFirstFile(ShortFileName, udtW32FD)
    If hFindFile = INVALID_HANDLE_VALUE Then
        Exit Function
    Else
        IsDirectory = CBool(udtW32FD.dwFileAttributes And vbDirectory)
    End If
    Call FindClose(hFindFile)
    hFindFile = 0 '後ろで使用するので初期化しておこう

    'ディレクトリである場合
    If IsDirectory Then
       '最後尾が \ でない場合は付加する
       '\ を付加しないと下記の Instr で一番後ろのディレクトリを取得できなくなるので
       If Right$(ShortFileName, 1) <> "\" Then ShortFileName = ShortFileName & "\"
    End If

    '0番目のメモリー確保
    ReDim Preserve NameParts(ArrayIndex) As String
    'ネットワーク
    FoundPos = InStr(ShortFileName, "\\")
    If FoundPos > 0 Then
        NameParts(ArrayIndex) = "\\"
    '通常のドライブ
    Else
        FoundPos = InStr(ShortFileName, "\")
        NameParts(ArrayIndex) = Left$(ShortFileName, FoundPos)
    End If

    '\が見つからないなら終了。ここで終了することは理論的にありえない
    If FoundPos = 0 Then Exit Function

    '\単位に分ける
    FoundPos = FoundPos + IIf(Len(NameParts(ArrayIndex)) = 2, Len("\\"), Len("\"))
    Do
        '被交換文字列検索
        FoundPos = InStr(FoundPos, ShortFileName, "\")

        '検索文字列が見つからなかったらループ終了
        If FoundPos = 0 Then Exit Do

        'インデックスを増やしてメモリー確保
        ArrayIndex = ArrayIndex + 1
        ReDim Preserve NameParts(ArrayIndex) As String
        NameParts(ArrayIndex) = Left$(ShortFileName, FoundPos - 1)

        '最後尾が \ である場合は削除する
        '\ で終わっていると FindFirstFile 関数が INVALID_HANDLE_VALUE
        'を返すため(んなアホな!!)
        If Right$(NameParts(ArrayIndex), 1) = "\" Then
            NameParts(ArrayIndex) = Left$(NameParts(ArrayIndex), Len(NameParts(ArrayIndex)) - 1)
        End If

        '次回検索位置算出
        FoundPos = FoundPos + Len("\")
    Loop

    'ファイルである場合
    If IsDirectory = False Then
        'インデックスを増やしてメモリー確保
        ArrayIndex = ArrayIndex + 1
        ReDim Preserve NameParts(ArrayIndex) As String
        NameParts(ArrayIndex) = ShortFileName
    End If

    '後ろからディレクトリ名・ファイル名を復元する
    For i = UBound(NameParts) To 1 Step -1
        hFindFile = FindFirstFile(NameParts(i), udtW32FD)
        'ネットワーク対応
        'ルートパス(何て呼べば良いか分からない)以上を指定すると INVALID_HANDLE_VALUE が返る
        If hFindFile = INVALID_HANDLE_VALUE Then
            CnvShortToLong = NameParts(i) & TargetFileName
            Exit Function
        End If

        'パス連結
        TargetFileName = Left$(udtW32FD.cFileName, InStr(udtW32FD.cFileName, Chr$(0)) - 1) _
                           & IIf(i = UBound(NameParts), "", "\") & TargetFileName
        Call FindClose(hFindFile)
    Next i

    'C:\などのドライブ名を付加
    CnvShortToLong = NameParts(0) & TargetFileName

End Function

以下で動作確認

Private Sub Form_Load()

    Debug.Print CnvShortToLong("C:\PROGRA~1\INTERN~1\PLUGINS\QUICKT~1.CLA")
    Debug.Print CnvShortToLong("C:\PROGRA~1\INTERN~1\PLUGINS\")
    Debug.Print CnvShortToLong("C:\PROGRA~1\INTERN~1\PLUGINS")
    Debug.Print CnvShortToLong("C:\WINDOWS\青いレ~1.BMP")

End Sub

[実行結果]
C:\Program Files\Internet Explorer\PLUGINS\QuickTimePlugin.class
C:\Program Files\Internet Explorer\PLUGINS
C:\Program Files\Internet Explorer\PLUGINS
C:\WINDOWS\青いレース編み 16.bmp

戻る