瀏覽代碼

Added new [Setup] section directive: Output, which defaults to yes. If set to no the Setup Compiler will only check the script for errors and skip creating setup files.
Added new command line parameters supported by ISCC: /DO and /EO. These can be used to disable or enable output, overriding the Output directive.

Closes #86.

Martijn Laan 11 年之前
父節點
當前提交
09a53365ed
共有 9 個文件被更改,包括 273 次插入192 次删除
  1. 1 0
      Components/ScintStylerInnoSetup.pas
  2. 4 1
      Projects/CompForm.pas
  3. 3 1
      Projects/CompInt.pas
  4. 4 1
      Projects/CompMsgs.pas
  5. 212 177
      Projects/Compile.pas
  6. 19 6
      Projects/ISCC.dpr
  7. 18 5
      Projects/ISPP/ISPPCC.dpr
  8. 10 1
      ishelp/isetup.xml
  9. 2 0
      whatsnew.htm

+ 1 - 0
Components/ScintStylerInnoSetup.pas

@@ -176,6 +176,7 @@ type
     ssMessagesFile,
     ssMinVersion,
     ssOnlyBelowVersion,
+		ssOutput,
     ssOutputBaseFilename,
     ssOutputDir,
     ssOutputManifestFile,

+ 4 - 1
Projects/CompForm.pas

@@ -3574,8 +3574,11 @@ begin
     if FUninstExe = '' then
       raise Exception.Create(SCompilerNeedUninstExe);
     RunFilename := FUninstExe;
-  end else
+  end else begin
+    if FCompiledExe = '' then
+      raise Exception.Create(SCompilerNeedCompiledExe);
     RunFilename := FCompiledExe;
+	end;
   RunParameters := Format('/DEBUGWND=$%x ', [Handle]) + FRunParameters;
 
   ResetLineState;

+ 3 - 1
Projects/CompInt.pas

@@ -75,7 +75,9 @@ type
                                                per second (new in 5.1.13) }
 
       iscbNotifySuccess: (
-        OutputExeFilename: PChar;  { [in] The name of the resulting setup.exe }
+        OutputExeFilename: PChar;  { [in] The name of the resulting setup.exe,
+				                                  or empty if output was disabled
+																					(latter new in 5.5.5) }
         DebugInfo: Pointer;        { [in] Debug info (new in 3.0.0.1) }
         DebugInfoSize: Cardinal);  { [in] Size of debug info (new in 3.0.0.1) }
 

+ 4 - 1
Projects/CompMsgs.pas

@@ -103,6 +103,7 @@ const
   SCompilerStatusFilesVerInfo = '   Reading version info: %s';
   SCompilerStatusReadingFile = 'Reading file (%s)';
   SCompilerStatusPreparingSetupExe = 'Preparing Setup program executable';
+	SCompilerStatusSkippingPreparingSetupExe = 'Skipping preparing Setup program executable, output is disabled';
   SCompilerStatusSignedUninstallerNew = '   Creating new signed uninstaller file: %s';
   SCompilerStatusSignedUninstallerExisting = '   Using existing signed uninstaller file: %s';
   SCompilerStatusDeterminingCodePages = 'Determining language code pages';
@@ -114,6 +115,7 @@ const
   SCompilerStatusReadingInFile = '   File: %s';
   SCompilerStatusReadingInScriptMsgs = '   Messages in script file';
   SCompilerStatusCreateSetupFiles = 'Creating setup files';
+	SCompilerStatusSkippingCreateSetupFiles = 'Skipping creating setup files, output is disabled';
   SCompilerStatusCreateManifestFile = 'Creating manifest file';
   SCompilerStatusFilesInitEncryption = '   Initializing encryption';
   SCompilerStatusFilesCompressing = '   Compressing: %s';
@@ -136,7 +138,8 @@ const
     SNewLine +
     'Would you like to test the installation now?';
   SCompilerSuccessfulTitle = 'Compile Successful';
-  SCompilerNeedUninstExe = 'Cannot target Uninstall as this time. Please run Setup successfully to completion first';
+  SCompilerNeedCompiledExe = 'Cannot run Setup at this time. Please compile Setup successfully to completion first, with output enabled';
+  SCompilerNeedUninstExe = 'Cannot run Uninstall at this time. Please run Setup successfully to completion first';
   SCompilerExecuteSetupError2 = 'Error executing "%s":' + SNewLine2 + '%d: %s';
 
   SCompilerAborted = 'Compile aborted. Please correct the problem and try again.';

+ 212 - 177
Projects/Compile.pas

