The Pascal scripting feature (modern Delphi-like Pascal) adds lots of new possibilities to customize your Setup or Uninstall at run-time. Some examples:

  • Support for aborting Setup or Uninstall startup under custom conditions.
  • Support for adding custom wizard pages to Setup at run-time.
  • Support for extracting and calling DLL or other files from the Pascal script before, during or after the installation.
  • Support for scripted constants that can do anything the normal constants, the read-from-registry, read-from-ini and read-from-commandline constants can do + more.
  • Support for run-time removal of types, components and/or tasks under custom conditions.
  • Support for conditional installation of [Files], [Registry], [Run] etc. entries based on custom conditions.
  • Lots of support functions to do from the Pascal script just about everything Inno Setup itself does/can do + more.

An integrated run-time debugger to debug your custom Pascal script is also available.

The scripting engine used by Inno Setup is RemObjects Pascal Script by Carlo Kok. Like Inno Setup, RemObjects Pascal Script is freely available and comes with source. See http://www.remobjects.com/ps for more information.

Note: the Pascal scripting feature works exclusively at run-time, and has no compile-time functionality.


See also:
Creating the [Code] section
Event Functions
Scripted Constants
Check Parameters
BeforeInstall and AfterInstall Parameters
Uninstall Code
Examples
Support Functions Reference
Support Classes Reference
Using Custom Wizard Pages
Using DLLs and .NET assemblies
Using COM Automation objects
Run-time debugger

The [Code] section is an optional section that specifies a Pascal script. A Pascal script can be used to customize Setup or Uninstall in many ways. Note that creating a Pascal script is not easy and requires experience with Inno Setup and knowledge about programming in Pascal or at least a similar programming language.

The Code*.iss, UninstallCode*.iss, and AllPagesExample.iss example scripts in the "Examples" subdirectory in your Inno Setup directory contain various example [Code] sections. Please study them carefully before trying to create your own Pascal script.

Note: to learn more about the Pascal programming language you may find useful to refer to Marco Cantù's free Essential Pascal book. See http://www.marcocantu.com/epascal/ and https://www.marcocantu.com/epascal/EssentialPascal.zip.

The Pascal script can contain several event functions which are called at appropriate times.

Setup event functions

Setup supports following event functions:

function InitializeSetup(): Boolean;

Called during Setup's initialization. Return False to abort Setup, True otherwise.

procedure InitializeWizard();

Use this event function to make changes to the wizard or wizard pages at startup. You can't use the InitializeSetup event function for this since at the time it is triggered, the wizard form does not yet exist.

procedure DeinitializeSetup();

Called just before Setup terminates. Note that this function is called even if the user exits Setup before anything is installed.

procedure CurStepChanged(CurStep: TSetupStep);

You can use this event function to perform your own pre-install and post-install tasks.

Called with CurStep=ssInstall just before the actual installation starts, with CurStep=ssPostInstall just after the actual installation finishes, and with CurStep=ssDone just before Setup terminates after a successful install.

procedure CurInstallProgressChanged(CurProgress, MaxProgress: Integer);

You can use this event function to monitor progress while Setup is extracting files, creating shortcuts, creating INI entries, and creating registry entries.

function NextButtonClick(CurPageID: Integer): Boolean;

Called when the user clicks the Next button. If you return True, the wizard will move to the next page; if you return False, it will remain on the current page (specified by CurPageID).

Note that this function is called on silent installs as well, even though there is no Next button that the user can click. Setup instead simulates "clicks" on the Next button. On a silent install, if your NextButtonClick function returns False prior to installation starting, Setup will exit automatically.

function BackButtonClick(CurPageID: Integer): Boolean;

Called when the user clicks the Back button. If you return True, the wizard will move to the previous page; if you return False, it will remain on the current page (specified by CurPageID).

procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);

Called when the user clicks the Cancel button or clicks the window's Close button. The Cancel parameter specifies whether normal cancel processing should occur; it defaults to True. The Confirm parameter specifies whether an "Exit Setup?" message box should be displayed; it usually defaults to True. If Cancel is set to False, then the value of Confirm is ignored.

