May 2, 2023

INNOSETUP

INNOSETUP

로드리고 루즈의 소스를 보구서 InnoSetup 을 사용해보려고 돌아다니면서 읽어보기 시작했다.
역시 초보한테는…Inno setup 의 컴포넌트 설치에서부터 에러를…

우선 화일들부터 정리를 해두고 다시 차근차근 해보자…

INNOSETUP SITE : jrsoftware
INNOSETUP Manual : Inno Setup Help
INNOSETUP Source : Inno Setup Source
INNOSETUP ThirdParty PlugIn: Vcl-styles-plugins

소스는 위 소스주소에 가서 하단의 설명을 보면서 Git 을 설치해서 실행한후에 콘솔에서 명령어를 입력해서 다운받아야 한다.(설치파일을 만들거라면 소스를 받을 필요는 없다.)

First you need to download the sources from Github. From the command line do:

>
> git clone https://github.com/jrsoftware/issrc.git is
> cd is
> git submodule init
> git submodule update
>

만약 Git 클라이언트가 없다면 http://git-scm.com/ 에서 받으면 된다.

Pro Git : Git 매뉴얼

소스를 최신으로 업데이트를 하려면 아래와 같이 입력한다.

>
> git pull
> git submodule update
>

위에서 Git 를 통해 받은 화일은 다음 폴더에 저장이 된다.

InnoSetup의 소스 폴더를 펼쳐봤다. 어떤것들이 있는지 알아둬야해서

innofolder

아직 아무것도 안했다. 다음은 컴포넌트 설치를 성공하고 나서.

unit Unit1;
 
interface
 
uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics,  Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
 
type
  TForm1 = class(TForm)
  private
    { Private declarations }
  public
    { Public declarations }
  end;
 
var
  Form1: TForm1;
 
implementation
 
{$R *.dfm}
 
end.

입력된 값이 잘못되었을때 버튼 비활성화 처리

var
  UserInfoPage: TInputQueryWizardPage;
  UserName, UserCompany: String;
 
procedure CreateWizardPages;
var
//  UserInfoPage: TInputQueryWizardPage;
//  UserName, UserCompany: String;
  BitmapImage: TBitmapImage;
  BitmapFileName: String;
begin
  BitmapFileName := ExpandConstant('{tmp}\background3.bmp');
  ExtractTemporaryFile(ExtractFileName(BitmapFileName));
 
  { TBitmapImage }
//  Page := CreateCustomPage(wpInstalling, '사용자정보',
  UserInfoPage := CreateInputQueryPage(wpWelcome, '사용자정보 입력', '설치하는 PC의 사용자정보 입력','정확하게 입력해주세요.');
 
  BitmapImage := TBitmapImage.Create(UserInfoPage);
  BitmapImage.AutoSize := True;
  BitmapImage.Left := 100;
  BitmapImage.Top  := 145;
  BitmapImage.Bitmap.LoadFromFile(BitmapFileName);
  BitmapImage.Cursor := crHand;
  BitmapImage.OnClick := @BitmapImageOnClick;
  BitmapImage.Parent := UserInfoPage.Surface;
  //BitmapImage.Align:=alCLient;
  BitmapImage.Align:=alNone;
  BitmapImage.Stretch:=False;
 
 
// Add items (False means it's not a password edit)
  UserInfoPage.Add('사용자이름 :', False);
  UserInfoPage.Add('소속부서명 :', False);
 
// Set initial values (optional)
  UserInfoPage.Values[0] := ExpandConstant('{sysuserinfoname}');
  UserInfoPage.Values[1] := ExpandConstant('{sysuserinfoorg}');
 
  UserName := UserInfoPage.Values[0];
  UserCompany := UserInfoPage.Values[1];
 
end;
 
procedure ValidatePage;
begin
  if ( UserInfoPage.Values[0] <> '' ) and ( UserInfoPage.Values[1] <> '' ) 
  then WizardForm.NextButton.Enabled := True
  else WizardForm.NextButton.Enabled := False;
