2008年7月30日

ファイル名を長い形式に変換(GetLongPathName版)

Win32APIのGetLongPathNameを使用して8.3形式の短いファイル名(Short File Name)の混じったフルパス名を全て長いファイル名(Long File Name)に変換する方法です。Windows 2000以降でのみ動作します。
uses
  Windows, SysUtils;

type
  TGetLongPathNameFunc = function(lpszShortPath: PChar;
                                  lpszLongPath: PChar;
                                  cchBuffer: DWORD): DWORD; stdcall;

function ToLongFilename(const Filename: String): String;
var
  Size: Integer;
  GetLongPathName: TGetLongPathNameFunc;
begin

  Result := Filename;

  if (Win32Platform = VER_PLATFORM_WIN32_NT) and
     (Win32MajorVersion >= 5) then  // Windows 2000 or later
  begin
    @GetLongPathName := GetProcAddress(GetModuleHandle('Kernel32.dll'),
{$IFDEF Unicode}
                                       'GetLongPathNameW');
{$ELSE}
                                       'GetLongPathNameA');
{$ENDIF}
    if Assigned(GetLongPathName) = True then
    begin
      { Calculate buffer size }
      Size := GetLongPathName(PChar(Filename),nil,0);
      if Size = 0 then
      begin
        Exit;
      end;

      { Convert to long name }
      SetLength(Result,Size);
      Size := GetLongPathName(PChar(Filename),PChar(Result),Size);
      SetLength(Result,Size);
    end;
  end;

end;

この例でもGetShortPathNameを使用する場合と同様に、対象となるファイルが存在しないと最初のGetLongPathName呼び出しで0が返ってきて変換不能になってしまうため、注意が必要です。

2018/11/08追記: TGetLongPathNameFuncの宣言で引数名が入れ替わっていたものを修正。ご指摘ありがとうございます。

2 件のコメント:

匿名 さんのコメント...

宣言の変数名の意味合いが間違ってるよ。
どっちもポインタだから動作上は問題ないけど。

DWORD GetLongPathName(
LPCTSTR lpszShortPath,
LPTSTR lpszLongPath,
DWORD cchBuffer
);

ふー さんのコメント...

あーほんとですね。ご指摘ありがどうございます。