function ShouldSkipPage(PageID: Integer): Boolean;

The wizard calls this event function to determine whether or not a particular page (specified by PageID) should be shown at all. If you return True, the page will be skipped; if you return False, the page may be shown.

Note: This event function isn't called for the wpPreparing, and wpInstalling pages, nor for pages that Setup has already determined should be skipped (for example, wpSelectComponents in an install containing no components).

procedure CurPageChanged(CurPageID: Integer);

Called after a new wizard page (specified by CurPageID) is shown.

function CheckPassword(Password: String): Boolean;

If Setup finds the CheckPassword event function in the Pascal script, it automatically displays the Password page and calls CheckPassword to check passwords. Return True to accept the password and False to reject it.

To avoid storing the actual password inside the compiled [Code] section which is stored inside Setup, you should use comparisons by hash only: calculate the SHA-256 hash of your salted password yourself and then compare that to GetSHA256OfString(Password). This way the actual value of the password is better protected.

Note: If Setup is run with a /PASSWORD= command line parameter, your CheckPassword function will be called before any other event function is called, including InitializeSetup.

Also note: If Encryption is set to yes and your CheckPassword function accepts passwords different from the one used for the encryption, make sure to only extract non encrypted files.

function NeedRestart(): Boolean;

Return True to instruct Setup to prompt the user to restart the system at the end of a successful installation, False otherwise.

function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;

If Setup finds the UpdateReadyMemo event function in the Pascal script, it is called automatically when the Ready to Install wizard page becomes the active page. It should return the text to be displayed in the settings memo on the Ready to Install wizard page as a single string with lines separated by the NewLine parameter. Parameter Space contains a string with spaces. Setup uses this string to indent settings. The other parameters contain the (possibly empty) strings that Setup would have used as the setting sections. The MemoDirInfo parameter for example contains the string for the Selected Directory section.

procedure RegisterPreviousData(PreviousDataKey: Integer);

To store user settings entered on custom wizard pages, place a RegisterPreviousData event function in the Pascal script and call SetPreviousData(PreviousDataKey, ...) inside it, once per setting.

function CheckSerial(Serial: String): Boolean;

If Setup finds the CheckSerial event function in the Pascal script, a serial number field will automatically appear on the User Info wizard page (which must be enabled using UserInfoPage=yes in your [Setup] section!). Return True to accept the serial number and False to reject it. When using serial numbers, it's important to keep in mind that since no encryption is used and the source code to Inno Setup is freely available, it would not be too difficult for an experienced individual to remove the serial number protection from an installation. Use this only as a convenience to the end user and double check the entered serial number (stored in the {userinfoserial} constant) in your application.

function GetCustomSetupExitCode: Integer;

Return a non zero number to instruct Setup to return a custom exit code. This function is only called if Setup was successfully run to completion and the exit code would have been 0. Also see Setup Exit Codes.

function PrepareToInstall(var NeedsRestart: Boolean): String;

You can use this event function to detect and install missing prerequisites and/or to shutdown any application which is about to be updated.

Return a non empty string to instruct Setup to stop at the Preparing to Install wizard page, showing the returned string as the error message. Set NeedsRestart to True (and return a non empty string) if a restart is needed. If Setup is stopped this way, it will exit with a dedicated exit code as described in Setup Exit Codes. Any custom exit code set by the /RESTARTEXITCODE= command line parameter will not be used in this case.

This function is called before Setup checks for files being in-use if CloseApplications is set to yes.

This function is only called if Setup didn't already determine it can't continue because one or more files specified in the [Files] and [InstallDelete] sections were queued (by some other installation) to be replaced or deleted on the next restart.

procedure RegisterExtraCloseApplicationsResources;

To register extra files which Setup should check for being in-use if CloseApplications is set to yes, place a RegisterExtraCloseApplicationsResources event function in the Pascal script and call RegisterExtraCloseApplicationsResource inside it, once per file.

Uninstall event functions

Uninstall supports following event functions:

function InitializeUninstall(): Boolean;

Return False to abort Uninstall, True otherwise.

