不要在 Inno Setup 安装程序中多次包含重复文件

Do not include duplicate files multiple times in the Inno Setup installer

可以减小我的安装程序的大小吗?

目前我的 GoogleAuthAndSync 支持实用程序有以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
; Google Calendar Interface v3
Source:"Google.Apis.Auth.dll"; DestDir:"{app}"; Flags: ignoreversion
Source:"Google.Apis.Auth.PlatformServices.dll"; DestDir:"{app}"; Flags: ignoreversion
Source:"Google.Apis.Calendar.v3.dll"; DestDir:"{app}"; Flags: ignoreversion
Source:"Google.Apis.Core.dll"; DestDir:"{app}"; Flags: ignoreversion
Source:"Google.Apis.dll"; DestDir:"{app}"; Flags: ignoreversion
Source:"Google.Apis.PlatformServices.dll"; DestDir:"{app}"; Flags: ignoreversion
Source:"Google.GData.Client.dll"; DestDir:"{app}"; Flags: ignoreversion
Source:"Google.GData.Contacts.dll"; DestDir:"{app}"; Flags: ignoreversion
Source:"Google.GData.Extensions.dll"; DestDir:"{app}"; Flags: ignoreversion
Source:"GoogleAuthandSync.exe"; DestDir:"{app}"; Flags: ignoreversion
Source:"GoogleAuthandSync.exe.config"; DestDir:"{app}"; Flags: ignoreversion
Source:"Microsoft.Threading.Tasks.dll"; DestDir:"{app}"; Flags: ignoreversion
Source:"Microsoft.Threading.Tasks.Extensions.Desktop.dll"; DestDir:"{app}"; Flags: ignoreversion
Source:"Microsoft.Threading.Tasks.Extensions.dll"; DestDir:"{app}"; Flags: ignoreversion
Source:"Newtonsoft.Json.dll"; DestDir:"{app}"; Flags: ignoreversion
Source:"System.Net.Http.dll"; DestDir:"{app}"; Flags: ignoreversion
Source:"System.Net.Http.Extensions.dll"; DestDir:"{app}"; Flags: ignoreversion
Source:"System.Net.Http.Primitives.dll"; DestDir:"{app}"; Flags: ignoreversion
Source:"Zlib.Portable.dll"; DestDir:"{app}"; Flags: ignoreversion

如您所见,这些文件被安装到 {app} 文件夹中。我没有使用通配符的原因是因为我也有语言资源 dll 文件并且不想包含它们。

然后,我将 OutlookCalIFConsole 实用程序安装到子文件夹中:

1
2
3
4
; Outlook Calendar Interface
Source:"OutlookCalIFConsole\\*.dll"; DestDir:"{app}\\OutlookCalIFConsole"; Flags: ignoreversion
Source:"OutlookCalIFConsole\\OutlookCalIFConsole.exe"; DestDir:"{app}\\OutlookCalIFConsole"; Flags: ignoreversion sign
Source:"OutlookCalIFConsole\\OutlookCalIFConsole.exe.config"; DestDir:"{app}\\OutlookCalIFConsole"; Flags: ignoreversion

我刚刚更新了两个项目中的所有 Nuget 包,这是 DLL 文件的结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
D:\\My Programs\\2017\\GoogleAuthandSync\\GoogleAuthandSync\\bin\
elease>dir *.dll