@@ -135,6 +135,7 @@ type
     ssMessagesFile,
     ssMinVersion,
     ssOnlyBelowVersion,
+		ssOutput,
     ssOutputBaseFilename,
     ssOutputDir,
     ssOutputManifestFile,
@@ -343,7 +344,7 @@ type
 
     OutputDir, OutputBaseFilename, OutputManifestFile, SignedUninstallerDir,
       ExeFilename: String;
-    FixedOutputDir, FixedOutputBaseFilename: Boolean;
+    Output, FixedOutput, FixedOutputDir, FixedOutputBaseFilename: Boolean;
     CompressMethod: TSetupCompressMethod;
     InternalCompressLevel, CompressLevel: Integer;
     InternalCompressProps, CompressProps: TLZMACompressorProps;
@@ -3943,23 +3944,19 @@ begin
         if not StrToVersionNumbers(Value, SetupHeader.OnlyBelowVersion) then
           Invalid;
       end;
+		ssOutput: begin
+		    if not FixedOutput then
+					Output := StrToBool(Value);
+		end;
     ssOutputBaseFilename: begin
-        if not FixedOutputBaseFilename then begin
-          if Value = '' then
-            Invalid;
+        if not FixedOutputBaseFilename then
           OutputBaseFilename := Value;
-        end;
       end;
     ssOutputDir: begin
-        if not FixedOutputDir then begin
-          if Value = '' then
-            Invalid;
+        if not FixedOutputDir then
           OutputDir := Value;
-        end;
       end;
     ssOutputManifestFile: begin
-        if Value = '' then
-          Invalid;
         OutputManifestFile := Value;
       end;
     ssPassword: begin
@@ -7445,36 +7442,40 @@ procedure TSetupCompiler.Compile;
     HasNumbers: Boolean;
   begin
     { Delete SETUP.* and SETUP-*.BIN if they existed in the output directory }
-    DelFile(OutputBaseFilename + '.exe');
-    H := FindFirstFile(PChar(OutputDir + OutputBaseFilename + '-*.bin'), FindData);
-    if H <> INVALID_HANDLE_VALUE then begin
-      try
-        repeat
-          if FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY = 0 then begin
-            N := FindData.cFileName;
-            if PathStartsWith(N, OutputBaseFilename) then begin
-              I := Length(OutputBaseFilename) + 1;
-              if (I <= Length(N)) and (N[I] = '-') then begin
-                Inc(I);
-                HasNumbers := False;
-                while (I <= Length(N)) and CharInSet(N[I], ['0'..'9']) do begin
-                  HasNumbers := True;
-                  Inc(I);
-                end;
-                if HasNumbers then begin
-                  if (I <= Length(N)) and CharInSet(UpCase(N[I]), ['A'..'Z']) then
-                    Inc(I);
-                  if CompareText(Copy(N, I, Maxint), '.bin') = 0 then
-                    DelFile(N);
-                end;
-              end;
-            end;
-          end;
-        until not FindNextFile(H, FindData);
-      finally
-        Windows.FindClose(H);
-      end;
-    end;
+		if OutputBaseFilename <> '' then begin
+			DelFile(OutputBaseFilename + '.exe');
+			if OutputDir <> '' then begin
+				H := FindFirstFile(PChar(OutputDir + OutputBaseFilename + '-*.bin'), FindData);
+				if H <> INVALID_HANDLE_VALUE then begin
+					try
+						repeat
+							if FindData.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY = 0 then begin
+								N := FindData.cFileName;
+								if PathStartsWith(N, OutputBaseFilename) then begin
+									I := Length(OutputBaseFilename) + 1;
+									if (I <= Length(N)) and (N[I] = '-') then begin
+										Inc(I);
+										HasNumbers := False;
+										while (I <= Length(N)) and CharInSet(N[I], ['0'..'9']) do begin
+											HasNumbers := True;
+											Inc(I);
+										end;
+										if HasNumbers then begin
+											if (I <= Length(N)) and CharInSet(UpCase(N[I]), ['A'..'Z']) then
+												Inc(I);
+											if CompareText(Copy(N, I, Maxint), '.bin') = 0 then
+												DelFile(N);
+										end;
+									end;
+								end;
+							end;
+						until not FindNextFile(H, FindData);
+					finally
+						Windows.FindClose(H);
+					end;
+				end;
+			end;
+		end;
   end;
 
   procedure FreeListItems(const List: TList; const NumStrings, NumAnsiStrings: Integer);
@@ -8038,7 +8039,6 @@ var
   var
     TempFilename, E32Filename, ConvertFilename: String;
   begin
