DOBON.NET プログラミング道: .NET Framework, VB.NET, C#, Visual Basic, Visual Studio, インストーラ, ...

長いパス名から短いパス名を取得する、短いパス名から長いパス名を取得する

長いパス名から短いパス名を取得する

長いパス名(ファイル名)から8.3の短いパス名を取得する方法は、.NET Frameworkでは用意されていません。Win32 APIのGetShortPathName関数を使う必要があります。

以下にGetShortPathName関数を使って短いパス名を取得する例を示します。

VB.NET
コードを隠すコードを選択
<System.Runtime.InteropServices.DllImport("kernel32.dll", _
    CharSet:=System.Runtime.InteropServices.CharSet.Auto)> _
Private Shared Function GetShortPathName( _
    <System.Runtime.InteropServices.MarshalAs( _
        System.Runtime.InteropServices.UnmanagedType.LPTStr)> _
    ByVal lpszLongPath As String, _
    <System.Runtime.InteropServices.MarshalAs( _
        System.Runtime.InteropServices.UnmanagedType.LPTStr)> _
    ByVal lpszShortPath As System.Text.StringBuilder, _
    ByVal cchBuffer As Integer) As Integer
End Function

''' <summary>
''' 短いファイルパス名を取得する
''' </summary>
''' <param name="path">ファイルのパス</param>
''' <returns>短いパス名</returns>
Public Shared Function GetShortPath(ByVal path As String) As String
    Dim sb As New System.Text.StringBuilder(1023)
    Dim ret As Integer = GetShortPathName(path, sb, sb.Capacity)
    If ret = 0 Then
        Throw New Exception("短いファイル名の取得に失敗しました。")
    End If
    Return sb.ToString()
End Function

'Button1のClickイベントハンドラ
Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) _
        Handles Button1.Click
    Console.WriteLine(GetShortPath("C:\Documents and Settings"))
End Sub
C#
コードを隠すコードを選択
[System.Runtime.InteropServices.DllImport("kernel32.dll",
    CharSet = System.Runtime.InteropServices.CharSet.Auto)]
private static extern uint GetShortPathName(
    [System.Runtime.InteropServices.MarshalAs(
        System.Runtime.InteropServices.UnmanagedType.LPTStr)]
    string lpszLongPath,
    [System.Runtime.InteropServices.MarshalAs(
        System.Runtime.InteropServices.UnmanagedType.LPTStr)]
    System.Text.StringBuilder lpszShortPath,
    uint cchBuffer);

/// <summary>
/// 短いファイルパス名を取得する
/// </summary>
/// <param name="path">ファイルのパス</param>
/// <returns>短いパス名</returns>
public static string GetShortPath(string path)
{
    System.Text.StringBuilder sb = new System.Text.StringBuilder(1024);
    uint ret = GetShortPathName(path, sb, (uint)sb.Capacity);
    if (ret == 0)
        throw new Exception("短いファイル名の取得に失敗しました。");
    return sb.ToString();
}

//Button1のClickイベントハンドラ
private void Button1_Click(object sender, EventArgs e)
{
    Console.WriteLine(GetShortPath("C:\\Documents and Settings"));
}

短いパス名から長いパス名を取得する

Path.GetFullPathメソッドを使用する方法

.NET Framework 3.0からは、Path.GetFullPathメソッドを使って、短いパス名から長いパス名を取得することができます。

MSDNのPath.GetFullPathメソッドの説明によると、.NET Framework 2.0までは「ショートファイル名で渡すと、長いファイル名に拡張されません」と書かれていますので、.NET Framework 2.0以下ではこの方法は使えないかもしれません。(私が試した限りでは、.NET Framework 2.0でも長いパス名に変換できました。)

上記の方法が使用できない場合

上記の方法が使用できない場合は、面倒ですが、ルートフォルダから順番にDirectoryInfoクラスGetFileSystemInfosプロパティを使って一つずつ正しいフォルダ名(最後はファイル名)を取得していくという方法が考えられます。このような方法は、ニュースグループのこちらの投稿などで紹介されています。

上に紹介した記事にあるコードで十分ですが、私なりに書いたものを以下に紹介します。

VB.NET
コードを隠すコードを選択
''' <summary>
''' 短いファイル名から長いファイル名を取得する
''' </summary>
''' <param name="path">短いファイル名(フルパス)</param>
''' <returns>長いファイル名</returns>
Public Shared Function GetLongPath(ByVal path As String) As String
    'ルートディレクトリを取得
    Dim root As String = System.IO.Path.GetPathRoot(path)
    'ルートディレクトリ以降を'\'で分割
    Dim folders As String() = path.Substring(root.Length). _
        Split(System.IO.Path.DirectorySeparatorChar)

    Dim res As String = root
    Dim name As String
    For Each name In folders
        Dim di = New DirectoryInfo(res)
        'ディレクトリ(またはファイル)を探す
        Dim fsi As System.IO.FileSystemInfo() = _
            di.GetFileSystemInfos(name)
        If fsi.Length = 1 Then
            res = fsi(0).FullName
        Else
            Throw New Exception("ERROR")
        End If
    Next name

    Return res
End Function
C#
コードを隠すコードを選択
/// <summary>
/// 短いファイル名から長いファイル名を取得する
/// </summary>
/// <param name="path">短いファイル名(フルパス)</param>
/// <returns>長いファイル名</returns>
public static string GetLongPath(string path)
{
    //ルートディレクトリを取得
    string root = System.IO.Path.GetPathRoot(path);
    //ルートディレクトリ以降を'\'で分割
    string[] folders = path.Substring(root.Length)
        .Split(System.IO.Path.DirectorySeparatorChar);

    string res = root;
    foreach (string name in folders)
    {
        System.IO.DirectoryInfo di = new DirectoryInfo(res);
        //ディレクトリ(またはファイル)を探す
        System.IO.FileSystemInfo[] fsi = di.GetFileSystemInfos(name);
        if (fsi.Length == 1)
            res = fsi[0].FullName;
        else
            throw new Exception("ERROR");
    }

    return res;
}
  • 履歴:
  • 2016/5/11 「Path.GetFullPathメソッドを使用する方法」を追加。

注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。

  • イベントハンドラの意味が分からない、C#のコードをそのまま書いても動かないという方は、こちらをご覧ください。
  • Windows Vista以降でUACが有効になっていると、ファイルへの書き込みに失敗する可能性があります。詳しくは、こちらをご覧ください。
  • .NET Tipsをご利用いただく際は、注意事項をお守りください。