正在阅读:软件的版本更新检查实现软件的版本更新检查实现

2004-11-01 15:25 出处:CSDN 作者:Raptor 责任编辑:linjixiong

  还是在“PIA-MyPhotoGallery”中,为了能让使用者及时知道软件的更新版本发布,我增加了自动更新检查功能。鉴于这种功能具有很好的实用价值,所以写本文说明此功能的实现。

  要实现更新检查,需要解决两个方面的问题:

  1、通过Internet获取最新发布的版本号;
  2、取得当前程序的版本,并与取得的最新版本相比较。

  如果检查到有新版本发布,则打开下载页面(至于直接下载更新本文暂不讨论)。

  对于第一个问题,最简单的解决办法就是在网站上发布新版本软件的同时,发布一个记录着版竞诺奈募T谌砑邪姹炯觳槭保ū热绯绦蚱舳保ü齀nternet下载此文件,并读出最新的版本号。

  注意:此方法仅适用于简单更新的情况,对于像杀毒软件的病毒库这样增量更新的情况,这种简单方法是不合适的,通常还需要有相应的服务端程序配合才行。

  要通过Internet下载文件有很多方法,比如用WinINet API或现成的控件都可以。本文以Indy的TIdHTTP控件为例。

  TIdHTTP控件的用法非常简单,但是直接使用它下载会有一个问题:程序会被阻塞着,直到文件被下载或连接超时(比如网络未连接)。所以必须将它放到线程中处理。

  在PIA-MyPhotoGallery中,我用的代码如下:


  //---------------------------------------------------------------------------
  //  Get new version thread
  class TGetNewVersionThread : public TThread
  {
  private:
  AnsiString      FURL;
  TMFileVersion * FVer;
  protected:
  void __fastcall Execute( );
  public:
  __fastcall TGetNewVersionThread( AnsiString aURL )
  : TThread( true ), FURL( aURL ), FVer( new TMFileVersion( ) )
  {
  FreeOnTerminate = true;
  }
  __fastcall ~TGetNewVersionThread( ) { delete FVer; }
  __property TMFileVersion * Version  = { read=FVer };
  };




察看评论详细内容 我要发表评论
作者笔名简短内容 发表时间
:



  //---------------------------------------------------------------------------
  //  TGetNewVersionThread
  //---------------------------------------------------------------------------
  void __fastcall TGetNewVersionThread::Execute( )
  {
  boost::scoped_ptr webConn( new TIdHTTP( NULL ) );
  boost::scoped_ptr ss( new TStringList( ) );
  try {
  ss->Text = webConn->Get( FURL );
  }
  catch ( ... )
  {
  ss->Text = "";
  }
  AnsiString s = ss->Values["piapg"];
  if ( s != "" )
  FVer->VerStr = s;
  }
  //---------------------------------------------------------------------------

  这段代码很简单:创建一个线程,在线程里创建一个TIdHTTP实例,然后下载URL对应的文件,最后从中读出“piapg”的版本号。为了偷懒,我用了boost库里的smart pointer--scoped_ptr。

  这个线程类的使用方法如下:


  //---------------------------------------------------------------------------
  //  在程序启动时执行:
  if ( PIAPGCfg->AutoUpd )  //  如果选择了“检查更新”选项则执行检查
  {
  if ( SplashDlg )  //  如果有splash,则在其中显示提示文本
  {
  SplashDlg->labProgress->Caption = "正在检查新版本...";
  SplashDlg->labProgress->Refresh( );
  }
  //  创建检查新版本的线程
  TGetNewVersionThread * pThread = new TGetNewVersionThread( "http://mental.mentsu.com/update.txt" );
  pThread->OnTerminate = GetNewVersionDone;
  pThread->Resume( );
  }
  //---------------------------------------------------------------------------
  //  版本文件下载完成或超时
  void __fastcall TMainForm::GetNewVersionDone(TObject * Sender)
  {
  TGetNewVersionThread * pThread = dynamic_cast( Sender );
  boost::scoped_ptr fv( new TMFileVersion( ) );
  fv->GetVersionFromFile( Application->ExeName );  //  读取当前程序的版本
  if ( ( pThread->Version->Compare( fv.get( ) ) > 0 )  //  如果有新版本,则提示
  && ( Application->MessageBox( "发现更新版本的程序,是否现在更新?",
  "新版本检查", MB_YESNO | MB_ICONINFORMATION ) == IDYES ) )
  {
  ShellExecute( NULL, "open", "http://mental.mentsu.com", NULL, NULL, SW_SHOW );
  PostQuitMessage( 0 );
  }
  }
  //---------------------------------------------------------------------------

  此代码的功能详见其中的注释。

  再来看第二个问题:程序版本的问题。

  在上面的代码中,用到了一个类:TMFileVersion。这是我以前用DELPHI写的一个用于处理可执行文件版本号的类。实现代码如下:


  TMFileVersion = class
  private
  FMajor   : Integer;
  FMinor   : Integer;
  FRelease : Integer;
  FBuild   : Integer;




