浏览代码

Cleanup NoUninstallFuncError/NoSetupFuncError handling (centralize checks + show true function names instead of uppercased ones). Also put the helper funcs together.

Martijn Laan 10 月之前
父节点
当前提交
b575511ee3
共有 1 个文件被更改,包括 179 次插入199 次删除
  1. 179 199
      Projects/Src/Setup.ScriptFunc.pas

+ 179 - 199
Projects/Src/Setup.ScriptFunc.pas

@@ -32,26 +32,141 @@ uses
   Shared.DotNetVersion, Setup.MsiFunc, Compression.SevenZipDecoder,
   Setup.DebugClient;
 
-var
-  ScaleBaseUnitsInitialized: Boolean;
-  ScaleBaseUnitX, ScaleBaseUnitY: Integer;
+type
+  TPSStackHelper = class helper for TPSStack
+  private
+    function GetArray(const ItemNo, FieldNo: Longint; out N: Integer): TPSVariantIFC;
+    function SetArray(const ItemNo, FieldNo: Longint; const N: Integer): TPSVariantIFC; overload;
+  public
+    type
+      TArrayOfInteger = array of Integer;
+      TArrayOfString = array of String;
+      TArrayBuilder = record
+        Arr: TPSVariantIFC;
+        I: Integer;
+        procedure Add(const Data: String);
+      end;
+      TArrayEnumerator = record
+        Arr: TPSVariantIFC;
+        N, I: Integer;
+        function HasNext: Boolean;
+        function Next: String;
+      end;
+    function GetIntArray(const ItemNo: Longint; const FieldNo: Longint = -1): TArrayOfInteger;
+    function GetProc(const ItemNo: Longint; const Exec: TPSExec): TMethod;
+    function GetStringArray(const ItemNo: Longint; const FieldNo: Longint = -1): TArrayOfString;
+    function InitArrayBuilder(const ItemNo: LongInt; const FieldNo: Longint = -1): TArrayBuilder;
+    function InitArrayEnumerator(const ItemNo: LongInt; const FieldNo: Longint = -1): TArrayEnumerator;
+    procedure SetArray(const ItemNo: Longint; const Data: TArray<String>; const FieldNo: Longint = -1); overload;
+    procedure SetArray(const ItemNo: Longint; const Data: TStrings; const FieldNo: Longint = -1); overload;
+    procedure SetInt(const ItemNo: Longint; const Data: Integer; const FieldNo: Longint = -1);
+  end;
 
-procedure NoSetupFuncError(const C: AnsiString); overload;
+function TPSStackHelper.GetArray(const ItemNo, FieldNo: Longint;
+  out N: Integer): TPSVariantIFC;
 begin
-  InternalError(Format('Cannot call "%s" function during Setup', [C]));
+  if FieldNo >= 0 then
+    Result := NewTPSVariantRecordIFC(Items[ItemNo], FieldNo)
+  else
+    Result := NewTPSVariantIFC(Items[ItemNo], True);
+  N := PSDynArrayGetLength(Pointer(Result.Dta^), Result.aType);
 end;
 
-procedure NoUninstallFuncError(const C: AnsiString); overload;
+function TPSStackHelper.SetArray(const ItemNo, FieldNo: Longint;
+  const N: Integer): TPSVariantIFC;
 begin
-  InternalError(Format('Cannot call "%s" function during Uninstall', [C]));
+  if FieldNo >= 0 then
+    Result := NewTPSVariantRecordIFC(Items[ItemNo], FieldNo)
+  else
+    Result := NewTPSVariantIFC(Items[ItemNo], True);
+  PSDynArraySetLength(Pointer(Result.Dta^), Result.aType, N);
 end;
 
-procedure NoSetupFuncError(const C: UnicodeString); overload;
+function TPSStackHelper.GetIntArray(const ItemNo, FieldNo: Longint): TArrayOfInteger;
 begin
-  InternalError(Format('Cannot call "%s" function during Setup', [C]));
+  var N: Integer;
+  var Arr := GetArray(ItemNo, FieldNo, N);
+  SetLength(Result, N);
+  for var I := 0 to N-1 do
+    Result[I] := VNGetInt(PSGetArrayField(Arr, I));
 end;
 