procedure InitializeUninstallProgressForm();

Use this event function to make changes to the progress form at startup. You can't use the InitializeUninstall event function for this since at the time it is triggered, the progress form does not yet exist.

procedure DeinitializeUninstall();
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
function UninstallNeedRestart(): Boolean;

Return True to instruct Uninstall to prompt the user to restart the system at the end of a successful uninstallation, False otherwise.

Constants

Here's the list of constants used by these functions:

  • TSetupStep values
    ssInstall, ssPostInstall, ssDone
  • TUninstallStep values
    usAppMutexCheck, usUninstall, usPostUninstall, usDone
  • PageID values for predefined wizard pages
    wpWelcome, wpLicense, wpPassword, wpInfoBefore, wpUserInfo, wpSelectDir, wpSelectComponents, wpSelectProgramGroup, wpSelectTasks, wpReady, wpPreparing, wpInstalling, wpInfoAfter, wpFinished
Event Attributes

Normally a script can contain only one implementation per event function. Using event attributes it is possible to have multiple implementations of the same event function in your script. This is especially useful in included scripts implementing an event function to avoid conflicts with the main script.

Here is an example of a script which contains three implementations of the InitializeWizard event function.

[Code] procedure InitializeWizard; begin Log('InitializeWizard called'); end; <event('InitializeWizard')> procedure InitializeWizard2; begin Log('InitializeWizard2 called'); end; <event('InitializeWizard')> procedure InitializeWizard3; begin Log('InitializeWizard3 called'); end;

The following rules apply:

  • The implementations will be called in order of their definition except that any main implementation (=the implementation without an event attribute) will be called last.
  • Event attributes may be used for all event functions. If the event function has a return value then lazy evaluation is performed:
    • InitializeSetup, BackButtonClick, NextButtonClick, InitializeUninstall: All implementations must return True for the event function to be treated as returning True and an implementation returning False stops the calls to the other implementations.
    • CheckPassword, CheckSerial, ShouldSkipPage, NeedRestart: All implementations must return False for the event function to be treated as returning False and an implementation returning True stops the calls to the other implementations.
    • UpdateReadyMemo, PrepareToInstall: All implementations must return an empty string for the event function to be treated as returning an empty string and an implementation returning a non empty string stops the calls to the other implementations.
    • GetCustomSetupExitCode: All implementations must return zero for the event function to be treated as returning zero and an implementation returning a non zero number stops the calls to the other implementations.
  • Event attributes may only be used on procedures or functions which do not already have the name of an event function.
  • If the event function uses var parameters then the value will be passed on from implementation to implementation.
  • To call an implementation with an event attribute yourself from [Code] you should use the normal name of the function, just as if the implementation had no event attribute.

The Pascal script can contain several functions which are called when Setup wants to know the value of a scripted {code:...} constant. The called function must have 1 String parameter named Param, and must return a String or a Boolean value depending on where the constant is used.

The syntax of a {code:...} constant is: {code:FunctionName|Param}

  • FunctionName specifies the name of the Pascal script function.
  • Param specifies the string parameter to pass to the function. If you omit Param, an empty string will be passed.
  • If you wish to include a comma, vertical bar ("|"), or closing brace ("}") inside the constant, you must escape it via "%-encoding." Replace the character with a "%" character, followed by its two-digit hex code. A comma is "%2c", a vertical bar is "%7c", and a closing brace is "%7d". If you want to include an actual "%" character, use "%25".
  • Param may include constants. Note that you do not need to escape the closing brace of a constant as described above; that is only necessary when the closing brace is used elsewhere.
DefaultDirName={code:MyConst}\My Program

Here is an example of a [Code] section containing the MyConst function used above.

[Code] function MyConst(Param: String): String; begin Result := ExpandConstant('{autopf}'); end;

If the function specified by the {code:...} constant is not included in the [Code] section, it must be a support function. Here is an example.

[INI] FileName: "{app}\MyIni.ini"; Section: "MySettings"; Key: "ShortApp"; String: "{code:GetShortName|{app}}"


See also:
Constants

