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

Wednesday, February 22, 2012

Running a desktop java application on a system which doesn't have java installed

This is an extension of my previous post where we checked how to run a desktop java application on a system where java is installed. This post discusses on how to bundle jre along with your installer so that you don't need to have java installed on client machine..

Consider that all your files required for application are saved in the following folder heirarchy.
NewFolder(any folder where in my case my folder is in C:\Users\Aparna\NewFolder)


NewFolder
           ->bin
                  ->DB
                        ->db_data(embedded db)
                  ->DeskApp.jar
                  ->Tulips.ico
           ->jre (just copy paste your jre from jdk folder which includes the bin and lib folders)


                                                                  

Note that don't enter path but the name of the file holding jre bin and lib here its jre itself.
Now you have 

NewFolder
           ->bin
                  ->DB
                        ->db_data(embedded db)
                  ->DeskApp.jar
                  ->Tulips.ico
           ->jre
           ->win.exe
           ->cfg




Now as we did in previous post use inno setup compiler for setting up installer , only thing you have to keep in mind is copy the jre into another folder within Newfolder like below.

NewFolder
           ->bin
                  ->DB
                        ->db_data(embedded db)
                  ->DeskApp.jar
                  ->Tulips.ico
           ->installer_jre
                  ->jre
           ->win.exe
           ->cfg
This folder heirarchy must be kept because it is necessary for avoiding any path issues. You can see it yourself once you finish installation and view the folders in the installed file.

Add this installer_jre file as a directory in inno setup wizard along with adding DB directory. This will do







Please try and let me know if it was helpful .Thank you have a great day!

Software License for Launch4j
Software License for InnosetUp

Thursday, February 16, 2012

Packaging and Deploying a Desktop Java Application which uses embedded derby database

We have already discussed about creating an embedded derby database .For those who are here for the first time check this  first so that it might be easier.  So before coming to packaging first we will create a desktop application in java with netbeans as an example for checking the packaging issues. 

First we need an embedded db for creating this application .I am not elaborating as we have discussed it in my previous post in detail. It is necessary to have at-least 1 column set as primary key.For example create a database named db_data with 1 table named as table1 with 2 columns col1 and col2. Let col1 be set to primary key. After all this insert 2 rows into it and disconnect the db . If you already have an embedded db create a skelton of it in netbeans and with that create the desktop application. Later while including the db include your desired db file along with exe file.

Creating the sample desktop application

From  File->New Project->under Java->choose Java Desktop Application.
Click next and give a project name for instance 'DeskApp' is our project.
Under Choose application shell  choose database application and click next.
Select the database url you just created and under cloumns to include choose all columns(we have only 2 columns now you can change it according to your need), click next and finish.

Now you have your DeskApp in the projects window. 
Right click on DeskApp and select Clean and build.  After this choose Files where you will see the files and libraries included in your application.  There is a dist folder which contains your jar and lib files .This is created while you build your project.

Normally the jar file is only necessary to launch an application.  But here we have dependent lib folder and the database file which should be included so first we package the lib into the jar folder created so that we  have a single jar and the database file.  For this, you will see a build.xml file under your project .  In this xml  code, just before closing </project> paste the code in the below site.
For reading about this further check this site.

(change the line in the above code to name of your project <property name="store.jar.name" value="DeskApp"/> now that it is DeskApp)

Save your project and right click build.xml->RunTarget->OtherTarget->package for storage as seen in the screen shot in here

project files

Now if you check folders under your project you will find a new store directory where your final jar is stored.  This jar contains both lib and you jar file in a single jar file
This is what we need for packaging.





        Creating an exe file for your jar file

Download and install any converter that does this. I used  Launch4j  for this purpose which is an open source software. Once you have downloaded and installed launch4j start it on your PC. Before beginning, create a NewFolder and copy your jar file (in the store folder of your project) and your db_data file (after disconnecting from netbeans move to the folder containing your embedded db file and copy this file to newly created folder under another folder say DB) into it. If you like to have an icon, add any icon file(.ico format). You can convert it here.
Now you have
     NewFolder
            ->  DeskApp.jar
            ->  DB
Building wrapper
                   ->db_data
            ->Tulips.ico

Once you start your launch4j , under the Basic tab, browse for output file and save it for instance win.exe.(eg ..\NewFolder\win.exe)
 Browse for the jar file you copied just now(DeskApp.jar under NewFolder) in *jar. In the icon field browse and choose your icon. You can leave all other fields empty .
Now jump to the jre tab and fill the minimum jre version say 1.4.0(as you want it to be) and select the Build Wrapper tool on top .
Testing wrapper

Once you select this give a name say config for the file to be saved. When your log says succesfully created the file select the Test wrapper next to Build Wrapper .Now you have your exe file in the folder you selected

       NewFolder
                 ->  DeskApp.jar
                 ->  DB
                          ->db_data
                  ->Tulips.ico
                  ->win.exe
                                                                 ->config                                                                                        

Creating an installer for your application 

There might be easier and efficient ways of doing this but right now I used the Inno setup compiler .I think its simpler for beginners.

Once you have this installed in your system start it. First you will find a welcome window under that choose only Create a new script file using the script wizard and then click OK





The Inno set up Script wizard appears on this.
Click next and fill the details of your application your company profile etc where only name of your application and its version is necessary.

On next page specify where you want your application to be installed (normally it will be in program files) you can also give a folder name for your application (which is recommended) and check allow user to change folder.
Next you have to choose the exe file you created just now using launch4j.
Below that you will see Add folder .Browse and add the main DB folder .Select yes for should subfolders be included?






In application documentation you can include text files for license etc(not mandatory).
Choose your language and click next .
There you can choose a folder where you want your set up file to reside under Custom compiler output folder and the icon file used for exe file(you can have another image).
Finish the wizard.






Choose yes when it asks would you like to compile the new script now ? and save the script before compiling .This can be useful later if you have to change the script.


After the compilation is done you can check the setup folder. Double click the file and you can see your installer running.After all installation is done you will see the desktop icon of your application . You can double click and run your application from desktop (For windows 7 right click on icon and run as administrator)  In control panel you can also find your application under uninstall programs ,from where you can remove it completely


This may or may not be a  professional way of approaching this issue...   .just found a small thing and was excited to share with all. Hope this was helpful in some way and you got a slight idea about deployment. Looking forward to your feedback's and comments.

Check out my next post for deploying a desktop application on a system without java installed
Software License for Launch4j
Software License for InnosetUp