The Power of Visual Studio .NET Build Events Part #2

Posted by Kamarudin • 4 minute read • Comments

Melanjutkan pembahasan postingan sebelumnya yaitu tentang fitur Build Events yang dimiliki oleh Visual Studio .NET.

Di postingan bagian #1 kita memanfaatkan fitur ini untuk melakukan proses copy file (exe, dll, config) secara otomatis setelah proses build project selesai.

Nah di postingan kali ini kita akan menambahkan perintah untuk mengcompile skrip Inno Setup sehingga proses pembuatan paket installer pun jadi otomatis.

Inno Setup

Inno Setup adalah salah satu software favorit untuk membuat paket installer berbasis windows. Selain gratis software ini juga didukung oleh dokumentasi yang lengkap sehingga memudahkan kita untuk mempelajarinya. Saya juga ada menulis beberapa postingan tentang Inno Setup yang bisa anda baca disini.

Jadi untuk melanjutkan pembahasan ini, saya mengasumsikan Anda sudah pernah menggunakan Inno Setup untuk membuat paket installer.

Untuk membuat skrip Inno Setup itu gampang, contohnya seperti berikut :

[Setup]
AppName={code:GetAppName}
AppVerName={code:GetAppName} Versi {code:GetAppVersion}
AppPublisher={code:GetVendorName}
AppVersion={code:GetAppVersion}
AllowCancelDuringInstall = yes
DefaultDirName={pf}\KRSchool
DefaultGroupName={code:GetAppName}
Compression = lzma
SolidCompression = yes
OutputBaseFilename=SetupKRSchool
AllowNoIcons = yes
AlwaysRestart = no
AlwaysShowComponentsList = no
DisableProgramGroupPage = yes
AppendDefaultDirName = yes
CreateUninstallRegKey = yes
DisableStartupPrompt = yes
LanguageDetectionMethod=none
ShowLanguageDialog=no
UsePreviousLanguage=no
Uninstallable = yes
UninstallFilesDir={app}\uninst
UninstallDisplayIcon={app}\KRSchool.exe,0
UninstallDisplayName={code:GetAppName}
WindowVisible = no
AppCopyright=Copyright © 2015. {code:GetVendorName}
FlatComponentsList = yes
PrivilegesRequired = admin
VersionInfoVersion=1.0.0.0
SetupIconFile=E:\Master\Developer Tools\Package\Setup.ico
WizardImageFile=E:\Master\Developer Tools\Inno Setup\WizardImages\Modern\SetupModern16.bmp
WizardSmallImageFile=E:\Master\Developer Tools\Inno Setup\WizardImages\Modern\Small\SetupModernSmall26.bmp

[Languages]
Name: ina; MessagesFile: compiler:Indonesia.isl
Name: en; MessagesFile: compiler:grin:efault.isl

[Tasks]
Name: desktopicon; Description: {cm:CreateDesktopIcon}; GroupDescription: {cm:AdditionalIcons}; Flags: checkedonce
Name: quicklaunchicon; Description: {cm:CreateQuickLaunchIcon}; GroupDescription: {cm:AdditionalIcons}; Flags: unchecked

[Files]
;My Application Runtime
Source: *.*; DestDir: {app}; Flags: ignoreversion

; .net framework
Source: "E:\Master\Developer Tools\dotNET Framework\dotNetFx40_Full_x86_x64.exe"; DestDir: {tmp}; Flags: deleteafterinstall; Check: FrameworkIsNotInstalled 

;skin
Source: E:\Master\Developer Tools\Package\dll&ocx\ISSkin.dll; DestDir: {app}; Flags: dontcopy
Source: E:\Master\Developer Tools\Package\dll&ocx\Office2007.cjstyles; DestDir: {tmp}; Flags: dontcopy

[Icons]
Name: {group}\{code:GetAppName}; Filename: {app}\KRSchool.exe; WorkingDir: {app}; IconFilename: {app}\main.ico
Name: {userdesktop}\{code:GetAppName}; Filename: {app}\KRSchool.exe; WorkingDir: {app}; IconFilename: {app}\main.ico; Tasks: desktopicon

[Registry]
;INSTALL DIR
Root: HKCU; Subkey: "Software\{code:GetVendorName}\{code:GetAppName}"; ValueName: "installDir"; ValueType: String; ValueData: {app}; Flags: uninsdeletevalue

[Run]
Filename: {tmp}\dotNetFx40_Full_x86_x64.exe; Parameters: "/q:a /c:""install /l /q"""; Check: FrameworkIsNotInstalled; StatusMsg: "Sedang menginstall Microsoft Framework 4.0 ..."