There is one optional parameter that is supported by all sections whose entries are separated into parameters. This is:

The name of a check function that determines whether an entry has to be processed or not. The function must either be a custom function in the [Code] section or a support function.

Besides a single name, you may also use boolean expressions. See Components and Tasks parameters for examples of boolean expressions.

For each check function, may include a comma separated list of parameters that Setup should pass to the check function. Allowed parameter types are String, Integer and Boolean. String parameters may include constants. These constants will not be automatically expanded. If you want to pass an expanded constant, there's one special support function that may be called from within a parameter list for this: ExpandConstant.

[Files]
Source: "MYPROG.EXE"; DestDir: "{app}"; Check: MyProgCheck
Source: "A\MYFILE.TXT"; DestDir: "{app}"; Check: MyDirCheck(ExpandConstant('{app}\A'))
Source: "B\MYFILE.TXT"; DestDir: "{app}"; Check: DirExists(ExpandConstant('{app}\B'))

All check functions must have a Boolean return value. If a check function (or the boolean expression) returns True, the entry is processed otherwise it's skipped.

For all sections except [Types] and [Components], Setup might call each check function several times, even if there's only one entry that uses the check function. If your function performs a lengthy piece of code, you can optimize it by performing the code only once and 'caching' the result in a global variable.

A check function isn't called if Setup already determined the entry shouldn't be processed.

A check function for a [Files] section entry using a wildcard but not the external flag is called once per file matching the wildcard, instead of once per entry. Use CurrentFileName to check for which file the function is called.

Here is an example of a [Code] section containing the check functions used above. Function DirExists is a support function and therefore not included in this [Code] section.

[Code] var MyProgChecked: Boolean; MyProgCheckResult: Boolean; function MyProgCheck(): Boolean; begin if not MyProgChecked then begin MyProgCheckResult := MsgBox('Do you want to install MyProg.exe to ' + ExtractFilePath(CurrentFileName) + '?', mbConfirmation, MB_YESNO) = idYes; MyProgChecked := True; end; Result := MyProgCheckResult; end; function MyDirCheck(DirName: String): Boolean; begin Result := DirExists(DirName); end;

There are two optional parameters that are supported by all sections whose entries are separated into parameters except for [Languages], [Types], [Components] and [Tasks]. These are:

The name of a function that is to be called once just before an entry is installed. The function must either be a custom function in the [Code] section or a support function.

May include a comma separated list of parameters that Setup should pass to the function. Allowed parameter types are String, Integer and Boolean. String parameters may include constants. These constants will not be automatically expanded. If you want to pass an expanded constant, there's one special support function that may be called from within a parameter list for this: ExpandConstant.

[Files]
Source: "MYPROG.EXE"; DestDir: "{app}"; BeforeInstall: MyBeforeInstall
Source: "A\MYFILE.TXT"; DestDir: "{app}"; BeforeInstall: MyBeforeInstall2('{app}\A\MYFILE.TXT')
Source: "B\MYFILE.TXT"; DestDir: "{app}"; BeforeInstall: MyBeforeInstall2('{app}\B\MYFILE.TXT')
Source: "MYPROG.CHM"; DestDir: "{app}"; BeforeInstall: Log('Before MYPROG.CHM Install')

The name of a function that is to be called once just after an entry is installed. The function must either be a custom function in the [Code] section or a support function.

May include a comma separated list of parameters that Setup should pass to the function. Allowed parameter types are String, Integer and Boolean. String parameters may include constants. These constants will not be automatically expanded. If you want to pass an expanded constant, there's one special support function that may be called from within a parameter list for this: ExpandConstant.

[Files]
Source: "MYPROG.EXE"; DestDir: "{app}"; AfterInstall: MyAfterInstall
Source: "A\MYFILE.TXT"; DestDir: "{app}"; AfterInstall: MyAfterInstall2('{app}\A\MYFILE.TXT')
Source: "B\MYFILE.TXT"; DestDir: "{app}"; AfterInstall: MyAfterInstall2('{app}\B\MYFILE.TXT')
Source: "MYPROG.CHM"; DestDir: "{app}"; AfterInstall: Log('After MYPROG.CHM Install')

