📜 ⬆️ ⬇️

Inno Setup: creating an installer using the example of deploying a C # application

Introduction



I am not a professional programmer. In the sense that I do not earn money with this craft, but I use my skills as a tool for basic, scientific, activity. Therefore, all my “crafts” live only for the period set aside for them to solve a specific task and do not go beyond the project catalogs. In addition, for a long time already, I departed from developing for Windows, because Linux is more convenient for solving my problems.

However, scientists also want to eat, decently dress and fill the car. Therefore (although quite rarely) there is a need for a bit of poflelance.
')
Recently, they planted a not too complicated project for me - one company wants to write an analogue of a program that exists in another. A bit of reversing, a bit of coding, in general, the project is quite ordinary. However, the question of creating an installer immediately arose - the client would like to have a “turnkey” product to click on the “setup”, click “Next” and get the program ready for work.

I never created installers. Therefore, this question was thoroughly "zaguglen", among other things, got such an article from Habr. The choice of tools for such a task is quite wide, and includes both proprietary and open source products. Here is a list of what I "felt"

  1. InstallShield - a classic of the genre, quite a solid proprietary product
  2. Adnvanced Installer is a proprietary tool with extensive customization capabilities through the GUI. The site says that if you are a blogger and you will write many good words about this product, then you have the opportunity to get a Free License
  3. WiX is an open source XML-based free product. Powerful, well-documented stuff. I haven’t dealt with it yet, because time is precious (and the soul is not very good for XML). Maybe someday I will return to it. Yes, it has plug-ins for Visual Studio, which is a definite plus.
  4. Inno Setup is an open source project whose code is available on the github . Due to the free and low threshold of entry, my choice was on it, as a tool that allowed me to do the job quickly and efficiently.


So in the article we will look at an example of using Inno Setup, for which there is a useful Inno Script Studio frontend that allows you to create simple installers using a wizard and change settings through the GUI. I needed the GUI for the first acquaintance with the product, but we will not pay much attention to it - my “Linux brain” has more and more taken me away from the desire to use all kinds of “masters” (this is subjective, please do not kick) . We will consider a hardcore way of writing a script from scratch.



1. Installation, configuration and simple (but pretty solid) script



I think that downloading the program from the official site and installing it will not be difficult. Run Inno Setup Compiler and see this window.

Frighteningly sadly meets us Inno Setup ...


What is it? In fact, it is simply an editor for a set of scripts, equipped with syntax highlighting and compile and launch buttons. We are expected to start typing the script text in this window that defines the logic of the future installer. Well, let's not waste time.

First of all, we define the necessary constants.
;------------------------------------------------------------------------------ ; ;     Inno Setup 5.5.5 ; (c) maisvendoo, 15.04.2015 ; ;------------------------------------------------------------------------------ ;------------------------------------------------------------------------------ ;    ;------------------------------------------------------------------------------ ;   #define Name "Miramishi Painter" ;   #define Version "0.0.1" ; - #define Publisher "Miramishi" ;    #define URL "http://www.miramishi.com" ;    #define ExeName "Miramishi.exe" 


These lines will often be found in script code, so we define them, as in C, using the directive #define