end;  
 
procedure EditChange(Sender: TObject);
begin
  ValidatePage;
end;
 
procedure PageActivate(Sender: TWizardPage);
begin
  ValidatePage;
end;
 
procedure InitializeWizard();
begin
  CreateWizardPages;
   
  UserInfoPage.OnActivate := @PageActivate;
//  UserInfoPage.Add(...,False);
  UserInfoPage.Edits[0].OnChange := @EditChange; 
  UserInfoPage.Edits[1].OnChange := @EditChange; 
 
//  if Page.UserName = '' then MsgBox('Null Name.', mbInformation, MB_OK);
 
end;

길이 및 형식 제한이 있는 사용자 입력 쿼리 페이지 작성 및 입력 사용

var
  Page: TInputQueryWizardPage;
 
{ Prevent user from typing spaces ... }
procedure EditKeyPress(Sender: TObject; var Key: Char);
begin
  if Key = ' ' then Key := #0;
end;
 
{ ... but check anyway if some spaces were sneaked in }
{ (e.g. by pasting from a clipboard) }
function ValidateInput(Sender: TWizardPage): Boolean;
begin
  Result := True;
 
  if Pos(' ', Page.Values[0]) > 0 then
  begin
    MsgBox('Profile Name cannot contain spaces.', mbError, MB_OK);
    Result := False;
  end;
end;
 
procedure InitializeWizard();
begin
  Page := CreateInputQueryPage(...);
  Page.OnNextButtonClick := @ValidateInput;
  Page.Add('Name:', False);
  Page.Edits[0].MaxLength := 15;
  Page.Edits[0].OnKeyPress := @EditKeyPress;
  Page.Values[0] := 'YourName';
  ...
end;

설치시에 프로세스 죽이기

[Files]
Source: "Agent.exe"; DestDir: "{app}"; Flags: ignoreversion; BeforeInstall: TaskKill('Agent.exe')
 
[Code]
procedure TaskKill(FileName: String);
var
  ResultCode: Integer;
begin
    Exec(ExpandConstant('taskkill.exe'), '/f /im ' + '"' + FileName + '"', '', SW_HIDE,
     ewWaitUntilTerminated, ResultCode);
end;

설치시 입력값을 레지스트리에 저장하기

[Registry]
Root: "HKCU32"; Subkey: "SOFTWARE\Test\MyApplication"; ValueType: string; ValueName: "UserName"; ValueData: {code:GetUserName}; Flags: createvalueifdoesntexist uninsdeletekey
Root: "HKCU32"; Subkey: "SOFTWARE\Test\MyApplication"; ValueType: string; ValueName: "PartyName"; ValueData: {code:GetPartyName}; Flags: createvalueifdoesntexist uninsdeletekey
 
[Code]
var
  UserInfoPage: TInputQueryWizardPage;
  UserName, UserGroup: String;
// Import the LoadVCLStyle function from VclStylesInno.DLL
procedure LoadVCLStyle(VClStyleFile: String); external 'LoadVCLStyleW@files:VclStylesInno.dll stdcall';
// Import the UnLoadVCLStyles function from VclStylesInno.DLL
procedure UnLoadVCLStyles; external 'UnLoadVCLStyles@files:VclStylesInno.dll stdcall';
 
function GetUninstallString(): String;
var
  sUnInstPath: String;
  sUnInstallString: String;
begin
  sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
  sUnInstallString := '';
  if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
    RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
  Result := sUnInstallString;
end;
 
function IsUpgrade(): Boolean;
begin
  Result := (GetUninstallString() <> '');
end;
 
function UnInstallOldVersion(): Integer;
var
  sUnInstallString: String;
  iResultCode: Integer;
begin
  Result := 0;
  sUnInstallString := GetUninstallString();
  if sUnInstallString <> '' then begin
    sUnInstallString := RemoveQuotes(sUnInstallString);
    if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then
      Result := 3
    else
      Result := 2;
  end else
    Result := 1;