-    AddStatus(SCompilerStatusPreparingSetupExe);
     TempFilename := '';
     try
       E32Filename := CompilerDir + 'SETUP.E32';
@@ -8215,6 +8215,8 @@ begin
 
     { Initialize defaults }
     OriginalSourceDir := AddBackslash(PathExpand(SourceDir));
+    if not FixedOutput then
+      Output := True;
     if not FixedOutputDir then
       OutputDir := 'Output';
     if not FixedOutputBaseFilename then
@@ -8410,6 +8412,20 @@ begin
     CheckCheckOrInstall('CreateUninstallRegKey', SetupHeader.CreateUninstallRegKey, cikDirectiveCheck);
     LineNumber := SetupDirectiveLines[ssUninstallable];
     CheckCheckOrInstall('Uninstallable', SetupHeader.Uninstallable, cikDirectiveCheck);
+		if Output then begin
+		  if OutputDir = '' then begin
+				LineNumber := SetupDirectiveLines[ssOutput];
+				AbortCompileOnLineFmt(SCompilerEntryInvalid2, ['Setup', 'OutputDir']);
+			end;
+		  if OutputBaseFileName = '' then begin
+				LineNumber := SetupDirectiveLines[ssOutputBaseFileName];
+				AbortCompileOnLineFmt(SCompilerEntryInvalid2, ['Setup', 'OutputBaseFileName']);
+			end;
+		  if (SetupDirectiveLines[ssOutputManifestfile] <> 0) and (OutputManifestFile = '') then begin
+				LineNumber := SetupDirectiveLines[ssOutputManifestFile];
+				AbortCompileOnLineFmt(SCompilerEntryInvalid2, ['Setup', 'OutputManifestFile']);
+			end;
+		end;
 
     LineNumber := 0;
 
@@ -8465,7 +8481,11 @@ begin
     LineNumber := 0;
 
     { Prepare Setup executable & signed uninstaller data }