All BeforeInstall and AfterInstall functions must not have a return value.

A BeforeInstall or AfterInstall function isn't called if Setup already determined the entry shouldn't be processed.

A BeforeInstall or AfterInstall function for a [Files] section entry using a wildcard but not the external flag is called once per file matching the wildcard, instead of once per entry. Use CurrentFileName to check for which file the function is called.

Here is an example of a [Code] section containing the functions used above. Functions CurrentFileName and Log are support functions and therefore not included in this [Code] section.

[Code] procedure MyBeforeInstall(); begin MsgBox('About to install MyProg.exe as ' + CurrentFileName + '.', mbInformation, MB_OK); end; procedure MyBeforeInstall2(FileName: String); begin MsgBox('About to install ' + FileName + ' as ' + CurrentFileName + '.', mbInformation, MB_OK); end; procedure MyAfterInstall(); begin MsgBox('Just installed MyProg.exe as ' + CurrentFileName + '.', mbInformation, MB_OK); end; procedure MyAfterInstall2(FileName: String); begin MsgBox('Just installed ' + FileName + ' as ' + CurrentFileName + '.', mbInformation, MB_OK); end;

The Pascal script can also contain code invoked at uninstall time. See the Event Functions topic for more information.

There is one thing that's important to be aware of when designing code to be executed at uninstall time: In cases where multiple versions of an application are installed over each other, only one Pascal script is run at uninstall time. Ordinarily, the script from the most recent install will be chosen. If, however, you were to downgrade your version of Inno Setup in a new version of your application, the script from the install built with the most recent Inno Setup version may be chosen instead. A similar situation can occur if a user installs an older version of your application over a newer one.

When producing an installation that is a "patch" for another install, and the patch install shares the same uninstall log as the original install (i.e. Uninstallable is set to yes and AppId is the set the same as the original install), make sure the patch includes a copy of the full [Code] section from the original install. Otherwise, no code would be run at uninstall time.

If, however, the patch install has Uninstallable set to no then Setup will not touch the existing uninstaller EXE or uninstall log; in this case, the patch install need not contain a copy of the [Code] section from the original install.

The Pascal Scripting example scripts are located in separate files. Open one of the Code*.iss, UninstallCode*.iss, or AllPagesExample.iss example scripts in the "Examples" subdirectory in your Inno Setup directory.

The Pascal script allows you to add custom pages to Setup's wizard. This includes "pre-built" wizard pages for common queries and completely custom wizard pages with the controls of your choice.

To use custom wizard pages, first create them inside your InitializeWizard event function. You can either use pre-built pages created by the CreateInput...Page and CreateOutput...Page functions or "empty" pages created by the CreateCustomPage function. See Support Functions topic for a listing and explanation of all Create...Page functions.

After creating each page, you add controls to it, either by calling the special methods of the pre-built pages, or by manually creating controls on the page yourself.

Most of the Create...Page functions take a "page ID" as their first parameter; this identifies the existing page after which the newly created page should be placed. There are several ways to find the "page ID" of an existing page. The pages you create yourself have ID properties which hold their page IDs. Built-in wizard pages have predefined IDs. For example, for the Welcome wizard page this is wpWelcome. See the Support Functions topic for a listing of all predefined IDs.

After the custom wizard pages are created, Setup will show and handle them just as if they were built-in wizard pages. This includes the calling of all page related event functions such as NextButtonClick and ShouldSkipPage.

At any time during Setup you can retrieve the values entered by the user either by using the special properties of the pre-built pages, or by using the properties of the controls you created yourself.

Open the "CodeDlg.iss" script in the "Examples" subdirectory of your Inno Setup directory for an example of how to use pre-built custom wizard pages and event functions. Open the "CodeClasses.iss" script for an example of how to use completely custom wizard pages and controls.

The Pascal script can call functions inside external DLLs. This includes both standard Win32 API functions inside standard Windows DLLs and custom functions in custom made DLLs. Additionally .NET assemblies can be called.