察看评论详细内容 我要发表评论
作者笔名简短内容 发表时间
:



  Function  GetVerStr : String;
  Procedure SetVerStr( aVerStr : String );
  public
  constructor Create;
  destructor Destroy; override;
  Procedure GetVersionFromFile( aFileName : String );
  Function  Compare( aVer : TMFileVersion ) : Integer;
  Property VerStr : String read GetVerStr write SetVerStr;
  End;
  { TMFileVersion }
  //  init
  constructor TMFileVersion.Create;
  Begin
  Inherited;
  FMajor   := 0;
  FMinor   := 0;
  FRelease := 0;
  FBuild   := 0;
  End;
  destructor TMFileVersion.Destroy;
  Begin
  Inherited;
  End;
  //  Get version info from a file
  Procedure TMFileVersion.GetVersionFromFile( aFileName : String );
  Type
  PVS_FIXEDFILEINFO = ^VS_FIXEDFILEINFO;
  Var
  h : Cardinal;        // a handle, ignore
  nSize : Cardinal;    // version info size
  pData : Pointer;     // version info data
  pffiData : PVS_FIXEDFILEINFO;  // fixed file info data
  nffiSize : Cardinal; // fixed file info size
  Begin
  FMajor   := 0;
  FMinor   := 0;
  FRelease := 0;
  FBuild   := 0;
  If ( FileExists( aFileName ) ) Then
  FBuild := 1;
  nSize := GetFileVersionInfoSize( PChar( aFileName ), h );
  If ( nSize = 0 ) Then
  Exit;
  GetMem( pData, nSize );
  Try
  GetFileVersionInfo( PChar( aFileName ), h, nSize, pData );
  If ( VerQueryValue( pData, '\', Pointer( pffiData ), nffiSize ) ) Then
  Begin
  FMajor   := ( pffiData^.dwFileVersionMS ) SHR 16;
  FMinor   := ( pffiData^.dwFileVersionMS ) AND $FFFF;
  FRelease := ( pffiData^.dwFileVersionLS ) SHR 16;
  FBuild   := ( pffiData^.dwFileVersionLS ) AND $FFFF;
  End;
  Finally
  FreeMem( pData );
  End;
  End;




察看评论详细内容 我要发表评论
作者笔名简短内容 发表时间
:



  //  Compare two version info
  Function TMFileVersion.Compare( aVer : TMFileVersion ) : Integer;
  Var
  n1, n2 : Cardinal;
  Begin
  n1 := ( FMajor SHL 16 ) OR FMinor;
  With aVer Do
  n2 := ( FMajor SHL 16 ) OR FMinor;
  If ( n1 > n2 ) Then
  Result := 1
  Else If ( n1 < n2 ) Then
  Result := -1
  Else
  Begin
  n1 := ( FRelease SHL 16 ) OR FBuild;
  With aVer Do
  n2 := ( FRelease SHL 16 ) OR FBuild;
  If ( n1 > n2 ) Then
  Result := 1
  Else IF ( n1 < n2 ) Then
  Result := -1
  Else
  Result := 0;
  End;
  End;
  //  Get/Set property - VerStr
  Function TMFileVersion.GetVerStr : String;
  Begin
  Result := Format( '%d,%.02d,%d,%.02d', [FMajor, FMinor, FRelease, FBuild] );
  End;
  Procedure TMFileVersion.SetVerStr( aVerStr : String );
  Var
  sTemp : TStrings;
  Begin
  FMajor   := 0;
  FMinor   := 0;
  FRelease := 0;
  FBuild   := 0;
  sTemp := TStringList.Create;
  Try
  sTemp.CommaText := aVerStr;
  Try
  FMajor   := StrToInt( sTemp.Strings[0] );
  FMinor   := StrToInt( sTemp.Strings[1] );
  FRelease := StrToInt( sTemp.Strings[2] );
  FBuild   := StrToInt( sTemp.Strings[3] );
  Except
  //  Do nothing
  End;
  Finally
  sTemp.Free;
  End;
  End;

  解决了这两个问题,自动更新检查的功能也就解决了。

  



察看评论详细内容 我要发表评论
作者笔名简短内容 发表时间
:

相关文章

关注我们

最新资讯离线随时看 聊天吐槽赢奖品