MiniM. Saving time.


| About | Download | Tools | Knowledge Base | How to Buy |

MiniM Overview

Getting Started

Download

Documentation

Tools

Cache Tools

GT.M Tools

Knowledge Base

FAQ

Contacts

Copyrights

MiniM Knowledge Base | Dec 2, 2010

How to create ZDLL module installer on InnoSetup

Before installer creation we must define main installer goals. In case ZDLL module installer we must to do:

  1. Let to user select one of available MiniM server installed.
  2. If this server is not running, run one.
  3. Copy into /bin subdirectory appropriate zdll file and utility routine if one exists.
  4. Make routine import if one exists.
Next we create in InnoSetup install script file iss and fill script header. In current case we create installer for NTLM authorization module.

Sample of [Setup] section filling:

[Setup]
AppName=MiniM ZDLL module for NTLM autorization
AppVerName=MiniM ZDLL NTLM module
OutputBaseFilename=setup-zntlm
DefaultDirName={pf}\MiniM
DefaultGroupName=MiniM
AppPublisher=Eugene Karataev
AppPublisherURL=http://karataev.nm.ru
AllowNoIcons=yes
OutputDir=W:\MiniM\zdll\install
Compression=lzma
SolidCompression=yes
Uninstallable = no
The [Files] section contains only two files to install:
[Files]
Source: "w:\MiniM\bin\zntlm.dll"; DestDir: "{app}\bin"
Source: "w:\MiniM\zdll\zntlm\%ntlm.rou"; DestDir: "{app}\bin"
Next we cannot use default directory choosen by installer by default, and must ask user to select one of installed MiniM server. List of available MiniM servers installed we can obtain from the Windows registry, and instead of default installer page for directory selection we must create custom installer page.

In the [CustomMessages] we create special constant strings:

[CustomMessages]
SelectInstanceCaption=Select available MiniM instance to install to
SelectInstanceDescription=
In the [Code] section we create function for custom installer page and add into InitializeWizard call to this function:
[Code]
var
  lblInstance: TLabel;
  lbInstanceList: TListBox;
  InstallName: String;

procedure SelectInstance_Activate(Page: TWizardPage);
begin
  lbInstanceList.ItemIndex := -1;
  WizardForm.NextButton.Enabled := False;
end;

function SelectInstance_ShouldSkipPage(Page: TWizardPage): Boolean;
begin
  Result := False;
end;

function SelectInstance_BackButtonClick(Page: TWizardPage): Boolean;
begin
  Result := True;
end;

function SelectInstance_NextButtonClick(Page: TWizardPage): Boolean;
begin
  Result := True;
end;

procedure SelectInstance_CancelButtonClick(Page: TWizardPage; var Cancel, 
Confirm: Boolean);
begin
end;

procedure SelectInstance_Click( Sender: TObject);
var
  Index: Integer;
  Dir: String;
  Group: String;
begin
  Index := lbInstanceList.ItemIndex;
  if Index = - 1 then
  begin
    WizardForm.NextButton.Enabled := False;
  end
  else
  begin
    InstallName := lbInstanceList.Items.Strings[ Index];
    InstallName := Copy( InstallName, 1, Pos( ' ', InstallName) - 1);
    RegQueryStringValue( HKEY_LOCAL_MACHINE,
      'SOFTWARE\MiniM Group\MiniM\Instance\' + 
      InstallName, 'Directory', Dir);
    WizardForm.DirBrowseButton.Visible := False;
    WizardForm.DirEdit.Enabled := False;
    WizardForm.DirEdit.Text := Dir;
    RegQueryStringValue( HKEY_LOCAL_MACHINE,
      'SOFTWARE\MiniM Group\MiniM\Instance\' + 
      InstallName, 'Group', Group);
    WizardForm.GroupEdit.Text := Group;
    WizardForm.NextButton.Enabled := True;
  end;
end;

function SelectInstance_CreatePage(PreviousPageId: Integer): Integer;
var
  Page: TWizardPage;
  Names: TArrayOfString;
  I: Integer;
  Ver: String;