end;
 
procedure BitmapImageOnClick(Sender: TObject);
var
  ErrorCode : Integer;
begin
  ShellExec('open', 'https://www.isecurekr.com/', '', '', SW_SHOWNORMAL, ewNoWait, ErrorCode);
end;
 
procedure CreateWizardPages;
var
  BitmapImage: TBitmapImage;
  BitmapFileName: String;
begin
  BitmapFileName := ExpandConstant('{tmp}\background3.bmp');
  ExtractTemporaryFile(ExtractFileName(BitmapFileName));
 
  { TBitmapImage }
  UserInfoPage := CreateInputQueryPage(wpWelcome, '사용자정보 입력', '설치하는 PC의 사용자정보 입력','입력하신 정보가 필요합니다.');
 
  BitmapImage := TBitmapImage.Create(UserInfoPage);
  BitmapImage.AutoSize := True;
  BitmapImage.Left := 100;
  BitmapImage.Top  := 145;
  BitmapImage.Bitmap.LoadFromFile(BitmapFileName);
  BitmapImage.Cursor := crHand;
  BitmapImage.OnClick := @BitmapImageOnClick;
  BitmapImage.Parent := UserInfoPage.Surface;
  //BitmapImage.Align:=alCLient;
  BitmapImage.Align:=alNone;
  BitmapImage.Stretch:=False;
 
 
// Add items (False means it's not a password edit)
  UserInfoPage.Add('사용자이름 :', False);
  UserInfoPage.Add('소속부서명 :', False);
 
// Set initial values (optional)
  UserInfoPage.Values[0] := ExpandConstant('{sysuserinfoname}');
  UserInfoPage.Values[1] := ExpandConstant('{sysuserinfoorg}');
 
  UserName := UserInfoPage.Values[0];
  UserGroup := UserInfoPage.Values[1];
 
//  if UserName = '' then MsgBox('Null Name.', mbInformation, MB_OK);
 
end;
 
procedure ValidatePage;
begin
  if ( UserInfoPage.Values[0] <> '' ) and ( UserInfoPage.Values[1] <> '' ) 
  then begin
   UserName := UserInfoPage.Values[0];
   UserGroup := UserInfoPage.Values[1];
   WizardForm.NextButton.Enabled := True;    
  end else
  begin
   WizardForm.NextButton.Enabled := False;
  end;
   
end;  
 
procedure EditChange(Sender: TObject);
begin
  ValidatePage;
end;
 
procedure PageActivate(Sender: TWizardPage);
begin
  ValidatePage;
end;
 
procedure InitializeWizard();
begin
  CreateWizardPages;
   
  UserInfoPage.OnActivate := @PageActivate;
  UserInfoPage.Edits[0].OnChange := @EditChange; 
  UserInfoPage.Edits[1].OnChange := @EditChange; 
//  if Page.UserName = '' then MsgBox('Null Name.', mbInformation, MB_OK);
 
end;
 
function InitializeSetup(): Boolean;
begin
 
   ExtractTemporaryFile('Light.vsf');
   LoadVCLStyle(ExpandConstant('{tmp}\Light.vsf'));
   Result:=True;
end;
 
procedure DeinitializeSetup();
begin
    UnLoadVCLStyles;
end;
 
procedure CurStepChanged(CurStep: TSetupStep);
begin
  if (CurStep=ssInstall) then
  begin
    if (IsUpgrade()) then
    begin
      UnInstallOldVersion();
    end;
  end;
end;
 
 
procedure TaskKill(FileName: String);
var
  ResultCode: Integer;
begin
    Exec(ExpandConstant('taskkill.exe'), '/f /im ' + '"' + FileName + '"', '', SW_HIDE,
     ewWaitUntilTerminated, ResultCode);
end;
 
function GetUserName(Param: String): string;
begin
  result := UserName;
end;
 
function GetPartyName(Param: String): string;
begin
  result := UserGroup;
end;