Tuesday, September 11, 2012

Serial Key based installer


In the previous post we discussed about deploying an application on a client system with the help of installers. We have explored the inno setup compiler for the same in brief. Now let us make a serial key based installer( ie the installation is completed only when you provide a valid serial key) using innosetup compiler.

For this you will have to generate the script as mentioned in detail in previous post and before running the script (generated by inno setup) you will have to edit the code. That is when it asks do you want to compile the new script now ? select no as image below shows 



Now you can edit the script which is similar to pascal but a dedicated inno setup script.


There are two ways to make the installer ask for serial key

1. Under the [Setup] tag add UserInfoPage=yes and also write the event function CheckSerial  after the [code] tag. You can write the code for checking serial key within this function. Only these two things have to be added extra. Documentation of this function can be read here. For instance here i am checking whether the key is a 9 digit even number.



function CheckSerial (Serial: String): Boolean;
var

  CanContinue: Boolean;
  New_New:Longint;
   
begin
CanContinue:=False;
New_New:=1;
 New_New:=StrToIntDef(Serial,New_New);

  if(New_New mod 2 = 0) and (Length(Serial)=9) then  //simple check if the value 
                                                    //is a 9 digit even number
begin CanContinue:= True ;  end
else begin  CanContinue:=False; end;

WizardForm.NextButton.Enabled := CanContinue;  
Result:=CanContinue;


end;

2. You can create a new page for serial key validation which requires a few more steps.
Documentation on creating Custom Wizard Pages can be read here and here. A detailed description of the code is given side by side


[code]

//declaring global variables
var
  EditFields: array of TEdit;             //declaring an array of editfields to hold your serial key.
  PageToDisplaySerialKey: TWizardPage;    //declaring a custom wizard page  

//declaring constants that is used throughout the code
const
  
  NO_OF_FIELDS = 1;     //no of editfields you require . Here only 1 editfield is shown
  CHAR_PER_FIELD = 9;   // no.of characters per field

 //procedure that constantly checks for changes in editfields
procedure EditChange(From: TObject);
//declare variables used in this procedure
var
  I: Integer;
  CanContinue: Boolean;
  x:String;
  Can:Boolean;
  New_New:Longint;

begin
//initialize all variables
  CanContinue := False;
  Can:=False;
  x:='';
  New_New:=1;
  x:= EditFields[0].Text; //get the value in the editfield.. here only 1 edit field so index 0 
  New_New:=StrToIntDef(x,New_New); // in this installer i allow only numbers as key, so converting string to integer

   //in a for loop check whether 9 characters(CHAR_PER_FIELD) have been entered
  for I := 0 to GetArrayLength(EditFields) - 1 do
    if Length(EditFields[I].Text) < CHAR_PER_FIELD then
    begin
      CanContinue := False;
      Break;
    end
    else begin CanContinue := True; end;
    // if all characters are entered then validate the key. Here i am using a simple logic.. check whether the entered 99 didgit number
    //is even or not. If it is even proceed else disable the next button        
  if(Length(x)=(NO_OF_FIELDS *CHAR_PER_FIELD)) and CanContinue then 
    begin 
      if New_New mod 2 = 0 Then  
         begin Can:= True ;  end; 
    end;
  WizardForm.NextButton.Enabled := Can;
end;
    //designing the custom page
procedure SerialKeyPage;
var
  I: Integer;
  EditField: TEdit;
  Labels: TLabel;
  Width: Integer;
begin
  PageToDisplaySerialKey := CreateCustomPage(wpWelcome, 'Serial Key validation','');//where  wpWelcome is the predefined id for Welcome page
                                                                                    //http://www.jrsoftware.org/ishelp/index.php?topic=scriptpages

  Labels := TLabel.Create(PageToDisplaySerialKey);
  Labels.Parent := PageToDisplaySerialKey.Surface;
  Labels.Caption := 'Provide a valid serial number and continue with the installation process';  //caption that appears on the page
  SetArrayLength(EditFields, NO_OF_FIELDS);
  Width := (PageToDisplaySerialKey.SurfaceWidth - ((NO_OF_FIELDS - 1)*5)) div NO_OF_FIELDS; //not necessary now since we have only 1 field
                                                                                            
        // a loop isn't necessary as now we have only 1 field but else useful
  
    EditField := TEdit.Create(PageToDisplaySerialKey);
    EditField.Top := 110;   //space on top of the editfield
    EditField.Width := Width;
    EditField.OnChange := @EditChange; //execute the  EditChange procedure everytime the text changes
    EditField.MaxLength := CHAR_PER_FIELD;//allows only this much characters 
    EditField.Parent := PageToDisplaySerialKey.Surface;
    EditFields[0] := EditField;
 
end;

procedure CurPageChanged(PageID: Integer);
begin
//if the current page is the custom page diable next button initially and enable only when key is correct
  if PageID = PageToDisplaySerialKey.ID then
    WizardForm.NextButton.Enabled := False;  
end;

procedure InitializeWizard;
begin
//shows the serial key page after the welcome page
  SerialKeyPage;
  end;


Once you finish editing the script  compile the code as shown in these   figures and save this script for later verification.



This is the welcome screen that appears first when you compile the code















         
FIGURE 1                                                                                                                                FIGURE 2

FIGURE 1 is the screen that appears if you made use of the first approach and FIGURE 2 is the result of second approach.

Software License for InnosetUp