windows - 检查 Inno Setup 中是否存在指向特定目标的快捷方式

标签 windows installation inno-setup shortcut pascalscript

在我的 Inno Setup 安装程序中,我需要确保文件夹中存在某个文件的快捷方式。快捷方式的名称是任意的,不受我的控制。我只知道它需要指向哪个文件。如果缺少快捷方式,我需要生成快捷方式。如果它已经存在,则不得再次创建它。

我猜想以某种方式可以迭代相关文件夹中的所有快捷方式文件并检查它们指向哪个文件。在 a comment回答Shared Shortcuts/Icons ,提到了一个IShellLink接口(interface),但我不知道如何在Code部分使其可用。 (使用 ShlObj; 无法识别)

有人建议我如何解决这个问题吗?

最佳答案

基于

需要 Inno Setup 的 Unicode 版本(从 Inno Setup 6 开始的唯一版本)。

const
  MAX_PATH = 260;
  STGM_READ = $00000000;
  SLGP_SHORTPATH = $1; 
  SLGP_RAWPATH = $4; 
  SLGP_RELATIVEPRIORITY = $8;
  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;

关于windows - 检查 Inno Setup 中是否存在指向特定目标的快捷方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34220914/

相关文章:

c++ - Visual Studio Express 显示错误 : "internal error occured in compiler"

python - 在 Windows 上安装 TensorFlow (Python 3.6.x)

r - 从源代码安装包?

inno-setup - 在 Inno Setup 中从 {tmp} 调用连续的 DLL

使用安装项目安装时未显示 Windows 服务

c# - 某些服务在未被其他服务使用时会自动停止

java - 关于将Java的计算器程序转换为Exe文件

inno-setup - Inno Setup - 如果应用程序正在运行,则在 'Cancel' 页面上仅提供 "Preparing to Install"选项

inno-setup - 如何测试 Inno Setup 运行的文件夹中是否存在文件?

python - 通过 WMI 确定正在运行的 GPU