-procedure NoUninstallFuncError(const C: UnicodeString); overload;
+function TPSStackHelper.GetProc(const ItemNo: Longint; const Exec: TPSExec): TMethod;
+begin
+  var P := PPSVariantProcPtr(Items[ItemNo]);
+  { ProcNo 0 means nil was passed by the script and GetProcAsMethod will then return a (nil, nil) TMethod }
+  Result := Exec.GetProcAsMethod(P.ProcNo);
+end;
+
+function TPSStackHelper.GetStringArray(const ItemNo, FieldNo: Longint): TArrayOfString;
+begin
+  var N: Integer;
+  var Arr := GetArray(ItemNo, FieldNo, N);
+  SetLength(Result, N);
+  for var I := 0 to N-1 do
+    Result[I] := VNGetString(PSGetArrayField(Arr, I));
+end;
+
+function TPSStackHelper.InitArrayBuilder(const ItemNo, FieldNo: Longint): TArrayBuilder;
+begin
+  Result.Arr := SetArray(ItemNo, FieldNo, 0);
+  Result.I := 0;
+end;
+
+procedure TPSStackHelper.TArrayBuilder.Add(const Data: String);
+begin
+  PSDynArraySetLength(Pointer(Arr.Dta^), Arr.aType, I+1);
+  VNSetString(PSGetArrayField(Arr, I), Data);
+  Inc(I);
+end;
+
+function TPSStackHelper.InitArrayEnumerator(const ItemNo, FieldNo: Longint): TArrayEnumerator;
+begin
+  Result.Arr := GetArray(ItemNo, FieldNo, Result.N);
+  Result.I := 0;
+end;
+
+function TPSStackHelper.TArrayEnumerator.HasNext: Boolean;
+begin
+  Result := I < N;
+end;
+
+function TPSStackHelper.TArrayEnumerator.Next: String;
+begin
+  Result := VNGetString(PSGetArrayField(Arr, I));
+  Inc(I);
+end;
+
+procedure TPSStackHelper.SetArray(const ItemNo: Longint; const Data: TArray<String>; const FieldNo: Longint);
+begin
+  var N := System.Length(Data);
+  var Arr := SetArray(ItemNo, FieldNo, N);
+  for var I := 0 to N-1 do
+    VNSetString(PSGetArrayField(Arr, I), Data[I]);
+end;
+
+procedure TPSStackHelper.SetArray(const ItemNo: Longint; const Data: TStrings; const FieldNo: Longint);
+begin
+  var N := Data.Count;
+  var Arr := SetArray(ItemNo, FieldNo, N);
+  for var I := 0 to N-1 do
+    VNSetString(PSGetArrayField(Arr, I), Data[I]);
+end;
+
+procedure TPSStackHelper.SetInt(const ItemNo: Longint; const Data: Integer;
+  const FieldNo: Longint);
+begin
+  if FieldNo = -1 then
+    inherited SetInt(ItemNo, Data)
+  else begin
+    var PSVariantIFC := NewTPSVariantRecordIFC(Items[ItemNo], FieldNo);
+    VNSetInt(PSVariantIFC, Data);
+  end;
+end;
+
+{---}
+
+procedure NoUninstallFuncError(const C: AnsiString); overload;
 begin
   InternalError(Format('Cannot call "%s" function during Uninstall', [C]));
 end;
@@ -88,6 +203,10 @@ begin
   Result := SetupMessages[ID];
 end;
 
+var
+  ScaleBaseUnitsInitialized: Boolean;
+  ScaleBaseUnitX, ScaleBaseUnitY: Integer;
+
 procedure InitializeScaleBaseUnits;
 var
   Font: TFont;
@@ -114,8 +233,6 @@ begin
     Result := False;
 end;
 
-{---}
-
 type
   { *Must* keep this in synch with ScriptFunc_C }
   TFindRec = record
@@ -183,7 +300,7 @@ begin
 end;
 
 type
-  { *Must* keep this in synch with ScriptFunc_C }
+  { *Must* keep this in synch with Compiler.ScriptFunc.pas }
   TWindowsVersion = packed record
     Major: Cardinal;
     Minor: Cardinal;
@@ -207,142 +324,6 @@ begin
   Version.SuiteMask := WindowsSuiteMask;
 end;
 
