Asta Logo ASTA AutoUpdate

Automatic Client Updates

 

 

Automatic Client Updates

One of Asta’s powerful features is that Clients can be updated automatically when they log in to the server.  For a server with a large number of widespread clients, this is a great time and energy saver. You can download the example here

For the updating to work correctly, very little coding need be done, but the following points must be checked:

The project AutoUpgrade.BPG contains 2 applications, a server and a client.  The server, in particular, contains very little code. 

The Server Application

I dropped an memo and an AstaServerSocket component on a form F_Ser, renamed the memo mm, and the AstaSocket ss, set the Active property to TRUE, and coded the OnClientLogin() event as:

procedure TF_Ser.ssClientLogin(Sender: TObject; UserName,

  Password, AppName: String; var Verified: Boolean);

var

   sz : string;

begin

   sz := format( 'User %s, Password %s, AppName %s', [ UserName, Password, AppName ] );

   Verified := ( trim( Password ) <> '' ) and

      ( trim( AppName ) <> '' );

   if Verified then

      mm.Lines.Add( sz + ' - accepted' )

   else

      mm.Lines.Add( sz + ' - rejected' );

end;

 

 

I then coded the Server Socket OnAstaClientUpdate() event to:

procedure TF_Ser.ssClientDisconnect(Sender: TObject;

  Socket: TCustomWinSocket);

begin

   mm.Lines.Add( format( 'Socket %s:%d disconnected',

      [ Socket.RemoteAddress, Socket.RemotePort ] ) );

end;

 

procedure TF_Ser.ssClientError(Sender: TObject;

  Socket: TCustomWinSocket; ErrorEvent: TErrorEvent;

  var ErrorCode: Integer);

begin

   mm.Lines.Add( format( 'Error %d', [ Errorcode ] ) );

end;

 

and the OnError() and OnDisconnect() events as:

procedure TF_Ser.ssAstaClientUpdate(Sender: TObject;

  UserName, AppName, OldVer, NewVer: String);

begin

   mm.Lines.Add(

        format( 'App %s (User %s), updated from %s to %s',

       [ AppName, UserName, OldVer, NewVer ] ) );

end;

 

 

And that is all that is required at the Server!

The Client Project

The Client project is hardly more complicated.  Starting a new project I dropped a memo, an AstaclientSocket, 4 buttons, a DataSource,  a Grid and a Navigator onto a form F_Cli.

I set the AstaclientSocket properties as follows:

I coded the OnConnect Event as:

procedure TF_Cli.csConnect(Sender: TObject; Socket: TCustomWinSocket);

begin

   mm.Lines.Add( 'Connected' );

end;

 

 

The OnDisconnect Event as:

procedure TF_Cli.csDisconnect(Sender: TObject; Socket: TCustomWinSocket);

begin

   mm.Lines.Add( 'Disconnected' );

end;

 

 

The OnLoginAttempt Event as:

procedure TF_Cli.csLoginAttempt(Sender: TObject; ClientVerified:       Boolean);

begin

   if ClientVerified then

      mm.Lines.Add( 'Login Accepted' )

   else

      mm.Lines.Add( 'Login Refused' );

end;

 

and the ServerUtilityInfoEvent() as:

procedure TF_Cli.csServerUtilityInfoEvent(Sender: TObject; MsgID: Integer;

  Params: TAstaParamList);

begin

   if MsgId = ord( uiAutoClientUpgradeInfo ) then begin

      Src.DataSet.Free;

      Src.DataSet := StringToDataSet( params[ 0 ].AsString );

   end;

end;

 

Note:  You will find you need to include units AstaDrv2 and AstaStringLine for this to compile.

Coding BtnConnect’s  OnClick() event as

procedure TF_Cli.btnConnectClick(Sender: TObject);

begin

   if cs.Active then begin

      cs.Active := FALSE;

      cs.Close;

   end else

      cs.Active := TRUE;

end;

 

 

and the form’s FormCreate() as:

procedure TF_Cli.FormCreate(Sender: TObject);

