| 406上位机VC MFC实现离线安装包更新   实现离线安装包更新
 功能展示
 我们平时电脑软件都是在线更新,但工控机上的软件一般都是使用更新包离线升级,我们当前例程就实现了指定程序离线升级功能,效果如图,点击更新按钮,程序会依次执行 终止要更新的程序运行,从注册表获取要更新程序的安装目录,从实例中解包全部新版本文件到缓存目录并复制到安装目录,最后清理缓存目录完成更新
 
 要点提示
 例程中,指定程序离线功能的实现,主要过程为 :
 1.将全新新版本文件打包生成EXE可执行文件即生成一个更新包;
 2.运行EXE文件,用户允许升级后检查及退出运行中要更新的程序;
 3.从注册表获取要更新程序的安装目录;
 4.从更新包程序中解包文件到缓存文件,并复制到安装目录进行文件更新;
 5.清空缓存目录释放出的文件,完整更新;
 
 1.解包与打包功能使用了上一例程中的函数,主要是PackAFile () UnpackAllFiles () ExtractSrc ();
 2.要更新程序的终止运行是通过遍历系统运行中的程序,将程序名与我们要终止运行的程序名比对,名称相同则调用函数TerminateProcess()终止其运行,例程是通过KillProgram(CString sExeName)实现, sExeName为要终止的程序名如gkbc8.exe;
 3.从注册表获取要更新程序的安装目录是通过遍历注册表HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall键下的键名及指定程序名进行对比,相同则进一步读取此键下特定的键值项,获取其安装目录;例程是通过GetProgramPath()实现;
 4.从缓存目录中获取解包出的全部文件及全部文件的函数是通过函数GetNewFiles()和DeleteDirectory()实现
 
 实现功能
 1.新建基于对话框的应用程序
 2.与前一例程一样在主对话框头文件包含头文件及结构体申明,以及自定义的变量与函数
 
 #include<io.h>
 #include <afxtempl.h>
 #include "tlhelp32.h"
 #include <shlwapi.h>
 #pragma comment(lib,"shlwapi.lib")
 #define MAX_FILE_COUNT 10// 包文件中最大可容纳的文件个数
 typedef struct SMaseFileHeader // 资源包文件头结构
 {
 UINT uFileFlag; // 包文件头标记: 'MASE'
 UINT uFileCount; // 包内文件个数
 LONG uFileListOfs; // 文件列表偏移
 UINT uMaxFileCount; // 最大子文件个数
 LONG uFileSize; // 包文件的大小
 }PackHeader;
 typedef struct SFilesMessage // 包内文件信息结构
 {
 LONG uFileOfs; // 本文件在包内的偏移
 LONG uFileSize; // 本文件的大小
 char szFileName[_MAX_PATH]; // 文件名
 }PackFileMsg;
 public:
 BOOL KillProgram(CString sExeName="gkbc8.exe");//未运行返回真
 void GetProgramPath(CString sKeyName="gkbc8");//从注册表读取要更新的目录
 void GetNewFiles();//获得全部新文件名
 void DeleteDirectory(CString strDir);//删除整个目录
 void DoUpdate();//执行更新
 private:
 CString m_TempPath; //解包用临时目录
 CString m_sToPath; //目标目录
 CStringList m_FileList;//新文件名链
 BOOL PackAFile(CString sPackName,CString sFile);//打包文件,sPackName包绝对路径,sFile文件绝对路径
 BOOL UnpackAllFiles(CString sPackName,CString sPath);//全部解包,sPackName包绝对路径,sPath文件夹
 BOOL ExtractSrc(CString sSrcType,UINT nSrcID, CString sSavePathName, UINT nTYPE=0);//将资源释放为文件
 void CToolForUptDlg:
  oUpdate() {
 if(IDOK != MessageBox("是否执行更新?","提示",MB_OKCANCEL) )
 return;
 if(!KillProgram("gkbc8.exe") )//关闭指定程序
 return;
 GetProgramPath("gkbc8");//从注册表获取要更新的目录
 GetNewFiles();//获得全部新文件名
 //<>
 CString sSourceFile,sToFile,sFileName;
 POSITION Pos = m_FileList.GetHeadPosition();
 while( NULL != Pos)
 {
 sSourceFile = m_FileList.GetNext(Pos);
 sFileName = sSourceFile;
 sFileName = sFileName.Right(sFileName.GetLength()-sFileName.ReverseFind('\\'));
 sToFile = m_sToPath+sFileName;
 if(!::CopyFile(sSourceFile,sToFile,FALSE) )//系统文件操作先获得管理权限
 {
 int nError =GetLastError();
 sSourceFile.Format("更新时复制失败,代码: %d",nError);
 MessageBox(sSourceFile);
 return;
 }
 :
  eleteFile(sSourceFile); }
 DeleteDirectory(m_TempPath);//删除释放用临时文件
 }
 3.复制根目录文<件测试(安装来测试).exe><Data.bin>到自己工程根目录,并将Data.bin载入到工程类型命名为SOURCE,资源ID不改变既IDR_SOURCE1。
 4.添加按钮<执行更新>关联点击函数调用DoUpdate()执行更新
 void CToolForUptDlg::OnButton3() { DoUpdate();//执行更新}
 
 
 
 我们来演示下功能实现的整个过程
 
 
 
 
 
 |