-{---}
-
-type
-  TPSStackHelper = class helper for TPSStack
-  private
-    function GetArray(const ItemNo, FieldNo: Longint; out N: Integer): TPSVariantIFC;
-    function SetArray(const ItemNo, FieldNo: Longint; const N: Integer): TPSVariantIFC; overload;
-  public
-    type
-      TArrayOfInteger = array of Integer;
-      TArrayOfString = array of String;
-      TArrayBuilder = record
-        Arr: TPSVariantIFC;
-        I: Integer;
-        procedure Add(const Data: String);
-      end;
-      TArrayEnumerator = record
-        Arr: TPSVariantIFC;
-        N, I: Integer;
-        function HasNext: Boolean;
-        function Next: String;
-      end;
-    function GetIntArray(const ItemNo: Longint; const FieldNo: Longint = -1): TArrayOfInteger;
-    function GetProc(const ItemNo: Longint; const Exec: TPSExec): TMethod;
-    function GetStringArray(const ItemNo: Longint; const FieldNo: Longint = -1): TArrayOfString;
-    function InitArrayBuilder(const ItemNo: LongInt; const FieldNo: Longint = -1): TArrayBuilder;
-    function InitArrayEnumerator(const ItemNo: LongInt; const FieldNo: Longint = -1): TArrayEnumerator;
-    procedure SetArray(const ItemNo: Longint; const Data: TArray<String>; const FieldNo: Longint = -1); overload;
-    procedure SetArray(const ItemNo: Longint; const Data: TStrings; const FieldNo: Longint = -1); overload;
-    procedure SetInt(const ItemNo: Longint; const Data: Integer; const FieldNo: Longint = -1);
-  end;
-
-function TPSStackHelper.GetArray(const ItemNo, FieldNo: Longint;
-  out N: Integer): TPSVariantIFC;
-begin
-  if FieldNo >= 0 then
-    Result := NewTPSVariantRecordIFC(Items[ItemNo], FieldNo)
-  else
-    Result := NewTPSVariantIFC(Items[ItemNo], True);
-  N := PSDynArrayGetLength(Pointer(Result.Dta^), Result.aType);
-end;
-
-function TPSStackHelper.SetArray(const ItemNo, FieldNo: Longint;
-  const N: Integer): TPSVariantIFC;
-begin
-  if FieldNo >= 0 then
-    Result := NewTPSVariantRecordIFC(Items[ItemNo], FieldNo)
-  else
-    Result := NewTPSVariantIFC(Items[ItemNo], True);
-  PSDynArraySetLength(Pointer(Result.Dta^), Result.aType, N);
-end;
-
-function TPSStackHelper.GetIntArray(const ItemNo, FieldNo: Longint): TArrayOfInteger;
-begin
-  var N: Integer;
-  var Arr := GetArray(ItemNo, FieldNo, N);
-  SetLength(Result, N);
-  for var I := 0 to N-1 do
-    Result[I] := VNGetInt(PSGetArrayField(Arr, I));
-end;
-
-function TPSStackHelper.GetProc(const ItemNo: Longint; const Exec: TPSExec): TMethod;
-begin
-  var P := PPSVariantProcPtr(Items[ItemNo]);
-  { ProcNo 0 means nil was passed by the script and GetProcAsMethod will then return a (nil, nil) TMethod }
-  Result := Exec.GetProcAsMethod(P.ProcNo);
-end;
-
-function TPSStackHelper.GetStringArray(const ItemNo, FieldNo: Longint): TArrayOfString;
-begin
-  var N: Integer;
-  var Arr := GetArray(ItemNo, FieldNo, N);
-  SetLength(Result, N);
-  for var I := 0 to N-1 do
-    Result[I] := VNGetString(PSGetArrayField(Arr, I));
-end;
-
-function TPSStackHelper.InitArrayBuilder(const ItemNo, FieldNo: Longint): TArrayBuilder;
-begin
-  Result.Arr := SetArray(ItemNo, FieldNo, 0);
-  Result.I := 0;
-end;
-
-procedure TPSStackHelper.TArrayBuilder.Add(const Data: String);
-begin
-  PSDynArraySetLength(Pointer(Arr.Dta^), Arr.aType, I+1);
-  VNSetString(PSGetArrayField(Arr, I), Data);
-  Inc(I);
-end;
-
-function TPSStackHelper.InitArrayEnumerator(const ItemNo, FieldNo: Longint): TArrayEnumerator;
-begin
-  Result.Arr := GetArray(ItemNo, FieldNo, Result.N);
-  Result.I := 0;
-end;
-
-function TPSStackHelper.TArrayEnumerator.HasNext: Boolean;
-begin
-  Result := I < N;
-end;
-
-function TPSStackHelper.TArrayEnumerator.Next: String;
-begin
-  Result := VNGetString(PSGetArrayField(Arr, I));
-  Inc(I);
-end;
-
-procedure TPSStackHelper.SetArray(const ItemNo: Longint; const Data: TArray<String>; const FieldNo: Longint);
-begin
-  var N := System.Length(Data);
-  var Arr := SetArray(ItemNo, FieldNo, N);
-  for var I := 0 to N-1 do
-    VNSetString(PSGetArrayField(Arr, I), Data[I]);
-end;
-
-procedure TPSStackHelper.SetArray(const ItemNo: Longint; const Data: TStrings; const FieldNo: Longint);
-begin
-  var N := Data.Count;
-  var Arr := SetArray(ItemNo, FieldNo, N);
-  for var I := 0 to N-1 do
-    VNSetString(PSGetArrayField(Arr, I), Data[I]);
-end;
-
-procedure TPSStackHelper.SetInt(const ItemNo: Longint; const Data: Integer;
-  const FieldNo: Longint);
-begin
-  if FieldNo = -1 then
-    inherited SetInt(ItemNo, Data)
-  else begin
-    var PSVariantIFC := NewTPSVariantRecordIFC(Items[ItemNo], FieldNo);
-    VNSetInt(PSVariantIFC, Data);
-  end;
-end;
-
-{---}
-
 procedure CrackCodeRootKey(CodeRootKey: HKEY; var RegView: TRegView;
   var RootKey: HKEY);
 begin
