Note: I’m not maintaining IssProc project anymore, all projects copyrights and feature updates will be released from now here
This is a small article describing how to enable IssProc to be multi-language aware by expanding and using the {language} constant with InnoSetup Pascal scripting.
Before we start you should know that some pascal scripting knowledge is required to fully understand and modify (if required) the iss script snippet (see below links if you’re new with Inno).
Intro
The power of Inno Setup (the best free installer for Windows programs) lies in the integrated Pascal scripting engine giving the setup developers control over all the setup actions. Because you can use Pascal code in your setup script you will not be limited to the setup build-in actions, you can take control over the entirely setup and write your own code. If you’re not to familiar with Pascal scripting you can build your own extensions (dll – Dynamic-link library ) and use them when/if needed, hence you’ll have no limits.
IssProc and multilingual installations
In version 1.0.1, of IssProc extension, support for multi-language has been added. This enables setup authors to display the File-In-Use Window with text informations in any language or even the one selected by user at startup, if the setup was build with multi-language support. To make that work all you need to do is expand the {language} constant and use it with IssFindModule function from IssProc extension. That’s easy, right? Oh, yeah I almost forgot, you will need to add your language translation in the IssProcLanguage.ini file and add this file to the setup. Adding an extra language to IssProcLanguage.ini file it’s easy: just copy & paste the english section (english section for install it’s named [en] and for uninstall it’s [enu] ), translate them in your language and rename the sections according to your language name (first two characters of the language name, or any other name as long as you pass that section name on IssFindModule language parameter ). For example if you need french translation you should have one section called [fr], used on install with info texts in french, and one called [fru], used on unistall.
Let’s code
- Part 1: The standard iss script sections, app info, files, icons, languages etc.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | ; Script generated by the Inno Setup Script Wizard. ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! [Setup] AppName=My Program AppVerName=My Program 1.5 AppPublisher=My Company, Inc. AppPublisherURL=http://www.example.com/ AppSupportURL=http://www.example.com/ AppUpdatesURL=http://www.example.com/ DefaultDirName={pf}\My Program DefaultGroupName=My Program OutputBaseFilename=setup Compression=lzma SolidCompression=yes [Languages] Name: english; MessagesFile: compiler:Default.isl Name: basque; MessagesFile: compiler:Languages\Basque.isl Name: brazilianportuguese; MessagesFile: compiler:Languages\BrazilianPortuguese.isl Name: catalan; MessagesFile: compiler:Languages\Catalan.isl Name: czech; MessagesFile: compiler:Languages\Czech.isl Name: danish; MessagesFile: compiler:Languages\Danish.isl Name: dutch; MessagesFile: compiler:Languages\Dutch.isl Name: finnish; MessagesFile: compiler:Languages\Finnish.isl Name: french; MessagesFile: compiler:Languages\French.isl Name: german; MessagesFile: compiler:Languages\German.isl Name: hebrew; MessagesFile: compiler:Languages\Hebrew.isl Name: hungarian; MessagesFile: compiler:Languages\Hungarian.isl Name: italian; MessagesFile: compiler:Languages\Italian.isl Name: norwegian; MessagesFile: compiler:Languages\Norwegian.isl Name: polish; MessagesFile: compiler:Languages\Polish.isl Name: portuguese; MessagesFile: compiler:Languages\Portuguese.isl Name: russian; MessagesFile: compiler:Languages\Russian.isl Name: slovak; MessagesFile: compiler:Languages\Slovak.isl Name: slovenian; MessagesFile: compiler:Languages\Slovenian.isl Name: spanish; MessagesFile: compiler:Languages\Spanish.isl [Tasks] Name: desktopicon; Description: {cm:CreateDesktopIcon}; GroupDescription: {cm:AdditionalIcons}; Flags: unchecked [Files] Source: C:\Program Files\Inno Setup 5\Examples\MyProg.exe; DestDir: {app}; Flags: ignoreversion ; NOTE: Do not use "Flags: ignoreversion" on any shared system files ;------ add Files In Use Extension Source: IssProc.dll; DestDir: {tmp}; Flags: dontcopy ;------ add Files In Use Extension extra language file (you don t need to add this file if you are using english only) Source: IssProcLanguage.ini; DestDir: {tmp}; Flags: dontcopy ;------ Copy IssProc.dll in your app folder if you want to use it on unistall Source: IssProc.dll; DestDir: {app} Source: IssProcLanguage.ini; DestDir: {app} ;------ [Icons] Name: {group}\My Program; Filename: {app}\MyProg.exe Name: {commondesktop}\My Program; Filename: {app}\MyProg.exe; Tasks: desktopicon [Run] Filename: {app}\MyProg.exe; Description: {cm:LaunchProgram,My Program}; Flags: nowait postinstall skipifsilent |
- Part 2: The Code section (Inno Pascal scripting)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | [Code] // IssFindModule called on install function IssFindModule(hWnd: Integer; Modulename: PChar; Language: PChar; Silent: Boolean; CanIgnore: Boolean ): Integer; external '[email protected]:IssProc.dll stdcall setuponly'; // IssFindModule called on uninstall function IssFindModuleU(hWnd: Integer; Modulename: PChar; Language: PChar; Silent: Boolean; CanIgnore: Boolean ): Integer; external '[email protected]{app}\IssProc.dll stdcall uninstallonly'; //******************************************************************************************************************************************** // IssFindModule function returns: 0 if no module found; 1 if cancel pressed; 2 if ignore pressed; -1 if an error occured // // hWnd = main wizard window handle. // // Modulename = module name(s) to check. You can use a full path to a DLL/EXE/OCX or wildcard file name/path. Separate multiple modules with semicolon. // Example1 : Modulename='*mymodule.dll'; - will search in any path for mymodule.dll // Example2 : Modulename=ExpandConstant('{app}\mymodule.dll'); - will search for mymodule.dll only in {app} folder (the application directory) // Example3 : Modulename=ExpandConstant('{app}\mymodule.dll;*myApp.exe'); - just like Example2 + search for myApp.exe regardless of his path. // // Language = files in use language dialog. Set this value to empty '' and default english will be used // ( see and include IssProcLanguage.ini if you need custom text or other language) // // Silent = silent mode : set this var to true if you don't want to display the files in use dialog. // When Silent is true IssFindModule will return 1 if it founds the Modulename or 0 if nothing found // // CanIgnore = set this var to false to Disable the Ignore button forcing the user to close those applications before continuing // set this var to true to Enable the Ignore button allowing the user to continue without closing those applications //****************************************************************************************************************************************** function NextButtonClick(CurPage: Integer): Boolean; var hWnd: Integer; sModuleName: String; sCurLanguage: String; nCode: Integer; {IssFindModule returns: 0 if no module found; 1 if cancel pressed; 2 if ignore pressed; -1 if an error occured } begin Result := true; if CurPage = wpReady then begin Result := false; sCurLanguage:=Copy(ExpandConstant('{language}'),0,2); { extract first 2 characters from current setup language name } ExtractTemporaryFile('IssProcLanguage.ini'); { extract extra language file - you don't need to add this line if you are using english only } hWnd := StrToInt(ExpandConstant('{wizardhwnd}')); { get main wizard handle } sModuleName :=ExpandConstant('*ker*'); { searched modules. Tip: separate multiple modules with semicolon Ex: '*mymodule.dll;*mymodule2.dll;*mymodule3.dll'} nCode:=IssFindModule(hWnd,sModuleName,sCurLanguage,false,true); { search for module and display files-in-use window if found } if nCode=1 then begin { cancel pressed or files-in-use window closed } PostMessage (WizardForm.Handle, $0010, 0, 0); { quit setup, $0010=WM_CLOSE } end else if (nCode=0) or (nCode=2) then begin { no module found or ignored pressed} Result := true; { continue setup } end; end; end; function InitializeUninstall(): Boolean; var sModuleName: String; sCurLanguage: String; nCode: Integer; {IssFindModule returns: 0 if no module found; 1 if cancel pressed; 2 if ignore pressed; -1 if an error occured } begin Result := false; sCurLanguage:=Copy(ExpandConstant('{language}'),0,2)+'u'; { extract first 2 characters from current setup language name and add 'u' for uninstall} sModuleName := ExpandConstant('*ker*;'); { searched module. Tip: separate multiple modules with semicolon Ex: '*mymodule.dll;*mymodule2.dll;*myapp.exe'} nCode:=IssFindModuleU(0,sModuleName,sCurLanguage,false,false); { search for module and display files-in-use window if found } if (nCode=0) or (nCode=2) then begin { no module found or ignored pressed} Result := true; { continue setup } end; // Unload the extension, otherwise it will not be deleted by the uninstaller UnloadDLL(ExpandConstant('{app}\IssProc.dll')); end; |
Final words
The only code changes are made before using the IssFindModule function (on Part 2 line 38,for install and on line 59, for uninstall). We just extract the first characters from the expanded constant {language}, which contains the selected user language name, and use it with IssFindModule function in order to use/load the right language section from IssProcLanguage.ini file, easy right?
Resources
- Inno Setup Frequently Asked Questions
- Files-In-Use Extension for Inno Setup (IssProc)
- Inno Setup Extensions Knowledge Base (ISXKB)
- Learn Pascal tutorial
Hi, and if I need to internationalize in code? How can I do this?
For example, I have a new form install writed in script. I need to internationalize this form. How can I acess the .isl to use that variable names?
A better way is to use the ISO code for the name of the Language, and use the full content of the language constant (because the first 2 letters of a language are not always the iso code)
I’m glad you like it.
Thanks for your feedback.
what a nice way to teach… really liked it..