Open the "CodeDll.iss" file in the "Examples" subdirectory in your Inno Setup directory for an example script using DLLs.

The "Examples" subdirectory also contains three custom DLL example projects, one for Microsoft Visual C++, one for Microsoft Visual C# and one for Borland Delphi. The C# example shows how to make your .NET assemblies callable by the Pascal script.

To be able to call a DLL function you should first write the function prototype as normal but instead of then writing the function body, you use the 'external' keyword to specify a DLL. If your function has for example prototype function A(B: Integer): Integer;, the following three forms are supported:

[Code] function A(B: Integer): Integer; external '<dllfunctionname>@<dllfilename>'; function A(B: Integer): Integer; external '<dllfunctionname>@<dllfilename> <callingconvention>'; function A(B: Integer): Integer; external '<dllfunctionname>@<dllfilename> <callingconvention> <options>';

The first form specifies that the DLL function should be called using default calling convention, which is 'stdcall'. All standard Win32 API functions use 'stdcall' just like most custom DLL functions.

The second form specifies that the DLL function should be called using a special calling convention. Valid calling conventions are: 'stdcall' (the default), 'cdecl', 'pascal' and 'register'.

The third form specifies additional one or more options for loading the DLL, separated by spaces:

Specifies that the DLL should be delay loaded. Normally the Pascal script checks at startup whether the DLL function can be called and if not, refuses to run. This does not happen if you specify delay loading using 'delayload'. Use delay loading if you want to call a DLL function for which you don't know whether it will actually be available at runtime: if the DLL function can't be called, the Pascal script will still run but throw an exception when you try to call the DLL function which you can catch to handle the absence of the DLL function.

Specifies that the DLL should be loaded using the Windows flag LOAD_WITH_ALTERED_SEARCH_PATH, which, in essence, causes the loader to search for any dependent DLLs in the directory containing the DLL.

Specifies that the DLL should only be loaded when the script is running from Setup.

Specifies that the DLL should only be loaded when the script is running from Uninstall.

An example (of the second form) if the DLL function has name 'A2' inside the DLL, the DLL has name 'MyDll.dll' and the DLL function uses the 'stdcall' calling convention:

[Code] function A(B: Integer): Integer; external 'A2@MyDll.dll stdcall';

Constants may be used in the DLL filename.

During Setup, a special 'files:' prefix may also be used to instruct Setup to automatically extract one or more DLLs from the [Files] section before loading the first DLL. For example:

[Files] Source: "MyDll.dll"; Flags: dontcopy noencryption Source: "A.dll"; Flags: dontcopy noencryption Source: "B.dll"; Flags: dontcopy noencryption [Code] procedure MyDllFunc(hWnd: Integer; lpText, lpCaption: AnsiString; uType: Cardinal); external 'MyDllFunc@files:MyDll.dll stdcall'; procedure ADllFunc(hWnd: Integer; lpText, lpCaption: AnsiString; uType: Cardinal); external 'ADllFunc@files:A.dll,B.dll stdcall loadwithalteredsearchpath'; //A.dll depends on B.dll

If you use a 'files:' prefix and solid compression is enabled, be sure to list your DLLs at (or near) the top of the [Files] section. In order to extract an arbitrary file in a solid-compressed installation, Setup must first decompress all prior files (to a temporary buffer in memory). This can result in a substantial delay if a number of other files are listed above the specified file in the [Files] section.

Use CreateCallback to be able to perform direct callbacks from DLL functions (like Windows API functions) to functions in your script

The Pascal script can access COM (also known as OLE or ActiveX) methods and properties via the COM Automation objects support. This allows you to access for example standard Windows COM servers, custom COM servers, Visual Basic ActiveX DLLs and .NET assemblies via COM Interop.

IDispatch based COM

There are two support functions to initialize IDispatch based COM Automation objects: CreateOleObject and GetActiveOleObject.

Use CreateOleObject to create a new COM object with the specified class name. This function returns a variable of type Variant if successful and throws an exception otherwise.

Use GetActiveOleObject to connect to an existing COM object with the specified class name. This function returns a variable of type Variant if successful and throws an exception otherwise. In case of some programs, this can be used to detect whether the program is running or not.

