- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
JclShell.TShellLink.Target
返回错误的路径:
uses
JclShell;
...
var
ThisShellLinkRecord: JclShell.TShellLink;
ThisTargetExePath: string;
begin
JclShell.ShellLinkResolve('C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Xara\Xara Designer Pro X9\Xara Designer Pro X9.lnk', ThisShellLinkRecord);
ThisTargetExePath := ThisShellLinkRecord.Target;
上述代码结果中的
ThisTargetExePath
为:C:\Program Files (x86)\Xara\Xara Designer Pro X9\DesignerPro.exe
请注意生成的目标路径中的 (x86)
,它表示 32 位程序文件路径。
但是,这是错误的路径并且不存在!当我从 Windows 开始菜单手动打开 Xara Designer Pro 开始菜单链接的属性对话框时,目标路径为:C:\Program Files\Xara\Xara Designer Pro X9\DesignerPro.exe
请注意,这是 64 位程序文件路径并且确实存在!
那么为什么 ShellLinkResolve 会在这里返回错误的数据呢?
编辑:我在 Notepad++ 中打开了链接:我只在其中找到了绝对 64 位程序文件路径(无环境变量),请参见此处:goo.gl/jWUDb9
编辑2:
你说得对,编译为32位程序和64位程序会有不同的结果:
procedure TForm1.btn1Click(Sender: TObject);
var
ThisShellLinkRecord: JclShell.TShellLink;
begin
JclShell.ShellLinkResolve(Edit1.Text, ThisShellLinkRecord);
{$IFDEF WIN32}
Form1.Caption := 'This is a 32-bit program';
Label1.Caption := ThisShellLinkRecord.Target;
{$ELSE}
Form1.Caption := 'This is a 64-bit program';
Label1.Caption := JclFileUtils.PathGetLongName(ThisShellLinkRecord.Target);
{$ENDIF}
end;
以下是视觉结果:
http://goo.gl/MttrZA
http://goo.gl/hvQqP6
EDIT3:这是编码的链接文件(Xara Designer Pro X9.lnk
,使用 Soap.EncdDecd.EncodeBase64
编码):
TAAAAAEUAgAAAAAAwAAAAAAAEabAAAAICAAAHCmGD2HDc8Ba9NGcKwWzwFwphg9hw3PASiAxAEAAAAAAQAAAAAAAAAAAAAAAAAAANcBFAAFUOBP0CDqOmkQotgIACswMJ0ZAC9DOlwAAAAAAAAAAAAAAAAAAAAAAAAAiAAxAAAAAAA1RFVrESBQUk9HUkF+MQAAcAAIAAQA777uOoUaNURVayoAAAA8AAAAAAABAAAAAAAAAAAAARgAAAAAAUAByAG8AZwByAGEAbQAgAEYAaQBsAGUAcwAAAEAAcwBoAGUAbABsADMAMgAuAGQAbABsACwALQAyADEANwA4ADEAAAAYAEoAMQAAAAAANURVaxAgWGFyYQAANgAIAAQA第7741章RFlrECBYQVJBREV+MQAAVgAIAAQA7741RFVrNURZayoAAABqfRUAAAADAAAAAAAAAAAAAAAAAAAWABHIAYQAgAEQAZQBzAGkAZwBuAGUAcgAgAFAAcgBVACAAWAA5AAAAGABoADIAKIDEASlE+rAgIERFU0lHTn4xLkVYRQAATAAIAAQA774pRPqwNURZayoAAACEgRUAAAADAAAAAAAAAAAAAAAAAAARABLAHMAaQBnAG4AZQByAFAAcgBVAC4AZQB4AGUAAAAcAAAAcwAAABwAAAABAAAAHAAAADcAAAAAAAAAcgAAABsAAAADAAAAdG6zfBAAAABXaW43U1lTVEVNAEM6XFByb2dyYW0gRmlsZXNcWGFyYVxYYXJhIERlc2lnbmVyIFBybyBYOVxEZXNpZ25lclByby5leGUAAEwALgAuAFwALgAuAFwALgAuAFwALgAuAFwALgAuAFwALgAuAFwALgAuAFwAUAByAG8AZwByAGEAbQAgAEYAaQBsAGUAcwBcAFgAYQByAGEAXABYAGEAcgBhACAARABLAHMAaQBnAG4AZQByACAAUAByAG8AIABYADkAXABEAGUAcwBpAGcAbgBlAHIAUAByAG8ALgBLAHgAZQArAEMAOgBcAFAAcgBvAGcAcgBhAG0AIABGAGkAbABLAHMAXABYAGEAcgBhAFwawabhAHIAYQAgAEQAZQBzAGkAZwBuAGUAcgAgAFAAcgBvACAAWAA5AFwAEAAAAAUAAKAmAAAAtQAAABwAAAALAACgtmNekL/BTkmynGW3MtPSGrUAAABNAAAACQAAoEEAAAAxU1BT4opYRrxMOEO7/BOTJphtziUAAAAEAAAAAB8AAAAJAAAAUwAtADEALQA1AC0AMQA4AAAAAAAAAAAAAAAAAAGAAAAADAACgWAAAAAAAAABoYXVwdC1wYwAAAAAAAAAAEIn2YAe8i0eH0eCntqcHxhEBFJmGguMRs54cb2UwHBYQifZgB7yLR4fR4Ke2pwfGEQEUmYaC4xGznhxvZTAcFgAAAAA=
最佳答案
也许这有帮助:通过解析内部结构从lnk文件直接读取目标路径:
type
TdecShellLinkHeader = packed record
HeaderSize: DWORD;
LinkCLSID: TGUID;
LinkFlags: DWORD;
FileAttributes: DWORD;
CreationTime: TFILETIME;
AccessTime: TFILETIME;
WriteTime: TFILETIME;
FileSize: DWORD;
IconIndex: Integer;
ShowCommand: DWORD;
HotKey: Word;
Reserved1: Word;
Reserved2: DWORD;
Reserved3: DWORD;
end;
const
LnkFileCLSID: TGUID = '{00021401-0000-0000-C000-000000000046}';
function DirectReadTargetNameFromLnkFile(const AFileName: UnicodeString): UnicodeString;
var
Stream: TStream;
Header: TdecShellLinkHeader;
Size: Word;
IDList: PItemIDList;
Desktop: IShellFolder;
ShellFolder: IShellFolder;
ChildItem: PItemIDList;
StrRet: TStrRet;
AnsiResult: AnsiString;
Result2: UnicodeString;
begin
Result := '';
Stream := TFileStream.Create(AFileName, fmOpenRead);
try
Stream.ReadBuffer(Header, SizeOf(Header));
if not (Header.HeaderSize = SizeOf(Header)) or
not IsEqualCLSID(Header.LinkCLSID, LnkFileCLSID) then
raise Exception.Create('Invalid Lnk file');
if Header.LinkFlags and SLDF_HAS_ID_LIST <> 0 then
begin
Stream.ReadBuffer(Size, SizeOf(Size));
IDList := CoTaskMemAlloc(Size);
try
Stream.ReadBuffer(IDList^, Size);
OleCheck(SHGetDesktopFolder(Desktop));
try
OleCheck(SHBindToParent(IDList, IShellFolder, Pointer(ShellFolder), ChildItem));
try
OleCheck(ShellFolder.GetDisplayNameOf(ChildItem, SHGDN_FORPARSING, StrRet));
case StrRet.uType of
STRRET_WSTR:
begin
Result := StrRet.pOleStr;
CoTaskMemFree(StrRet.pOleStr);
end;
STRRET_OFFSET:
begin
Inc(PByte(ChildItem), StrRet.uOffset);
Result := UnicodeString(PAnsiChar(ChildItem));
end;
STRRET_CSTR:
Result := UnicodeString(AnsiString(StrRet.cStr));
else Result := '';
end;
Exit;
finally
ShellFolder := nil;
end;
finally
Desktop := nil;
end;
finally
CoTaskMemFree(IDList);
end;
end;
if Header.LinkFlags and SLDF_HAS_LINK_INFO <> 0 then
begin
Stream.ReadBuffer(Size, SizeOf(Size));
Stream.Seek(Size - SizeOf(Size), soFromCurrent);
end;
if Header.LinkFlags and SLDF_HAS_NAME <> 0 then
begin
Stream.ReadBuffer(Size, SizeOf(Size));
if Header.LinkFlags and SLDF_UNICODE <> 0 then
Stream.Seek(Size * SizeOf(WideChar), soFromCurrent)
else
Stream.Seek(Size * SizeOf(AnsiChar), soFromCurrent);
end;
if Header.LinkFlags and SLDF_HAS_RELPATH <> 0 then
begin
Stream.ReadBuffer(Size, SizeOf(Size));
if Header.LinkFlags and SLDF_UNICODE <> 0 then
begin
SetLength(Result, Size);
if Size > 0 then
Stream.ReadBuffer(PWideChar(Result)^, Size * SizeOf(WideChar));
end
else
begin
SetLength(AnsiResult, Size);
if Size > 0 then
Stream.ReadBuffer(PAnsiChar(AnsiResult)^, Size * SizeOf(AnsiChar));
Result := AnsiResult;
end;
if Header.LinkFlags and SLDF_HAS_EXP_SZ <> 0 then
begin
Size := ExpandEnvironmentStringsW(PWideChar(Result), nil, 0);
if Size > 1 then
begin
SetLength(Result2, Size - 1);
ExpandEnvironmentStringsW(PWideChar(Result), PWideChar(Result2), Size);
Result := Result2;
end;
end;
Result2 := ExtractFileDir(AFileName);
while Pos('..\', Result) = 1 do
begin
Result2 := ExtractFileDir(Result2);
Delete(Result, 1, 3);
end;
Result := Result2 + '\' + Result;
end;
finally
Stream.Free;
end;
end;
使用风险自负!
关于delphi - JclShell.ShellLinkResolve 获取错误数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22357992/
JclShell.TShellLink.Target 返回错误的路径: uses JclShell; ... var ThisShellLinkRecord: JclShell.TShellL
我是一名优秀的程序员,十分优秀!