Friday, May 27, 2005

Inno installation script: VB6, MSDE, MDAC

An Inno installation script I wrote to install a VB6 application and optionally, MSDE and MDAC. It also executes several database scripts as well as prompts the user to install MSDE or choose an existing SQL Server database.


; MyApp Install Script
; Author: Jeff Hunsaker
; Version: 1.0.0.0


#define AppName "MyApp"
#define AppNameLong "My App"
#define AppPublisher "My Firm, Inc."
#define Ver1 "1"
#define Ver2 "0"
#define Ver3 "0"
#define Ver4 "0"
#define MinVersion "4.1.1998,4.0.1381sp5"
#define DBInstance "DBInstance" ;when MSDE installed locally/new
#define DBDatabase "DBDatabase"
#define DBDefaultSaPassword "sapassword"
#define DBDefaultSaAccount "sa"
#define DBAppUserName "AppUser"
#define DBAppPassword "password"
#define DBDefaultServer "(LOCAL)"
#define DBDSN "MyApp"
#define DBDSNDescription = "My App"

[Setup]
MinVersion={#MinVersion}
OnlyBelowVersion=0,0
AppCopyright=© 2005 {#AppPublisher}
AppName={#AppNameLong}
AppVerName={#AppNameLong} {#Ver1}.{#Ver2}.{#Ver3}.{#Ver4}
PrivilegesRequired=admin
AllowRootDirectory=true
AllowUNCPath=false
ShowLanguageDialog=no
WizardImageFile=logos\some.bmp
WizardImageStretch=no
AppID={{42F4A6D5-72BF-4C3E-AFE9-A345C13C842D}
AppMutex={#AppName}
DefaultDirName={pf}\{#AppName}
EnableDirDoesntExistWarning=true
AlwaysShowComponentsList=false
DisableReadyPage=no
LanguageDetectionMethod=none
AppPublisher={#AppPublisher}
AppPublisherURL=http://www.myfirm.com/
AppVersion={#Ver1}.{#Ver2}
UninstallDisplayName={#AppNameLong} {#Ver1}.{#Ver2}.{#Ver3}.{#Ver4}
UserInfoPage=yes
UsePreviousUserInfo=yes
DefaultGroupName={#AppName}
DisableProgramGroupPage=yes

[_ISTool]
LogFile=cwinstall.log
LogFileAppEND=true

[Icons]
Name: {group}\{#AppName}; Filename: {app}\{#AppName}.exe; WorkingDir: {app}
Name: {group}\{cm:UninstallProgram, {#AppName}}; Filename: {uninstallexe}

[Files]
;************************************************************************************************
; VB system files
;************************************************************************************************
; see also
; http://support.microsoft.com/default.aspx?scid=kb;en-us;830761
;************************************************************************************************
Source: vbfiles\stdole2.tlb; DestDir: {sys}; Flags: restartreplace uninsneveruninstall sharedfile regtypelib
Source: vbfiles\msvbvm60.dll; DestDir: {sys}; Flags: restartreplace uninsneveruninstall sharedfile regserver
Source: vbfiles\oleaut32.dll; DestDir: {sys}; Flags: restartreplace uninsneveruninstall sharedfile regserver
Source: vbfiles\olepro32.dll; DestDir: {sys}; Flags: restartreplace uninsneveruninstall sharedfile regserver
Source: vbfiles\asycfilt.dll; DestDir: {sys}; Flags: restartreplace uninsneveruninstall sharedfile
Source: vbfiles\comcat.dll; DestDir: {sys}; Flags: restartreplace uninsneveruninstall sharedfile regserver


;************************************************************************************************
; 3rd party DLL files
;************************************************************************************************
Source: projectfiles\somedll.DLL; DestDir: {app}; Flags: restartreplace sharedfile uninsnosharedfileprompt


;************************************************************************************************
; MS DLL files
;************************************************************************************************
Source: system32\msstdfmt.dll; DestDir: {sys}; Flags: restartreplace sharedfile regserver
Source: system32\msbind.dll; DestDir: {sys}; Flags: restartreplace sharedfile regserver
Source: misc\dao360.dll; DestDir: {dao}; Flags: restartreplace sharedfile regserver
Source: misc\sqlns.rll; DestDir: {pf}\Microsoft SQL Server\80\Tools\Binn\Resources\1033; Flags: restartreplace sharedfile


;************************************************************************************************
; VB OCX files
;************************************************************************************************
Source: msocxs\COMCT332.ocx; DestDir: {sys}; Flags: restartreplace sharedfile regserver uninsneveruninstall
Source: msocxs\MSCOMCT2.ocx; DestDir: {sys}; Flags: restartreplace sharedfile regserver uninsneveruninstall
Source: msocxs\MSCOMCTL.ocx; DestDir: {sys}; Flags: restartreplace sharedfile regserver uninsneveruninstall
Source: msocxs\TABCTL32.ocx; DestDir: {sys}; Flags: restartreplace sharedfile regserver uninsneveruninstall
Source: msocxs\MSMASK32.ocx; DestDir: {sys}; Flags: restartreplace sharedfile regserver uninsneveruninstall
Source: msocxs\MSDATGRD.ocx; DestDir: {sys}; Flags: restartreplace sharedfile regserver uninsneveruninstall
Source: msocxs\COMDLG32.ocx; DestDir: {sys}; Flags: restartreplace sharedfile regserver uninsneveruninstall
Source: msocxs\MSADODC.ocx; DestDir: {sys}; Flags: restartreplace sharedfile regserver uninsneveruninstall



;************************************************************************************************
; 3rd party OCX files
;************************************************************************************************
Source: system32\someocx.ocx; DestDir: {sys}; Flags: restartreplace sharedfile regserver uninsnosharedfileprompt



;************************************************************************************************
; project files
;************************************************************************************************
Source: projectfiles\{#AppName}.exe; DestDir: {app}; Flags: replacesameversion uninsnosharedfileprompt



;************************************************************************************************
; MDAC
;************************************************************************************************
Source: MDAC\mdac_typ.exe; DestDir: {tmp}\mdac; MinVersion: {#MinVersion}; Flags: ignoreversion; Check: GetNotInstallMSDEFlag


;************************************************************************************************
; MSDE 2000 SP3a
;************************************************************************************************
Source: msde\*.*; DestDir: {tmp}\msde; MinVersion: {#MinVersion}; Flags: ignoreversion; Check: GetInstallMSDEFlag
Source: msde\msi\*.*; DestDir: {tmp}\msde\msi; MinVersion: {#MinVersion}; Flags: ignoreversion; Check: GetInstallMSDEFlag
Source: msde\msm\*.*; DestDir: {tmp}\msde\msm; MinVersion: {#MinVersion}; Flags: ignoreversion; Check: GetInstallMSDEFlag
Source: msde\msm\1033\*.*; DestDir: {tmp}\msde\msm\1033; MinVersion: {#MinVersion}; Flags: ignoreversion; Check: GetInstallMSDEFlag
Source: msde\setup\*.*; DestDir: {tmp}\msde\setup; MinVersion: {#MinVersion}; Flags: ignoreversion; Check: GetInstallMSDEFlag



;************************************************************************************************
; SQL scripts
;************************************************************************************************
Source: scripts\osql.exe; DestDir: {tmp}\scripts
Source: scripts\buildobjects.sql; DestDir: {tmp}\scripts
Source: scripts\createdatabase.sql; DestDir: {tmp}\scripts
Source: scripts\populatedata.sql; DestDir: {tmp}\scripts


[Run]
;************************************************************************************************
; MSDE 2000 SP3a:
;************************************************************************************************
; see also:
; http: //msdn.microsoft.com/library/default.asp?url=/library/en-us/distsql/distsql_84xl.asp
;************************************************************************************************
Filename: {tmp}\msde\Setup.exe; Parameters: SECURITYMODE=SQL INSTANCENAME={#DBInstance} SAPWD={#DBDefaultSaPassword}; WorkingDir: {tmp}\msde; MinVersion: {#MinVersion}; StatusMsg: Installing Microsoft Data Engine (MSDE); Check: GetInstallMSDEFlag
Filename: {pf}\Microsoft SQL Server\80\Tools\Binn\scm.exe; Parameters: -Action 1 -Pwd {code:GetDbPassword} -Service MSSQL${#DBInstance} -Silent 1; WorkingDir: {pf}\Microsoft SQL Server\80\Tools\Binn; MinVersion: {#MinVersion}; StatusMsg: Starting Microsoft Data Engine (MSDE); Check: GetInstallMSDEFlag


;************************************************************************************************
; MDAC 2.7 SP1 Refresh (WinXP)
;************************************************************************************************
; see also:
; http://msdn.microsoft.com/library/default.asp?url=/library/en-us/mdacsdk/htm/wphistory_redistributemdac.asp
; http://support.microsoft.com/default.aspx?scid=kb;EN-US;842262
;************************************************************************************************
Filename: {tmp}\mdac\mdac_typ.exe; Parameters: "/Q:A /C:""dasetup /Q:D /N"""; WorkingDir: {tmp}\mdac; MinVersion: {#MinVersion}; StatusMsg: Installing Microsoft Data Access Components (MDAC); Check: GetNotInstallMSDEFlag


;************************************************************************************************
; SQL scripts
;************************************************************************************************
; execute base SQL for new installations
Filename: {tmp}\scripts\osql.exe; Parameters: -U{code:GetDbLogin} -P{code:GetDbPassword} -S{code:GetDbServer} -dmaster -ocreatedatabase.log -r -e -i{tmp}\scripts\createdatabase.sql; WorkingDir: {tmp}\scripts; Flags: runhidden; Check: GetDatabaseNotExistsFlag; StatusMsg: Executing database scripts: create database
Filename: {tmp}\scripts\osql.exe; Parameters: "-U{code:GetDbLogin} -P{code:GetDbPassword} -S{code:GetDbServer} -dmaster -oaddlogin.log -r -e -Q""if not exists(SELECT * FROM master..syslogins WHERE name='{#DBAppUserName}') exec sp_addlogin '{#DBAppUserName}', '{#DBAppPassword}', '{#DBDatabase}';"""; WorkingDir: {tmp}\scripts; Flags: runhidden; StatusMsg: Executing database scripts: create application account
Filename: {tmp}\scripts\osql.exe; Parameters: "-U{code:GetDbLogin} -P{code:GetDbPassword} -S{code:GetDbServer} -d{#DBDatabase} -ograntdbaccess.log -r -e -Q""if not exists(SELECT * FROM sysusers WHERE name='{#DBAppUserName}') exec sp_grantdbaccess @loginame='{#DBAppUserName}';"""; WorkingDir: {tmp}\scripts; Flags: runhidden; StatusMsg: Executing database scripts: create application account
Filename: {tmp}\scripts\osql.exe; Parameters: "-U{code:GetDbLogin} -P{code:GetDbPassword} -S{code:GetDbServer} -d{#DBDatabase} -oaddrole.log -r -e -Q""exec sp_addrolemember @rolename='db_owner', @membername='{#DBAppUserName}';"""; WorkingDir: {tmp}\scripts; Flags: runhidden; StatusMsg: Executing database scripts: create application account
Filename: {tmp}\scripts\osql.exe; Parameters: -U{code:GetDbLogin} -P{code:GetDbPassword} -S{code:GetDbServer} -d{#DBDatabase} -obuildobjects.log -r -e -i{tmp}\scripts\buildobjects.sql; WorkingDir: {tmp}\scripts; Flags: runhidden; Check: GetDatabaseNotExistsFlag; StatusMsg: Executing database scripts: create objects
Filename: {tmp}\scripts\osql.exe; Parameters: -U{code:GetDbLogin} -P{code:GetDbPassword} -S{code:GetDbServer} -d{#DBDatabase} -opopulatedata.log -r -e -i{tmp}\scripts\populatedata.sql; WorkingDir: {tmp}\scripts; Flags: runhidden; Check: GetDatabaseNotExistsFlag; StatusMsg: Executing database scripts: populate data

; TODO: execute update SQL for this version

; update database version value
Filename: {tmp}\scripts\osql.exe; Parameters: "-U{code:GetDbLogin} -P{code:GetDbPassword} -S{code:GetDbServer} -d{#DBDatabase} -odel_DatabaseVersion.log -r -e -Q""DELETE FROM {#DBDatabase}..DatabaseVersion"""; WorkingDir: {tmp}\scripts; Flags: runhidden; StatusMsg: Executing database scripts: update version
Filename: {tmp}\scripts\osql.exe; Parameters: "-U{code:GetDbLogin} -P{code:GetDbPassword} -S{code:GetDbServer} -d{#DBDatabase} -oins_DatabaseVersion.log -r -e -Q""INSERT INTO {#DBDatabase}..DatabaseVersion (DatabaseVersionID, CurrentVersion) VALUES (1, '{#Ver1}.{#Ver2}.{#Ver3}.{#Ver4}')"""; WorkingDir: {tmp}\scripts; Flags: runhidden; StatusMsg: Executing database scripts: update version



[Registry]
Root: HKLM; SubKey: Software\ODBC\ODBC.INI\ODBC Data Sources; Flags: createvalueifdoesntexist uninsdeletevalue deletevalue; ValueName: {#DBDSN}; ValueType: string; ValueData: SQL Server
Root: HKLM; SubKey: Software\ODBC\ODBC.INI\{#DBDSN}; Flags: createvalueifdoesntexist uninsdeletevalue deletevalue; ValueName: Driver; ValueType: string; ValueData: {sys}\SQLSRV32.dll
Root: HKLM; SubKey: Software\ODBC\ODBC.INI\{#DBDSN}; Flags: createvalueifdoesntexist uninsdeletevalue deletevalue; ValueName: Server; ValueType: string; ValueData: {code:GetDbServer}
Root: HKLM; SubKey: Software\ODBC\ODBC.INI\{#DBDSN}; Flags: createvalueifdoesntexist uninsdeletevalue deletevalue; ValueName: Database; ValueType: string; ValueData: {#DBDatabase}
Root: HKLM; SubKey: Software\ODBC\ODBC.INI\{#DBDSN}; Flags: createvalueifdoesntexist uninsdeletevalue deletevalue; ValueName: Description; ValueType: string; ValueData: {#DBDSNDescription}

[INI]


[CustomMessages]
databaseInfoCaption=Database information
databaseInfoDescription=Please indicate the database information

[Code]
var
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
txtServer: TEdit;
rbInstallMSDE: TRadioButton;
rbUseExisting: TRadioButton;
txtLogin: TEdit;
txtPassword: TEdit;
_installMSDE: boolean; // installing MSDE locally or using existing SQL instance
dbExists: boolean; // installing to new or existing database
dbServer: String; // use existing SQL Server server name
dbLogin: String; // use existing SQL Server login
dbPassword: String; // use existing SQL Server password

//************************************************************************************************
// EVENT HANDLERS
//************************************************************************************************
procedure databaseInfo_Activate(Page: TWizardPage);
begin
end;

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

procedure rbUseExisting_Click(Sender: TObject);
begin
// enable entry fields
txtServer.Enabled := True;
txtServer.ReadOnly := False;
txtLogin.Enabled := True;
txtLogin.ReadOnly := False;
txtPassword.Enabled := True;
txtPassword.ReadOnly := False;
end;

procedure rbInstallMSDE_Click(Sender: TObject);
begin
// disable entry fields
txtServer.Enabled := False
txtServer.ReadOnly := True;
txtLogin.Enabled := False;
txtLogin.ReadOnly := True;
txtPassword.Enabled := False;
txtPassword.ReadOnly := True;
end;

//************************************************************************************************
// FUNCTIONS
//************************************************************************************************
function InitializeSetup(): Boolean;
begin
// extract OSQL.exe file...needed in databaseInfo_NextButtonClick()
ExtractTemporaryFile('osql.exe');
Result := True;
end;

procedure DeInitializeSetup();
begin
end;

function GetInstallMSDEFlag: Boolean;
begin
Result := _installMSDE;
end;

function GetNotInstallMSDEFlag: Boolean;
begin
Result := not _installMSDE; // coded this way to accommodate the Check values
end;

function GetDatabaseExistsFlag: Boolean;
begin
Result := dbExists;
end;

function GetDatabaseNotExistsFlag: Boolean;
begin
Result := not dbExists; // coded this way to accommodate the Check values
end;

function GetDbServer(Default:String): String;
begin
Result := dbServer;
end;

function GetDbLogin(Default:String): String;
begin
Result := dbLogin;
end;

function GetDbPassword(Default:String): String;
begin
Result := dbPassword;
end;

function GetDbInstallType(Default:String): String;
begin
if (_installMSDE) then
Result := 'Local'
else
Result := 'Remote';
end;

// returns a string given a boolean and 2 representative return strings
function BoolToStr(b:boolean; TrueValue:string; FalseValue:string) : String;
begin
if b then
Result:=TrueValue
else
Result:=FalseValue;
end;

// output pre-installation stats
function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
var
cTemp: String;
DatabaseInfo: String;
begin

// create database information
DatabaseInfo := 'Database information:' + NewLine;
if (_installMSDE) then
begin
DatabaseInfo := DatabaseInfo + CHR(9) + 'Install MSDE locally' + NewLine;
DatabaseInfo := DatabaseInfo + CHR(9) + 'Server: ' + dbServer + NewLine;
DatabaseInfo := DatabaseInfo + CHR(9) + 'Login: ' + dbLogin + NewLine;
// DatabaseInfo := DatabaseInfo + CHR(9) + 'Password: *****' + NewLine;
DatabaseInfo := DatabaseInfo + CHR(9) + 'Password: ' + dbPassword + NewLine;
end
else
begin
DatabaseInfo := DatabaseInfo + CHR(9) + 'Use existing SQL Server' + NewLine;
DatabaseInfo := DatabaseInfo + CHR(9) + 'Server: ' + dbServer + NewLine;
DatabaseInfo := DatabaseInfo + CHR(9) + 'Login: ' + dbLogin + NewLine;
// DatabaseInfo := DatabaseInfo + CHR(9) + 'Password: *****' + NewLine;
DatabaseInfo := DatabaseInfo + CHR(9) + 'Password: ' + dbPassword + NewLine;
end;

cTemp := MemoUserInfoInfo + NewLine + NewLine;
cTemp := cTemp + MemoDirInfo + NewLine + NewLine;
cTemp := cTemp + DatabaseInfo + NewLine + NewLine;

Result := cTemp;
end;


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

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

// executes upon clicking Next within database info dialog
function databaseInfo_NextButtonClick(Page: TWizardPage): Boolean;

var
ResultCode: Integer;
output: String;
begin

// initialize
_installMSDE := False;
dbExists := False;

// install MSDE ok
if (rbInstallMSDE.Checked) then
begin
_installMSDE := True; // MAY be overriden in the logic below
dbServer := '{#DBDefaultServer}\{#DBInstance}';
dbLogin := '{#DBDefaultSaAccount}';
dbPassword := '{#DBDefaultSaPassword}';
Result := True;
end
else
begin
// ensure all fields provided if use existing selected
if ((rbUseExisting.Checked) and
((txtServer.Text = '') or
(txtLogin.Text = '') or
(txtPassword.Text = ''))) then
begin
MsgBox('You must provide server, login, and password for an existing installation.', mberror, MB_OK);
Result := False;
end
else
begin
// persist entered values
dbServer := txtServer.Text;
dbLogin := txtLogin.Text;
dbPassword := txtPassword.Text;
_installMSDE := False;
Result := True;
end
end;

// output check for existing database message
MsgBox ('Setup will now determine if the database exists. This may take up to 30 seconds.', mbInformation, MB_OK);

// determine if instance/database exist
if Exec(ExpandConstant('{tmp}\osql.exe'), '-U' + dbLogin + ' -P' + dbPassword + ' -S' + dbServer + ' -l10 -odatabaseexists.log -Q"EXIT(SELECT COUNT(*) FROM master..sysdatabases WHERE name=''{#DBDatabase}'')"', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) then
begin
// read in the OSQL output file 0 if not exists, 1 if exists --> MUST LOOK FOR '0' FIRST because file returns 1 record(s) affected
if LoadStringFromFile(ExpandConstant('{tmp}\databaseexists.log'), output) then
begin
if Pos(ExpandConstant(IntToStr(0)), output)>0 then
begin
if (_installMSDE) then
begin

// Delete any stragler crgp .mdf and .ldf files but leave the directory itself
DelTree(ExpandConstant('{pf}\Microsoft SQL Server\MSSQL${#DBInstance}\Data\{#DBDatabase}*'), False, True, True);
DelTree(ExpandConstant('{pf}\Microsoft SQL Server\MSSQL${#DBInstance}\Data\' + Lowercase(ExpandConstant('{#DBDatabase}')) + '*'), False, True, True);

// database does not exist but instance does; user indicated install MSDE; else user indicated use existing SQL Server
MsgBox ('The database does not yet exist and will be created during installation. Original system account and password is assumed. Click back and choose existing SQL Server if this is incorrect.', mbInformation, MB_OK);

_installMSDE := False;
end
else
MsgBox ('The database does not yet exist and will be created during installation using the credentials supplied.', mbInformation, MB_OK);
end
else
begin
if Pos(ExpandConstant(IntToStr(1)), output)>0 then
begin
if (_installMSDE) then
begin
// database and instance exist; user indicated install MSDE; else user indicated use existing SQL Server
// should never hit this but coded it anyway just in case
MsgBox ('The database exists and will undergo an upgrade during installation. Original system account and password is assumed. Click back and choose existing SQL Server if this is incorrect.', mbInformation, MB_OK);
_installMSDE := False;
end
else
MsgBox ('The database exists and will undergo an upgrade during installation using the credentials supplied.', mbInformation, MB_OK);
dbExists := True;
_installMSDE := False;
end
else
begin
if Pos('Login failed for user', output)>0 then
begin
// credentials incorrect
MsgBox ('Incorrect login credentials.', mbInformation, MB_OK);
Result := False;
end
else
begin
if Pos('SQL Server does not exist', output)>0 then
begin
// server does not exist
if not _installMSDE then
begin
MsgBox ('SQL Server does not exist. Try re-entering the information.', mbInformation, MB_OK);
Result := False;
end
else
begin

// Delete any stragler crgp .mdf and .ldf files but leave the directory itself
DelTree(ExpandConstant('{pf}\Microsoft SQL Server\MSSQL${#DBInstance}\Data\{#DBDatabase}*'), False, True, True);
DelTree(ExpandConstant('{pf}\Microsoft SQL Server\MSSQL${#DBInstance}\Data\' + Lowercase(ExpandConstant('{#DBDatabase}')) + '*'), False, True, True);

MsgBox ('MSDE will be installed locally. Afterward, a reboot may be required (select yes if prompted).', mbInformation, MB_OK);

Result := True;
_installMSDE := True;
end
end
end
end
end
end
end;
end;

function databaseInfo_CreatePage(PreviousPageId: Integer): Integer;
var
Page: TWizardPage;
begin
Page := CreateCustomPage(
PreviousPageId,
ExpandConstant('{cm:databaseInfoCaption}'),
ExpandConstant('{cm:databaseInfoDescription}')
);

{ Label1 }
Label1 := TLabel.Create(Page);
with Label1 do
begin
Parent := Page.Surface;
Left := ScaleX(16);
Top := ScaleY(56);
Width := ScaleX(58);
Height := ScaleY(13);
Caption := 'SQL Server:';
end;

{ Label2 }
Label2 := TLabel.Create(Page);
with Label2 do
begin
Parent := Page.Surface;
Left := ScaleX(16);
Top := ScaleY(104);
Width := ScaleX(58);
Height := ScaleY(13);
Caption := 'Login name:';
end;

{ Label3 }
Label3 := TLabel.Create(Page);
with Label3 do
begin
Parent := Page.Surface;
Left := ScaleX(16);
Top := ScaleY(152);
Width := ScaleX(50);
Height := ScaleY(13);
Caption := 'Password:';
end;

{ rbInstallMSDE }
rbInstallMSDE := TRadioButton.Create(Page);
with rbInstallMSDE do
begin
Parent := Page.Surface;
Left := ScaleX(0);
Top := ScaleY(8);
Width := ScaleX(361);
Height := ScaleY(17);
Caption := 'Install Microsoft SQL Server Database Engine (MSDE) locally';
TabOrder := 1;
Checked := True;
ONCLICK := @rbInstallMSDE_Click;
end;

{ rbUseExisting }
rbUseExisting := TRadioButton.Create(Page);
with rbUseExisting do
begin
Parent := Page.Surface;
Left := ScaleX(0);
Top := ScaleY(32);
Width := ScaleX(401);
Height := ScaleY(17);
Caption := 'Use existing SQL Server installation. Account must have administrative rights.';
TabOrder := 2;
TabStop := True;
ONCLICK := @rbUseExisting_Click;
end;

{ txtServer }
txtServer := TEdit.Create(Page);
with txtServer do
begin
Parent := Page.Surface;
Left := ScaleX(16);
Top := ScaleY(72);
Width := ScaleX(257);
Height := ScaleY(21);
Enabled := False;
ReadOnly := True;
TabOrder := 3;
end;

{ txtLogin }
txtLogin := TEdit.Create(Page);
with txtLogin do
begin
Parent := Page.Surface;
Left := ScaleX(16);
Top := ScaleY(120);
Width := ScaleX(257);
Height := ScaleY(21);
Enabled := False;
ReadOnly := True;
TabOrder := 4;
end;

{ txtPassword }
txtPassword := TEdit.Create(Page);
with txtPassword do
begin
Parent := Page.Surface;
Left := ScaleX(16);
Top := ScaleY(168);
Width := ScaleX(257);
Height := ScaleY(21);
Enabled := False;
ReadOnly := True;
TabOrder := 5;
end;


with Page do
begin
OnActivate := @databaseInfo_Activate;
OnShouldSkipPage := @databaseInfo_ShouldSkipPage;
OnBackButtonClick := @databaseInfo_BackButtonClick;
OnNextButtonClick := @databaseInfo_NextButtonClick;
OnCancelButtonClick := @databaseInfo_CancelButtonClick;
end;

Result := Page.ID;
end;

//************************************************************************************************
// PROCEDURES
//************************************************************************************************
procedure InitializeWizard();
begin
// display custom database page after selecting directory
databaseInfo_CreatePage(wpSelectDir);
end;

Tuesday, May 24, 2005

Google Hack: overriding word breaks

Recently, while working on an Inno installer project, I grew frustrated at Google for returning many "...in no..." results while searching for the string "inno". The solution to override word breaks in Google is to add a preceeding "+" (e.g. +Inno). Not sure why but I thought it was cool I actually received a response from Google:

--------------------------------------------------------------------------------

Re: [#26513876] inno search
1 message

--------------------------------------------------------------------------------
help@google.com Mon, May 23, 2005 at 8:02 PM
To: jeff.com
Hi Jeff,

Thank you for your note. To help "force" a particular search term, you can include a + symbol in front of the word or words you're searching for. For example, a search for [ +inno ] returns the following search results:

http://www.google.com/search?hl=en&lr=&safe=off&c2coff=1&q=%2Binno&btnG=Search

For additional tips, please see http://www.google.com/help/refinesearch.html or check out http://www.google.com/help/operators.html. If you'd like a little guidance, try searching from our Advanced Search page: http://www.google.com/advanced_search

Regards,
The Google Team

Original Message Follows:
------------------------
From: jeff.com
Subject: inno search
Date: Wed, 18 May 2005 18:12:35 -0000

Hi, I'm trying to search on the word inno but it returns results 'in no'.
Enclosing in quotes doesn't seem to help. Suggestions?

Thanks.

Jeff...


Language: en
WebUserLocale: en
IssueType: find_specific

Monday, May 23, 2005

Virtual PC for MSDN Windows 98

I had the darnest time establishing a MS Virtual PC instance using the MSDN copy of Windows 98 SE. The Windows XP and 2000 bootable CDs prompted me during installation while Windows 98, living in a subdirectory and not bootable, just kept throwing errors. Finally, I came up with the following:

1. Obtain a Window 98 boot disk (I ended up using Bootdisk.com). (A little scary from a security aspect, but I needed to get this done)
2. Boot from this disk normally until arriving at a command prompt
3. fdisk the virtual C: drive
4. format the virtual C: drive
5. copy the Windows 98 installation directory and files from the CD onto the virtual C:
6. execute setup.exe from the directory where you just copied the files

BTW, it would be an improvement if Virtual PC MSDN would include vanilla installations for all the MS operating systems. Windows XP and 2000 are straightforward but Windows 98 is tricky and they all consume quite a bit of time to establish. A fat DVD containing vanilla instances would be tight.

Wednesday, May 04, 2005

Regular Expression Resource Sites

Regular Expression Library
Regex Coach
Extreme Regex Foo

Great discussion implementation: Scotts.com

I think Scott's lawn care site does an outstanding job providing very helpful information in a discussion format. The branding matches the root web site dead on, it looks very professional yet fresh and appealing, and real live experts (e.g. "Scotts WebLawn Guy") monitor the site providing resolution to otherwise elusive problems. Accounts are integrated with the scotts.com site but one doesn't need to log in to view discussion postings. The technology is Fuse Talk available in Cold Fusion and ASP.Net. Basic edition is $129.

Finally, this vehicle creates a huge marketing win for Scott's. For example, check out this softball thread. Scotts WebLawn Guy knocks one out of the park when asking "If Scotts could make (product idea) that would (blank), I would definitely buy it." and receiving 21 posts!

SMB: Backup Options

Small Business Backup Comparisons