The value returned by CreateOleObject or GetActiveOleObject can then be used to access the properties and methods of the COM object. The access is done via 'late binding' which means it is not checked whether the methods or properties you're trying to access actually exist until Setup actually needs to at run time.

To access a property or method whose name is a reserved word, use IDispatchInvoke.

Open the "CodeAutomation.iss" file in the "Examples" subdirectory in your Inno Setup directory for an example script using IDispatch based COM Automation objects.

If you're using a .NET COM object and loading it fails since Inno Setup 5.5.9 try putting this line in your script before creating the COM object: LoadDLL(ExpandConstant('{sys}\mscoree.dll'), ErrorCode); and add a variable ErrorCode of type Integer.

IUnknown based COM

If the IDispatch interface isn't implemented by the object, you can use the IUnknown based COM support.

To initialize IUnknown based COM Automation objects use CreateComObject.

The value returned by CreateComObject can then be used to access the methods of the COM object after casting it to the desired interface. The access is done via 'early binding' which means the desired interface needs to be defined in the script, unlike for IDispatch based COM support.

StringToGUID can be used to convert the string representation of a GUID into a 'real' GUID. Use OleCheck to check the return values of any method you call.

If you copy the interface definition from any existing Delphi source code, remove the brackets around the interface GUID string. Also remove any calling conventions, Inno Setup assumes 'stdcall'. If the interface contains any functions you won't call, you can replace these by dummies to avoid having to define any special types used by them.

Open the "CodeAutomation2.iss" file in the "Examples" subdirectory in your Inno Setup directory for an example script using IUnknown based COM Automation objects.

General

COM objects are released automatically when they go out of scope. There are no functions to 'destroy' or 'free' them.

If you are extracting a COM Automation library to a temporary location and want to be able to delete it after using it, make sure you no longer have any references to the library and then call CoFreeUnusedLibraries. This Windows function will then attempt to unload the library so you can delete it.

The Compiler IDE contains an integrated run-time debugger to debug your custom Pascal script, accessed via the Run menu. This debugger works very much like debuggers in other IDE's and uses the following menu items:

Run To Cursor (F4 or Ctrl+F10*)

Runs or unpauses Setup until it reaches the line of the cursor, then pauses it.

Step Into (F7 or F11)

Runs or unpauses Setup until it reaches the next line, then pauses it. By continually pressing F7 you can follow the entire execution flow of Setup.

Step Over (F8 or F10)

Runs or unpauses Setup until it reaches the next line, then pauses it. Lines inside functions calls are skipped.

Step Out (Shift+F8 or Shift+F11)

Unpauses Setup until it reaches the end of the current function, then pauses it on the next line.

Toggle Breakpoint (F5 or F9)

Next time Setup reaches the line of the cursor, it pauses. There can be multiple breakpoints at once and breakpoints can be removed by pressing F5 or F9 again.

Pause

Next time Setup reaches any line, it pauses.

When Setup is paused variables and constants can be inspected by hovering the mouse over them.

To debug Uninstall instead of Setup first run Setup to completion then choose Target Uninstall (Ctrl+W) and finally use one of the above menu items.

Lines which can be paused on are marked by a gray square in the gutter. The square turns green the first time Setup reaches the line.

Besides lines in the Pascal script, lines in some other sections can also be paused on, again shown by a gray square in the gutter. For example, toggling a breakpoint on a line in the [Files] section will pause Setup when that file is about to be processed. On such lines Step Over and Step Out both act as Step Into.

* = actual shortcut depends on the "Menu keys" option.

See also:
Debugging

See Pascal Scripting: Check Parameters for more information on boolean expressions and see Uninstallable for an example.

This is the list of support functions which test if the system matches an architecture identifier:

IsArm32Compatible
IsArm64
IsWin64
IsX64Compatible
IsX64OS
IsX86Compatible
IsX86OS

IsX64 (alias for IsX64OS; deprecated)
IsX86 (alias for IsX86OS)

See also:
ProcessorArchitecture