2005-10-07 17:42:18 +02:00
unit UnitInstall;
interface
uses SysUtils, Classes, Windows, Graphics, Forms, ShellAPI, Controls, Messages,
TlHelp32, IdFTPCommon, ComCtrls;
type TOS = ( osWindows, osLinux) ;
procedure AddStatus( Text : String ; Color: TColor; ShowTime: Boolean = True ) ;
procedure AddDone( Additional: String = '' ) ;
procedure AddSkipped;
procedure AddNotFound;
procedure DownloadFile( eFile: String ; eDestination: String ) ;
2007-10-10 23:48:44 +02:00
procedure BasicInstallation( ePath: String ; SteamInstall, ListenInstall: Boolean ; OS: TOS; const Source: Boolean ) ;
procedure InstallDedicated( eModPath: String ; const UseSteam, Source: Boolean ) ;
procedure InstallListen( ePath: String ; const Source: Boolean ) ;
procedure InstallCustom( ePath: String ; eOS: TOS; const Source: Boolean ) ;
procedure InstallFTP( OS: TOS; const Source: Boolean ) ;
2005-10-07 17:42:18 +02:00
var StartTime: TDateTime;
SteamPath: String ;
StandaloneServer: String ;
Cancel: Boolean = False ;
implementation
uses UnitfrmMain, UnitfrmProxy, UnitFunctions, UnitPackSystem;
// useful stuff
function InstallTime: String ;
begin
2007-10-16 21:02:33 +02:00
Result : = Copy( FormatDateTime( 'HH:MM:SS' , Now - StartTime) , 4 , 5 ) ;
2005-10-07 17:42:18 +02:00
end ;
procedure AddStatus( Text : String ; Color: TColor; ShowTime: Boolean = True ) ;
begin
frmMain. rtfDetails. SelStart : = Length( frmMain. rtfDetails. Text ) ;
if ShowTime then begin
frmMain. rtfDetails. SelAttributes. Color : = clBlack;
if frmMain. rtfDetails. Text = '' then
frmMain. rtfDetails. SelText : = '[' + InstallTime + '] '
else
frmMain. rtfDetails. SelText : = #13 #10 + '[' + InstallTime + '] ' ;
frmMain. rtfDetails. SelStart : = Length( frmMain. rtfDetails. Text ) ;
end
else
frmMain. rtfDetails. SelText : = #13 #10 ;
frmMain. rtfDetails. SelStart : = Length( frmMain. rtfDetails. Text ) ;
frmMain. rtfDetails. SelAttributes. Color : = Color;
frmMain. rtfDetails. SelText : = Text ;
frmMain. rtfDetails. Perform( WM_VSCROLL, SB_BOTTOM, 0 ) ;
frmMain. Repaint;
Application. ProcessMessages;
end ;
procedure AddDone( Additional: String = '' ) ;
begin
frmMain. rtfDetails. SelStart : = Length( frmMain. rtfDetails. Text ) ;
frmMain. rtfDetails. SelAttributes. Color : = clGreen;
if Additional = '' then
frmMain. rtfDetails. SelText : = ' Done.'
else
frmMain. rtfDetails. SelText : = ' Done, ' + Additional + '.' ;
frmMain. rtfDetails. Perform( WM_VSCROLL, SB_BOTTOM, 0 ) ;
frmMain. Repaint;
Application. ProcessMessages;
end ;
procedure AddSkipped;
begin
frmMain. rtfDetails. SelStart : = Length( frmMain. rtfDetails. Text ) ;
frmMain. rtfDetails. SelAttributes. Color : = $004080FF ; // orange
frmMain. rtfDetails. SelText : = ' Skipped.' ;
frmMain. rtfDetails. Perform( WM_VSCROLL, SB_BOTTOM, 0 ) ;
frmMain. Repaint;
Application. ProcessMessages;
end ;
procedure AddNotFound;
begin
frmMain. rtfDetails. SelStart : = Length( frmMain. rtfDetails. Text ) ;
frmMain. rtfDetails. SelAttributes. Color : = clRed;
frmMain. rtfDetails. SelText : = ' Not found.' ;
frmMain. rtfDetails. Perform( WM_VSCROLL, SB_BOTTOM, 0 ) ;
frmMain. Repaint;
Application. ProcessMessages;
end ;
procedure FileCopy( Source, Destination: String ; CopyConfig: Boolean ; AddStatus: Boolean = True ) ;
begin
if ( not CopyConfig) and ( Pos( 'config' , Source) < > 0 ) then begin
if AddStatus then
AddSkipped;
exit;
end ;
if not FileExists( Source) then begin
if AddStatus then
AddNotFound;
exit;
end ;
try
if FileExists( Destination) then
DeleteFile( PChar( Destination) ) ;
CopyFile( PChar( Source) , PChar( Destination) , False ) ;
except
Application. ProcessMessages;
end ;
if AddStatus then
AddDone;
end ;
procedure DownloadFile( eFile: String ; eDestination: String ) ;
var TransferType: TIdFTPTransferType;
begin
// There's only one file to download and it's ASCII :]
TransferType : = ftASCII;
if frmMain. IdFTP. TransferType < > TransferType then
frmMain. IdFTP. TransferType : = TransferType;
// download the file
frmMain. IdFTP. Get( eFile, eDestination, True ) ;
end ;
procedure UploadFile( eFile: String ; eDestination: String ; CopyConfig: Boolean = True ) ;
var TransferType: TIdFTPTransferType;
begin
if ( Pos( 'config' , eFile) > 0 ) and ( not CopyConfig) then begin
AddSkipped;
exit;
end ;
eDestination : = StringReplace( eDestination, '\' , '/' , [ rfReplaceAll] ) ;
// the same as in DownloadFile()
TransferType : = ftBinary;
if ExtractFileExt( LowerCase( eFile) ) = '.txt' then TransferType : = ftASCII;
if frmMain. IdFTP. TransferType < > TransferType then
frmMain. IdFTP. TransferType : = TransferType;
// upload the file
frmMain. IdFTP. Put( eFile, eDestination) ;
AddDone;
end ;
procedure FTPMakeDir( eDir: String ) ;
begin
eDir : = StringReplace( eDir, '\' , '/' , [ rfReplaceAll] ) ;
try
frmMain. IdFTP. MakeDir( eDir) ;
except
Application. ProcessMessages;
end ;
end ;
function FSize( eFile: String ) : Cardinal ;
var eRec: TSearchRec;
begin
if FindFirst( eFile, faAnyFile, eRec) = 0 then
Result : = eRec. Size
else
Result : = 0 ;
end ;
// stuff for killing processes
function GetProcessID( sProcName: String ) : Integer ;
var
hProcSnap: THandle;
pe32: TProcessEntry32;
begin
result : = - 1 ;
hProcSnap : = CreateToolHelp32SnapShot( TH32CS_SNAPPROCESS, 0 ) ;
if hProcSnap = INVALID_HANDLE_VALUE then
exit;
pe32. dwSize : = SizeOf( ProcessEntry32) ;
if Process32First( hProcSnap, pe32) = true then begin
while Process32Next( hProcSnap, pe32) = true do begin
if pos( sProcName, pe32. szExeFile) < > 0 then
result : = pe32. th32ProcessID;
end ;
end ;
CloseHandle( hProcSnap) ;
end ;
procedure KillProcess( dwProcID: DWORD) ;
var
hProcess : Cardinal ;
dw : DWORD;
begin
hProcess : = OpenProcess( SYNCHRONIZE or PROCESS_TERMINATE, False , dwProcID) ;
TerminateProcess( hProcess, 0 ) ;
dw : = WaitForSingleObject( hProcess, 5 0 0 0 ) ;
case dw of
WAIT_TIMEOUT: begin
CloseHandle( hProcess) ;
exit;
end ;
WAIT_FAILED: begin
RaiseLastOSError;
CloseHandle( hProcess) ;
exit;
end ;
end ;
CloseHandle( hProcess) ;
end ;
// Installation here
{ Basic Installation }
2007-10-10 23:48:44 +02:00
procedure BasicInstallation( ePath: String ; SteamInstall, ListenInstall: Boolean ; OS: TOS; const Source: Boolean ) ;
2005-10-07 17:42:18 +02:00
var eStr: TStringList;
i: integer ;
CopyConfig: Boolean ;
eFound: Boolean ;
begin
2005-12-28 01:09:55 +01:00
frmMain. ggeAll. MaxValue : = 8 ;
2005-10-07 17:42:18 +02:00
frmMain. ggeAll. Progress : = 0 ;
frmMain. ggeItem. MaxValue : = 1 ;
frmMain. ggeItem. Progress : = 0 ;
2007-10-13 22:10:19 +02:00
{ if ( GetProcessID( 'Steam.exe' ) < > - 1 ) and ( SteamInstall) then begin
2005-10-07 17:42:18 +02:00
if MessageBox( frmMain. Handle, 'Steam is still running. It is necersarry to shut it down before you install Metamod:Source. Shut it down now?' , PChar( frmMain. Caption) , MB_ICONQUESTION + MB_YESNO) = mrYes then begin
AddStatus( 'Shutting down Steam...' , clBlack, False ) ;
if GetProcessID( 'Steam.exe' ) = - 1 then
AddDone
else
KillProcess( GetProcessID( 'Steam.exe' ) ) ;
while GetProcessID( 'Steam.exe' ) < > - 1 do begin // sure is sure...
Sleep( 5 0 ) ;
Application. ProcessMessages;
end ;
AddDone;
end
else begin
Application. Terminate;
exit;
end ;
2007-10-13 22:10:19 +02:00
end ; }
2005-10-07 17:42:18 +02:00
frmMain. ggeAll. Progress : = 1 ;
frmMain. ggeItem. Progress : = 1 ;
{ Unpack }
frmMain. ggeItem. Progress : = 0 ;
AddStatus( 'Unpacking files...' , clBlack) ;
2007-10-10 23:48:44 +02:00
if not Unpack( Source) then begin
2006-06-28 00:39:42 +02:00
AddStatus( 'No files attached!' , clRed) ;
Screen. Cursor : = crDefault;
exit;
end ;
2005-10-07 17:42:18 +02:00
AddDone;
frmMain. ggeAll. Progress : = 2 ;
frmMain. ggeItem. Progress : = 1 ;
2005-12-28 01:09:55 +01:00
{ Check for installation / Create directories }
2005-10-07 17:42:18 +02:00
CopyConfig : = True ;
2005-12-28 01:09:55 +01:00
AddStatus( 'Creating directories...' , clBlack) ;
2005-10-07 17:42:18 +02:00
if DirectoryExists( ePath + 'addons\metamod\bin' ) then begin
case MessageBox( frmMain. Handle, 'A Metamod:Source installation was already detected. If you choose to reinstall, your configuration files will be erased. Click Yes to continue, No to Upgrade, or Cancel to abort the install.' , PChar( frmMain. Caption) , MB_ICONQUESTION + MB_YESNOCANCEL) of
mrNo: CopyConfig : = False ;
mrCancel: begin
Application. Terminate;
exit;
end ;
end ;
2005-12-28 01:09:55 +01:00
AddSkipped;
end
else begin
2005-10-07 17:42:18 +02:00
frmMain. ggeItem. Progress : = 0 ;
ForceDirectories( ePath + 'addons\metamod\bin' ) ;
AddDone;
2005-12-28 01:09:55 +01:00
end ;
2005-10-07 17:42:18 +02:00
frmMain. ggeItem. Progress : = 1 ;
frmMain. ggeAll. Progress : = 3 ;
{ gameinfo.txt }
if not FileExists( ePath + 'gameinfo.txt' ) then begin
if MessageBox( frmMain. Handle, 'The file "gameinfo.txt" couldn' 't be found. Continue installation?' , PChar( frmMain. Caption) , MB_ICONQUESTION + MB_YESNO) = mrNo then begin
AddStatus( 'Installation canceled by user!' , clRed, False ) ;
Screen. Cursor : = crDefault;
Cancel : = True ;
exit;
end ;
end
else begin
eStr : = TStringList. Create;
{ Metaplugins.ini }
frmMain. ggeItem. Progress : = 0 ;
AddStatus( 'Creating metaplugins.ini...' , clBlack) ;
if CopyConfig then begin
eStr. SaveToFile( ePath + 'addons\metamod\metaplugins.ini' ) ;
AddDone;
end
else
AddSkipped;
frmMain. ggeItem. Progress : = 1 ;
frmMain. ggeAll. Progress : = 4 ;
{ Gameinfo.txt }
frmMain. ggeItem. Progress : = 0 ;
eFound : = False ;
AddStatus( 'Editing gameinfo.txt...' , clBlack) ;
eStr. LoadFromFile( ePath + 'gameinfo.txt' ) ;
for i : = 0 to eStr. Count - 1 do begin
if Trim( LowerCase( eStr[ i] ) ) = 'gamebin |gameinfo_path|addons/metamod/bin' then begin
eFound : = True ;
break;
end ;
end ;
if not eFound then begin
for i : = 0 to eStr. Count - 1 do begin
if Trim( eStr[ i] ) = 'SearchPaths' then begin
eStr. Insert( i + 2 , ' GameBin |gameinfo_path|addons/metamod/bin' ) ;
break;
end ;
end ;
2005-12-28 01:09:55 +01:00
SetFileAttributes( PChar( ePath + 'gameinfo.txt' ) , 0 ) ;
2005-10-07 17:42:18 +02:00
eStr. SaveToFile( ePath + 'gameinfo.txt' ) ;
2005-12-28 01:09:55 +01:00
SetFileAttributes( PChar( ePath + 'gameinfo.txt' ) , faReadOnly) ; // important for listen servers
2005-10-07 17:42:18 +02:00
AddDone;
end
else
AddSkipped;
eStr. Free;
frmMain. ggeItem. Progress : = 1 ;
frmMain. ggeAll. Progress : = 5 ;
end ;
{ Copy files }
frmMain. ggeItem. Progress : = 0 ;
AddStatus( 'Copying server.dll...' , clBlack) ;
CopyFile( PChar( ExtractFilePath( ParamStr( 0 ) ) + 'server.dll' ) , PChar( ePath + 'addons\metamod\bin\server.dll' ) , False ) ;
AddDone;
frmMain. ggeItem. Progress : = 1 ;
frmMain. ggeAll. Progress : = 6 ;
2005-12-28 01:09:55 +01:00
if ListenInstall then begin
ePath : = ExtractFilePath( Copy( ePath, 1 , Length( ePath) - 1 ) ) ;
AddStatus( 'Copying hl2launch.exe...' , clBlack) ;
CopyFile( PChar( ExtractFilePath( ParamStr( 0 ) ) + 'hl2launch.exe' ) , PChar( ePath + 'hl2launch.exe' ) , False ) ;
AddDone;
end ;
2005-10-07 17:42:18 +02:00
{ Remove files }
frmMain. ggeItem. Progress : = 0 ;
AddStatus( 'Removing temporary files...' , clBlack) ;
2005-12-28 01:09:55 +01:00
DeleteFile( PChar( ExtractFilePath( ParamStr( 0 ) ) + 'hl2launch.exe' ) ) ;
2005-10-07 17:42:18 +02:00
DeleteFile( PChar( ExtractFilePath( ParamStr( 0 ) ) + 'server.dll' ) ) ;
DeleteFile( PChar( ExtractFilePath( ParamStr( 0 ) ) + 'server_i486.so' ) ) ;
AddDone;
frmMain. ggeItem. Progress : = 1 ;
2005-12-28 01:09:55 +01:00
frmMain. ggeAll. Progress : = 8 ;
2005-10-07 17:42:18 +02:00
{ Finish }
AddStatus( '' , clBlack, False ) ;
AddStatus( 'Finished installation!' , clBlack, False ) ;
frmMain. cmdNext. Enabled : = True ;
frmMain. cmdCancel. Hide;
Screen. Cursor : = crDefault;
2005-12-28 01:09:55 +01:00
if ListenInstall then
2007-10-16 21:02:33 +02:00
MessageBox( frmMain. Handle, PChar( 'The Source launcher "hl2launch.exe" has been copied to ' + ePath + '. You can use it to start your game with Metamod:Source enabled.' ) , PChar( Application. Title) , MB_ICONINFORMATION) ;
2005-10-07 17:42:18 +02:00
end ;
{ Dedicated Server }
2007-10-10 23:48:44 +02:00
procedure InstallDedicated( eModPath: String ; const UseSteam, Source: Boolean ) ;
2005-10-07 17:42:18 +02:00
begin
StartTime : = Now;
Screen. Cursor : = crHourGlass;
AddStatus( 'Starting Metamod:Source installation on dedicated server...' , clBlack, False ) ;
2007-10-10 23:48:44 +02:00
BasicInstallation( eModPath, UseSteam, False , osWindows, Source) ;
2005-10-07 17:42:18 +02:00
end ;
{ Listen Server }
2007-10-10 23:48:44 +02:00
procedure InstallListen( ePath: String ; const Source: Boolean ) ;
2005-10-07 17:42:18 +02:00
begin
StartTime : = Now;
Screen. Cursor : = crHourGlass;
AddStatus( 'Starting Metamod:Source installation on the listen server...' , clBlack) ;
2007-10-10 23:48:44 +02:00
BasicInstallation( ePath, True , True , osWindows, Source) ;
2005-10-07 17:42:18 +02:00
end ;
{ Custom mod }
2007-10-10 23:48:44 +02:00
procedure InstallCustom( ePath: String ; eOS: TOS; const Source: Boolean ) ;
2005-10-07 17:42:18 +02:00
begin
StartTime : = Now;
Screen. Cursor : = crHourGlass;
AddStatus( 'Starting Metamod:Source installation...' , clBlack) ;
2007-10-10 23:48:44 +02:00
BasicInstallation( ePath, False , False , eOS, Source) ;
2005-10-07 17:42:18 +02:00
end ;
{ FTP }
2007-10-10 23:48:44 +02:00
procedure InstallFTP( OS: TOS; const Source: Boolean ) ;
2005-10-07 17:42:18 +02:00
function DoReconnect: Boolean ;
begin
Result : = False ;
if MessageBox( frmMain. Handle, 'You have been disconnected due to an error. Try to reconnect?' , PChar( Application. Title) , MB_ICONQUESTION + MB_YESNO) = mrYes then begin
try
frmMain. IdFTP. Connect;
Result : = True ;
except
MessageBox( frmMain. Handle, 'Failed to reconnect. Installation aborted.' , PChar( Application. Title) , MB_ICONSTOP) ;
end ;
end ;
end ;
label CreateAgain;
label UploadAgain;
var eStr: TStringList;
i: integer ;
CopyConfig, eFound: Boolean ;
begin
frmMain. cmdCancel. Show;
frmMain. cmdNext. Hide;
Screen. Cursor : = crHourGlass;
frmMain. ggeAll. MaxValue : = 6 ;
frmMain. ggeAll. Progress : = 0 ;
frmMain. ggeItem. MaxValue : = 1 ;
frmMain. ggeItem. Progress : = 0 ;
{ Unpack }
frmMain. ggeItem. Progress : = 0 ;
AddStatus( 'Unpacking files...' , clBlack) ;
2007-10-10 23:48:44 +02:00
if not Unpack( Source) then begin
2006-06-28 00:39:42 +02:00
AddStatus( 'No files attached!' , clRed) ;
Screen. Cursor : = crDefault;
exit;
end ;
2005-10-07 17:42:18 +02:00
AddDone;
frmMain. ggeAll. Progress : = 2 ;
frmMain. ggeItem. Progress : = 1 ;
{ Check for installation }
AddStatus( 'Editing gameinfo.txt...' , clBlack) ;
eStr : = TStringList. Create;
DownloadFile( 'gameinfo.txt' , ExtractFilePath( ParamStr( 0 ) ) + 'gameinfo.txt' ) ;
eStr. LoadFromFile( ExtractFilePath( ParamStr( 0 ) ) + 'gameinfo.txt' ) ;
CopyConfig : = True ;
eFound : = False ;
for i : = 0 to eStr. Count - 1 do begin
if Trim( LowerCase( eStr[ i] ) ) = 'gamebin |gameinfo_path|addons/metamod/bin' then begin
eFound : = True ;
case MessageBox( frmMain. Handle, 'A Metamod:Source installation was already detected. If you choose to reinstall, your configuration files will be erased. Click Yes to continue, No to Upgrade, or Cancel to abort the install.' , PChar( frmMain. Caption) , MB_ICONQUESTION + MB_YESNOCANCEL) of
mrNo: CopyConfig : = False ;
mrCancel: begin
Application. Terminate;
eStr. Free;
exit;
end ;
end ;
break;
end ;
end ;
if not eFound then begin
for i : = 0 to eStr. Count - 1 do begin
if Trim( eStr[ i] ) = 'SearchPaths' then begin
eStr. Insert( i + 2 , ' GameBin |gameinfo_path|addons/metamod/bin' ) ;
AddDone;
break;
end ;
end ;
eStr. SaveToFile( ExtractFilePath( ParamStr( 0 ) ) + 'gameinfo.txt' ) ;
UploadFile( ExtractFilePath( ParamStr( 0 ) ) + 'gameinfo.txt' , 'gameinfo.txt' ) ;
try
AddStatus( 'Trying to set gameinfo.txt to read-only...' , clBlack) ;
frmMain. IdFTP. Site( 'CHMOD 744 gameinfo.txt' ) ;
AddDone;
except
AddStatus( 'Warning: CHMOD not supported.' , clMaroon) ;
end ;
DeleteFile( PChar( ExtractFilePath( ParamStr( 0 ) ) + 'gameinfo.txt' ) ) ;
end
else
AddSkipped;
frmMain. ggeAll. Progress : = 3 ;
frmMain. ggeItem. Progress : = 1 ;
{ Create directories }
frmMain. ggeItem. Progress : = 0 ;
frmMain. ggeItem. MaxValue : = 3 ;
AddStatus( 'Creating directories...' , clBlack) ;
if not eFound then begin
FTPMakeDir( 'addons' ) ;
frmMain. IdFTP. ChangeDir( 'addons' ) ;
frmMain. ggeItem. Progress : = 1 ;
FTPMakeDir( 'metamod' ) ;
frmMain. IdFTP. ChangeDir( 'metamod' ) ;
frmMain. ggeItem. Progress : = 2 ;
FTPMakeDir( 'bin' ) ;
frmMain. ggeItem. Progress : = 3 ;
AddDone;
end
else
AddSkipped;
frmMain. ggeAll. Progress : = 4 ;
frmMain. ggeItem. Progress : = 3 ;
{ Upload metaplugins.ini }
frmMain. ggeAll. Progress : = 4 ;
frmMain. ggeItem. MaxValue : = 1 ;
frmMain. ggeItem. Progress : = 0 ;
AddStatus( 'Uploading metaplugins.ini...' , clBlack) ;
if CopyConfig then begin
eStr. Clear;
eStr. SaveToFile( ExtractFilePath( ParamStr( 0 ) ) + 'metaplugins.ini' ) ;
UploadFile( ExtractFilePath( ParamStr( 0 ) ) + 'metaplugins.ini' , 'metaplugins.ini' ) ;
DeleteFile( PChar( ExtractFilePath( ParamStr( 0 ) ) + 'metaplugins.ini' ) ) ;
end
else
AddSkipped;
frmMain. ggeAll. Progress : = 5 ;
frmMain. ggeItem. Progress : = 1 ;
{ Upload server.dll / server_i486.so }
frmMain. tmrSpeed. Enabled : = True ;
frmMain. ggeItem. Progress : = 0 ;
frmMain. IdFTP. ChangeDir( 'bin' ) ;
if OS = osWindows then begin
AddStatus( 'Uploading server.dll...' , clBlack) ;
frmMain. ggeItem. MaxValue : = FSize( ExtractFilePath( ParamStr( 0 ) ) + 'server.dll' ) ;
UploadFile( ExtractFilePath( ParamStr( 0 ) ) + 'server.dll' , 'server.dll' ) ;
end
else begin
AddStatus( 'Uploading server_i486.so...' , clBlack) ;
frmMain. ggeItem. MaxValue : = FSize( ExtractFilePath( ParamStr( 0 ) ) + 'server_i486.so' ) ;
UploadFile( ExtractFilePath( ParamStr( 0 ) ) + 'server_i486.so' , 'server_i486.so' ) ;
end ;
{ Remove created files }
AddStatus( 'Removing temporary files...' , clBlack) ;
2005-12-28 01:51:22 +01:00
DeleteFile( PChar( ExtractFilePath( ParamStr( 0 ) ) + 'hl2launch.exe' ) ) ;
2005-10-07 17:42:18 +02:00
DeleteFile( PChar( ExtractFilePath( ParamStr( 0 ) ) + 'server.dll' ) ) ;
DeleteFile( PChar( ExtractFilePath( ParamStr( 0 ) ) + 'server_i486.so' ) ) ;
AddDone;
{ End }
frmMain. IdFTP. Disconnect;
frmMain. ggeAll. Progress : = frmMain. ggeAll. MaxValue;
frmMain. ggeItem. Progress : = frmMain. ggeItem. MaxValue;
AddStatus( '' , clBlack, False ) ;
AddStatus( 'Finished installation!' , clBlack, False ) ;
frmMain. tmrSpeed. Enabled : = False ;
eStr. Free;
Screen. Cursor : = crDefault;
frmMain. cmdNext. Enabled : = True ;
frmMain. cmdCancel. Hide;
frmMain. cmdNext. Show;
frmMain. tmrSpeed. Enabled : = False ;
frmMain. Caption : = Application. Title;
end ;
end .