@@ -812,16 +793,37 @@ end;
 
 type
   TScriptFunc = reference to procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal);
-  TScriptFuncs = TDictionary<AnsiString, TScriptFunc>;
+  TScriptFuncTyp = (sfNormal, sfNoUninstall, sfOnlyUninstall);
+  TScriptFuncEx = record
+    OrgName: AnsiString;
+    ScriptFunc: TScriptFunc;
+    Typ: TScriptFuncTyp;
+    constructor Create(const AOrgName: AnsiString; const AScriptFunc: TScriptFunc; const ATyp: TScriptFuncTyp);
+  end;
+  TScriptFuncs = TDictionary<AnsiString, TScriptFuncEx>;
+
 var
   ScriptFuncs: TScriptFuncs;
 
+constructor TScriptFuncEx.Create(const AOrgName: AnsiString; const AScriptFunc: TScriptFunc; const ATyp: TScriptFuncTyp);
+begin
+  OrgName := AOrgName;
+  ScriptFunc := AScriptFunc;
+  Typ := ATyp;
+end;
+
 function ScriptFuncPSProc(Caller: TPSExec; Proc: TPSExternalProcRec; Global, Stack: TPSStack): Boolean;
 begin
-  var ScriptFunc: TScriptFunc;
-  Result := ScriptFuncs.TryGetValue(Proc.Name, ScriptFunc);
-  if Result then
-    ScriptFunc(Caller, Proc.Name, Stack, Stack.Count-1);
+  var ScriptFuncEx: TScriptFuncEx;
+  Result := ScriptFuncs.TryGetValue(Proc.Name, ScriptFuncEx);
+  if Result then begin
+    if (ScriptFuncEx.Typ = sfNoUninstall) and IsUninstaller then
+      NoUninstallFuncError(Proc.Name)
+    else if (ScriptFuncEx.Typ = sfOnlyUninstall) and not IsUninstaller then
+      InternalError(Format('Cannot call "%s" function during Setup', [ScriptFuncEx.OrgName]))
+    else
+      ScriptFuncEx.ScriptFunc(Caller, Proc.Name, Stack, Stack.Count-1);
+  end;
 end;
 
 procedure ScriptFuncLibraryRegister_R(ScriptInterpreter: TPSExec);
@@ -830,15 +832,21 @@ var
   Count: Integer;
 {$ENDIF}
 
-  procedure RegisterScriptFunc(const Name: AnsiString; const ScriptFunc: TScriptFunc); overload;
+  procedure RegisterScriptFunc(const Name: AnsiString; const ScriptFuncTyp: TScriptFuncTyp; const ScriptFunc: TScriptFunc); overload;
   begin
