检查 Inno Setup 中是否存在指向特定目标的快捷方式
Check for existence of a shortcut pointing to a specific target in Inno Setup
在我的 Inno Setup 安装程序中,我需要确保文件夹中存在指向特定文件的快捷方式。快捷方式的名称是任意的,不受我控制。我只知道它需要指向哪个文件。如果缺少快捷方式,我需要生成快捷方式。如果已经存在,则不得再次创建。
我想可以通过某种方式遍历相关文件夹中的所有快捷方式文件并检查它们指向哪个文件。在a comment to an answer to Shared Shortcuts/Icons中提到了一个IShellLink
接口,但我不知道如何在Code
部分使它可用。 (Uses ShlObj;
无法识别)
有人建议我如何解决这个问题吗?
基于
- official Inno Setup
CodeAutomation2.iss
example 和
- 删除了@TLama 对 How to get shortcut target path with InnoSetup 的回答。
需要 Unicode 版本的 Inno Setup(Inno Setup 6 的唯一版本)。
const
MAX_PATH = 260;
STGM_READ = [=10=]000000;
SLGP_SHORTPATH = ;
SLGP_RAWPATH = ;
SLGP_RELATIVEPRIORITY = ;
CLSID_ShellLink = '{00021401-0000-0000-C000-000000000046}';
type
TWin32FindDataW = record
dwFileAttributes: DWORD;
ftCreationTime: TFileTime;
ftLastAccessTime: TFileTime;
ftLastWriteTime: TFileTime;
nFileSizeHigh: DWORD;
nFileSizeLow: DWORD;
dwReserved0: DWORD;
dwReserved1: DWORD;
cFileName: array[0..MAX_PATH-1] of Char;
cAlternateFileName: array[0..13] of Char;
end;
IShellLinkW = interface(IUnknown)
'{000214F9-0000-0000-C000-000000000046}'
function GetPath(pszFile: string; cchMaxPath: Integer;
var FindData: TWin32FindDataW; fFlags: DWORD): HRESULT;
procedure Dummy2;
procedure Dummy3;
function GetDescription(pszName: string; cchMaxName: Integer): HRESULT;
function SetDescription(pszName: string): HRESULT;
function GetWorkingDirectory(pszDir: string; cchMaxPath: Integer): HRESULT;
function SetWorkingDirectory(pszDir: string): HRESULT;
function GetArguments(pszArgs: string; cchMaxPath: Integer): HRESULT;
function SetArguments(pszArgs: string): HRESULT;
function GetHotkey(var pwHotkey: Word): HRESULT;
function SetHotkey(wHotkey: Word): HRESULT;
function GetShowCmd(out piShowCmd: Integer): HRESULT;
function SetShowCmd(iShowCmd: Integer): HRESULT;
function GetIconLocation(pszIconPath: string; cchIconPath: Integer;
out piIcon: Integer): HRESULT;
function SetIconLocation(pszIconPath: string; iIcon: Integer): HRESULT;
function SetRelativePath(pszPathRel: string; dwReserved: DWORD): HRESULT;
function Resolve(Wnd: HWND; fFlags: DWORD): HRESULT;
function SetPath(pszFile: string): HRESULT;
end;
IPersist = interface(IUnknown)
'{0000010C-0000-0000-C000-000000000046}'
function GetClassID(var classID: TGUID): HRESULT;
end;
IPersistFile = interface(IPersist)
'{0000010B-0000-0000-C000-000000000046}'
function IsDirty: HRESULT;
function Load(pszFileName: string; dwMode: Longint): HRESULT;
function Save(pszFileName: string; fRemember: BOOL): HRESULT;
function SaveCompleted(pszFileName: string): HRESULT;
function GetCurFile(out pszFileName: string): HRESULT;
end;
function GetLinkFileTarget(const FileName: string): string;
var
FindData: TWin32FindDataW;
ComObject: IUnknown;
ShellLink: IShellLinkW;
PersistFile: IPersistFile;
begin
ComObject := CreateComObject(StringToGuid(CLSID_ShellLink));
PersistFile := IPersistFile(ComObject);
OleCheck(PersistFile.Load(FileName, STGM_READ));
ShellLink := IShellLinkW(ComObject);
SetLength(Result, MAX_PATH);
OleCheck(ShellLink.GetPath(Result, MAX_PATH, FindData, SLGP_RAWPATH));
SetLength(Result, Pos(#0, Result) - 1);
end;
procedure IterateShortcuts(Path: string);
var
FindRec: TFindRec;
ShortcutPath: string;
TargetPath: string;
begin
Path := AddBackslash(Path);
Log(Format('Looking for .lnk in [%s]', [Path]));
if FindFirst(Path + '*.lnk', FindRec) then
begin
try
repeat
ShortcutPath := Path + FindRec.Name;
TargetPath := GetLinkFileTarget(ShortcutPath);
Log(Format('Target of shortcut [%s] is [%s]', [
ShortcutPath, TargetPath]));
until not FindNext(FindRec);
finally
FindClose(FindRec);
end;
end;
end;
在我的 Inno Setup 安装程序中,我需要确保文件夹中存在指向特定文件的快捷方式。快捷方式的名称是任意的,不受我控制。我只知道它需要指向哪个文件。如果缺少快捷方式,我需要生成快捷方式。如果已经存在,则不得再次创建。
我想可以通过某种方式遍历相关文件夹中的所有快捷方式文件并检查它们指向哪个文件。在a comment to an answer to Shared Shortcuts/Icons中提到了一个IShellLink
接口,但我不知道如何在Code
部分使它可用。 (Uses ShlObj;
无法识别)
有人建议我如何解决这个问题吗?
基于
- official Inno Setup
CodeAutomation2.iss
example 和 - 删除了@TLama 对 How to get shortcut target path with InnoSetup 的回答。
需要 Unicode 版本的 Inno Setup(Inno Setup 6 的唯一版本)。
const
MAX_PATH = 260;
STGM_READ = [=10=]000000;
SLGP_SHORTPATH = ;
SLGP_RAWPATH = ;
SLGP_RELATIVEPRIORITY = ;
CLSID_ShellLink = '{00021401-0000-0000-C000-000000000046}';
type
TWin32FindDataW = record
dwFileAttributes: DWORD;
ftCreationTime: TFileTime;
ftLastAccessTime: TFileTime;
ftLastWriteTime: TFileTime;
nFileSizeHigh: DWORD;
nFileSizeLow: DWORD;
dwReserved0: DWORD;
dwReserved1: DWORD;
cFileName: array[0..MAX_PATH-1] of Char;
cAlternateFileName: array[0..13] of Char;
end;
IShellLinkW = interface(IUnknown)
'{000214F9-0000-0000-C000-000000000046}'
function GetPath(pszFile: string; cchMaxPath: Integer;
var FindData: TWin32FindDataW; fFlags: DWORD): HRESULT;
procedure Dummy2;
procedure Dummy3;
function GetDescription(pszName: string; cchMaxName: Integer): HRESULT;
function SetDescription(pszName: string): HRESULT;
function GetWorkingDirectory(pszDir: string; cchMaxPath: Integer): HRESULT;
function SetWorkingDirectory(pszDir: string): HRESULT;
function GetArguments(pszArgs: string; cchMaxPath: Integer): HRESULT;
function SetArguments(pszArgs: string): HRESULT;
function GetHotkey(var pwHotkey: Word): HRESULT;
function SetHotkey(wHotkey: Word): HRESULT;
function GetShowCmd(out piShowCmd: Integer): HRESULT;
function SetShowCmd(iShowCmd: Integer): HRESULT;
function GetIconLocation(pszIconPath: string; cchIconPath: Integer;
out piIcon: Integer): HRESULT;
function SetIconLocation(pszIconPath: string; iIcon: Integer): HRESULT;
function SetRelativePath(pszPathRel: string; dwReserved: DWORD): HRESULT;
function Resolve(Wnd: HWND; fFlags: DWORD): HRESULT;
function SetPath(pszFile: string): HRESULT;
end;
IPersist = interface(IUnknown)
'{0000010C-0000-0000-C000-000000000046}'
function GetClassID(var classID: TGUID): HRESULT;
end;
IPersistFile = interface(IPersist)
'{0000010B-0000-0000-C000-000000000046}'
function IsDirty: HRESULT;
function Load(pszFileName: string; dwMode: Longint): HRESULT;
function Save(pszFileName: string; fRemember: BOOL): HRESULT;
function SaveCompleted(pszFileName: string): HRESULT;
function GetCurFile(out pszFileName: string): HRESULT;
end;
function GetLinkFileTarget(const FileName: string): string;
var
FindData: TWin32FindDataW;
ComObject: IUnknown;
ShellLink: IShellLinkW;
PersistFile: IPersistFile;
begin
ComObject := CreateComObject(StringToGuid(CLSID_ShellLink));
PersistFile := IPersistFile(ComObject);
OleCheck(PersistFile.Load(FileName, STGM_READ));
ShellLink := IShellLinkW(ComObject);
SetLength(Result, MAX_PATH);
OleCheck(ShellLink.GetPath(Result, MAX_PATH, FindData, SLGP_RAWPATH));
SetLength(Result, Pos(#0, Result) - 1);
end;
procedure IterateShortcuts(Path: string);
var
FindRec: TFindRec;
ShortcutPath: string;
TargetPath: string;
begin
Path := AddBackslash(Path);
Log(Format('Looking for .lnk in [%s]', [Path]));
if FindFirst(Path + '*.lnk', FindRec) then
begin
try
repeat
ShortcutPath := Path + FindRec.Name;
TargetPath := GetLinkFileTarget(ShortcutPath);
Log(Format('Target of shortcut [%s] is [%s]', [
ShortcutPath, TargetPath]));
until not FindNext(FindRec);
finally
FindClose(FindRec);
end;
end;
end;