begin

   Caption := format( 'AppName: %s, Version %s',

       [ cs.ApplicationName, cs.ApplicationVersion ] );

end;

 

gave me a basic working system, and I was able to test it with the server running to check that both ends registered Logins and Disconnects.

The client application now looks like:

Fig. 1.1

Now for the interesting stuff!  Code a method for the Request Versions button as:

procedure TF_Cli.btnReqVerClick(Sender: TObject);

begin

   cs.RequestUtilityInfo( uiAutoClientUpgradeInfo, '' );

end;

 

and a method for the Upgrade Versions button as:

procedure TF_Cli.btnUpgradeVerClick(Sender: TObject);

var

   P : TAstaParamList;

begin

   if Src.DataSet = nil then

      raise EDataBaseError.Create(

           'You need fetch a dataset first!');

   if Src.DataSet.state in [ dsedit, dsinsert ] then

      Src.DataSet.Post;

 

   P := TAstaParamList.Create;

   try

      P.FastAdd( DataSetToString( TAstaDataSet( Src.DataSet ) ) );

      cs.RequestUtilityInfo( uiWriteAutoClientUpgradeDataSet,                                                                               P.AsTokenizedString( False ) );

   finally

      P.Free;

   end;

end;

 

When you rerun the application, and request Version information, a dataset, initially empty is sent.  The dataset fields are:

FieldName

Example for this client program

Comments

Application Name

upgCli

Should be set to match the ApplicationName version of the client application you wish to upgrade.  It is case-insensitive.

Version

1.1

Should be set to the latest version of the client application.  This (although entered as string value) should be numeric, and will normally be a floating-point value.  This is the value that will be compared to your current client ApplicationVersion.

New File Name

cliapps\upgcli.1.1

This should be set to the location and filename of the client application on the server system.  It can be either an absolute location, or a location relative to the application directory of the server.  Note that it does not need to have a EXE extension.

 

When you have entered the above values, and sent the updated dataset back to the server, (to be stored in the registry), restart the client and server, press the request button again, and verify that the dataset information has been stored correctly.  The client screen should appear as:

Fig. 1.2

To complete the client, code the following for the Set Client Version button:

procedure TF_Cli.btnSetCliVerClick(Sender: TObject);

var

   sz : string;

   dVer : extended;

begin

   sz := cs.ApplicationVersion;

   if InputQuery( 'Application Version', 'Version', sz ) then

      try

         dVer := StrToFloat( sz );

         cs.ApplicationVersion := sz;

         Caption := format( 'AppName: %s, Version %s',

           [ cs.ApplicationName, cs.ApplicationVersion ] );

      except

         raise Exception.Create( 'Version must be numeric' );

      end;

end;

 

 

and code a SetButtons routine to tidy up the display:

Procedure TF_Cli.SetButtons;

begin

   if cs.Active then

      btnConnect.Caption := 'DisConnect'

   else

      btnConnect.Caption := 'Connect';

   btnReqVer.Enabled := cs.Active;

   btnUpgradeVer.Enabled := cs.Active and ( Src.DataSet <> NIL );

end;

 

 

This routine should be called from FormCreate(), OnConnect(), OnDisconnect() and OnServerUtilityEvent(). 

Compile and save the new exe to the cliapps subdirectory and rename it (in that location) to upgcli.1.1

Now, to test the automatic upgrade:

·         start the server upgser.exe

·         start the client upgcli.exe

·         login in the usual way

·         disconnect

·         change the version number from 1.1 to 1.0 (unrealistic to downgrade via a button in this way, but this is only for testing)

·         login again – behold your application should disappear before your eyes, and be replaced by the 1.1 version you stored in cliapps!

Summary

You can achieve Automatic upgrading of client applications easily with Asta.  All it requires is a small amount of coding, and systematic version numbering of the client applications.

You will probably want to write a small Admin Client that retrieves and updates the Versions dataset in the same way as the upgcli application.

How to Make Yourself Unpopular

All your users will login, and the server will check the version, find that they are at version 1.0, and send them what it believes to be Version 1.1, but is in fact 1.0.  The users will then login again…and again…