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 Source: "A.dll"; Flags: dontcopy Source: "B.dll"; Flags: dontcopy [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.
To automatically choose between the ANSI or Unicode version of a function depending on the installed version of Inno Setup, use ISPP:
[Code] function MessageBox(hWnd: Integer; lpText, lpCaption: String; uType: Cardinal): Integer; #ifdef UNICODE external 'MessageBoxW@user32.dll stdcall'; #else external 'MessageBoxA@user32.dll stdcall'; #endif