Вверх ↑
Этот топик читают: Гость
Ответов: 64
Рейтинг: 15
#1: 2017-05-14 06:45:14 ЛС | профиль | цитата
Здравствуйте.
Понадобилось прочесть свойство ярлыка компонентом "ShortCut" и как оказалось источник с файлом в свойстве "RFileName" читается с короткими именеми, хотя рабочую директорию в "RWorkingDirectory" читает нормально.

RFileName
C:\New folder\Новый текстовый документ.txt
C:\NEWFOL~1\700C~1.TXT

RWorkingDirectory
C:\New folder

Кто-то сталкивался и может можно как-то иначе прочесть в свойствах ярлыка, полный путь к файлу?

Добавлю: HiAsm 4.04, Win7 x86

Редактировалось 1 раз(а), последний 2017-05-14 06:49:42
карма: 0

0
vip
#1.1контекстная реклама от партнеров
Разработчик
Ответов: 26071
Рейтинг: 2122
#2: 2017-05-14 11:12:58 ЛС | профиль | цитата
sintet писал(а):
RFileName
C:\New folder\Новый текстовый документ.txt
C:\NEWFOL~1\700C~1.TXT

Так и должно быть. Короткое имя не должно превышать 8 символов.
карма: 22

0
Ответов: 64
Рейтинг: 15
#3: 2017-05-14 11:16:51 ЛС | профиль | цитата
nesco писал(а):
Так и должно быть. Короткое имя не должно превышать 8 символов.

Понятно, хотя не восьми, а 8 + 3 символа через точку, расширение файла. 8.3 формат записи имени файла со времён MS-DOS.

Как же получить полное имя файла?

Редактировалось 2 раз(а), последний 2017-05-14 11:32:40
карма: 0

0
Разработчик
Ответов: 26071
Рейтинг: 2122
#4: 2017-05-14 13:08:33 ЛС | профиль | цитата
sintet писал(а):
Как же получить полное имя файла?

Так как методы ссылки используют интерфейс Винды, а он не предусматривает использование длинных имен (ХЗ почему), то получение полного пути становится весьма нетривиальной задачей, тк нет API прямого преобразования короткого имени в длинное.
карма: 22

0
Ответов: 64
Рейтинг: 15
#5: 2017-05-14 14:16:17 ЛС | профиль | цитата
Кстати если открывать ярлыки в hex редакторе или текстовом редакторе, в нём можно увидеть полный путь к файлу. Остаётся понять как его правильно находить в HiAsm.
карма: 0

0
Разработчик
Ответов: 26071
Рейтинг: 2122
#6: 2017-05-14 18:11:15 ЛС | профиль | цитата
Решение нетривиальной задачи -- получение полного имени по короткому имени
Схема