26/04/2016  12:16         2,236,416 BouncyCastle.Crypto.dll
08/02/2018  11:32           105,472 Google.Apis.Auth.dll
08/02/2018  11:32             5,120 Google.Apis.Auth.PlatformServices.dll
26/03/2018  08:38            89,600 Google.Apis.Calendar.v3.dll
08/02/2018  11:32            67,072 Google.Apis.Core.dll
08/02/2018  11:32            71,680 Google.Apis.dll
08/02/2018  11:32             4,096 Google.Apis.PlatformServices.dll
25/06/2013  11:24           212,992 Google.GData.Client.dll
25/06/2013  11:33            29,184 Google.GData.Contacts.dll
25/06/2013  11:27            90,112 Google.GData.Extensions.dll
08/03/2017  20:26           276,480 log4net.dll
24/03/2018  18:44           662,528 Newtonsoft.Json.dll
13/08/2013  01:19            27,296 System.Data.DataSetExtensions.dll
13/08/2013  01:19         1,172,568 System.Data.dll
13/08/2013  01:19            63,064 System.Net.dll
05/09/2017  14:54           197,984 System.Net.Http.dll
19/02/2015  21:10            22,232 System.Net.Http.Extensions.dll
19/02/2015  21:10            21,720 System.Net.Http.Primitives.dll
14/10/2017  18:34            39,848 System.Security.Cryptography.Algorithms.dll
05/11/2016  05:57            23,480 System.Security.Cryptography.Encoding.dll
05/11/2016  05:57            22,816 System.Security.Cryptography.Primitives.dll
14/10/2017  18:34            38,848 System.Security.Cryptography.X509Certificates.dll
13/08/2013  01:19           921,688 System.XML.dll
13/08/2013  01:19            43,112 System.Xml.Linq.dll
22/06/2015  09:00            81,920 Zlib.Portable.dll

D:\\My Programs\\2017\\OutlookCalIFConsole\\OutlookCalIFConsole\\bin\
elease>dir *.dll

11/01/2018  01:05           185,856 CommandLine.dll
23/03/2018  15:10            63,488 Microsoft.Graph.Core.dll
26/03/2018  11:13         4,714,520 Microsoft.Graph.dll
08/05/2017  17:49           226,528 Microsoft.Identity.Client.dll
24/03/2018  18:44           662,528 Newtonsoft.Json.dll
05/11/2016  05:55            34,496 System.Console.dll
05/11/2016  05:56            22,184 System.IO.dll
05/09/2017  14:54           197,984 System.Net.Http.dll
05/11/2016  05:56            22,728 System.Reflection.dll
19/07/2017  10:01            29,440 System.Reflection.TypeExtensions.dll
05/11/2016  05:57            29,880 System.Runtime.dll
05/11/2016  05:56            33,000 System.Runtime.Extensions.dll
14/10/2017  18:34            39,848 System.Security.Cryptography.Algorithms.dll
05/11/2016  05:57            23,480 System.Security.Cryptography.Encoding.dll
05/11/2016  05:57            22,816 System.Security.Cryptography.Primitives.dll
14/10/2017  18:34            38,848 System.Security.Cryptography.X509Certificates.dll

现在许多 DLL 文件的日期相同,等等。那么,有没有办法只将受影响的文件添加到安装程序中一次并部署到两个位置?

我不想让事情过于复杂或给自己造成维护问题。

请注意,我还设置了 SourceDir 指令:

1
2
3
4
5
[ISPP]
#define SourceDir"..\\Meeting Schedule Assistant\
elease"
[Setup]
SourceDir={#SourceDir}


我找到了允许 InnoSetup 编译器在压缩期间成功删除重复文件的解决方案,我的配置中感兴趣的部分是:

1
2
3
4
5
6
Compression=lzma2/ultra64
LZMANumBlockThreads=4
CompressionThreads=4
LZMADictionarySize=262144 ; this allows to find duplicated files and succesfully deduplicate them (but compressor consumes up to 2.5GB / ram during compilation)
LZMAUseSeparateProcess=yes
SolidCompression=yes

InnoSetup 版本是 6.0.2 (u)


您可以使用预处理器来迭代子文件夹中的 DLL 文件,并将它们与基础文件夹中的文件进行比较。如果它们匹配,则使用基本文件夹中的文件作为源。多次使用时,Inno Setup 只会将源文件编译一次给安装程序。

由于使用了 SourceDir 指令(预处理器显然不知道),代码有些复杂。如果没有指令,代码会更简单。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[Files]
#pragma parseroption -p-

#define FileEntry(Source, DestPath) \\
   "Source:" + Source +"; DestDir:" + DestPath +"\
"

#define GetFileTimestamp(Path) GetFileDateTimeString(Path, 'dd/mm/yyyy hh:nn:ss', '-', ':')

#define ProcessFile(RootPath, Path, AlternativePath, DestPath, FindResult, FindHandle) \\
    FindResult ? \\
        Local[0] = FindGetFileName(FindHandle), \\
        Local[1] = AddBackslash(Path) + Local[0], \\
        Local[2] = AddBackslash(AlternativePath) + Local[0], \\
        Local[3] = AddBackslash(RootPath) + Local[1], \\
        Local[4] = AddBackslash(RootPath) + Local[2], \\
        Local[5] = \\
           FileExists(Local[4]) && \\
           (GetFileTimestamp(Local[3]) == GetFileTimestamp(Local[4])), \\
        FileEntry((Local[5] ? Local[2] : Local[1]), DestPath) + \\
        ProcessFile(RootPath, Path, AlternativePath, DestPath, \\
            FindNext(FindHandle), FindHandle) \\
    :""

#define ProcessFolderWithAlternativeSource(RootPath, Path, AlternativePath, DestPath) \\
    Local[0] = FindFirst(AddBackslash(AddBackslash(RootPath) + Path) +"*.dll", 0), \\
    ProcessFile(RootPath, Path, AlternativePath, DestPath, Local[0], Local[0])

#pragma parseroption -p+

#emit ProcessFolderWithAlternativeSource( \\
   "..\\Meeting Schedule Assistant\
elease","OutlookCalIFConsole",".", \\
   "{app}\\OutlookCalIFConsole")

