使用Inno Setup创建硬链接

4

我有成千上万个自己的安装程序,需要一个关键的dll文件来进行卸载步骤,这个dll文件大小约为2mb,为了避免不必要的磁盘空间浪费(2mb * 100个安装程序),我希望只在{cf}中存储一次该文件,然后为下一个需要该文件的安装程序创建硬链接。

我能否在Inno Setup中创建硬链接,而无需使用外部应用程序如mklink.exe

这是我拥有的内容的简要示例,所有我的安装程序都遵循相同的“结构”:

[Files]
; VCL Styles
Source: {tmp}\uninstall.vsf; DestDir: {app}; \
    Flags: ignoreversion
Source: {tmp}\uninstall.dll; DestDir: {app}; \
    Flags: ignoreversion uninsneveruninstall

; Temp files
Source: {tmp}\*; DestDir: {tmp}; Excludes: uninstall.dll, uninstall.vsf; \
    Flags: recursesubdirs createallsubdirs ignoreversion

; Program
Source: {app}\*; DestDir: {app}; \
    Flags: recursesubdirs createallsubdirs ignoreversion

如您所见,我正在将 uninstall.dll 移动到 {app},但我想要做的是:如果不存在,则将 uninstall.dll 文件复制到 {cf}\InnoSetup\uninstall.dll 文件路径,并创建一个硬链接到 {app}\uninstall.dll。如果文件已经存在,则只需创建硬链接,不需要再存储 uninstall.dll 文件在 {app}\uninstall.dll 中,我只需要一个符号引用,因为 uninstall.dll 文件永远不应该被卸载。

我应该如何操作呢?

1个回答

8

Inno Setup不支持原生创建硬链接。


我不认为mklink是外部应用程序。它是一个内置的 Windows 工具。因此,如果您不需要支持 Windows XP,则可以放心地依赖它。或者,如果mklink不可用,可以回退到常规安装 DLL。请保留 HTML 标签。

或者使用 Code 部分中的 CreateHardLink 函数

#define MyApp "MyApp"
#define UninstallDll "uninstall.dll"

[Files]
Source: "{#UninstallDll}"; DestDir: "{cf}\{#MyApp}"; \
  Flags: ignoreversion uninsneveruninstall

[Code]
function CreateHardLink(lpFileName, lpExistingFileName: string;
  lpSecurityAttributes: Integer): Boolean;
  external 'CreateHardLinkW@kernel32.dll stdcall';

procedure CurStepChanged(CurStep: TSetupStep);
var
  ExistingFile, NewFile: string;
begin
  if CurStep = ssPostInstall then
  begin
    ExistingFile := ExpandConstant('{cf}\{#MyApp}\{#UninstallDll}');
    NewFile := ExpandConstant('{app}\{#UninstallDll}');
    if CreateHardLink(NewFile, ExistingFile, 0) then
    begin
      Log('Hardlink created');
    end
      else
    if FileCopy(ExistingFile, NewFile, False) then
    begin
      // FAT file system?
      Log('Hardlink could not be created, file copied instead');
    end
      else
    begin
      MsgBox('Cannot install {#UninstallDll}', mbError, MB_OK);
    end;
  end;
end;

(在Inno Setup 6中,仅支持Unicode版本进行测试)
卸载时请不要忘记删除该文件:
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
  if CurUninstallStep = usUninstall then
  begin
    if DeleteFile(ExpandConstant('{app}\{#UninstallDll}')) then
    begin
      Log('File deleted');
    end
      else
    begin
      Log('Cannot delete file');
    end;
  end;
end;

当然,您也可以使用[UninstallDelete]条目。我只是喜欢使用与安装相同的技术来卸载文件。


您的问题标题是“使用Inno Setup创建硬链接

CreateHardLink创建一个硬链接。硬链接是指向相同内容的另一个引用。基本上,硬链接与原始文件无法区分(实际上,原始文件也是硬链接)。原始文件和硬链接都只是指向相同内容的引用。如果您删除原始文件(或新的硬链接),则实际上只会删除对内容的一个引用。只有最后一个引用被删除时,才会删除内容。硬链接不会占用磁盘上的额外空间(内容仅存储一次)。

有关详细信息,请参见Wikipedia上的硬链接文章

mklink默认创建符号链接(又称为软链接)。符号链接类似于快捷方式,它是对原始文件的引用(而不是内容)。它本身是一个文件,包含指向目标文件的路径。符号链接具有自己的大小(由指向目标文件的引用占用)。如果您删除原始文件,则符号链接仍然存在(因为原始文件没有对符号链接的引用),但变为无效(内容已经丢失)。同样,这类似于快捷方式。

有关详细信息,请参见维基百科上的符号链接文章

如果添加/H开关,您可以使用mklink创建硬链接:

/H 创建硬链接而不是符号链接。

如果你想创建符号链接而不是硬链接,那就是另一个问题(尽管答案很简单,使用 CreateSymbolicLink 函数)。但是要再次注意,硬链接不会占用磁盘上的额外空间,这似乎是你关心的问题。因此,我认为你应该继续使用 CreateHardLink 函数。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接