Add(MainForm,2953706,126,154)
{
link(onCreate,10060746:doPart,[])
}
Add(Edit,15933287,245,168)
{
Left=10
Top=10
Width=365
Text=""
link(onChange,361315:doGetLongName,[])
}
Add(Edit,5034711,357,168)
{
Left=10
Top=35
Width=365
Text=""
}
Add(FilePartElm,10060746,189,168)
{
Mode=5
link(onPart,15933287:doText,[])
link(FileName,9893726:AppFileName,[])
}
Add(Application,9893726,189,112)
{
}
Add(InlineCode,361315,301,168)
{
@Hint=#11:GetLongName|
WorkPoints=#13:doGetLongName|
EventPoints=#13:onGetLongName|
Code=#15:unit HiAsmUnit;|0:|9:interface|0:|29:uses Windows,kol,Share,Debug;|0:|4:type|28: THiAsmClass = class(TDebug)|10: private|0:|9: public|30: onGetLongName: THI_Event;|80: procedure doGetLongName(var _Data: TData; Index: word); // path name WOExt|5: end;|0:|14:implementation|0:|4:type|77: TFNGetLongPathName = function(lpszShortName: LPCTSTR; lpszLongName: LPTSTR;|38: cchBuffer: DWORD): DWORD; stdcall;|58: TMbcsByteType = (mbSingleByte, mbLeadByte, mbTrailByte);|0:|4:type|28: TSysLocale = packed record|22: DefaultLCID: LCID;|22: PriLangID: LANGID;|22: SubLangID: LANGID;|21: FarEast: Boolean;|24: MiddleEast: Boolean;|6: end;|11: |3:var|44: GetLongPathName: TFNGetLongPathName = nil;|30: LeadBytes: set of Char = [];|26: SysLocale: TSysLocale; |2: |63:function ByteTypeTest(P: PChar; Index: Integer): TMbcsByteType;|3:var|13: I: Integer;|5:begin|25: Result := mbSingleByte;|45: if (P = nil) or (P[Index] = #$0) then Exit;|21: if (Index = 0) then|7: begin|51: if P[0] in LeadBytes then Result := mbLeadByte;|5: end|6: else|7: begin|19: I := Index - 1;|53: while (I >= 0) and (P[I] in LeadBytes) do Dec(I);|57: if ((Index - I) mod 2) = 0 then Result := mbTrailByte|60: else if P[Index] in LeadBytes then Result := mbLeadByte;|6: end;|4:end;|0:|66:function ByteType(const S: string; Index: Integer): TMbcsByteType;|5:begin|25: Result := mbSingleByte;|27: if SysLocale.FarEast then|46: Result := ByteTypeTest(PChar(S), Index-1);|4:end;|0:|61:function LastDelimiter(const Delimiters, S: string): Integer;|3:var|11: P: PChar;|5:begin|22: Result := Length(S);|25: P := PChar(Delimiters);|21: while Result > 0 do|7: begin|64: if (S[Result] <> #0) and (StrScan(P, S[Result]) <> nil) then|49: if (ByteType(S, Result) = mbTrailByte) then|19: Dec(Result)|10: else|13: Exit;|16: Dec(Result);|6: end;|4:end;|0:|56:function ExtractFileDir(const FileName: string): string;|3:var|13: I: Integer;|5:begin|36: I := LastDelimiter('\:',Filename);|40: if (I > 1) and (FileName[I] = '\') and|43: (not (FileName[I - 1] in ['\', ':']) or|57: (ByteType(FileName, I-1) = mbTrailByte)) then Dec(I);|33: Result := Copy(FileName, 1, I);|4:end;|0:|58:function ExtractFileDrive(const FileName: string): string;|3:var|16: I, J: Integer;|5:begin|57: if (Length(FileName) >= 2) and (FileName[2] = ':') then|34: Result := Copy(FileName, 1, 2)|61: else if (Length(FileName) >= 2) and (FileName[1] = '\') and|28: (FileName[2] = '\') then|7: begin|11: J := 0;|11: I := 3;|47: While (I < Length(FileName)) and (J < 2) do|9: begin|39: if FileName[I] = '\' then Inc(J);|27: if J < 2 then Inc(I);|8: end;|37: if FileName[I] = '\' then Dec(I);|35: Result := Copy(FileName, 1, I);|24: end else Result := '';|4:end;|0:|55:function ShortToLongFileName(FileName: string): string;|3:var|27: FindData: TWin32FindData;|18: Search: THandle;|5:begin|67: // Use GetLongPathName where available (Win98 and later) to avoid|68: // Win98 SE problems accessing UNC paths on NT/2K/XP based systems|35: if Assigned(GetLongPathName) then|7: begin|36: SetLength(Result, MAX_PATH + 1);|78: SetLength(Result, GetLongPathName(PChar(FileName), @Result[1], MAX_PATH));|5: end|6: else|7: begin|17: Result := '';|0:|74: // Strip off one directory level at a time starting with the file name|76: // and store it into the result. FindFirstFile will return the long file|37: // name from the short file name.|19: while (True) do|9: begin|65: Search := Windows.FindFirstFile(PChar(FileName), FindData);|0:|43: if Search = INVALID_HANDLE_VALUE then|14: Break;|0:|58: Result := string('\') + FindData.cFileName + Result;|43: FileName := ExtractFileDir(FileName);|32: Windows.FindClose(Search);|0:|54: // Found the drive letter followed by the colon.|35: if Length(FileName) <= 2 then|14: Break;|8: end;|0:|50: Result := ExtractFileDrive(FileName) + Result;|6: end;|4:end;|0:|3:var|22:KernelHandle: THandle;|0:|36:procedure THiAsmClass.doGetLongName;|5:begin|67: _hi_onEvent(onGetLongName, ShortToLongFileName(ToString(_Data)));|4:end;|0:|14:initialization|0:|44:KernelHandle := GetModuleHandle('KERNEL32');|25:if KernelHandle <> 0 then|69:@GetLongPathName := GetProcAddress(KernelHandle, 'GetLongPathNameA');|0:|4:end.|
link(onGetLongName,5034711:doText,[])
AddHint(47,-37,84,13,@Hint)
}


