win32 自动更新的一种方案

PS:文章是从本人sina博客搬移过来:

win32 自动更新的一种方案

ps:此只是一个思路,上不了台面的哈;


因工作需要,需要做出一个自动更新的方案;主要是作为内部使用,因此需要考虑的因素并不多。YI给出了其使用C#做的一些方法,然后提示了我应该怎么去做自动更新。其实个人感觉自动更新大体的思路都是一样。画出思路丢在了工作笔记本上,然后又是其他的事耽搁了,而上头亦没有做出什么要求,汗,直到那天YI给我看他的年终报告,才知道YI把这事记上了,而我有没有主动去弄,汗,有点对不起YI,于是上午就狠狠的弄了下把方案演示做给了YI.给出个交代.......

   具体思路:程序启动时,开启一个线程AA线程用来读取运行程序的版本号,并获取更新地址上保存的版本信息,然后比较版本是否有更新,如果有更新,则提示用户是否选择更新。如果选择了更新,那么,开启预设定好的下载进程,关闭正在运行的程序(好的更新程序会保存当前的工作,或者保存当前工作的配置等,更新完毕后悔重新启动原有程序,在此只是做一个方案,不要求有如此高的功能),下载完成后,覆盖原有的文件,启动安装进程。当然这是一种不规范的方法。仅供参考;贴上程序;程序一:模拟主函数运行,线程检测版本信息。程序二:下载存放在服务器上已更新的文件,覆盖原有文件,重新安装;

    程序一:
#pragmaonce

#pragmacomment(lib,"Wininet.lib")
#pragmacomment(lib,"Version.lib")

#include
#include
#include
#include

#defineMAX 1024

usingnamespace std;

DWORDWINAPI StartCheckVersion(LPVOID lpParam);
bool Compareversion(char* Buff); //
比较版本信息;
WCHAR* GetAppVersion();//
得到程序的版本信息;
boolStartDownloadNewVersion();//
启动下载新版本

intmain(int argv,char * argc[])
{

 HANDLEhCheckThread;
 DWORDdwThreadId;
 hCheckThread=CreateThread(   //
启动线程函数StartCheckVersion来检查存放在服务器上的版本信息;
       NULL,
       0,
       StartCheckVersion,
       NULL,
       0,
       &dwThreadId);
 if(hCheckThread)
 {
  while(1)
  {
   Sleep(1000);
   cout<<"testthe main function :is running!"<<endl;
  }
 }

 return0;
}