begin
  Page := CreateCustomPage(
    PreviousPageId,
    ExpandConstant('{cm:SelectInstanceCaption}'),
    ExpandConstant('{cm:SelectInstanceDescription}')
  );

  { lblInstance }
  lblInstance := TLabel.Create(Page);
  with lblInstance do
  begin
    Parent := Page.Surface;
    Left := ScaleX(16);
    Top := ScaleY(8);
    Width := ScaleX(150);
    Height := ScaleY(13);
    Caption := 'Select available MiniM instance:';
  end;

  { lbInstanceList }
  lbInstanceList := TListBox.Create(Page);
  with lbInstanceList do
  begin
    Parent := Page.Surface;
    Left := ScaleX(24);
    Top := ScaleY(24);
    Width := ScaleX(321);
    Height := ScaleY(201);
    TabOrder := 0;
    OnClick := @SelectInstance_Click;
  end;

  // заполняем список перечнем имеющихся инсталляций
  RegGetSubkeyNames( HKEY_LOCAL_MACHINE,
    'SOFTWARE\MiniM Group\MiniM\Instance', Names);
  for I := 0 to GetArrayLength(Names)-1 do
  begin
    RegQueryStringValue( HKEY_LOCAL_MACHINE,
      'SOFTWARE\MiniM Group\MiniM\Instance\' + 
      Names[ I], 'Version', Ver);
    lbInstanceList.Items.Add( Names[ I] + 
      '          (ver. ' + Ver + ')');
  end;

  lbInstanceList.ItemIndex := -1;

  with Page do
  begin
    OnActivate := @SelectInstance_Activate;
    OnShouldSkipPage := @SelectInstance_ShouldSkipPage;
    OnBackButtonClick := @SelectInstance_BackButtonClick;
    OnNextButtonClick := @SelectInstance_NextButtonClick;
    OnCancelButtonClick := @SelectInstance_CancelButtonClick;
  end;

  Result := Page.ID;
end;

procedure InitializeWizard();
begin
  SelectInstance_CreatePage(wpWelcome);
end;
To specify that installer cannot continue installation without MiniM server selection we add this check into SelectInstance_Activate function:
procedure SelectInstance_Activate(Page: TWizardPage);
begin
  lbInstanceList.ItemIndex := -1;
  WizardForm.NextButton.Enabled := False;
end;
And in the SelectInstance_Click function add allowing to continue installation:
  if Index = - 1 then
  begin
    WizardForm.NextButton.Enabled := False;
  end
  else
  begin
    ...
    WizardForm.NextButton.Enabled := True;
  end;
Steps of DirBrowseButton and DirEdit state changes we use to specify installer that we select install directory in our code:
    
    WizardForm.DirBrowseButton.Visible := False;
    WizardForm.DirEdit.Enabled := False;
    WizardForm.DirEdit.Text := Dir;
After dll and rou files have been copied into appropriate directory (it is selected directory in our code), we must run MiniM server. If this server is already running, we must ignore run result. This step we do in the CurStepChanged function on the CurStep = ssPostInstall step.
procedure CurStepChanged(CurStep: TSetupStep);
var
  AppDir: String;
  ErrorCode: Integer;
begin
  if CurStep = ssPostInstall then
  begin
    AppDir := ExpandConstant('{app}');
    // start mnmsvc.exe
    ShellExec( 'open', 'net', 
      'start "MiniM Service for ' + InstallName, AppDir + '\bin',
      SW_HIDE, ewWaitUntilTerminated, ErrorCode);
    // import routines
    ShellExec( 'open', AppDir + 
      '\bin\minim.exe', 
      '-x "zn \"%sys"" d imp^boot0(\"%ntlm.rou\")" -h', 
      AppDir + '\bin',
      SW_SHOW, ewWaitUntilTerminated, ErrorCode);
  end;
end;
As the result of compilation we got exe with installer, which show message about installation, ask user to select one of available MiniM server, installs into /bin subdirectory two files - dll + rou and executes import routine into need database. After installation completes this ZDLL module is ready to use.

So, we use the following key steps to craete installer:

  • Create custom installer page
  • Cancel default installation directory usage
  • Add into post-install step server running using net start
  • Add into post-install step routine import in the same order as used by MiniM installer.

After installation we have in the /bin subdirectory the dll file which is used as ZDLL module and a rou file, which can be used later to import again. This rou file can be deleted by your opinion.

Additionally installer can install other files, such as documentation, samples, additional scripts on the other languages.

Eugene Karataev
support@minimdb.com


Copyright (C) Eugene Karataev
Info Support