Редактировалось 1 раз(а), последний 2017-05-14 18:11:33
карма: 22

1
Голосовали:sintet
Ответов: 64
Рейтинг: 15
#7: 2017-05-14 18:37:56 ЛС | профиль | цитата
nesco, круто спасибо.

Другое решение нетривиальной задачи

Add(MainForm,2953706,126,140)
{
link(onCreate,5766131:doEnum,[])
}
Add(FileStream,1374420,308,91)
{
link(onLoad,2439570:doConvert,[(350,97)(350,131)(296,131)(296,146)])
link(FileName,16324795:Value,[])
}
Add(StreamConvertor,2439570,308,140)
{
Mode=4
Symbol="*"
link(onResult,1791558:doEnum,[])
link(Data,1374420:Stream,[])
}
Add(Str_Enum,1791558,357,140)
{
Delimiter="*"
link(onEnum,350085:doLength,[])
}
Add(Length,350085,406,140)
{
link(onLength,14245398:doCompare,[])
}
Add(If_else,14245398,448,140)
{
Type=1
Op2=Integer(3)
link(onFalse,13642079:doData,[(491,153)(491,187)(345,187)(345,202)])
}
Add(DoData,13642079,364,196)
{
link(onEventData,8100567:doValue,[])
link(Data,1791558:Part,[])
}
Add(Copy,4408847,448,196)
{
Position=2
Count=2
link(onCopy,13659489:doCompare,[])
}
Add(Memory,8100567,406,196)
{
link(onData,4408847:doCopy,[])
}
Add(If_else,13659489,497,196)
{
Op2=String(:\)
link(onTrue,12382021:doData,[(539,202)(539,237)(394,237)(394,251)])
}
Add(DoData,12382021,406,245)
{
Data=String()
link(onEventData,8405695:doText,[])
link(Data,8100567:Value,[])
}
Add(Edit,8405695,448,245)
{
Left=5
Top=25
Width=382
}
Add(DropFile,2308361,217,42)
{
link(onDropFile,8045379:doEvent1,[])
link(onEndDrop,16181761:doEvent1,[(261,55)(261,97)])
}
Add(Memory,16324795,308,42)
{
}
Add(Application,12841581,210,105)
{
}
Add(ArrayEnum,5766131,217,154)
{
link(onItem,8045379:doEvent2,[(269,160)(269,55)])
link(onEndEnum,16181761:doEvent2,[(261,167)(261,104)])
link(Array,12841581:Params,[])
}
Add(Hub,16181761,280,91)
{
InCount=2
OutCount=1
link(onEvent1,1374420:doOpen,[])
}
Add(Hub,8045379,280,42)
{
InCount=2
OutCount=1
link(onEvent1,16324795:doValue,[])
}

Редактировалось 2 раз(а), последний 2017-05-14 18:39:28
карма: 0

0
Разработчик
Ответов: 26071
Рейтинг: 2122
#8: 2017-05-14 19:06:55 ЛС | профиль | цитата
sintet писал(а):
спасибо

Добавлен новый метод FileLong в компонент FilePartElm. Обновись с SVN и можешь использовать без всяких IC и извратов. Там используется (как оказалось после детального поиска) штатная API-функция Винды -- GetLongPathName
карма: 22

1
Голосовали:sintet
8
Сообщение
...
Прикрепленные файлы
(файлы не залиты)