Convert short file names to long ones (Views: 30)
Problem/Question/Abstract: How do I convert a short (alias) filename or directory name into its long equivalent? Answer: Solve 1: {Parameters: shortname: File name or path to convert. This can be a fully qualified file name or a path relative to the current directory. It can contain long and / or short forms for the names. Returns: Fully qualified filename using the long names for all elements of the path. Description: Recursively uses FindFirst to find the long names for the path elements. Error Conditions: Will raise an exception if any part of the path was not found. Created: 15.01.98 14:09:26 by Peter Below} function GetLongFilename(shortname: string): string; function GetL(shortname: string): string; var srec: TSearchRec; begin { Lob off the last element of the passed name. If we received only a root name, e.g. c:\, ExtractFileDir returns the path unchanged. } Result := ExtractFileDir(shortname); if (Result <> shortname) then begin { We still have an unconverted path element. So convert the last one in the current shortname and combine the resulting long name with what we get by calling ourselves recursively with the rest of the path. } if FindFirst(shortname, faAnyfile, srec) = 0 then try Result := GetL(Result) + '\' + srec.Name; finally FindClose(srec); end else raise Exception.CreateFmt('Path %s does not exist!', [shortname]); end else { Only the root remains. Remove the backslash since the caller will add it back anyway. } Delete(Result, length(result), 1); end; begin { Create fully qualified path and pass it to the converter. } Result := GetL(ExpandFilename(shortname)); end; Solve 2: {Get LFN from 8.3} function GetLongPathName(const PathName: string): string; var Drive: string; Path: string; SearchRec: TSearchRec; begin if PathName = '' then Exit; Drive := ExtractFileDrive(PathName); Path := Copy(PathName, Length(Drive) + 1, Length(PathName)); if (Path = '') or (Path = '\') then begin Result := PathName; if Result[Length(Result)] = '\' then Delete(Result, Length(Result), 1); end else begin Path := GetLongPathName(ExtractFileDir(PathName)); if FindFirst(PathName, faAnyFile, SearchRec) = 0 then begin Result := Path + '\' + SearchRec.FindData.cFileName; FindClose(SearchRec); end else Result := Path + '\' + ExtractFileName(PathName); end; end; Solve 3: You could try the following. It should work on Win95 and above. unit WhateverYouWantToCallIt; interface function LongPathFromShort(const ShortPath: string): string; implementation uses Windows, SysUtils, ActiveX, ShlObj; function LongPathFromShort(const ShortPath: string): string; var iAttributes: Cardinal; iEaten: Cardinal; IntfDesktop: IShellFolder; IntfMalloc: IMalloc; pItemList: PItemIDList; sFile: WideString; szFile: array[0..MAX_PATH] of Char; begin Result := ShortPath; if not FileExists(ShortPath) then Exit; if Succeeded(SHGetDesktopFolder(IntfDesktop)) then begin sFile := ShortPath; iAttributes := 0; if Succeeded(IntfDesktop.ParseDisplayName(0, nil, POleStr(sFile), iEaten, pItemList, iAttributes)) then begin SHGetPathFromIDList(pItemList, szFile); Result := szFile; SHGetMalloc(IntfMalloc); IntfMalloc.Free(pItemList) end end end; end. Solve 4: GetFullPathName converts a relative path to an absolute path. You can use GetLongPathName, but this requires Win98 and later or Win2k and later. function GetLongName(const APath: string): string; var Buffer: array[0..MAX_PATH] of Char; Required: Integer; begin Required := GetLongPathName(PChar(APath), Buffer, Length(Buffer)); if Required > MAX_PATH then {Buffer too small} begin SetLength(Result, Required - 1); GetLongPathName(PChar(APath), Pointer(Result), Required); end else if Required = 0 then {Error} Result := APath else SetString(Result, Buffer, Required); end; For an ANSI only function you can reduce the above to: function GetLongName(const APath: AnsiString): AnsiString; var Buffer: array[0..MAX_PATH] of AnsiChar; Required: Integer; begin Required := GetLongPathNameA(PChar(APath), Buffer, Length(Buffer)); SetString(Result, Buffer, Required); end; If you need to support for Win95 or WinNT, you can use this function: function GetLongPathName(Path: string): string; var I: Integer; SearchHandle: THandle; FindData: TWin32FindData; IsBackSlash: Boolean; begin Path := ExpandFileName(Path); Result := ExtractFileDrive(Path); I := Length(Result); if Length(Path) <= I then {only drive} Exit; if Path[I + 1] = '\' then begin Result := Result + '\'; Inc(I); end; Delete(Path, 1, I); repeat I := Pos('\', Path); IsBackSlash := I > 0; if not IsBackSlash then I := Length(Path) + 1; SearchHandle := FindFirstFile(PChar(Result + Copy(Path, 1, I - 1)), FindData); if SearchHandle <> INVALID_HANDLE_VALUE then begin try Result := Result + FindData.cFileName; if IsBackSlash then Result := Result + '\'; finally Windows.FindClose(SearchHandle); end; end else begin Result := Result + Path; Break; end; Delete(Path, 1, I); until Length(Path) = 0; end; |