-    ScriptFuncs.Add(FastUpperCase(Name), ScriptFunc);
+    var ScriptFuncEx: TScriptFuncEx;
+    ScriptFuncs.Add(FastUpperCase(Name), TScriptFuncEx.Create(Name, ScriptFunc, ScriptFuncTyp));
     ScriptInterpreter.RegisterFunctionName(Name, ScriptFuncPSProc, nil, nil);
     {$IFDEF DEBUG}
     Inc(Count);
     {$ENDIF}
   end;
 
+  procedure RegisterScriptFunc(const Name: AnsiString; const ScriptFunc: TScriptFunc); overload;
+  begin
+    RegisterScriptFunc(Name, sfNormal, ScriptFunc);
+  end;
+
   procedure RegisterScriptFunc(const Names: array of AnsiString; const ScriptFunc: TScriptFunc); overload;
   begin
     for var Name in Names do
@@ -847,22 +855,16 @@ var
 
   procedure RegisterScriptDlgScriptFuncs;
   begin
-    RegisterScriptFunc('PAGEFROMID', procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
+    RegisterScriptFunc('PageFromID', sfNoUninstall, procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     begin
-      if IsUninstaller then
-        NoUninstallFuncError(Name);
       Stack.SetClass(PStart, GetWizardForm.PageFromID(Stack.GetInt(PStart-1)));
     end);
-    RegisterScriptFunc('PAGEINDEXFROMID', procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
+    RegisterScriptFunc('PageIndexFromID', sfNoUninstall, procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     begin
-      if IsUninstaller then
-        NoUninstallFuncError(Name);
       Stack.SetInt(PStart, GetWizardForm.PageIndexFromID(Stack.GetInt(PStart-1)));
     end);
-    RegisterScriptFunc('CREATECUSTOMPAGE', procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
+    RegisterScriptFunc('CreateCustomPage', sfNoUninstall, procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     begin
-      if IsUninstaller then
-        NoUninstallFuncError(Name);
       var NewPage := TWizardPage.Create(GetWizardForm);
       try
         NewPage.Caption := Stack.GetString(PStart-2);
@@ -874,10 +876,8 @@ var
       end;
       Stack.SetClass(PStart, NewPage);
     end);
-    RegisterScriptFunc('CREATEINPUTQUERYPAGE', procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
+    RegisterScriptFunc('CreateInputQueryPage', sfNoUninstall, procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     begin
-      if IsUninstaller then
-        NoUninstallFuncError(Name);
       var NewInputQueryPage := TInputQueryWizardPage.Create(GetWizardForm);
       try
         NewInputQueryPage.Caption := Stack.GetString(PStart-2);
@@ -890,10 +890,8 @@ var
       end;
       Stack.SetClass(PStart, NewInputQueryPage);
     end);
-    RegisterScriptFunc('CREATEINPUTOPTIONPAGE', procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
+    RegisterScriptFunc('CreateInputOptionPage', sfNoUninstall, procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     begin
-      if IsUninstaller then
-        NoUninstallFuncError(Name);
       var NewInputOptionPage := TInputOptionWizardPage.Create(GetWizardForm);
       try
         NewInputOptionPage.Caption := Stack.GetString(PStart-2);
@@ -907,10 +905,8 @@ var
       end;
       Stack.SetClass(PStart, NewInputOptionPage);
     end);
-    RegisterScriptFunc('CREATEINPUTDIRPAGE', procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
+    RegisterScriptFunc('CREATEINPUTDIRPAGE', sfNoUninstall, procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     begin
-      if IsUninstaller then
-        NoUninstallFuncError(Name);
       var NewInputDirPage := TInputDirWizardPage.Create(GetWizardForm);
       try
         NewInputDirPage.Caption := Stack.GetString(PStart-2);
@@ -924,10 +920,8 @@ var
       end;
       Stack.SetClass(PStart, NewInputDirPage);
     end);
-    RegisterScriptFunc('CREATEINPUTFILEPAGE', procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
+    RegisterScriptFunc('CREATEINPUTFILEPAGE', sfNoUninstall, procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     begin
-      if IsUninstaller then
-        NoUninstallFuncError(Name);
       var NewInputFilePage := TInputFileWizardPage.Create(GetWizardForm);
       try
         NewInputFilePage.Caption := Stack.GetString(PStart-2);
@@ -940,10 +934,8 @@ var
       end;
       Stack.SetClass(PStart, NewInputFilePage);
     end);
-    RegisterScriptFunc('CREATEOUTPUTMSGPAGE', procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
+    RegisterScriptFunc('CREATEOUTPUTMSGPAGE', sfNoUninstall, procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     begin
-      if IsUninstaller then
-        NoUninstallFuncError(Name);
       var NewOutputMsgPage := TOutputMsgWizardPage.Create(GetWizardForm);
       try
         NewOutputMsgPage.Caption := Stack.GetString(PStart-2);
@@ -956,10 +948,8 @@ var
       end;
       Stack.SetClass(PStart, NewOutputMsgPage);
     end);
-    RegisterScriptFunc('CREATEOUTPUTMSGMEMOPAGE', procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
+    RegisterScriptFunc('CREATEOUTPUTMSGMEMOPAGE', sfNoUninstall, procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     begin
-      if IsUninstaller then
-        NoUninstallFuncError(Name);
       var NewOutputMsgMemoPage := TOutputMsgMemoWizardPage.Create(GetWizardForm);
       try
         NewOutputMsgMemoPage.Caption := Stack.GetString(PStart-2);
@@ -973,10 +963,8 @@ var
       end;
       Stack.SetClass(PStart, NewOutputMsgMemoPage);
     end);
-    RegisterScriptFunc('CREATEOUTPUTPROGRESSPAGE', procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
+    RegisterScriptFunc('CREATEOUTPUTPROGRESSPAGE', sfNoUninstall, procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     begin
-      if IsUninstaller then
-        NoUninstallFuncError(Name);
       var NewOutputProgressPage := TOutputProgressWizardPage.Create(GetWizardForm);
       try
         NewOutputProgressPage.Caption := Stack.GetString(PStart-1);
@@ -989,10 +977,8 @@ var
       end;
       Stack.SetClass(PStart, NewOutputProgressPage);
     end);
-    RegisterScriptFunc('CREATEOUTPUTMARQUEEPROGRESSPAGE', procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
+    RegisterScriptFunc('CREATEOUTPUTMARQUEEPROGRESSPAGE', sfNoUninstall, procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     begin
-      if IsUninstaller then
-        NoUninstallFuncError(Name);
       var NewOutputMarqueeProgressPage := TOutputMarqueeProgressWizardPage.Create(GetWizardForm);
       try
         NewOutputMarqueeProgressPage.Caption := Stack.GetString(PStart-1);
@@ -1005,10 +991,8 @@ var
       end;
       Stack.SetClass(PStart, NewOutputMarqueeProgressPage);
     end);
-    RegisterScriptFunc('CREATEDOWNLOADPAGE', procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
-    begin
-      if IsUninstaller then
-        NoUninstallFuncError(Name);
+    RegisterScriptFunc('CREATEDOWNLOADPAGE', sfNoUninstall, procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
+    begin;
       var NewDownloadPage := TDownloadWizardPage.Create(GetWizardForm);
       try
         NewDownloadPage.Caption := Stack.GetString(PStart-1);
@@ -1022,10 +1006,8 @@ var
       end;
       Stack.SetClass(PStart, NewDownloadPage);
     end);
-    RegisterScriptFunc('CREATEEXTRACTIONPAGE', procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
+    RegisterScriptFunc('CREATEEXTRACTIONPAGE', sfNoUninstall, procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     begin
-      if IsUninstaller then
-        NoUninstallFuncError(Name);
       var NewExtractionPage := TExtractionWizardPage.Create(GetWizardForm);
       try
         NewExtractionPage.Caption := Stack.GetString(PStart-1);
@@ -2439,10 +2421,8 @@ var
     begin
       Stack.SetBool(PStart, IsUninstaller);
     end);
-    RegisterScriptFunc('UNINSTALLSILENT', procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
+    RegisterScriptFunc('UninstallSilent', sfOnlyUninstall, procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)
     begin
-      if not IsUninstaller then
-        NoSetupFuncError(Name);
       Stack.SetBool(PStart, UninstallSilent);
     end);
     RegisterScriptFunc('CURRENTFILENAME', procedure(const Caller: TPSExec; const Name: AnsiString; const Stack: TPSStack; const PStart: Cardinal)