Răsfoiți Sursa

New Script Wizard and the Generate [Files] Entries tool: add support for download and extractarchive.

Also fixes a small memory leak in TWizardFormFilesHelper.
Martijn Laan 1 săptămână în urmă
părinte
comite
8ea8b45d08

+ 14 - 8
Projects/Src/IDE.FilesDesignerForm.dfm

@@ -23,8 +23,6 @@ object FilesDesignerForm: TFilesDesignerForm
     Align = alBottom
     Align = alBottom
     BevelOuter = bvNone
     BevelOuter = bvNone
     TabOrder = 0
     TabOrder = 0
-    ExplicitTop = 360
-    ExplicitWidth = 571
     object Bevel1: TBevel
     object Bevel1: TBevel
       Left = 0
       Left = 0
       Top = 0
       Top = 0
@@ -57,7 +55,7 @@ object FilesDesignerForm: TFilesDesignerForm
   end
   end
   object AppFilesEditButton: TButton
   object AppFilesEditButton: TButton
     Left = 476
     Left = 476
-    Top = 107
+    Top = 135
     Width = 89
     Width = 89
     Height = 23
     Height = 23
     Caption = '&Parameters...'
     Caption = '&Parameters...'
@@ -65,7 +63,7 @@ object FilesDesignerForm: TFilesDesignerForm
   end
   end
   object AppFilesRemoveButton: TButton
   object AppFilesRemoveButton: TButton
     Left = 476
     Left = 476
-    Top = 135
+    Top = 162
     Width = 89
     Width = 89
     Height = 23
     Height = 23
     Caption = 'Remo&ve'
     Caption = 'Remo&ve'
@@ -81,7 +79,7 @@ object FilesDesignerForm: TFilesDesignerForm
   end
   end
   object AppFilesAddButton: TButton
   object AppFilesAddButton: TButton
     Left = 476
     Left = 476
-    Top = 51
+    Top = 50
     Width = 89
     Width = 89
     Height = 23
     Height = 23
     Caption = '&Add file(s)...'
     Caption = '&Add file(s)...'
@@ -90,7 +88,7 @@ object FilesDesignerForm: TFilesDesignerForm
   object AppFilesListBox: TDropListBox
   object AppFilesListBox: TDropListBox
     Left = 8
     Left = 8
     Top = 52
     Top = 52
-    Width = 453
+    Width = 449
     Height = 297
     Height = 297
     ItemHeight = 15
     ItemHeight = 15
     TabOrder = 5
     TabOrder = 5
@@ -103,7 +101,7 @@ object FilesDesignerForm: TFilesDesignerForm
     AutoSize = False
     AutoSize = False
     Caption = '&Files:'
     Caption = '&Files:'
     FocusControl = AppFilesListBox
     FocusControl = AppFilesListBox
-    TabOrder = 6
+    TabOrder = 7
     WordWrap = True
     WordWrap = True
   end
   end
   object NotCreateAppDirCheck: TCheckBox
   object NotCreateAppDirCheck: TCheckBox
@@ -112,6 +110,14 @@ object FilesDesignerForm: TFilesDesignerForm
     Width = 253
     Width = 253
     Height = 17
     Height = 17
     Caption = '&Script has CreateAppDir=no'
     Caption = '&Script has CreateAppDir=no'
-    TabOrder = 7
+    TabOrder = 8
+  end
+  object AppFilesAddDownloadButton: TButton
+    Left = 476
+    Top = 106
+    Width = 89
+    Height = 23
+    Caption = 'Do&wnload...'
+    TabOrder = 6
   end
   end
 end
 end

+ 3 - 2
Projects/Src/IDE.FilesDesignerForm.pas