DWORDWINAPI StartCheckVersion(LPVOID lpParam) //线程函数,检测版本信息;
{
 charBuff[MAX]={0};
 LPCWSTRversionaddress=_T("
http://localhost/WebService/Version.txt");  //
在本地的上发布了一个web,存放了最新的版本信息;
 DWORDdwRead;
 HINTERNET hInet=NULL,hfile=NULL;
 boolnewversion=false;
 hInet=InternetOpen(
     _T("Test"),
     INTERNET_OPEN_TYPE_DIRECT,
     NULL,
     NULL,
     0);
 if(hInet)
 {
  hfile=InternetOpenUrl(
       hInet,
       versionaddress,
       NULL,
       0,
       0,
       0);
  if(hfile)
  {
   InternetReadFile(   //
取得服务器上的版本信息,存放在Buff中;
       hInet,
       Buff,
       20,
       &dwRead);
   if(dwRead)
   {
    newversion=Compareversion(Buff);   //
比较版本信息;
   }
   if(newversion)
   {
    if(::MessageBox(NULL,_T("
检测到有版本更新,是否需要下载?"),_T("更新提示"),MB_OKCANCEL)==IDOK)
    {
     //
以下是启动新进程所必须的两个结体,具体含意查MSDN;
     STARTUPINFOsi;
     PROCESS_INFORMATIONpi;
     ZeroMemory(&si,sizeof(si));
     si.cb=sizeof(si);
     si.wShowWindow=SW_SHOWNORMAL;   //
设置窗口为正常显示;
     ZeroMemory(&pi,sizeof(pi));
     if(!CreateProcess(
         _T("C:\\Download.exe"),   //
设置为我们写好的下载程序;
         NULL,
         NULL,
         NULL,
         FALSE,
         0,
         NULL,
         NULL,
         &si,
         &pi))
     {
      cout<<"CreateProcess failed "<<GetLastError()<<endl;
      return0;
     }
     InternetCloseHandle(hfile);
     InternetCloseHandle(hInet);
     exit(0);            //
结束当前程序;
    }
   }

  }
  
 }
 else
  {
   cout<<"internetopenerror"<<endl;
   InternetCloseHandle(hfile);    //
关闭句柄动作,
   InternetCloseHandle(hInet);
   return0;
  }
 return 0;
}

boolCompareversion(char *Buff)
{
 WCHAR *Version;
 WORDdwMinSize;
 WCHAR*T_Version,*T_WBuff;
 dwMinSize=MultiByteToWideChar(CP_ACP,0,Buff,-1,NULL,0);
 WCHAR*WBuff=newWCHAR[dwMinSize];
 MultiByteToWideChar(CP_ACP,0,Buff,-1,WBuff,dwMinSize);
 Version=GetAppVersion();//
得到指定的程序的版本信息;
 T_Version=Version;
 T_WBuff=WBuff;
 while((*T_Version)!='\0')   //
这里仅仅做了简单的相同匹配来判断是否有更新;
 {
  if((*T_Version++)!=(*T_WBuff++))
  {
   deleteWBuff;
   delete Version;
   returntrue;       //
如果版本不一样,则返回true,通知程序有新版本;
  }
 }
 deleteWBuff;
 delete Version;
 return false;
}

WCHAR*GetAppVersion()
{
 struct String{
  WCHARFileVersion[20];
 }*VersionString;
 DWORDlpdwhand;
 DWORD FileVersionSize;
 WCHAR*Version;
 WCHARFILEPATH[]=_T("d:\\Reader.exe");       //
这里是我测试的一个程序;
 FileVersionSize=GetFileVersionInfoSize(FILEPATH,&lpdwhand);    //
获得指定程序的版本属性文件信息;
 Version=newWCHAR[FileVersionSize+1];
 LPVOID lpBuffer=NULL;
 UINTuLen=0;
 WCHAR*VersionInfo;
 VerQueryValue(Version,TEXT("
\\StringFileInfo\\040904e4\\FileVersion"),(LPVOID*)&VersionString,&uLen);   //
遍历出版本号
 VersionInfo=newWCHAR[uLen+1];
 VersionInfo[uLen]='\0';
 UINTtest=0;
 while(test<=uLen)
 {
  VersionInfo[test]=VersionString->FileVersion[test];  //
赋给VersionInfo;
  test++;
 }
 delete[]Version;
 return VersionInfo;
}

 

 

程序二:Download.exe

//Download.cpp : 定义控制台应用程序的入口点。
//

#include"stdafx.h"

boolStartDownloadNewVersion();
bool StartSetup();
DWORD WINAPIShowrate(LPVOID lpParam);


DWORDfilesize;
float total=0.0;
float downloaddone=1;
floatrate=0.0;

int_tmain(int argc, _TCHAR* argv[])
{
 HANDLE Hshow;
 DWORDdwThread;
 if(::MessageBox(NULL,_T("
下载新版本,按确定继续"),_T("提示"),MB_OKCANCEL)==IDOK)
 {
  Hshow=CreateThread(    //
做了一个简单显示下载进度的显示;
       NULL,
       0,
       Showrate,  //
显示进度函数;
       NULL,
       0,
       &dwThread);
  if(Hshow)
  {
   if(StartDownloadNewVersion())    //
从指定的服务器上下载新的文件,这里是一个安装文件.msi
   {
    cout<<"100%Download the new version havedown"<<endl;
    MessageBox(NULL,_T("
下载成功,进行安装"),_T("成功"),MB_OK);
    StartSetup();        //
启动安装程序。当然在相应的盘符下得有这个setup.exe程序,
   }
   else
   {
    cout<<"Downloadthe version error"<<endl;
    return0;
   }
  }
  return0;
 }
 return 0;
}

boolStartDownloadNewVersion()
{
 char Buff[1024]={0};
 WCHAR*File=_T("D:\\READDER.msi");
 LPCWSTRversionaddress=_T("
http://localhost/webservice/READER.msi");  //
模拟发布在本机;
 DWORDdwRead,dwWrite;
 HINTERNET hInet=NULL,hfile=NULL;
 HANDLEHandfile=NULL;
 hInet=InternetOpen( 
     _T("Test"),
     INTERNET_OPEN_TYPE_DIRECT,
     NULL,
     NULL,
     0);
 if(hInet)
 {
  hfile=InternetOpenUrl(hInet,versionaddress,NULL,0,0,0);
  if(hfile)
  {
   Handfile=CreateFile(  //
在指定文件夹中创建改文件名;
        File,
        GENERIC_READ|GENERIC_WRITE,
        FILE_SHARE_READ,
        NULL,
        OPEN_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
   if(Handfile)
   {
    InternetQueryDataAvailable(hfile,&filesize,0,0);   //
预先得到将要下载的文件的大小,为显示进度做准备用;
    total=filesize/1024;
    do{
     InternetReadFile(hfile,Buff,1024,&dwRead);    //
从网络上读取文件,每次读1k
     if(dwRead)
     {
      downloaddone++;
      WriteFile(Handfile,Buff,dwRead,&dwWrite,NULL);   //
写入到创建的文件中;
      rate=downloaddone/total;
      Sleep(1);    //
延时,为了好观察,也防止CPU100%
     }
    }while(dwRead!=0);    //
下载完毕;
   }

  }
 }
 else
 {
  InternetCloseHandle(hfile);   //
扫尾工作
  InternetCloseHandle(hInet);
  CloseHandle(Handfile);
  returnfalse;
 }

  InternetCloseHandle(hfile);
  InternetCloseHandle(hInet);
  CloseHandle(Handfile);
  returntrue;
}


DWORDWINAPI Showrate(LPVOIDlpParam)
{
 cout.precision(4);   //
设置为显示小数点后后4位;
 while(1)
 {
  if(rate>1.00)
  break;    //
退出;
  cout<<rate*100<<"%";
  system("cls");    //
清屏;
 }
return0;
}
bool StartSetup()
{
 STARTUPINFOsi;
 PROCESS_INFORMATIONpi;
 ZeroMemory(&si,sizeof(si));
 si.cb=sizeof(si);
 si.wShowWindow=SW_SHOWNORMAL;
 ZeroMemory(&pi,sizeof(pi));
 if(!CreateProcess(
  _T("c:\\setup.exe"),  //
程序的安装程序
  NULL,
  NULL,
  NULL,
  FALSE,
  0,
  NULL,
  NULL,
  &si,
  &pi)
  )
 {
  cout<<"CreateProcessfailed"<<GetLastError()<<endl;
  returnfalse;
 }
 exit(1);
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本工具多次测试均未出现问题,可以使用,如果发现自己无法使用,请先看下面介绍与说明 谢谢!! 感谢驴友yxrsys,在verycd发布资源 非安装软件,直接双击运行,傻瓜式修复,可运行于32位和64位系统和WINPE系统 程序根据当前系统non-Unicode设置自动显示中/英界面 "自动修复"自动判断和系统启动有关的条件并自动修复程序支持的盘符上的NT系统启动,无需用户手工干预 "高级修复"只供特殊需要的朋友,参看下面应用实例中的高级修复部分 PE中自动判断PE环境,单硬盘可以直接"自动修复",如多硬盘在PE中修复时推荐使用"高级"修复选择你作为系统引导的盘符 适用范围: -------- 1.启动菜单/启动文件丢失修复: 适用所有NT5.x(2000/XP/2003)和NT6.x(Vista/2008/Win7/2008r2) 2.修复其他因BCD相关引起的故障 a. Win7/2008r2中 BCD 的修复计算机(Windows Recovery Environment)菜单丢失 b. Win7/2008r2中 BCD 引起的3D启动画面丢失(变成VISTA滚动条启动画面) c. BCD 引起的启动菜单选择界面乱码现象 3.系统BCD非法的强制修复 - 现象:Vista/2008/Win7/2008r2中 a. 运行msconfig后"启动"或"引导"栏空白 b. 管理员身份运行命令提示符中后运行bcdedit等和BCD相关的操作提示出错 c. 系统属性的"启动和故障恢复"窗口无法配置"默认操作系统"和"等待时间" d. 其他软件无法添加/删除/修改基于 BCD 管理的新启动菜单 注: 3的这种情况是否要强制修复自行决定。 额外功能: 为VISTA/2008添加修复计算机(Windows Recovery Environment)菜单 使用方法:在系统盘符中新建recovery文件夹,再把光盘或安装程序中的boot\boot.sdi和sources\boot.wim复制至 recovery文件夹,再运行本程序,即可自动添加。 修复效果: 存在原BCD或Boot.ini时程序将予备份,备份文件名/路径在修复完成后给出提示 NT5.x菜单在boot.ini中以"Microsoft Windows Server 2003 x86"形式存在 NT6.x菜单在BCD中以"Windows Server ® 2008 Standard x86"形式存在 NT6.x的修复过程提示成功即时写入生效,NT5.x的修复在最后完成后再一并写入生效 NT5.x支持最多同接8个硬盘时的修复,但如果不同接口硬盘混用且三个或以上硬盘就未必能准确判断硬盘号,三硬盘以上 并混用的情况就算微软自己的控制台都未必能准确判断 NT6.x理论无限制硬盘数,也不限制混用 根据当前系统non-Unicode设置决定修复后的启动菜单中/英优先级 NT5.x+NT6.x的多系统中 - 当存在多个NT5.x时,修复后BCD显示的NT5.x相应菜单为“Earlier Version of Windows”, 当只有一个NT5.x系统,修复后BCD中显示的NT5.x相应菜单则为类如"Microsoft Windows Server 2003 x86"格式 不修复NT5.x的Boot.ini和NT6.x的BCD中的多余的启动菜单 因为精简版的精简程度无从判断,所以不保证能修复精简版系统启动故障 自BCDautofix发布以来极少回答一些朋友在使用上的疑问,这里和NTBOOTautofix一并释疑 一、BUG报告:readme中写的邮箱我极少打开,所以未必能及时回信。 二、请不要拿本工具和EasyBCD或VistaBoorPro等工具作比较: 那类工具重在管理 - 如改启动菜单名,添加/删除菜单等,要用在修复功能上需要使用者自己了解故障原因和解决流程后 才能手工修复,多数情况下其手工也无法完美修复。 而本工具重在修复,修复功能大多是那类工具无法实现的,当然本工具也不能实现那类工具的管理操作。 三、程序用批处理编写:请看不起批处理的免下载使用而避免下载后浪费诸多表情 四、如不能修复请自己先了解一下是否程序适用范围内:例如有些硬件原因引起的3D启动画面不存在,象这类的非BCD引起的类似故障是此工具无法处理的 五、手工处理教程为什么不写:其实以前曾经写过很多,但并不多人看,有时一个“活动分区”的识别就要大花唇舌说明,一句bcdedit /set {ntldr} description "Microsoft Windows XP"或bootsect /nt60 sys可以解决的手工处理方式不少人都

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值