The script body is divided into sections, each of which carries its own functional purpose. Mandatory [Setup] section sets global parameters of the installer and uninstaller.

 ;------------------------------------------------------------------------------ ;   ;------------------------------------------------------------------------------ [Setup] ;   , ;  Tools -> Generate GUID AppId={{F3E2EDB6-78E8-4539-9C8B-A78F059D8647} ;  ,    AppName={#Name} AppVersion={#Version} AppPublisher={#Publisher} AppPublisherURL={#URL} AppSupportURL={#URL} AppUpdatesURL={#URL} ;   - DefaultDirName={pf}\{#Name} ;     "" DefaultGroupName={#Name} ; ,     setup     OutputDir=E:\work\test-setup OutputBaseFileName=test-setup ;   SetupIconFile=E:\work\Mirami\Mirami\icon.ico ;   Compression=lzma SolidCompression=yes 


We pay close attention to the AddId option - a unique application identifier (GUID) used to register the application in the Windows registry. We write it not “from the lantern”, but we generate it by opening the curly bracket, and choosing Tools -> Generate GUID from the menu (or using the hot key Shift + Ctrl + G). Next, we indicate the name of the application under which it will be installed in the system, its version, data of the developer’s company, addresses of the developer’s sites, technical support and updates.

The default path offered by the installer for installation is determined by the DefaultDirName option. The {pf} variable is the path to the Program Files directory of the corresponding bitness. The DefaultGroupName option defines the program group name in the Start menu. Please note that to indicate the name of the application, we use the macro we defined above, framing it with curly braces and a grid.

A pair of options OutputDir and OutputBaseFileName specify the directory where the compiled setup will be written and its name (without extension). In addition, we specify where to get the icon for test-setup.exe with the SetupIconFile option.

The last options in this section define the compression algorithm (LZMA) and indicate that all files are compressed simultaneously and not separately ( SolidCompression ), which speeds up the unpacking process with a large number of files of the same type.

A good installer should support multiple languages. We include it in our "setup" using the optional [Languages] section. In the absence of this section, English will be used.

 ;------------------------------------------------------------------------------ ;      ;------------------------------------------------------------------------------ [Languages] Name: "english"; MessagesFile: "compiler:Default.isl"; LicenseFile: "License_ENG.txt" Name: "russian"; MessagesFile: "compiler:Languages\Russian.isl"; LicenseFile: "License_RUS.txt" 


Each line in this section defines one of the languages ​​used during the installation. The syntax of the line is

 < >: < > 


A semicolon is used as a parameter separator. The Name parameter speaks for itself - the “name” of the language, common two-letter abbreviations are allowed (“en”, “ru”, “de”, and so on). The MessagesFile parameter tells the compiler where to get the template of messages displayed during installation. These templates are taken in the Inno Setup compiler directory, which we inform about by the compiler directive. The Default.isl template is suitable for English, for Languages ​​\ Russian.isl for Russian.

The LicenseFile parameter specifies the path to the file with the license text in the corresponding language.

Usually the installer offers us, for example, to determine whether we want or do not want to create a shortcut on the desktop. Such installation options are determined by the optional [Tasks] section .

 ;------------------------------------------------------------------------------ ;  -  ,      ;------------------------------------------------------------------------------ [Tasks] ;      Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked 


Here Name sets the name of the operation - “desktopicom” - creating an icon on the desktop; Description - a checkbox description with an option that the user will see. Design

 {cm:< >} 


sets the standard message text corresponding to the language selected at the beginning of the installation. The GroupDescription parameter is a checkbox group header with options. The Flags parameter specifies certain actions and states of the controls, in this case indicating that the checkbox “create a shortcut on the desktop” should be unchecked.

To make it clear - this is the result.



Now we will indicate which files should be included in the distribution and where they should be placed during installation. To do this, use the mandatory section [Files]

 ;------------------------------------------------------------------------------ ; ,       ;------------------------------------------------------------------------------ [Files] ;   Source: "E:\work\Mirami\Mirami\bin\Release\Miramishi.exe"; DestDir: "{app}"; Flags: ignoreversion ;   Source: "E:\work\Mirami\Mirami\bin\Release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs 


Here



Finally, so that everything is beautiful, we will optionally tell the compiler where to get icons for placement in the program menu and on the desktop

 ;------------------------------------------------------------------------------ ;  ,      ;------------------------------------------------------------------------------ [Icons] Name: "{group}\{#Name}"; Filename: "{app}\{#ExeName}" Name: "{commondesktop}\{#Name}"; Filename: "{app}\{#ExeName}"; Tasks: desktopicon 


Here I indicate that for the group in the Start menu and for the desktop, the icon must be taken from the executable module. Naturally, the icon should be “compiled” into it, otherwise in the required places we will see a standard icon from the Windows collection.

So, everything seems to be ready. Hit Ctrl + F9 and try to build the installer. If syntax errors are not made, the build process will begin.

Inno Setup builds installer


After successful assembly, the installer can be started by pressing F9. If you are working under the account with limited rights (and I work in Windows that way), then you will have to go into the directory with the results of the compilation that we specified in the script, and run the installer with admin rights

Running the installer under a limited account


As a result, we will see a language selection window that is painfully familiar to every Windows user.

greeting master

license agreement


and so on. It's nice that the laconic design of the wizard is used by default, without ryushechek (which you can add if you wish)

What can I say? Hooray! We wrote our first "setup" and we could be happy, but

2. Deploying the .NET Framework



You did not notice that we have forgotten about something? An application created in C # will not work without the framework with which it was built, if it does not exist in the system. The corresponding framework must be installed, and for this you need

  1. To decide on how we will get the distribution kit of the framework. There are two options - to ship it along with the distribution package of the program or, if necessary, to install it, download it online to the target machine. We will focus on the option to include the framework in the distribution. The framework itself, say version 4.0, can be taken free of charge from Microsoft
  2. Detect the presence / absence of the given framework in the target system. To do this, you will need to write logic that analyzes the state of the registry.


The values ​​in the registry that need to be checked are listed in the official Microsoft documentation . In the article I will give a brief squeeze out of it.

Table 1 . Registry keys to check the installed version of the .NET Framework
.NET versionRegistry keyValue
3.0HKLM \ Software \ Microsoft \ NET Framework Setup \ NDP \ v3.0 \ Setup \ InstallSuccessone
3.5HKLM \ Software \ Microsoft \ NET Framework Setup \ NDP \ v3.0 \ Setup \ Installone
4.0 Client ProfileHKLM \ Software \ Microsoft \ NET Framework Setup \ NDP \ v4.0 \ Client \ Installone
4.0 Full ProfileHKLM \ Software \ Microsoft \ NET Framework Setup \ NDP \ v4.0 \ Full \ Installone
4.5HKLM \ Software \ Microsoft \ NET Framework Setup \ NDP \ v4.0 \ Full \ Releaserelease number


To implement arbitrary installer logic, Inno Setup provides the [Code] section. Within this section is placed the code implementing the logic of functions in the Pascal language. We will move this section into a separate dotnet.pas file and include the #include directive in the main script.

 ;------------------------------------------------------------------------------ ;       ;------------------------------------------------------------------------------ [Code] #include "dotnet.pas" 


although you can type the code directly in the [Code] section. It must be remembered that the Pascal syntax is used inside this section, and comments are preceded by the sequence "//" instead of the semicolon used in the main part of the script.

Let's write a function that determines whether the system has the correct version of .NET

 //----------------------------------------------------------------------------- //     //----------------------------------------------------------------------------- function IsDotNetDetected(version: string; release: cardinal): boolean; var reg_key: string; //     success: boolean; //     .NET release45: cardinal; //     4.5.x key_value: cardinal; //      sub_key: string; begin success := false; reg_key := 'SOFTWARE\Microsoft\NET Framework Setup\NDP\'; //  3.0 if Pos('v3.0', version) = 1 then begin sub_key := 'v3.0'; reg_key := reg_key + sub_key; success := RegQueryDWordValue(HKLM, reg_key, 'InstallSuccess', key_value); success := success and (key_value = 1); end; //  3.5 if Pos('v3.5', version) = 1 then begin sub_key := 'v3.5'; reg_key := reg_key + sub_key; success := RegQueryDWordValue(HKLM, reg_key, 'Install', key_value); success := success and (key_value = 1); end; //  4.0   if Pos('v4.0 Client Profile', version) = 1 then begin sub_key := 'v4\Client'; reg_key := reg_key + sub_key; success := RegQueryDWordValue(HKLM, reg_key, 'Install', key_value); success := success and (key_value = 1); end; //  4.0   if Pos('v4.0 Full Profile', version) = 1 then begin sub_key := 'v4\Full'; reg_key := reg_key + sub_key; success := RegQueryDWordValue(HKLM, reg_key, 'Install', key_value); success := success and (key_value = 1); end; //  4.5 if Pos('v4.5', version) = 1 then begin sub_key := 'v4\Full'; reg_key := reg_key + sub_key; success := RegQueryDWordValue(HKLM, reg_key, 'Release', release45); success := success and (release45 >= release); end; result := success; end; 


Despite the abundance of code, the logic of its operation is quite simple - depending on the value of the version parameter, the RegQueryDWordValue (...) function reads the value of the corresponding registry key and compares it with the required value (see table 1). For version 4.5, we also give the release number in the release parameter.

For the application that we are going to deploy, we need a well-defined version of .NET, so we will write a wrapper function to define it in the target system.

 //----------------------------------------------------------------------------- // -       //----------------------------------------------------------------------------- function IsRequiredDotNetDetected(): boolean; begin result := IsDotNetDetected('v4.0 Full Profile', 0); end; 


To start the installation, check the availability of the framework and inform the user about the actions taken using the Callback-function InitializeSetup ()

 //----------------------------------------------------------------------------- // Callback-,     //----------------------------------------------------------------------------- function InitializeSetup(): boolean; begin //     .NET    ,   //       if not IsDotNetDetected('v4.0 Full Profile', 0) then begin MsgBox('{#Name} requires Microsoft .NET Framework 4.0 Full Profile.'#13#13 'The installer will attempt to install it', mbInformation, MB_OK); end; result := true; end; 


Now in the [Files] section we will add an entry about where the compiler should take the .NET distribution kit, where the installer should unpack it, and under what conditions it should be unpacked

 ; .NET Framework 4.0 Source: "E:\install\dotNetFx40_Full_x86_x64.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall; Check: not IsRequiredDotNetDetected 


In the flags, we say that you need to remove the .NET distribution after installation (deleteafterinstall). The condition under which the unpacking is required is set with the Check option, where we call the IsRequiredDotNetDetected () function, unpacking the spruce, it returns false.

You can start the installation of the framework itself after installing the main program, therefore we include the [Run] section in the script, which indicates what needs to be started after the installation is completed

 ;------------------------------------------------------------------------------ ;       ;------------------------------------------------------------------------------ [Code] #include "dotnet.pas" [Run] ;------------------------------------------------------------------------------ ;     ;------------------------------------------------------------------------------ Filename: {tmp}\dotNetFx40_Full_x86_x64.exe; Parameters: "/q:a /c:""install /l /q"""; Check: not IsRequiredDotNetDetected; StatusMsg: Microsoft Framework 4.0 is installed. Please wait... 


Notice that we first specify the name of the [Run] section to close the [Code] section, and then we write a comment starting with a semicolon. This is necessary because of the difference in the syntax of the main script and the [Code] section; otherwise, we will get a syntax error during compilation.

In the section, the path to the installer of the framework is set - we have previously unpacked it into a temporary directory (the {tmp} variable contains the path to the temporal directory); set command line options. The Check option defines the condition for launching an installation — this is the absence of the necessary framework in the target system. The StatusMsg option defines the message that the user will see in the installer window.

Compile our project again. Now, when running on a “clean” Windows, the installer will display a message

We are told that the .NET Framework 4.0 is required and will be installed for us.


When unpacking, we note that it additionally unpacks the .NET distribution in a temporary folder.



and then the process switches to the .NET installation

Microsoft asks us to accept the license ...


Installing .NET


After that we get a workable C # application installed “for an adult”

Conclusion



I am not a professional and in many things I could be wrong. Please treat this with understanding. The article was written by a noob for noobs, its main goal is to set the search vector when solving the problem of writing an installer. For other questions, consult the documentation that came with Inno Setup.

The code for this example is available in my repository on Github. The "krakozyabry" in the comments are caused by the mismatch of the Cyrillic encodings. For myself, I always write English comments, but for a better understanding of the code I made this blunder. When downloading in Windows, everything looks fine, so I ask you to forgive me and this absurdity.

As for the rest, I think the hautushka came out decent and thank you for your attention to me.

Source: https://habr.com/ru/post/255807/


All Articles