@@ -2,7 +2,7 @@ unit IDE.FilesDesignerForm;
 
 
 {
 {
   Inno Setup
   Inno Setup
-  Copyright (C) 1997-2024 Jordan Russell
+  Copyright (C) 1997-2025 Jordan Russell
   Portions by Martijn Laan
   Portions by Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
   For conditions of distribution and use, see LICENSE.TXT.
 
 
@@ -28,6 +28,7 @@ type
     AppFilesLabel: TNewStaticText;
     AppFilesLabel: TNewStaticText;
     NotCreateAppDirCheck: TCheckBox;
     NotCreateAppDirCheck: TCheckBox;
     Bevel1: TBevel;
     Bevel1: TBevel;
+    AppFilesAddDownloadButton: TButton;
     procedure FormCreate(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure FormDestroy(Sender: TObject);
     procedure FormDestroy(Sender: TObject);
     procedure InsertButtonClick(Sender: TObject);
     procedure InsertButtonClick(Sender: TObject);
@@ -54,7 +55,7 @@ begin
 
 
   FFilesHelper := TWizardFormFilesHelper.Create(Self,
   FFilesHelper := TWizardFormFilesHelper.Create(Self,
     NotCreateAppDirCheck, AppFilesListBox, AppFilesAddButton, AppFilesAddDirButton,
     NotCreateAppDirCheck, AppFilesListBox, AppFilesAddButton, AppFilesAddDirButton,
-    AppFilesEditButton, AppFilesRemoveButton);
+    AppFilesAddDownloadButton, AppFilesEditButton, AppFilesRemoveButton);
 end;
 end;
 
 
 procedure TFilesDesignerForm.FormDestroy(Sender: TObject);
 procedure TFilesDesignerForm.FormDestroy(Sender: TObject);

+ 5 - 0
Projects/Src/IDE.Messages.pas

@@ -50,6 +50,11 @@ const
   SWizardAppFiles2 = 'Please specify the files that are part of your application.';
   SWizardAppFiles2 = 'Please specify the files that are part of your application.';
   SWizardAppFiles3 = 'Please specify the source folder.';
   SWizardAppFiles3 = 'Please specify the source folder.';
   SWizardAppFilesSubDirsMessage = 'Should files in subfolders of "%s" also be included?';
   SWizardAppFilesSubDirsMessage = 'Should files in subfolders of "%s" also be included?';
+  SWizardAppFilesDownloadExtractArchiveMessage = 'Is the file to download an archive which should be extracted?';
+  SWizardAppFilesDownloadDestNamePrompt = 'Name of the file:';
+  SWizardAppFilesDownloadArchiveDestNamePrompt = 'Name of the file (extension should match archive format):';
+  SWizardAppFilesDownloadExternalSizePrompt = 'Approximate size of the file in megabytes:';
+  SWizardAppFilesDownloadSourcePrompt = 'URL:';
   SWizardAppExeFilter = 'Application files (*.exe)|*.exe|All files|*.*';
   SWizardAppExeFilter = 'Application files (*.exe)|*.exe|All files|*.*';
   SWizardAppExeDefaultExt = 'exe';
   SWizardAppExeDefaultExt = 'exe';
   SWizardAppAssoc = 'Application File Association';
   SWizardAppAssoc = 'Application File Association';

+ 41 - 13
Projects/Src/IDE.Wizard.WizardFileForm.dfm

@@ -4,7 +4,7 @@ object WizardFileForm: TWizardFileForm
   BorderIcons = [biSystemMenu]
   BorderIcons = [biSystemMenu]
   BorderStyle = bsDialog
   BorderStyle = bsDialog
   Caption = 'Script Wizard File'
   Caption = 'Script Wizard File'
-  ClientHeight = 297
+  ClientHeight = 345
   ClientWidth = 420
   ClientWidth = 420
   Color = clBtnFace
   Color = clBtnFace
   Font.Charset = DEFAULT_CHARSET
   Font.Charset = DEFAULT_CHARSET
@@ -16,29 +16,31 @@ object WizardFileForm: TWizardFileForm
   OnCreate = FormCreate
   OnCreate = FormCreate
   DesignSize = (
   DesignSize = (
     420
     420
-    297)
+    345)
   TextHeight = 13
   TextHeight = 13
   object RequiredLabel1: TNewStaticText
   object RequiredLabel1: TNewStaticText
     Left = 8
     Left = 8
-    Top = 271
+    Top = 319
     Width = 21
     Width = 21
     Height = 14
     Height = 14
+    Anchors = [akLeft, akBottom]
     Caption = 'bold'
     Caption = 'bold'
     Enabled = False
     Enabled = False
     TabOrder = 4
     TabOrder = 4
   end
   end
   object RequiredLabel2: TNewStaticText
   object RequiredLabel2: TNewStaticText
     Left = 36
     Left = 36
-    Top = 271
+    Top = 319
     Width = 51
     Width = 51
     Height = 14
     Height = 14
+    Anchors = [akLeft, akBottom]
     Caption = ' = required'
     Caption = ' = required'
     Enabled = False
     Enabled = False
     TabOrder = 5
     TabOrder = 5
   end
   end
   object OKButton: TButton
   object OKButton: TButton
     Left = 258
     Left = 258
-    Top = 265
+    Top = 313
     Width = 73
     Width = 73
     Height = 23
     Height = 23
     Anchors = [akRight, akBottom]
     Anchors = [akRight, akBottom]
@@ -50,7 +52,7 @@ object WizardFileForm: TWizardFileForm
   end
   end
   object CancelButton: TButton
   object CancelButton: TButton
     Left = 338
     Left = 338
-    Top = 265
+    Top = 313
     Width = 73
     Width = 73
     Height = 23
     Height = 23
     Anchors = [akRight, akBottom]
     Anchors = [akRight, akBottom]
@@ -63,13 +65,13 @@ object WizardFileForm: TWizardFileForm
     Left = 8
     Left = 8
     Top = 108
     Top = 108
     Width = 403
     Width = 403
-    Height = 149
+    Height = 197
     Anchors = [akLeft, akTop, akRight]
     Anchors = [akLeft, akTop, akRight]
     Caption = ' Destination '
     Caption = ' Destination '
     TabOrder = 0
     TabOrder = 0
     DesignSize = (
     DesignSize = (
       403
       403
-      149)
+      197)
     object DestRootDirLabel: TNewStaticText
     object DestRootDirLabel: TNewStaticText
       Left = 12
       Left = 12
       Top = 20
       Top = 20
@@ -98,7 +100,7 @@ object WizardFileForm: TWizardFileForm
       Anchors = [akLeft, akTop, akRight]
       Anchors = [akLeft, akTop, akRight]
       TabOrder = 2
       TabOrder = 2
     end
     end
-    object SubDirLabel: TNewStaticText
+    object DestSubDirLabel: TNewStaticText
       Left = 12
       Left = 12
       Top = 96
       Top = 96
       Width = 103
       Width = 103
@@ -115,6 +117,23 @@ object WizardFileForm: TWizardFileForm
       Anchors = [akLeft, akTop, akRight]
       Anchors = [akLeft, akTop, akRight]
       TabOrder = 4
       TabOrder = 4
     end
     end
+    object DestNameEdit: TEdit
+      Left = 12
+      Top = 164
+      Width = 379
+      Height = 21
+      Anchors = [akLeft, akTop, akRight]
+      TabOrder = 5
+    end
+    object DestNameLabel: TNewStaticText
+      Left = 12
+      Top = 144
+      Width = 86
+      Height = 14
+      Caption = 'Destination &name:'
+      FocusControl = DestSubDirEdit
+      TabOrder = 6
+    end
   end
   end
   object GroupBox1: TGroupBox
   object GroupBox1: TGroupBox
     Left = 8
     Left = 8
@@ -149,19 +168,28 @@ object WizardFileForm: TWizardFileForm
     object RecurseSubDirsCheck: TCheckBox
     object RecurseSubDirsCheck: TCheckBox
       Left = 12
       Left = 12
       Top = 68
       Top = 68
-      Width = 141
+      Width = 125
       Height = 17
       Height = 17
       Caption = '&Recurse subfolders'
       Caption = '&Recurse subfolders'
       TabOrder = 2
       TabOrder = 2
-      OnClick = RecurseSubDirsCheckClick
+      OnClick = CheckClick
     end
     end
     object CreateAllSubDirsCheck: TCheckBox
     object CreateAllSubDirsCheck: TCheckBox
-      Left = 156
+      Left = 138
       Top = 68
       Top = 68
-      Width = 165
+      Width = 151
       Height = 17
       Height = 17
       Caption = '&Include empty subfolders'
       Caption = '&Include empty subfolders'
       TabOrder = 3
       TabOrder = 3
     end
     end
+    object ExtractArchiveCheck: TCheckBox
+      Left = 290
+      Top = 68
+      Width = 111
+      Height = 17
+      Caption = '&Extract archive'
+      TabOrder = 4
+      OnClick = CheckClick
+    end
   end
   end
 end
 end

+ 51 - 19
Projects/Src/IDE.Wizard.WizardFileForm.pas

@@ -2,7 +2,7 @@ unit IDE.Wizard.WizardFileForm;
 
 
 {
 {
   Inno Setup
   Inno Setup
-  Copyright (C) 1997-2020 Jordan Russell
+  Copyright (C) 1997-2025 Jordan Russell
   Portions by Martijn Laan
   Portions by Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
   For conditions of distribution and use, see LICENSE.TXT.
 
 
@@ -16,15 +16,18 @@ uses
   UIStateForm, StdCtrls, ExtCtrls, NewStaticText;
   UIStateForm, StdCtrls, ExtCtrls, NewStaticText;
 
 
 type
 type
+  TWizardFileOption = (foDownload, foExtractArchive, foRecurseSubDirs,  foCreateAllSubDirs);
+  TWizardFileOptions = set of TWizardFileOption;
 
 
   PWizardFile = ^TWizardFile;
   PWizardFile = ^TWizardFile;
   TWizardFile = record
   TWizardFile = record
     Source: String;
     Source: String;
-    RecurseSubDirs: Boolean;
-    CreateAllSubDirs: Boolean;
+    Options: TWizardFileOptions;
     DestRootDir: String;
     DestRootDir: String;
     DestRootDirIsConstant: Boolean;
     DestRootDirIsConstant: Boolean;
     DestSubDir: String;
     DestSubDir: String;
+    DestName: String;
+    ExternalSize: Int64;
   end;
   end;
 
 
   TWizardFileForm = class(TUIStateForm)
   TWizardFileForm = class(TUIStateForm)
@@ -35,7 +38,7 @@ type
     DestRootDirEdit: TEdit;
     DestRootDirEdit: TEdit;
     DestRootDirLabel: TNewStaticText;
     DestRootDirLabel: TNewStaticText;
     DestSubDirEdit: TEdit;
     DestSubDirEdit: TEdit;
-    SubDirLabel: TNewStaticText;
+    DestSubDirLabel: TNewStaticText;
     RequiredLabel1: TNewStaticText;
     RequiredLabel1: TNewStaticText;
     RequiredLabel2: TNewStaticText;
     RequiredLabel2: TNewStaticText;
     GroupBox1: TGroupBox;
     GroupBox1: TGroupBox;
@@ -43,10 +46,13 @@ type
     SourceEdit: TEdit;
     SourceEdit: TEdit;
     RecurseSubDirsCheck: TCheckBox;
     RecurseSubDirsCheck: TCheckBox;
     CreateAllSubDirsCheck: TCheckBox;
     CreateAllSubDirsCheck: TCheckBox;
+    ExtractArchiveCheck: TCheckBox;
+    DestNameLabel: TNewStaticText;
+    DestNameEdit: TEdit;
     procedure OKButtonClick(Sender: TObject);
     procedure OKButtonClick(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure DestRootDirComboBoxChange(Sender: TObject);
     procedure DestRootDirComboBoxChange(Sender: TObject);
-    procedure RecurseSubDirsCheckClick(Sender: TObject);
+    procedure CheckClick(Sender: TObject);
   private
   private
     FAllowAppDestRootDir: Boolean;
     FAllowAppDestRootDir: Boolean;
     FWizardFile: PWizardFile;
     FWizardFile: PWizardFile;
@@ -81,17 +87,36 @@ const
     ( Constant: '{sd}'; Description: 'System drive root directory')
     ( Constant: '{sd}'; Description: 'System drive root directory')
   );
   );
 
 
+procedure MakeBold(const Ctl: TNewStaticText);
+begin
+  Ctl.Font.Style := [fsBold];
+end;
+
 procedure TWizardFileForm.SetWizardFile(WizardFile: PWizardFile);
 procedure TWizardFileForm.SetWizardFile(WizardFile: PWizardFile);
 var
 var
   I: Integer;
   I: Integer;
 begin
 begin
   FWizardFile := WizardFile;
   FWizardFile := WizardFile;
 
 
-  SourceEdit.Text := WizardFile.Source;
-  if NewFileExists(SourceEdit.Text) then
-    RecurseSubDirsCheck.Enabled := False;
-  RecurseSubDirsCheck.Checked := WizardFile.RecurseSubDirs;
-  CreateAllSubDirsCheck.Checked := WizardFile.CreateAllSubDirs;
+  if foDownload in WizardFile.Options then begin
+    SourceLabel.Caption := '&Source URL:';
+    SourceEdit.Text := Format('%s (~%.0f MB)', [WizardFile.Source, WizardFile.ExternalSize/(1024*1024)]);
+    MakeBold(DestNameLabel);
+  end else begin
+    SourceEdit.Text := WizardFile.Source;
+    if NewFileExists(WizardFile.Source) then
+      RecurseSubDirsCheck.Enabled := False;
+    ExtractArchiveCheck.Visible := False;
+    if IsWildcard(WizardFile.Source) then begin
+      DestNameLabel.Enabled := False;
+      DestNameEdit.Color := clBtnFace;
+      DestNameEdit.ReadOnly := True;
+    end;
+  end;
+
+  ExtractArchiveCheck.Checked := foExtractArchive in WizardFile.Options;
+  RecurseSubDirsCheck.Checked := foRecurseSubDirs in WizardFile.Options;
+  CreateAllSubDirsCheck.Checked := foCreateAllSubDirs in WizardFile.Options;
   if WizardFile.DestRootDirIsConstant then begin
   if WizardFile.DestRootDirIsConstant then begin
     for I := Low(DestRootDirs) to High(DestRootDirs) do begin
     for I := Low(DestRootDirs) to High(DestRootDirs) do begin
       if DestRootDirs[I].Constant = WizardFile.DestRootDir then begin
       if DestRootDirs[I].Constant = WizardFile.DestRootDir then begin
@@ -104,6 +129,7 @@ begin
     DestRootDirEdit.Text := WizardFile.DestRootDir;
     DestRootDirEdit.Text := WizardFile.DestRootDir;
   end;
   end;
   DestSubDirEdit.Text := WizardFile.DestSubDir;
   DestSubDirEdit.Text := WizardFile.DestSubDir;
+  DestNameEdit.Text := WizardFile.DestName;
 
 
   UpdateUI;
   UpdateUI;
 end;
 end;
@@ -111,12 +137,6 @@ end;
 { --- }
 { --- }
 
 
 procedure TWizardFileForm.FormCreate(Sender: TObject);
 procedure TWizardFileForm.FormCreate(Sender: TObject);
-
-  procedure MakeBold(const Ctl: TNewStaticText);
-  begin
-    Ctl.Font.Style := [fsBold];
-  end;
-
 var
 var
   I: Integer;
   I: Integer;
 begin
 begin
@@ -138,6 +158,8 @@ end;
 
 
 procedure TWizardFileForm.UpdateUI;
 procedure TWizardFileForm.UpdateUI;
 begin
 begin
+  if foDownload in FWizardFile.Options then
+    RecurseSubDirsCheck.Enabled := ExtractArchiveCheck.Checked;
   CreateAllSubDirsCheck.Enabled := RecurseSubDirsCheck.Enabled and RecurseSubDirsCheck.Checked;
   CreateAllSubDirsCheck.Enabled := RecurseSubDirsCheck.Enabled and RecurseSubDirsCheck.Checked;
 
 
   if DestRootDirComboBox.ItemIndex = DestRootDirComboBox.Items.Count-1 then begin
   if DestRootDirComboBox.ItemIndex = DestRootDirComboBox.Items.Count-1 then begin
@@ -151,8 +173,12 @@ end;
 
 
 { --- }
 { --- }
 
 
-procedure TWizardFileForm.RecurseSubDirsCheckClick(Sender: TObject);
+procedure TWizardFileForm.CheckClick(Sender: TObject);
 begin
 begin
+  if (Sender = ExtractArchiveCheck) and ExtractArchiveCheck.Checked then begin
+    RecurseSubDirsCheck.Checked := True;
+    CreateAllSubDirsCheck.Checked := True;
+  end;
   UpdateUI;
   UpdateUI;
 end;
 end;
 
 
@@ -181,8 +207,13 @@ begin
     ModalResult := mrOk;
     ModalResult := mrOk;
 
 
   if ModalResult = mrOk then begin
   if ModalResult = mrOk then begin
-    FWizardFile.RecurseSubDirs := RecurseSubDirsCheck.Checked;
-    FWizardFile.CreateAllSubDirs := CreateAllSubDirsCheck.Checked;
+    FWizardFile.Options := FWizardFile.Options * [foDownload];
+    if ExtractArchiveCheck.Checked then
+      Include(FWizardFile.Options, foExtractArchive);
+    if RecurseSubDirsCheck.Checked then
+      Include(FWizardFile.Options, foRecurseSubDirs);
+    if CreateAllSubDirsCheck.Checked then
+      Include(FWizardFile.Options, foCreateAllSubDirs);
     if DestRootDirIndex = DestRootDirComboBox.Items.Count-1 then begin
     if DestRootDirIndex = DestRootDirComboBox.Items.Count-1 then begin
       FWizardFile.DestRootDir := DestRootDirEdit.Text;
       FWizardFile.DestRootDir := DestRootDirEdit.Text;
       FWizardFile.DestRootDirIsConstant := False;
       FWizardFile.DestRootDirIsConstant := False;
@@ -191,6 +222,7 @@ begin
       FWizardFile.DestRootDirIsConstant := True;
       FWizardFile.DestRootDirIsConstant := True;
     end;
     end;
     FWizardFile.DestSubDir := DestSubDirEdit.Text;
     FWizardFile.DestSubDir := DestSubDirEdit.Text;
+    FWizardFile.DestName := DestNameEdit.Text;
   end;
   end;
 end;
 end;
 
 

+ 13 - 4
Projects/Src/IDE.Wizard.WizardForm.dfm

@@ -687,21 +687,21 @@ object WizardForm: TWizardForm
           end
           end
           object AppFilesEditButton: TButton
           object AppFilesEditButton: TButton
             Left = 459
             Left = 459
-            Top = 175
+            Top = 203
             Width = 89
             Width = 89
             Height = 23
             Height = 23
             Anchors = [akTop, akRight]
             Anchors = [akTop, akRight]
             Caption = '&Parameters...'
             Caption = '&Parameters...'
-            TabOrder = 9
+            TabOrder = 10
           end
           end
           object AppFilesRemoveButton: TButton
           object AppFilesRemoveButton: TButton
             Left = 459
             Left = 459
-            Top = 203
+            Top = 231
             Width = 89
             Width = 89
             Height = 23
             Height = 23
             Anchors = [akTop, akRight]
             Anchors = [akTop, akRight]
             Caption = 'Remo&ve'
             Caption = 'Remo&ve'
-            TabOrder = 10
+            TabOrder = 11
           end
           end
           object AppExeEdit: TEdit
           object AppExeEdit: TEdit
             Left = 36
             Left = 36
@@ -749,6 +749,15 @@ object WizardForm: TWizardForm
             TabOrder = 4
             TabOrder = 4
             OnClick = NoAppExeCheckClick
             OnClick = NoAppExeCheckClick
           end
           end
+          object AppFilesAddDownloadButton: TButton
+            Left = 459
+            Top = 175
+            Width = 89
+            Height = 23
+            Anchors = [akTop, akRight]
+            Caption = 'Dow&nload...'
+            TabOrder = 9
+          end
         end
         end
         object AppAssocPage: TNewNotebookPage
         object AppAssocPage: TNewNotebookPage
           DesignSize = (
           DesignSize = (

+ 10 - 3
Projects/Src/IDE.Wizard.WizardForm.pas

@@ -142,6 +142,7 @@ type
     AppRegistryMinVerDocBitBtn: TBitmapButton;
     AppRegistryMinVerDocBitBtn: TBitmapButton;
     WelcomeImageDark: TImage;
     WelcomeImageDark: TImage;
     InnerImageDark: TImage;
     InnerImageDark: TImage;
+    AppFilesAddDownloadButton: TButton;
     procedure FormCreate(Sender: TObject);
     procedure FormCreate(Sender: TObject);
     procedure FormShow(Sender: TObject);
     procedure FormShow(Sender: TObject);
     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
@@ -285,7 +286,7 @@ begin
   FWizardName := SWizardDefaultName;
   FWizardName := SWizardDefaultName;
   FFilesHelper := TWizardFormFilesHelper.Create(Self,
   FFilesHelper := TWizardFormFilesHelper.Create(Self,
     NotCreateAppDirCheck, AppFilesListBox, AppFilesAddButton, AppFilesAddDirButton,
     NotCreateAppDirCheck, AppFilesListBox, AppFilesAddButton, AppFilesAddDirButton,
-    AppFilesEditButton, AppFilesRemoveButton);
+    AppFilesAddDownloadButton, AppFilesEditButton, AppFilesRemoveButton);
   FRegistryHelper := TWizardFormRegistryHelper.Create(Self, AppRegistryFileEdit,
   FRegistryHelper := TWizardFormRegistryHelper.Create(Self, AppRegistryFileEdit,
     AppRegistryFileButton, AppRegistryUninsDeleteKeyCheck,
     AppRegistryFileButton, AppRegistryUninsDeleteKeyCheck,
     AppRegistryUninsDeleteKeyIfEmptyCheck, AppRegistryUninsDeleteValueCheck,
     AppRegistryUninsDeleteKeyIfEmptyCheck, AppRegistryUninsDeleteValueCheck,
@@ -974,6 +975,14 @@ begin
       end;
       end;
     end;
     end;
 
 
+    var HasExtractArchive: Boolean;
+    FFilesHelper.AddScript(Files, HasExtractArchive);
+    if HasExtractArchive then begin
+      Setup := Setup + 'ArchiveExtraction=full' + SNewLine;
+      Setup := Setup + '; Use "ArchiveExtraction=enhanced" if all your archives are .7z files' + SNewLine;
+      Setup := Setup + '; Use "ArchiveExtraction=enhanced/nopassword" if all your archives are not password-protected' + SNewLine;
+    end;
+
     { AppAssocation }
     { AppAssocation }
     if CreateAssocCheck.Enabled and CreateAssocCheck.Checked then begin
     if CreateAssocCheck.Enabled and CreateAssocCheck.Checked then begin
       Setup := Setup + 'ChangesAssociations=yes' + SNewLine;
       Setup := Setup + 'ChangesAssociations=yes' + SNewLine;
@@ -983,8 +992,6 @@ begin
       Registry := Registry + 'Root: HKA; Subkey: "Software\Classes\' + AppAssocKey + '\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\' + AppExeName + '"" ""%1"""' + SNewLine;
       Registry := Registry + 'Root: HKA; Subkey: "Software\Classes\' + AppAssocKey + '\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\' + AppExeName + '"" ""%1"""' + SNewLine;
     end;
     end;
 
 
-    FFilesHelper.AddScript(Files);
-
     { AppGroup }
     { AppGroup }
     if not NotCreateAppDirCheck.Checked then begin
     if not NotCreateAppDirCheck.Checked then begin
       if UseAutoProgramsCheck.Enabled and UseAutoProgramsCheck.Checked then begin
       if UseAutoProgramsCheck.Enabled and UseAutoProgramsCheck.Checked then begin

+ 89 - 21
Projects/Src/IDE.Wizard.WizardFormFilesHelper.pas

@@ -2,7 +2,7 @@ unit IDE.Wizard.WizardFormFilesHelper;
 
 
 {
 {
   Inno Setup
   Inno Setup
-  Copyright (C) 1997-2024 Jordan Russell
+  Copyright (C) 1997-2025 Jordan Russell
   Portions by Martijn Laan
   Portions by Martijn Laan
   For conditions of distribution and use, see LICENSE.TXT.
   For conditions of distribution and use, see LICENSE.TXT.
 
 
@@ -13,7 +13,7 @@ interface
 
 
 uses
 uses
   Windows, Classes, Forms, StdCtrls,
   Windows, Classes, Forms, StdCtrls,
-  DropListBox;
+  DropListBox, IDE.Wizard.WizardFileForm;
 
 
 type
 type
   TWizardFormFilesHelper = class
   TWizardFormFilesHelper = class
@@ -24,7 +24,7 @@ type
       FFilesListBox: TDropListBox;
       FFilesListBox: TDropListBox;
       FEditButton: TButton;
       FEditButton: TButton;
       FRemoveButton: TButton;
       FRemoveButton: TButton;
-      procedure AddWizardFile(const Source: String; const RecurseSubDirs, CreateAllSubDirs: Boolean);
+      function AddWizardFile(const Source: String; const Options: TWizardFileOptions): PWizardFile;
       function GetWizardFilesCount: Integer;
       function GetWizardFilesCount: Integer;
       procedure UpdateWizardFiles;
       procedure UpdateWizardFiles;
       procedure UpdateWizardFilesButtons;
       procedure UpdateWizardFilesButtons;
@@ -33,27 +33,29 @@ type
       procedure FilesListBoxDropFile(Sender: TDropListBox; const FileName: String);
       procedure FilesListBoxDropFile(Sender: TDropListBox; const FileName: String);
       procedure AddButtonClick(Sender: TObject);
       procedure AddButtonClick(Sender: TObject);
       procedure AddDirButtonClick(Sender: TObject);
       procedure AddDirButtonClick(Sender: TObject);
+      procedure AddDownloadButtonClick(Sender: TObject);
       procedure EditButtonClick(Sender: TObject);
       procedure EditButtonClick(Sender: TObject);
       procedure RemoveButtonClick(Sender: TObject);
       procedure RemoveButtonClick(Sender: TObject);
     public
     public
       constructor Create(const Form: TForm;
       constructor Create(const Form: TForm;
         const NotCreateAppDirCheck: TCheckBox; const FilesListBox: TDropListBox;
         const NotCreateAppDirCheck: TCheckBox; const FilesListBox: TDropListBox;
-        const AddButton, AddDirButton, EditButton, RemoveButton: TButton);
+        const AddButton, AddDirButton, AddDownloadButton, EditButton, RemoveButton: TButton);
       destructor Destroy; override;
       destructor Destroy; override;
-      procedure AddScript(var Files: String);
+      procedure AddScript(var Files: String); overload;
+      procedure AddScript(var Files: String; out HasExtractArchive: Boolean); overload;
       property FilesCount: Integer read GetWizardFilesCount;
       property FilesCount: Integer read GetWizardFilesCount;
   end;
   end;
 
 
 implementation
 implementation
 
 
 uses
 uses
-  SysUtils, UITypes,
+  SysUtils, UITypes, Dialogs,
   Shared.CommonFunc.Vcl, Shared.CommonFunc, BrowseFunc, PathFunc,
   Shared.CommonFunc.Vcl, Shared.CommonFunc, BrowseFunc, PathFunc,
-  IDE.Messages, IDE.Wizard.WizardFileForm;
+  IDE.Messages;
 
 
 constructor TWizardFormFilesHelper.Create(const Form: TForm;
 constructor TWizardFormFilesHelper.Create(const Form: TForm;
   const NotCreateAppDirCheck: TCheckBox; const FilesListBox: TDropListBox;
   const NotCreateAppDirCheck: TCheckBox; const FilesListBox: TDropListBox;
-  const AddButton, AddDirButton, EditButton, RemoveButton: TButton);
+  const AddButton, AddDirButton, AddDownloadButton, EditButton, RemoveButton: TButton);
 begin
 begin
   inherited Create;
   inherited Create;
 
 
@@ -70,6 +72,7 @@ begin
   FilesListBox.OnDropFile :=   FilesListBoxDropFile;
   FilesListBox.OnDropFile :=   FilesListBoxDropFile;
   AddButton.OnClick := AddButtonClick;
   AddButton.OnClick := AddButtonClick;
   AddDirButton.OnClick := AddDirButtonClick;
   AddDirButton.OnClick := AddDirButtonClick;
+  AddDownloadButton.OnClick := AddDownloadButtonClick;
   EditButton.OnClick := EditButtonClick;
   EditButton.OnClick := EditButtonClick;
   RemoveButton.OnClick := RemoveButtonClick;
   RemoveButton.OnClick := RemoveButtonClick;
 
 
@@ -79,25 +82,26 @@ end;
 destructor TWizardFormFilesHelper.Destroy;
 destructor TWizardFormFilesHelper.Destroy;
 begin
 begin
   for var I := 0 to FWizardFiles.Count-1 do
   for var I := 0 to FWizardFiles.Count-1 do
-    Dispose(FWizardFiles[i]);
+    Dispose(PWizardFile(FWizardFiles[i]));
   FWizardFiles.Free;
   FWizardFiles.Free;
 end;
 end;
 
 
-procedure TWizardFormFilesHelper.AddWizardFile(const Source: String; const RecurseSubDirs, CreateAllSubDirs: Boolean);
+function TWizardFormFilesHelper.AddWizardFile(const Source: String; const Options: TWizardFileOptions): PWizardFile;
 var
 var
   WizardFile: PWizardFile;
   WizardFile: PWizardFile;
 begin
 begin
   New(WizardFile);
   New(WizardFile);
   WizardFile.Source := Source;
   WizardFile.Source := Source;
-  WizardFile.RecurseSubDirs := RecurseSubDirs;
-  WizardFile.CreateAllSubDirs := CreateAllSubDirs;
+  WizardFile.Options := Options;
   WizardFile.DestRootDirIsConstant := True;
   WizardFile.DestRootDirIsConstant := True;
   if not FNotCreateAppDirCheck.Checked then
   if not FNotCreateAppDirCheck.Checked then
     WizardFile.DestRootDir := '{app}'
     WizardFile.DestRootDir := '{app}'
   else
   else
     WizardFile.DestRootDir := '{win}';
     WizardFile.DestRootDir := '{win}';
   WizardFile.DestSubDir := '';
   WizardFile.DestSubDir := '';
+  WizardFile.DestName := '';
   FWizardFiles.Add(WizardFile);
   FWizardFiles.Add(WizardFile);
+  Result := WizardFile;
 end;
 end;
 
 
 function TWizardFormFilesHelper.GetWizardFilesCount: Integer;
 function TWizardFormFilesHelper.GetWizardFilesCount: Integer;
@@ -144,9 +148,9 @@ procedure TWizardFormFilesHelper.FilesListBoxDropFile(Sender: TDropListBox;
   const FileName: String);
   const FileName: String);
 begin
 begin
   if DirExists(FileName) then
   if DirExists(FileName) then
-    AddWizardFile(AddBackslash(FileName) + '*', True, True)
+    AddWizardFile(AddBackslash(FileName) + '*', [foRecurseSubDirs, foCreateAllSubDirs])
   else
   else
-    AddWizardFile(FileName, False, False);
+    AddWizardFile(FileName, []);
   UpdateWizardFiles;
   UpdateWizardFiles;
   UpdateWizardFilesButtons;
   UpdateWizardFilesButtons;
 end;
 end;
@@ -161,7 +165,7 @@ begin
     if NewGetOpenFileNameMulti('', FileList, '', SWizardAllFilesFilter, '', FForm.Handle) then begin
     if NewGetOpenFileNameMulti('', FileList, '', SWizardAllFilesFilter, '', FForm.Handle) then begin
       FileList.Sort;
       FileList.Sort;
       for I := 0 to FileList.Count-1 do
       for I := 0 to FileList.Count-1 do
-        AddWizardFile(FileList[I], False, False);
+        AddWizardFile(FileList[I], []);
       UpdateWizardFiles;
       UpdateWizardFiles;
     end;
     end;
   finally
   finally
@@ -182,11 +186,47 @@ begin
     else
     else
       Exit;
       Exit;
     end;
     end;
-    AddWizardFile(AddBackslash(Path) + '*', Recurse, Recurse);
+    var Options: TWizardFileOptions;
+    if Recurse then
+      Options := [foRecurseSubDirs, foCreateAllSubDirs]
+    else
+      Options := [];
+    AddWizardFile(AddBackslash(Path) + '*', Options);
     UpdateWizardFiles;
     UpdateWizardFiles;
   end;
   end;
 end;
 end;
 
 
+procedure TWizardFormFilesHelper.AddDownloadButtonClick(Sender: TObject);
+const
+  DestNamePrompts: array [Boolean] of string = (SWizardAppFilesDownloadDestNamePrompt, SWizardAppFilesDownloadArchiveDestNamePrompt);
+begin
+  var Source := 'https://www.example.com/MyProg.7z';
+  repeat
+    if not InputQuery(FForm.Caption, SWizardAppFilesDownloadSourcePrompt, Source)  then
+      Exit;
+  until Source <> '';
+  const ExtractArchive = MsgBox(SWizardAppFilesDownloadExtractArchiveMessage, '', mbConfirmation, MB_YESNO or MB_DEFBUTTON2) = IDYES;
+  var DestName := 'MyProg.7z';
+  repeat
+    if not InputQuery(FForm.Caption, DestNamePrompts[ExtractArchive], DestName)  then
+      Exit;
+  until DestName <> '';
+  var ExternalSizeAsString := '';
+  var ExternalSize: Extended;
+  repeat
+    if not InputQuery(FForm.Caption, SWizardAppFilesDownloadExternalSizePrompt, ExternalSizeAsString)  then
+      Exit;
+  until TryStrToFloat(ExternalSizeAsString, ExternalSize);
+
+  var Options: TWizardFileOptions := [foDownload];
+  if ExtractArchive then
+    Options := Options + [foExtractArchive, foRecurseSubDirs, foCreateAllSubDirs];
+  const WizardFile = AddWizardFile(Source, Options);
+  WizardFile.DestName := DestName;
+  WizardFile.ExternalSize := Round(ExternalSize*1024*1024);
+  UpdateWizardFiles;
+end;
+
 procedure TWizardFormFilesHelper.EditButtonClick(Sender: TObject);
 procedure TWizardFormFilesHelper.EditButtonClick(Sender: TObject);
 var
 var
   WizardFileForm: TWizardFileForm;
   WizardFileForm: TWizardFileForm;
@@ -213,26 +253,54 @@ var
   I: Integer;
   I: Integer;
 begin
 begin
   I := FFilesListBox.ItemIndex;
   I := FFilesListBox.ItemIndex;
-    Dispose(FWizardFiles[I]);
+  Dispose(PWizardFile(FWizardFiles[I]));
   FWizardFiles.Delete(I);
   FWizardFiles.Delete(I);
   UpdateWizardFiles;
   UpdateWizardFiles;
   UpdateWizardFilesButtons;
   UpdateWizardFilesButtons;
 end;
 end;
 
 
-procedure TWizardFormFilesHelper.AddScript(var Files: String);
+procedure TWizardFormFilesHelper.AddScript(var Files: String; out HasExtractArchive: Boolean);
 var
 var
   WizardFile: PWizardFile;
   WizardFile: PWizardFile;
   I: Integer;
   I: Integer;
 begin
 begin
+  var AddedVerificationNote := False;
+
   for I := 0 to FWizardFiles.Count-1 do begin
   for I := 0 to FWizardFiles.Count-1 do begin
     WizardFile := FWizardFiles[I];
     WizardFile := FWizardFiles[I];
-    Files := Files + 'Source: "' + WizardFile.Source + '"; DestDir: "' + RemoveBackslashUnlessRoot(AddBackslash(WizardFile.DestRootDir) + WizardFile.DestSubDir) + '"; Flags: ignoreversion';
-    if WizardFile.RecurseSubDirs then
+
+    if (foDownload in WizardFile.Options) and not AddedVerificationNote then begin
+      Files := Files + '; NOTE: Use the "issigverify" flag or the "Hash" parameter to verify downloads' + SNewLine;
+      AddedVerificationNote := True;
+    end;
+
+    if foExtractArchive in WizardFile.Options then
+      HasExtractArchive := True;
+
+    Files := Files + 'Source: "' + WizardFile.Source + '"; DestDir: "' + RemoveBackslashUnlessRoot(AddBackslash(WizardFile.DestRootDir) + WizardFile.DestSubDir) + '"';
+    if WizardFile.DestName <> '' then
+      Files := Files + '; DestName: "' + WizardFile.DestName + '"';
+    if WizardFile.ExternalSize <> 0 then
+      Files := Files + '; ExternalSize: "' + WizardFile.ExternalSize.ToString + '"';
+    Files := Files + '; Flags: ignoreversion';
+    if WizardFile.Options * [foDownload, foExtractArchive] <> [] then
+      Files := Files + ' external';
+    if foDownload in WizardFile.Options then
+      Files := Files + ' download';
+    if foExtractArchive in WizardFile.Options then
+      Files := Files + ' extractarchive';
+    if foRecurseSubDirs in WizardFile.Options then
       Files := Files + ' recursesubdirs';
       Files := Files + ' recursesubdirs';
-    if WizardFile.CreateAllSubDirs then
+    if foCreateAllSubDirs in WizardFile.Options then
       Files := Files + ' createallsubdirs';
       Files := Files + ' createallsubdirs';
     Files := Files + SNewLine;
     Files := Files + SNewLine;
   end;
   end;
 end;
 end;
 
 
+procedure TWizardFormFilesHelper.AddScript(var Files: String);
+begin
+  var HasExtractArchive: Boolean;
+  AddScript(Files, HasExtractArchive);
+end;
+
 end.
 end.

+ 1 - 0
whatsnew.htm

@@ -72,6 +72,7 @@ For conditions of distribution and use, see <a href="files/is/license.txt">LICEN
 <ul>
 <ul>
 <li>All download functionality now supports TLS 1.3 when available. Support for TLS 1.0 and 1.1 has been removed on all versions of Windows.</li>
 <li>All download functionality now supports TLS 1.3 when available. Support for TLS 1.0 and 1.1 has been removed on all versions of Windows.</li>
 <li>Archive extraction now supports the RAR5 format. Requires <tt>Setup</tt> section directive <tt>ArchiveExtraction</tt> to be set to <tt>full</tt>.</li>
 <li>Archive extraction now supports the RAR5 format. Requires <tt>Setup</tt> section directive <tt>ArchiveExtraction</tt> to be set to <tt>full</tt>.</li>
+<li>Compiler IDE: The New Script Wizard and the <i>Generate [Files] Entries</i> tool now support adding files to be downloaded. They will prompt you if the downloaded file is an archive that should be extracted.</li>
 </ul>
 </ul>
 <span class="head2">Other changes</span>
 <span class="head2">Other changes</span>
 <ul>
 <ul>