[Code]
const
  AppName = 'KR School';
  AppVersion = '1.0.0';
  VendorName = 'KR Software';

// Importing LoadSkin API from ISSkin.DLL
procedure LoadSkin(lpszPath: String; lpszIniFileName: String);
external 'LoadSkin@files:isskin.dll stdcall';

// Importing UnloadSkin API from ISSkin.DLL
procedure UnloadSkin();
external 'UnloadSkin@files:isskin.dll stdcall';

// Importing ShowWindow Windows API from User32.DLL
function ShowWindow(hWnd: Integer; uType: Integer): Integer;
external 'ShowWindow@user32.dll stdcall';

function IsDotNetDetected(version: string; service: cardinal): boolean;
// Indicates whether the specified version and service pack of the .NET Framework is installed.
//
// version -- Specify one of these strings for the required .NET Framework version:
//    'v1.1.4322'     .NET Framework 1.1
//    'v2.0.50727'    .NET Framework 2.0
//    'v3.0'          .NET Framework 3.0
//    'v3.5'          .NET Framework 3.5
//    'v4\Client'     .NET Framework 4.0 Client Profile
//    'v4\Full'       .NET Framework 4.0 Full Installation
//
// service -- Specify any non-negative integer for the required service pack level:
//    0               No service packs required
//    1, 2, etc.      Service pack 1, 2, etc. required
var
    key: string;
    install, serviceCount: cardinal;
    success: boolean;
begin
    key := 'SOFTWARE\Microsoft\NET Framework Setup\NDP\' + version;

    // .NET 3.0 uses value InstallSuccess in subkey Setup
    if Pos('v3.0', version) = 1 then begin
        success := RegQueryDWordValue(HKLM, key + '\Setup', 'InstallSuccess', install);
    end else begin
        success := RegQueryDWordValue(HKLM, key, 'Install', install);
    end;

    // .NET 4.0 uses value Servicing instead of SP
    if Pos('v4', version) = 1 then begin
        success := success and RegQueryDWordValue(HKLM, key, 'Servicing', serviceCount);
    end else begin
        success := success and RegQueryDWordValue(HKLM, key, 'SP', serviceCount);
    end;

    result := success and (install = 1) and (serviceCount >= service);
end;

function FrameworkIsNotInstalled: Boolean;
begin
    Result := not IsDotNetDetected('v4\Full', 0);
end;

function GetVendorName(Param: string): string;
begin
  Result := VendorName;
end;

function GetAppVersion(Param: string): string;
begin
  Result := AppVersion;
end;

function GetAppName(Param: string): string;
begin
  Result := AppName;
end;

function InitializeSetup(): Boolean;
begin

  ExtractTemporaryFile('Office2007.cjstyles');
  LoadSkin(ExpandConstant('{tmp}\Office2007.cjstyles'), 'NormalAqua.ini');
	    
  Result := True;
end;

procedure DeinitializeSetup();
begin
	// Hide Window before unloading skin so user does not get
	// a glimse of an unskinned window before it is closed.
	ShowWindow(StrToInt(ExpandConstant('{wizardhwnd}')), 0);
	UnloadSkin();
end;

Kemudian skrip di atas kita simpan di folder Rilis misal dengan nama ` SetupKRSchool.iss`

File SetupKRSchool.iss di atas akan kita compile menggunakan tool bawaan Inno Setup yaitu ISCC.exe. Untuk contoh penggunaanya seperti ini :

iscc "c:\rilis\SetupKRSchool.iss"

Nah perintah di atas akan kita panggil melalui Dialog Build Events

Revisi Perintah Build Event

Pada postingan sebelumnya kita sudah menulis perintah sederhana di dialog Build Events

Kita akan merivisi perintah diatas untuk menjalankan tool bawaan Inno Setup yaitu ISCC.exe. Dengan tool ini kita bisa langsung mengcompile skrip Inno Setup.

Berikut perintah lengkapnya.

Pada perintah di atas saya menambahkan kondisi

if "$(ConfigurationName)" == "Debug" goto skip

yang artinya perintah build event di atas hanya akan dijalankan jika Solution Configuration atau Configuration Manager di set Release.

Setelah itu lakukan proses build -> project, maka semua file dll atau exe yang ada di folder bin\Debug atau bin\Release akan dicopykan ke folder C:\Rilis, kemudian akan dilanjutkan dengan mengcompile skrip Inno Setup.

Selamat mencoba :blush:

Comments