-    PrepareSetupE32(SetupE32);
+		if Output then begin
+			AddStatus(SCompilerStatusPreparingSetupExe);
+			PrepareSetupE32(SetupE32);
+		end else
+			AddStatus(SCompilerStatusSkippingPreparingSetupExe);
 
     { Read languages:
 
@@ -8670,142 +8690,148 @@ begin
     CompileCode;
     CallIdleProc;
 
-    { Clear any existing setup* files out of the output directory first }
+    { Clear any existing setup* files out of the output directory first (even
+      if output is disabled. }
     EmptyOutputDir(True);
     if OutputManifestFile <> '' then
       DeleteFile(PrependDirName(OutputManifestFile, OutputDir));
 
     { Create setup files }
-    AddStatus(SCompilerStatusCreateSetupFiles);
-    ExeFilename := OutputDir + OutputBaseFilename + '.exe';
-    try
-      if not UseSetupLdr then begin
-        SetupFile := TFile.Create(ExeFilename, fdCreateAlways, faWrite, fsNone);
-        try
-          SetupFile.WriteBuffer(SetupE32.Memory^, SetupE32.Size.Lo);
-          SizeOfExe := SetupFile.Size.Lo;
-        finally
-          SetupFile.Free;
-        end;
-        CallIdleProc;
-
-        if not DiskSpanning then begin
-          { Create SETUP-0.BIN and SETUP-1.BIN }
-          CompressFiles('', 0);
-          CreateSetup0File;
-        end
-        else begin
-          { Create SETUP-0.BIN and SETUP-*.BIN }
-          SizeOfHeaders := CreateSetup0File;
-          CompressFiles('', RoundToNearestClusterSize(SizeOfExe) +
-            RoundToNearestClusterSize(SizeOfHeaders) +
-            RoundToNearestClusterSize(ReserveBytes));
-          { CompressFiles modifies setup header data, so go back and
-            rewrite it }
-          if CreateSetup0File <> SizeOfHeaders then
-            { Make sure new and old size match. No reason why they
-              shouldn't but check just in case }
-            AbortCompile(SCompilerSetup0Mismatch);
-        end;
-      end
-      else begin
-        CopyFileOrAbort(CompilerDir + 'SETUPLDR.E32', ExeFilename);
-        { if there was a read-only attribute, remove it }
-        SetFileAttributes(PChar(ExeFilename), FILE_ATTRIBUTE_ARCHIVE);
-        if SetupIconFilename <> '' then begin
-          { update icons }
-          AddStatus(Format(SCompilerStatusUpdatingIcons, ['SETUP.EXE']));
-          LineNumber := SetupDirectiveLines[ssSetupIconFile];
-          UpdateIcons(ExeFilename, PrependSourceDirName(SetupIconFilename));
-          LineNumber := 0;
-        end;
-        SetupFile := TFile.Create(ExeFilename, fdOpenExisting, faReadWrite, fsNone);
-        try
-          UpdateSetupPEHeaderFields(SetupFile, TerminalServicesAware);
-          SizeOfExe := SetupFile.Size.Lo;
-        finally
-          SetupFile.Free;
-        end;
-        CallIdleProc;
-
-        { When disk spanning isn't used, place the compressed files inside
-          SETUP.EXE }
-        if not DiskSpanning then
-          CompressFiles(ExeFilename, 0);
-
-        ExeFile := TFile.Create(ExeFilename, fdOpenExisting, faReadWrite, fsNone);
-        try
-          ExeFile.SeekToEnd;
-
-          { Move the data from SETUP.E?? into the SETUP.EXE, and write
-            header data }
-          FillChar(SetupLdrOffsetTable, SizeOf(SetupLdrOffsetTable), 0);
-          SetupLdrOffsetTable.ID := SetupLdrOffsetTableID;
-          SetupLdrOffsetTable.Version := SetupLdrOffsetTableVersion;
-          SetupLdrOffsetTable.Offset0 := ExeFile.Position.Lo;
-          SizeOfHeaders := WriteSetup0(ExeFile);
-          SetupLdrOffsetTable.OffsetEXE := ExeFile.Position.Lo;
-          CompressSetupE32(SetupE32, ExeFile, SetupLdrOffsetTable.UncompressedSizeEXE,
-            SetupLdrOffsetTable.CRCEXE);
-          SetupLdrOffsetTable.TotalSize := ExeFile.Size.Lo;
-          if DiskSpanning then begin
-            SetupLdrOffsetTable.Offset1 := 0;
-            { Compress the files in SETUP-*.BIN after we know the size of
-              SETUP.EXE }
-            CompressFiles('',
-              RoundToNearestClusterSize(SetupLdrOffsetTable.TotalSize) +
-              RoundToNearestClusterSize(ReserveBytes));
-            { CompressFiles modifies setup header data, so go back and
-              rewrite it }
-            ExeFile.Seek(SetupLdrOffsetTable.Offset0);
-            if WriteSetup0(ExeFile) <> SizeOfHeaders then
-              { Make sure new and old size match. No reason why they
-                shouldn't but check just in case }
-              AbortCompile(SCompilerSetup0Mismatch);
-          end
-          else
-            SetupLdrOffsetTable.Offset1 := SizeOfExe;
-          SetupLdrOffsetTable.TableCRC := GetCRC32(SetupLdrOffsetTable,
-            SizeOf(SetupLdrOffsetTable) - SizeOf(SetupLdrOffsetTable.TableCRC));
-
-          { Write SetupLdrOffsetTable to SETUP.EXE }
-          if SeekToResourceData(ExeFile, Cardinal(RT_RCDATA), SetupLdrOffsetTableResID) <> SizeOf(SetupLdrOffsetTable) then
-            AbortCompile('Wrong offset table resource size');
-          ExeFile.WriteBuffer(SetupLdrOffsetTable, SizeOf(SetupLdrOffsetTable));
-
-          { Update version info }
-          AddStatus(SCompilerStatusUpdatingVersionInfo);
-          UpdateVersionInfo(ExeFile, VersionInfoVersion, VersionInfoProductVersion, VersionInfoCompany,
-            VersionInfoDescription, VersionInfoTextVersion,
-            VersionInfoCopyright, VersionInfoProductName, VersionInfoProductTextVersion);
-
-          { For some reason, on Win95 the date/time of the EXE sometimes
-            doesn't get updated after it's been written to so it has to
-            manually set it. (I don't get it!!) }
-          UpdateTimeStamp(ExeFile.Handle);
-        finally
-          ExeFile.Free;
-        end;
-      end;
-
-      { Sign }
-      SignToolIndex := FindSignToolIndexByName(SignTool);
-      if SignToolIndex <> -1 then begin
-        AddStatus(SCompilerStatusSigningSetup);
-        Sign(TSignTool(SignToolList[SignToolIndex]).Command, SignToolParams, ExeFilename);
-      end;
-    except
-      EmptyOutputDir(False);
-      raise;
-    end;
-    CallIdleProc;
-
-    { Create manifest file }
-    if OutputManifestFile <> '' then begin
-      AddStatus(SCompilerStatusCreateManifestFile);
-      CreateManifestFile;
-      CallIdleProc;
-    end;
+		if Output then begin
+			AddStatus(SCompilerStatusCreateSetupFiles);
+			ExeFilename := OutputDir + OutputBaseFilename + '.exe';
+			try
+				if not UseSetupLdr then begin
+					SetupFile := TFile.Create(ExeFilename, fdCreateAlways, faWrite, fsNone);
+					try
+						SetupFile.WriteBuffer(SetupE32.Memory^, SetupE32.Size.Lo);
+						SizeOfExe := SetupFile.Size.Lo;
+					finally
+						SetupFile.Free;
+					end;
+					CallIdleProc;
+
+					if not DiskSpanning then begin
+						{ Create SETUP-0.BIN and SETUP-1.BIN }
+						CompressFiles('', 0);
+						CreateSetup0File;
+					end
+					else begin
+						{ Create SETUP-0.BIN and SETUP-*.BIN }
+						SizeOfHeaders := CreateSetup0File;
+						CompressFiles('', RoundToNearestClusterSize(SizeOfExe) +
+							RoundToNearestClusterSize(SizeOfHeaders) +
+							RoundToNearestClusterSize(ReserveBytes));
+						{ CompressFiles modifies setup header data, so go back and
+							rewrite it }
+						if CreateSetup0File <> SizeOfHeaders then
+							{ Make sure new and old size match. No reason why they
+								shouldn't but check just in case }
+							AbortCompile(SCompilerSetup0Mismatch);
+					end;
+				end
+				else begin
+					CopyFileOrAbort(CompilerDir + 'SETUPLDR.E32', ExeFilename);
+					{ if there was a read-only attribute, remove it }
+					SetFileAttributes(PChar(ExeFilename), FILE_ATTRIBUTE_ARCHIVE);
+					if SetupIconFilename <> '' then begin
+						{ update icons }
+						AddStatus(Format(SCompilerStatusUpdatingIcons, ['SETUP.EXE']));
+						LineNumber := SetupDirectiveLines[ssSetupIconFile];
+						UpdateIcons(ExeFilename, PrependSourceDirName(SetupIconFilename));
+						LineNumber := 0;
+					end;
+					SetupFile := TFile.Create(ExeFilename, fdOpenExisting, faReadWrite, fsNone);
+					try
+						UpdateSetupPEHeaderFields(SetupFile, TerminalServicesAware);
+						SizeOfExe := SetupFile.Size.Lo;
+					finally
+						SetupFile.Free;
+					end;
+					CallIdleProc;
+
+					{ When disk spanning isn't used, place the compressed files inside
+						SETUP.EXE }
+					if not DiskSpanning then
+						CompressFiles(ExeFilename, 0);
+
+					ExeFile := TFile.Create(ExeFilename, fdOpenExisting, faReadWrite, fsNone);
+					try
+						ExeFile.SeekToEnd;
+
+						{ Move the data from SETUP.E?? into the SETUP.EXE, and write
+							header data }
+						FillChar(SetupLdrOffsetTable, SizeOf(SetupLdrOffsetTable), 0);
+						SetupLdrOffsetTable.ID := SetupLdrOffsetTableID;
+						SetupLdrOffsetTable.Version := SetupLdrOffsetTableVersion;
+						SetupLdrOffsetTable.Offset0 := ExeFile.Position.Lo;
+						SizeOfHeaders := WriteSetup0(ExeFile);
+						SetupLdrOffsetTable.OffsetEXE := ExeFile.Position.Lo;
+						CompressSetupE32(SetupE32, ExeFile, SetupLdrOffsetTable.UncompressedSizeEXE,
+							SetupLdrOffsetTable.CRCEXE);
+						SetupLdrOffsetTable.TotalSize := ExeFile.Size.Lo;
+						if DiskSpanning then begin
+							SetupLdrOffsetTable.Offset1 := 0;
+							{ Compress the files in SETUP-*.BIN after we know the size of
+								SETUP.EXE }
+							CompressFiles('',
+								RoundToNearestClusterSize(SetupLdrOffsetTable.TotalSize) +
+								RoundToNearestClusterSize(ReserveBytes));
+							{ CompressFiles modifies setup header data, so go back and
+								rewrite it }
+							ExeFile.Seek(SetupLdrOffsetTable.Offset0);
+							if WriteSetup0(ExeFile) <> SizeOfHeaders then
+								{ Make sure new and old size match. No reason why they
+									shouldn't but check just in case }
+								AbortCompile(SCompilerSetup0Mismatch);
+						end
+						else
+							SetupLdrOffsetTable.Offset1 := SizeOfExe;
+						SetupLdrOffsetTable.TableCRC := GetCRC32(SetupLdrOffsetTable,
+							SizeOf(SetupLdrOffsetTable) - SizeOf(SetupLdrOffsetTable.TableCRC));
+
+						{ Write SetupLdrOffsetTable to SETUP.EXE }
+						if SeekToResourceData(ExeFile, Cardinal(RT_RCDATA), SetupLdrOffsetTableResID) <> SizeOf(SetupLdrOffsetTable) then
+							AbortCompile('Wrong offset table resource size');
+						ExeFile.WriteBuffer(SetupLdrOffsetTable, SizeOf(SetupLdrOffsetTable));
+
+						{ Update version info }
+						AddStatus(SCompilerStatusUpdatingVersionInfo);
+						UpdateVersionInfo(ExeFile, VersionInfoVersion, VersionInfoProductVersion, VersionInfoCompany,
+							VersionInfoDescription, VersionInfoTextVersion,
+							VersionInfoCopyright, VersionInfoProductName, VersionInfoProductTextVersion);
+
+						{ For some reason, on Win95 the date/time of the EXE sometimes
+							doesn't get updated after it's been written to so it has to
+							manually set it. (I don't get it!!) }
+						UpdateTimeStamp(ExeFile.Handle);
+					finally
+						ExeFile.Free;
+					end;
+				end;
+
+				{ Sign }
+				SignToolIndex := FindSignToolIndexByName(SignTool);
+				if SignToolIndex <> -1 then begin
+					AddStatus(SCompilerStatusSigningSetup);
+					Sign(TSignTool(SignToolList[SignToolIndex]).Command, SignToolParams, ExeFilename);
+				end;
+			except
+				EmptyOutputDir(False);
+				raise;
+			end;
+			CallIdleProc;
+
+			{ Create manifest file }
+			if OutputManifestFile <> '' then begin
+				AddStatus(SCompilerStatusCreateManifestFile);
+				CreateManifestFile;
+				CallIdleProc;
+			end;
+		end else begin
+			AddStatus(SCompilerStatusSkippingCreateSetupFiles);
+			ExeFilename := '';
+		end;
 
     { Finalize debug info }
     FinalizeDebugInfo;
@@ -8814,8 +8840,8 @@ begin
     AddStatus('');
     for I := 0 to WarningsList.Count-1 do
       AddStatus(SCompilerStatusWarning + WarningsList[I]);
-    asm jmp @1; db 0,'Inno Setup Compiler, Copyright (C) 1997-2010 Jordan Russell, '
-                  db 'Portions Copyright (C) 2000-2010 Martijn Laan',0; @1: end;
+    asm jmp @1; db 0,'Inno Setup Compiler, Copyright (C) 1997-2014 Jordan Russell, '
+                  db 'Portions Copyright (C) 2000-2014 Martijn Laan',0; @1: end;
     { Note: Removing or modifying the copyright text is a violation of the
       Inno Setup license agreement; see LICENSE.TXT. }
   finally
@@ -8888,7 +8914,16 @@ begin
     if (Params.Size <> SizeOf(TCompileScriptParams)) and Assigned(Params.Options) then begin
       P := Params.Options;
       while P^ <> #0 do begin
-        if StrLIComp(P, 'OutputDir=', Length('OutputDir=')) = 0 then begin
+        if StrLIComp(P, 'Output=', Length('Output=')) = 0 then begin
+          Inc(P, Length('Output='));
+					if TryStrToBoolean(P, SetupCompiler.Output) then
+            SetupCompiler.FixedOutput := True
+					else begin
+            { Bad option }
+            Result := isceInvalidParam;
+  				end;
+        end
+        else if StrLIComp(P, 'OutputDir=', Length('OutputDir=')) = 0 then begin
           Inc(P, Length('OutputDir='));
           SetupCompiler.OutputDir := P;
           SetupCompiler.FixedOutputDir := True;

+ 19 - 6
Projects/ISCC.dpr

@@ -35,7 +35,7 @@ type
 var
   StdOutHandle, StdErrHandle: THandle;
   ScriptFilename: String;
-  OutputPath, OutputFilename, SignTool: String;
+  Output, OutputPath, OutputFilename, SignTool: String;
   ScriptLines, NextScriptLine: PScriptLine;
   CurLine: String;
   StartTime, EndTime: DWORD;
@@ -136,10 +136,15 @@ begin
         EndTime := GetTickCount;
         if not Quiet then begin
           WriteStdOut('');
-          WriteStdOut(Format('Successful compile (%.3f sec). ' +
-            'Resulting Setup program filename is:',
-            [(EndTime - StartTime) / 1000]));
-          WriteStdOut(Data.OutputExeFilename);
+					if Data.OutputExeFilename <> '' then begin
+						WriteStdOut(Format('Successful compile (%.3f sec). ' +
+							'Resulting Setup program filename is:',
+							[(EndTime - StartTime) / 1000]));
+						WriteStdOut(Data.OutputExeFilename);
+					end else
+						WriteStdOut(Format('Successful compile (%.3f sec). ' +
+							'Output was disabled.',
+							[(EndTime - StartTime) / 1000]));
         end;
       end;
     iscbNotifyError:
@@ -171,7 +176,9 @@ procedure ProcessCommandLine;
   begin
     WriteStdErr('Usage:  iscc [options] scriptfile.iss');
     WriteStdErr('or to read from standard input:  iscc [options] -');
-    WriteStdErr('Options:  /Oc:\path      Output files to specified path (overrides OutputDir)');
+    WriteStdErr('Options:  /DO            Disable output (overrides Output)');
+    WriteStdErr('          /EO            Enable output (overrides Output)');
+		WriteStdErr('          /Oc:\path      Output files to specified path (overrides OutputDir)');
     WriteStdErr('          /Ffilename     Overrides OutputBaseFilename with the specified filename');
     WriteStdErr('          /Sname=command Sets a SignTool with the specified name and command');
     WriteStdErr('          /Q             Quiet compile (print error messages only)');
@@ -187,6 +194,10 @@ begin
     if (S = '') or (S[1] = '/') then begin
       if CompareText(S, '/Q') = 0 then
         Quiet := True
+      else if CompareText(Copy(S, 1, 3), '/DO') = 0 then
+        Output := 'no'
+      else if CompareText(Copy(S, 1, 3), '/EO') = 0 then
+        Output := 'yes'
       else if CompareText(Copy(S, 1, 2), '/O') = 0 then
         OutputPath := Copy(S, 3, MaxInt)
       else if CompareText(Copy(S, 1, 2), '/F') = 0 then
@@ -284,6 +295,8 @@ begin
     Params.SourcePath := PChar(ScriptPath);
     Params.CallbackProc := CompilerCallbackProc;
     Options := '';
+		if Output <> '' then
+      Options := Options + 'Output=' + Output + #0;
     if OutputPath <> '' then
       Options := Options + 'OutputDir=' + OutputPath + #0;
     if OutputFilename <> '' then

+ 18 - 5
Projects/ISPP/ISPPCC.dpr

@@ -146,10 +146,15 @@ begin
         EndTime := GetTickCount;
         if not Quiet then begin
           WriteStdOut('');
-          WriteStdOut(Format('Successful compile (%.3f sec). ' +
-            'Resulting Setup program filename is:',
-            [(EndTime - StartTime) / 1000]));
-          WriteStdOut(Data.OutputExeFilename);
+					if Data.OutputExeFilename <> '' then begin
+						WriteStdOut(Format('Successful compile (%.3f sec). ' +
+							'Resulting Setup program filename is:',
+							[(EndTime - StartTime) / 1000]));
+						WriteStdOut(Data.OutputExeFilename);
+					end else
+						WriteStdOut(Format('Successful compile (%.3f sec). ' +
+							'Output was disabled.',
+							[(EndTime - StartTime) / 1000]));
         end;
       end;
     iscbNotifyError:
@@ -249,6 +254,10 @@ procedure Go;
     WriteStdErr('            /{#<string>          #pragma inlinestart <string>');
     WriteStdErr('            /}<string>           #pragma inlineend <string>');
     WriteStdErr('            /v<number>           #pragma verboselevel <number>');
+    WriteStdErr('          Disable output (overrides Output):');
+    WriteStdErr('            /do');
+    WriteStdErr('          Enable output (overrides Output):');
+    WriteStdErr('            /eo');
     WriteStdErr('          Output files to specified path (overrides OutputDir):');
     WriteStdErr('            /o<path>');
     WriteStdErr('          Override OutputBaseFilename with the specified filename:');
@@ -268,7 +277,7 @@ var
   F: TTextFileReader;
   Params: TCompileScriptParamsEx;
   I: Integer;
-  S, IncludePath, Definitions, OutputPath, OutputFilename, SignTool: string;
+  S, IncludePath, Definitions, Output, OutputPath, OutputFilename, SignTool: string;
   Res: Integer;
 begin
   I := 1;
@@ -349,6 +358,8 @@ begin
   if S <> '' then Options.InlineEnd := AnsiString(S);
   I := 1; S := FindParam(I, 'V');
   if S <> '' then Options.VerboseLevel := StrToIntDef(S, 0);
+	I := 1; FindParam(I, 'DO'); if I <> MaxInt then Output := 'no';
+	I := 1; FindParam(I, 'EO'); if I <> MaxInt then Output := 'yes';
   I := 1; OutputPath := FindParam(I, 'O');
   I := 1; OutputFileName := FindParam(I, 'F');
   I := 1; SignTool := FindParam(I, 'S');
@@ -375,6 +386,8 @@ begin
     Params.SourcePath := PChar(ScriptPath);
     Params.CallbackProc := CompilerCallbackProc;
     S := '';
+    if Output <> '' then
+      AppendOption(S, 'Output', Output);
     if OutputPath <> '' then
       AppendOption(S, 'OutputDir', OutputPath);
     if OutputFilename <> '' then

+ 10 - 1
ishelp/isetup.xml

@@ -902,6 +902,7 @@ DefaultGroupName=My Program
 <li><link topic="setup_lzmanumfastbytes">LZMANumFastBytes</link></li>
 <li><link topic="setup_lzmauseseparateprocess">LZMAUseSeparateProcess</link></li>
 <li><link topic="setup_mergeduplicatefiles">MergeDuplicateFiles</link></li>
+<li><link topic="setup_output">Output</link></li>
 <li><link topic="setup_outputbasefilename">OutputBaseFilename</link></li>
 <li><link topic="setup_outputdir">OutputDir</link></li>
 <li><link topic="setup_outputmanifestfile">OutputManifestFile</link></li>
@@ -2974,7 +2975,7 @@ Filename: "{win}\MYPROG.INI"; Section: "InstallSettings"; Key: "InstallPath"; St
 
 <p>As shown in the example above, filenames that include spaces must be enclosed in quotes.</p>
 
-<p>Valid options are: "/O" to specify an output path (overriding any <tt>OutputDir</tt> setting in the script), "/F" to specify an output filename (overriding any <tt>OutputBaseFilename</tt> setting in the script), "/S" to specify a Sign Tool, "/Q" for quiet compile (print only error messages), and "/?" to show a help screen.</p>
+<p>Valid options are: "/DO" to disable output (overriding any <tt>Output</tt> setting in the script), "/EO" to enable output (overriding any <tt>Output</tt> setting in the script), "/O" to specify an output path (overriding any <tt>OutputDir</tt> setting in the script), "/F" to specify an output filename (overriding any <tt>OutputBaseFilename</tt> setting in the script), "/S" to specify a Sign Tool, "/Q" for quiet compile (print only error messages), and "/?" to show a help screen.</p>
 
 <indent>
 <example>iscc /Q /O"My Output" /F"MyProgram-1.0" /Sbyparam=$p "c:\isetup\samples\my script.iss"</example>
@@ -4028,6 +4029,14 @@ end;</pre></example>
 </body>
 </setuptopic>
 
+<setuptopic directive="Output">
+<setupvalid><link topic="yesnonotes"><tt>yes</tt> or <tt>no</tt></link></setupvalid>
+<setupdefault><tt>yes</tt></setupdefault>
+<body>
+<p>If set to <tt>no</tt> the Setup Compiler will only check the script for errors and skip creating setup files.</p>
+</body>
+</setuptopic>
+
 <setuptopic directive="OutputBaseFilename">
 <setupdefault><tt>setup</tt></setupdefault>
 <body>

+ 2 - 0
whatsnew.htm

@@ -28,6 +28,8 @@ For conditions of distribution and use, see <a href="http://www.jrsoftware.org/f
 
 <p><a name="5.5.5"></a><span class="ver">5.5.5-dev </span><span class="date">(?)</span></p>
 <ul>
+<li>Added new [Setup] section directive: <tt>Output</tt>, which defaults to <tt>yes</tt>. If set to <tt>no</tt> the Setup Compiler will only check the script for errors and skip creating setup files.</li>
+<li>Added new command line parameters supported by ISCC: /DO and /EO. These can be used to disable or enable output, overriding the <tt>Output</tt> directive.</li>
 <li>Pascal Scripting: The already-existing <tt>StrToFloat</tt> and <tt>FloatToStr</tt> functions are now documented.</li>
 <li>Added official Scottish Gaelic and Turskish translations.</li>
 </ul>