About The Autoupgrade Class Framework
Http://www.devx.com/dotnet/Article/10045/0/Page/4http://www.sml.hw.ac.uk/computing/delphi_updatevir.html
School of management computing helpdelphi applications: updatevir.exe
Updatevir.exe
Function: Reads Registry to determine current McAffee scan engine and virus database version; runs updated virus engine / database if required; optionally logs results to file Lists current update files (superdat) on Heriot-Watt FTP site via built-in FTP connection and. Changes Default Update FTP Site To Heriot-Watt University. Current Version: 1.6 Author: Duncan Potter Date: 8th October 2001 Location: Sys: public Download: Updatevir.zip (246K)
Updatevir.Pas (Main Body of Code)
unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Buttons, nwbase, nwlib, ExtCtrls, FileCtrl, Registry, INIFiles; type TForm1 = class (TForm) LblTitle: TLabel; MemoInfo: TMemo; BButtNext: TBitBtn; BButtCancel: TBitBtn; NWBase1: TNWBase; lblUserName: TLabel; Timer1: TTimer; LblCheckEngineVer: TLabel; Timer2: TTimer; PanelInfo: TPanel; LblFullName: TLabel; LblDetails: TLabel; LblEngineVersion: TLabel; LblEngineVerFound: TLabel; BButtHelp: TBitBtn; LblVirDef: TLabel; LblVirDefFound: TLabel; LblEngineUpdateVer: TLabel; LblVirDefInfo: TLabel; LblVirDefUpgrade: TLabel; LblCheckVirDef: TLabel; LblWinVersion: TLabel; procedure Startup (Sender: TObject); procedure ReadIni (Sender: TObject); procedure BButtCancelClick (Sender: TOBJECT); Procedure BbuttnextClick (Sender: TOBJECT); Procedure Timject; Procedure Checkstatus (Sender: Tobject) ); Procedure Timer2Timer (Sender: TObject); procedure BButtHelpClick (Sender: TObject); procedure FTPSiteChange (Sender: TObject); private {Private declarations} public {Public declarations} end; var Form1: TForm1; Username: String; EngineVerFound: string ; // that read from Registry EngineVerUpgrade: string; // Version of engine in upgrade (read from INI file) UpdateExe: string; // Superdat Executable that runs to upgrade scan engine and virus defs VirDefFound: string; // DAT file version read from Registry VirDefUpgrade: string; // Version of DAT file in the upgrade, read from INI file RunUpdate: Boolean; // If True then update will run WinVersion:.. String; // either 'W95' or 'NT4-2000 '
implementation uses help; function CreateProcessAndWait (AppPath, AppParams: String; Visibility: word): DWord; forward; function CompareEngineVersion (EngineVerFound, EngineVerUpgrade: String): String; forward; function CompareVirDefVersion (VirDefFound, VirDefUpgrade: String): String; forward; {$ R * .dfm} {---------------------------------------} procedure TForm1.Startup (Sender: TObject); begin username: = whoami (0); RunUpdate: = False; // Initialise LblUserName.Caption: = userName; LblUserName.Update; LblFullName.Caption: = FullName (0, username); .. LblFullName.Update; ReadIni (Sender); // Reads version of engine being upgraded CheckStatus (Sender); // Check if update has already run FTPSiteChange (Sender); // Change auto-update to HW FTP siteend; {- ---------------------------------------------} Procedure TFORM1 .Readini (sender: TOBJECT); {reads ini file to find initial settings} Varappini: Tinifile; {variable of type}} inifile: string; {Name of Ini File } Begin try INIFile: = ExtractFilePath (application.exename) 'updatevir.ini'; if not FileExists (INIFile) then begin ShowMessage ( 'Fatal Error: initialisation file' INIFile 'can not be found'); BButtCancelClick (Sender) ; // Quit exit; end; AppIni: = TIniFile.Create (iNIFile); {assign memory for TIniFile object} {Read the engine version to the application window} EngineVerUpgrade: = trim (AppIni.ReadString ( 'Engine', 'EngineUpgradeVer ',' engine unknown '); lblengineUpdatever.caption: = engineverupgrade; {read location of superdat update exe to be run} Updateexe: =
trim (AppIni.ReadString ( 'Engine', 'UpdateExe', 'unknown')); {Read version of virus definitions in the upgrade} VirDefUpgrade: = trim (AppIni.ReadString ( 'Engine', 'VirDefUpgrade', 'unknown' )); Lblvirdefupgrade.caption: = virdefupgrade; finally appini.free; end; end; {---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -----------------} procedure tform1.bbuttcancelclick (sender: TOBJECT); {Close form, check if update has been allowed to run.} begin // if engineverfound <> engineverupgrade then // Update required // if not FoundMoreRecent then // skip this check if more recent engine detected // if MessageDlg ( 'Are you sure your virus scan engine is more recent than' EngineVerUpgrade '?', mtConfirmation, [mbYes, MBNO], 0) = MRYES THEN // ShowMessage ('okay. please ignor this check.') // else // showMessage ('no questionm. this program will run again at login.'); memoinfo.clear; Memoinfo.update; close; application.terminate; en D; {----------------------------------- ----} procedure TForm1.FTPSiteChange (Sender: TObject); {On NT / 2000 changes the FTP DAT auto-update path to the Heriot-Watt site} varReg: TRegistry; FTPLocationHW: String; // Where McAfee should get it's FTP update info.FTPLocationFound: String; // Where McAfee looks for it's FTP update begin try Reg:. = TRegistry.Create; Reg.RootKey: = HKey_Local_Machine; // Section to look for within the registry if not Reg.KeyExists ( ' Software / McAfee / Virusscan / Tasks / Update '
) THEN EXIT // NOT AN NT MACHINE ELSE // AN NT or W2000 Machine with The Required Keys Begin // Room REGISTRY FTPLOCATIONHW: = 'ftp.hw.ac.uk/pub/internal/antivirus/Update/'; REG .OpenKey ( 'Software / McAfee / VirusScan / Tasks / Update', False); // False = Do not create if Reg.ValueExists ( 'szUpdateFTPLocation') then FTPLocationFound: = trim (Reg.ReadString ( 'szUpdateFTPLocation')) .; if lowercase (FTPLocationFound) <> lowercase (trim (FTPLocationHW)) then // change to HW site begin try Reg.WriteString ( 'szUpdateFTPLocation', FTPLocationHW); // Change to HW campus one except begin LblCheckVirDef.Caption: = 'UNABLE TO CHANGE FTP Location.'; Lblcheckvirdf.Update; end; end; // of try-except end; end; finally reg.closekey; reg.free; end; end; {--------- ------------------------------------------} Procedure TFORM1.BBUTTNEXTC Lick (Sender: TOBJECT); {Runs the Anti-Virus Update} // VAR // Updateexe: String; Begin // Updateexe: = 'N: /SCHOOL/INSTALL/VSCAN4.03/AUTOUPGRADE/Setup.exe'; if not FileExists (UpdateExe) then begin ShowMessage ( 'Can not find' UpdateExe); exit; end; Form1.Visible: = False; CreateProcessAndWait (UpdateExe, '', 1); BButtNext.Visible: = False; BButtCancel.Visible: = False; lblfullname.visible: = false; timer1.enabled: = true; // startup countdown to exit memoinfo.clear; memoinfo.visible: = false; lblcheckvirdef.caption: = '
Update is completion! '; Form1.clientHeight: = 104; Form1.Visible: = true; end; {--------------------------- ----------------------------} Function CreateProcessandwait (AppPath, Appparams: String; Visibility: Word): DWORD; VAR SI: TSTARTUPINFO; PI: TProcessInformation; Proc: Thandle; Begin Fillchar (Si, SIZEOF (SI), 0); Si.cb: = SizeOf (Si); Si.WShowWindow: = Visibility; if Not CreateProcess (Pchar (AppPath), Pchar (AppParams) ), NIL, NIL, FALSE, NIL, NIL, SI, PI) THEN RAISE Exception.createfmt ('Failed to Execute Program, Error Code% D', [getLastError]); proc: = pi.hprocess; CloseHandle Pi.hthread; if WaitforsingleObject (Proc, Infinite) <> Wait_failed1 getexitcodeProcess (Proc, Result); CloseHandle (Proc); end; {----------------- ---------------------} Procedure TFORM1.CHECKSTATUS (Sender: Tobject); {CHECKS 1) Version of Dat Files and Engine in registry} varreg: Tregistry; Begin Try {read version of eNG ine and DAT files from Registry} Reg: = TRegistry.Create; Reg.RootKey: = HKey_Local_Machine; // Section to look for within the registry {Check if OS is Windows 95 which stores Virus Def version string differently} Reg.OpenKey ( ' Software / Microsoft / Windows / CurrentVersion ', false; // false = don't create if reg.valueexists (' productname ') THEN WINVERSION: =' W95 'Else Winversion: =' NT4-2000 '; reg.closekey; LBLWINVERSION.CAPTION: = WINVERSION; LBLWINVERSION.UPDATE; if Not Reg.Keyexists ('Software / McAfee / Virusscan') THEN // No Registry Key ... ODD. Begin EngineverFound: = 'unknown';
LblEngineVerFound.Caption: = 'Unknown'; end else begin // Read from Registry Reg.OpenKey ( 'Software / McAfee / VirusScan', False); // False = Do not create if Reg.ValueExists ( 'szEngineVer') then EngineVerFound: = trim (Reg.ReadString ( 'szEngineVer')); LblEngineVerFound.Caption: = EngineVerFound; LblEngineVerFound.Update; if Reg.ValueExists ( 'szVirDefVer') then VirDefFound: = trim (Reg.ReadString ( 'szVirDefVer')) ; // NT4 has format 4.0.4121 // W95 has format 4121 LblVirDefFound.Caption: = VirDefFound; LblVirDefFound.Update; end; {Initial check to make sure value has real data, not 'unknown' etc.} if lowercase (EngineVerFound ) = 'unknown' then begin LblCheckEngineVer.Caption: = 'Unknown scan engine.'; LblCheckEngineVer.Update; BButtCancelClick (Sender); // quit without action exit; end; if length (EngineVerFound) <2 then // maybe no data Or Faulty Data. Begin LBLCheckennev er.Caption: = 'Unknown scan engine.'; LblCheckEngineVer.Update; BButtCancelClick (Sender); // quit without action exit; end; {Now take action depending on what version of engine was found:} if EngineVerFound = EngineVerUpgrade then / / no need to update engine, same versions begin // Form1.ClientHeight: = 112; // Reduce height of form LblCheckEngineVer.Caption: = 'Status: Engine already updated, thank-you!'; LblCheckEngineVer.Update; // Timer1 .Enabled: = true;
// Countdown to Exit end else begin if CompareEngineVersion (EngineVerFound, EngineVerUpgrade) = 'upgrade_yes' then begin RunUpdate: = True; // Set global flag to run the update exe MemoInfo.Visible: = True; MemoInfo.Update; LblCheckEngineVer.. Caption: = 'Status: Engine update required'; LblCheckEngineVer.Font.Color: = clRed; LblCheckEngineVer.Update; end else // function must have detected a later version begin // Form1.ClientHeight: = 112; // Reduce height of FORM LBLCHECKENGINEVER.CAPTION: = 'Status: current engine is more refact.'; lblCheckenGinever.Update; // Timer1.enabled: = true; // countdown to exit end; end; {nt4-2000 code ****** ******** Now CHECK VERSION OF Virus Definitions ***************************************** NT4 HAS VIRDEFFOOND AND VIRDEFUPGRADE Both in Same Format EG 4.0.4120 SO Next test will wor k:} if VirDefFound = VirDefUpgrade then // no need to update engine, same versions begin // Form1.ClientHeight: = 112; // Reduce height of form LblCheckVirDef.Caption: = 'Status: Virus Definitions already updated, thank-you ! '; LblCheckVirDef.Update; if not RunUpdate then begin Form1.ClientHeight: = 112; // Reduce height of form Timer1.Enabled: = True; // Countdown to Exit, since engine does not need update either end;
end else // Call the procedure which determines if a later or earlier version is installed begin // OR W95 is installed, in which case first test in IF block would also fail: if CompareVirDefVersion (VirDefFound, VirDefUpgrade) = 'upgrade_yes' then begin MemoInfo.Visible: = True; MemoInfo.Update; LblCheckVirDef.Caption: = 'Status: Virus Definition update required'; LblCheckVirDef.Font.Color: = clRed; LblCheckVirDef.Update; end else // function must have detected a later version so quit unless Engine needs update begin LblCheckVirDef.Caption: = 'Status: Current virus definitions are more recent.'; LblCheckVirDef.Update; if not RunUpdate then begin Form1.ClientHeight: = 112; // Hides the NEXT button, etc. Timer1. Enabled: = true; // start close procedure end; End; regree; // free registry memory. end; end; {-------------------------------------------------------------------------------------------------------------------------------------------------------- ---------------------------} Function CompareEngineVersion (EngineVerfound, EngineVerupgrade: String): string; {Compares Two Version Strings, Higher Numbers Indicate Later '.' version} {eg EngineVerFound 4.0.60 EngineVerUpgrade 4.0.70so break numbers into parts and compare each delimited value} varE_VerF: array [1..3] of string; // Array holding characters in EngineVerFoundE_VerU: array [1 .. 3] of string; // array Holding Characters in Engineverupgradei, J: Integer; // Loop Counterbit, Test: String; Begin If Length (Engineverfound) <2 Then Begin Result: = '
Upgrade_no '; exit; end; j: = 1; for i: = 1 to length (EngineverFound) do // Step through character, i, 1); // just a single character copied from the = COPY (ENGINEVERFOUND, I, 1) String if Bit = '.' TEN // We've Completed One Subversion of The Engine Version Begin J: = J 1; // So Next E_VER [J] To Be Incremented Will Refer to Next Subversion Number Else Begin // Still Building Subversion. E_VERF [J]: = E_VERF [J] Bit; End; end; {repeat for the Upgrade Engine ... Slightly Wasteful of code} J: = 1; for i : = 1 to Length (Engineverupgrade) Do // Step Through Characters Begin Bit: = COPY (Engineverupgrade, I, 1); // Just A Single Character Copied from the string if bit = '.' Ten // Weide Completed One Subversion of the Engine Version Begin J: = J 1; // So next E_VER [J] To Be Incremented Will Refer to Next Subversion Number End Else Begin // Still Building Subversion. E_VERU [J]: = E_VERU [J] Bit; End; End; {Test: = E_VERU [1] '-' E_VERU [2] '-' E_VERU [3]; showMessage ('Upgrade Version Was' Test); Test: = E_VERF [1] ' - ' E_VERF [2] ' - ' E_VERF [3]; showMessage (' Detected version was ' Test);} {Now compare each version, most significant bit first Convert to integers first} {If one subelement of Found version> that of upgrade version then do not upgrade} Result: =.'
Upgrade_yes'; // set a default for j: = 1 to 3 do begin // showMessage ('Found:' E_VERF [J] 'Upgrade:' E_VERU [J]); if STRTOINT (E_VERF [J]) > StrtOINT (E_VERU [J]) THEN // One Subversion Found> Equiv. Subversion Upgrade Begin Result: = 'Upgrade_no'; EXIT; End; End; End; {---------------- -----------------------------------------} Function Comparevirdefversion (Virdefound, VIRDEFUPGRADE: STRING '.';:) String {Compares two version strings of Virus Defs, higher numbers indicate later version} {eg VirDefFound 4.0.60 VirDefUpgrade 4.0.4104so break numbers into parts and compare each delimited value.Windows 95 stores only the last number - 4104 - WHEREAS NT4 and 2000 Store 4.0.4104, for example.} Vare_VERF: Array [1..3] of string; // array holding characters in virdefounde_veru: array [1..3] of string; // array holding character IN VIRDEFUPGRADEI, J: Integer; // Loop Counterbit: String; Begin if Length (VIRDEFFOON) <2 THEN Begin Result: = 'UPGRADE_NO'; exit; end; {split NT4 / 2000 Virus Def strings Into three Parts:} j: = 1; for i: = 1 to length (virdeffound) do // step through characters begin bit: = COPY (VIRDEFFOUND, I, 1); // Just A Single Character Copied from The String if Bit = '.' TEN // We've Completed One Subversion of The Engine Version Begin J: = J 1; // So next E_VER ELSE BEXT SUBVERSION Number Else Begin // Still Building Subversion. E_VERF [J]: = E_VERF [J] Bit; End; End;
{REPEAT for THE UPGRADE ENGINE ... SLIGHTLY WASTEFUL OF CODE} J: = 1; for i: = 1 to length (VIRDEFUPGRADE) Do // Step THROUGH Characters Begin Bit: = Copy (VirdefuPgrade, i, 1); // Just A Single Character Copied from The STRING IF BIT = '.' TEN // We've Completed One Subversion of The Engine Version Begin J: = J 1; // So Next E_VER [J] To Be Incremented Will Refer to Next NEXT Subversion Number End Else Begin // Still Building Subversion String OR at The End of The String. E_VERU [J]: = E_VERU [J] Bit; End; End; {Start W95 Code, Which Above Tests Will NOT Work for. THIS compares the final string of the upgrade virus definition with the VirDefFound string eg Last number of VirDefUpgrade (4.1.4014) is here '4014' VirDefFound for W95 is the single number '4014' The test thus compares the least significant bit of VirDefUpgrade, which Isn't Good But That's How McAffee Store The Virus Definition . Version string} if WinVersion = 'W95' then if StrToInt (E_VerU [3])> StrToInt (VirDefFound) then begin ShowMessage (VirDefFound); Result: = 'upgrade_yes'; exit; // Do not process NT4-2000 code END ELSE BEGIN RESULT: = 'upgrade_no'; exit; end; {test: = E_VERU [1] '-' E_VERU [2] '-' E_VERU [3]; showMessage ('Virus Def Upgrade Version Was " TEST); TEST: = E_VERF [1] '-' E_VERF [2] '-'