或者你可以使用 SetupSetting 来读取 SourceDir 指令:

1
2
#emit ProcessFolderWithAlternativeSource( \\
    SetupSetting("SourceDir"),"OutlookCalIFConsole",".","{app}\\OutlookCalIFConsole")

如果将 SaveToFile 添加到脚本的末尾:

1
#expr SaveToFile(AddBackslash(SourcePath) +"Preprocessed.iss")

... 那么您应该在 Preprocessed.iss:

中看到类似的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[Files]
Source: OutlookCalIFConsole\\CommandLine.dll; Dest: {app}\\OutlookCalIFConsole
Source: OutlookCalIFConsole\\Microsoft.Graph.Core.dll; Dest: {app}\\OutlookCalIFConsole
Source: OutlookCalIFConsole\\Microsoft.Graph.dll; Dest: {app}\\OutlookCalIFConsole
Source: OutlookCalIFConsole\\Microsoft.Identity.Client.dll; Dest: {app}\\OutlookCalIFConsole
Source: .\
ewtonsoft.Json.dll; Dest: {app}\\OutlookCalIFConsole
Source: OutlookCalIFConsole\\System.Console.dll; Dest: {app}\\OutlookCalIFConsole
Source: OutlookCalIFConsole\\System.IO.dll; Dest: {app}\\OutlookCalIFConsole
Source: .\\System.Net.Http.dll; Dest: {app}\\OutlookCalIFConsole
Source: OutlookCalIFConsole\\System.Reflection.dll; Dest: {app}\\OutlookCalIFConsole
Source: OutlookCalIFConsole\\System.Reflection.TypeExtensions.dll; Dest: {app}\\OutlookCalIFConsole
Source: OutlookCalIFConsole\\System.Runtime.dll; Dest: {app}\\OutlookCalIFConsole
Source: OutlookCalIFConsole\\System.Runtime.Extensions.dll; Dest: {app}\\OutlookCalIFConsole
Source: .\\System.Security.Cryptography.Algorithms.dll; Dest: {app}\\OutlookCalIFConsole
Source: .\\System.Security.Cryptography.Encoding.dll; Dest: {app}\\OutlookCalIFConsole
Source: .\\System.Security.Cryptography.Primitives.dll; Dest: {app}\\OutlookCalIFConsole
Source: .\\System.Security.Cryptography.X509Certificates.dll; Dest: {app}\\OutlookCalIFConsole

注意 Newtonsoft.Json.dllSystem.Net.Http.dllSystem.Security.Cryptography.* 的条目。

您也可以使用 GetFileVersion(因为文件是 DLL),而不是通过 GetFileDateTimeString(间接通过 GetFileDateTimeString)比较文件。

如果您需要在 [Files] 部分条目中添加其他参数,请相应地修改 FileEntry 宏。