The Pascal scripting feature (modern Delphi-like Pascal) adds lots of new possibilities to customize your Setup or Uninstall at run-time. Some examples:
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
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
The Pascal script can contain several event functions which are called at appropriate times.
Setup supports following event functions:
Called during Setup's initialization. Return False to abort Setup, True otherwise.
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.
Called just before Setup terminates. Note that this function is called even if the user exits Setup before anything is installed.
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.
You can use this event function to monitor progress while Setup is extracting files, creating shortcuts, creating INI entries, and creating registry entries.
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.
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).
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.
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).
Called after a new wizard page (specified by CurPageID) is shown.
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
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.
Return True to instruct Setup to prompt the user to restart the system at the end of a successful installation, False otherwise.
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.
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.
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.
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.
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.
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 supports following event functions:
Return False to abort Uninstall, True otherwise.
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.
Return True to instruct Uninstall to prompt the user to restart the system at the end of a successful uninstallation, False otherwise.
Here's the list of constants used by these functions:
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.
The following rules apply:
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}
DefaultDirName={code:MyConst}\My Program
Here is an example of a [Code] section containing the MyConst function used above.
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.
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.
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.
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:
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:
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:
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.
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.
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.
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:
Runs or unpauses Setup until it reaches the line of the cursor, then pauses it.
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.
Runs or unpauses Setup until it reaches the next line, then pauses it. Lines inside functions calls are skipped.
Unpauses Setup until it reaches the end of the current function, then pauses it on the next line.
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.
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