VB创建一个自动升级的程序

3,798次阅读
一条评论

共计 4699 个字符,预计需要花费 12 分钟才能阅读完成。

最近由于工作需要,给自己负责的产品制作一个可用于快速计算某些参数的通用小程序,由于最终需要分发给多人使用,但是在源码编制过程中的疏忽,会留下Bug。同时,为了避免每次更新升级程序之后,需要重新分发,确保每个人都在使用最新版本的源码所造成的重复性工作,所以需要在源码中嵌入一段自我升级的功能源码。

由于自己在VB编程方面,其实也是一个刚入门的人而已,所以参考了不少LiveUpdate的VB源码,再次对他们表示感谢,从他们的例子中,我得到了灵感和启发,所以完成了这段源码的编制。

具体过程和原理:

①使用外部文件(INI文件等),定义程序版本号,定义升级程序存储位置等信息用于提供校检;

②在主程序(MainApp.exe)窗口Load阶段,读取本地INI文件中版本号,升级程序信息,服务器中INI文件版本号

③比较两个版本号,若服务器中版本号比本地新,则运行更新程序(RunUpdate.exe)

④升级程序拷贝服务器中程序到本地,更新版本文件(INI文件)

⑤升级程序注销自身,启动主程序。

⑥升级完成。

当然,其中涉及到一些错误处理,比如无法连接到服务器情况,服务器或者本地文件缺失情况,需要单独作出错误处理,这里不讨论。各位相信会自己完成处理。

这里涉及到三段源码,分别摘录如下,各位如有问题,可以一起讨论。

1,MainApp.exe中Load阶段判断:

[php]
Private Sub MDIForm_Load()
‘确定启动检查是否有新版本
Dim ThisAppOldVersion As String
Dim ThisAppNewVersion As String
Dim ThisAppCheckFile As String
Dim ThisAppName As String
Dim AppUpdateFile As String
AppUpdateFile = GetIniStr(App.Path & "updatecheck.ini", "Config", "AppUpdateFile")
ThisAppCheckFile = GetIniStr(App.Path & "updatecheck.ini", "Config", "AppCheckFile")
ThisAppOldVersion = GetIniStr(App.Path & "updatecheck.ini", "Config", "Version")
ThisAppNewVersion = GetIniStr(ThisAppCheckFile, "Config", "Version")
ThisAppName = GetIniStr(ThisAppCheckFile, "Config", "AppName")
On Error Resume Next ‘更新错误仍然可以运行程序
If ThisAppNewVersion > ThisAppOldVersion Then
Shell App.Path & "RunUpdate.exe", vbNormalFocus ‘其中RunUpdate.exe即为更新升级程序
Unload Me
End If
End Sub
[/php]

updatecheck.ini即为存储基本程序信息的INI文件,其中大家完全可以把这段写死,不用这么多变量,我之所以这么留着,是为了能够使这个升级程序通用。

2、INI文件读写模块

[php]
Option Explicit

Private Declare Function GetPrivateProfileString Lib "KERNEL32" Alias "GetPrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpDefault As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal pFileName As String) As Long
Private Declare Function WritePrivateProfileString Lib "KERNEL32" Alias "WritePrivateProfileStringA" (ByVal lpApplicationName As String, ByVal lpKeyName As Any, ByVal lpString As Any, ByVal lpFileName As String) As Long
Private Declare Function GetPrivateProfileSection Lib "KERNEL32" Alias "GetPrivateProfileSectionA" (ByVal lpAppName As String, ByVal lpReturnedString As String, ByVal nSize As Long, ByVal lpFileName As String) As Long
‘*************************************
‘目的:写入数据至Ini文件

‘输入: FileName 文件名
‘ AppName 项目名
‘ In_Key 键名
‘ In_Data 键名上的数值

‘返回: 写入成功 True
‘ 写入失败 False

‘*************************************

Public Function WriteIniStr(ByVal FileName As String, ByVal AppName As String, ByVal In_Key As String, ByVal In_Data As String) As Boolean
On Error GoTo WriteIniStrErr
WriteIniStr = True
If VBA.Trim(In_Data) = "" Or VBA.Trim(In_Key) = "" Or VBA.Trim(AppName) = "" Then
GoTo WriteIniStrErr
Else
WritePrivateProfileString AppName, In_Key, In_Data, FileName
End If
Exit Function
WriteIniStrErr:
Err.Clear
WriteIniStr = False
End Function

‘*************************************
‘目的:从Ini文件中读取数据

‘输入: FileName 文件名
‘ AppName 项目名
‘ In_Key 键名

‘返回: 取得给定键名上的数据

‘*************************************

Public Function GetIniStr(ByVal FileName As String, ByVal AppName As String, ByVal In_Key As String) As String
On Error GoTo GetIniStrErr
If VBA.Trim(In_Key) = "" Then
GoTo GetIniStrErr
End If
Dim GetStr As String
GetStr = VBA.String(128, 0)
GetPrivateProfileString AppName, In_Key, "", GetStr, 256, FileName
GetStr = VBA.Replace(GetStr, VBA.Chr(0), "")
If GetStr = "" Then
GoTo GetIniStrErr
Else
GetIniStr = GetStr
GetStr = ""
End If
Exit Function
GetIniStrErr:
Err.Clear
GetIniStr = ""
GetStr = ""
End Function

‘Option Explicit

‘遍历ini文件 , 某个主键下的所有Key
Public Function GetInfoSection(strSection As String, strIniFile As String) As String()
Dim strReturn As String * 32767
Dim strTmp As String
Dim nStart As Integer
Dim nEnd As Integer
Dim i As Integer
Dim sArray() As String

Call GetPrivateProfileSection(strSection, strReturn, Len(strReturn), strIniFile)

strTmp = strReturn
i = 1
Do While strTmp <> ""
nStart = nEnd + 1
nEnd = InStr(nStart, strReturn, vbNullChar)
strTmp = Mid$(strReturn, nStart, nEnd – nStart)
If Len(strTmp) > 0 Then
ReDim Preserve sArray(1 To i)
sArray(i) = strTmp
i = i + 1
End If
Loop
GetInfoSection = sArray

End Function
[/php]

这个模块我直接借用别人写好的了。就不解释了。

3、升级程序源码

[php]
Option Explicit
Private Sub Form_Load()
Dim ThisAppOldVersion As String
Dim ThisAppNewVersion As String
Dim ThisAppCheckFile As String
Dim ThisAppName As String
Dim AppUpdateFile As String
ThisAppCheckFile = GetIniStr(App.Path & "updatecheck.ini", "Config", "AppCheckFile")
AppUpdateFile = GetIniStr(App.Path & "updatecheck.ini", "Config", "AppUpdateFile")
ThisAppOldVersion = GetIniStr(App.Path & "updatecheck.ini", "Config", "Version")
ThisAppNewVersion = GetIniStr(ThisAppCheckFile, "Config", "Version")
ThisAppName = GetIniStr(ThisAppCheckFile, "Config", "AppName")
If ThisAppNewVersion > ThisAppOldVersion Then
FileCopy AppUpdateFile, App.Path & "" & ThisAppName & ".exe"
FileCopy ThisAppCheckFile, App.Path & "updatecheck.ini"
Shell App.Path & "" & ThisAppName & ".exe", vbNormalFocus
Unload Me
Else
Shell App.Path & "" & ThisAppName & ".exe", vbNormalFocus
Unload Me
End If
End Sub
[/php]

这段代码生成EXE文件后,即可通过改变INI文件,实现兼容其他程序简单升级。

4、比较次要的INI文件内容了,这个比较简单,大家都会了。文件名称一定要统一,这里存为updatecheck.ini

[php]
[Config]
Version=2013.5.20
AppName=我的程序
AppCheckFile=D:Testupdatecheck.ini
AppUpdateFile=D:Test我的程序.exe
[/php]

程序到这里就写完,比较简单。欢迎大家提供更好的思路。

正文完
 0
评论(一条评论)
2013-05-24 01:13:02 回复

突然想到一个问题,那升级程序自身如何升级呢?
其实可以在MainApp.exe中,参照RunUpdate.exe中的方法,先对升级程序进行升级后,重新启动升级程序即可了。

 Windows  Firefox  中国吉林省长春市联通

空瓶子部落

文章搜索
推荐阅读
管理之道:解析三个重要、四个原则、六大布局与七种问题

管理之道:解析三个重要、四个原则、六大布局与七种问题

在现代企业管理中,有效的管理策略和方法对于企业的持续发展和竞争力至关重要。围绕“三个重要”、“四个原则”、“六...
5S级别的工厂什么样?

5S级别的工厂什么样?

关于5S,经常是挂在嘴上,茫在心里;天天说,但又不知道该怎么做?供应商说我都找人把墙重新粉刷了一遍,地重新漆了...
OpenWrt修改IP地址两种方法(直接命令修改跟后台修改)

OpenWrt修改IP地址两种方法(直接命令修改跟后台修改)

OpenWrt是什么?OpenWrt一般常见于无线路由器(软路由)第三方固件,它是一个高效、可靠、功能多的路由...
五大工具:SPC

五大工具:SPC

在当今竞争激烈的市场环境中,质量不仅是企业生存的基石,更是其发展壮大的关键。统计过程控制(Statistica...
最新文章
群晖 Let’s Encrypt 泛域名证书自动更新

群晖 Let’s Encrypt 泛域名证书自动更新

目前acme协议版本更新,开始支持泛域名(wildcard),也就是说,可以申请一个类似*.domain.co...
可以卸载TV Box 了,这款支持「绅士模式」的影视神器你值得拥有

可以卸载TV Box 了,这款支持「绅士模式」的影视神器你值得拥有

还在为找优秀片源难、广告多、平台会员太贵而烦恼?今天给大家挖到一款真正的影视宝藏工具——小猫影视! 作为开源免...
【收藏】一次性解决TV点播/直播自由

【收藏】一次性解决TV点播/直播自由

很多时候,资源就在面前,但是我们视而不见,因为长久的安逸,已经让人失去动手的兴趣。但是每次我需要挨个切换APP...
OpenWrt 存储空间扩容的两种方案

OpenWrt 存储空间扩容的两种方案

说明:当我们通过群晖 VMM 虚拟机安装 Open­Wrt 时,默认会分配一个 10GB 的存储空间,而实际情...
OpenWrt修改IP地址两种方法(直接命令修改跟后台修改)

OpenWrt修改IP地址两种方法(直接命令修改跟后台修改)

OpenWrt是什么?OpenWrt一般常见于无线路由器(软路由)第三方固件,它是一个高效、可靠、功能多的路由...
热门文章
提高过程能力指数(CP/CPK)的途径

提高过程能力指数(CP/CPK)的途径

编者按:过程能力指数(CP/CPK)想必各位质量人都耳熟能详、运用自如,质量工程师之家前期也共享过数篇关于过程...
SPC控制图的八种模式分析

SPC控制图的八种模式分析

SPC控制图有八种模式,即八种判断异常的检验准则,每一种检验准则代表一种异常现象,应用SPC控制图进行过程评估...
测量高手放大招:圆跳动测量技巧总结

测量高手放大招:圆跳动测量技巧总结

01. 前言 在五金机加工厂实际的测量工作中,经常碰到要求测量两个要素的圆跳动问题, 利用不同的测量辅件及夹具...
过程能力分析(CP&cpk)

过程能力分析(CP&cpk)

引入过程能力分析的目的? 在我们现有的管理过程中,我们经常会遇到有些具体指标总是不尽人意,存在许多需要改进的地...
新能源汽车 “两会”精神宣贯会

新能源汽车 “两会”精神宣贯会

此次和大家分享新能源汽车相关政策: [embeddoc url=”https://www.ctro...
最新评论
多乐士 多乐士 通过摸索发现ssh拉取会报错,直接网页访问下载会报404错误,不知道原因;但是可以通过群晖CM注册表访问下载,其方法如下: Container Manager-注册表-设置-新增-注册表名称随便写,注册表URL填你的加速地址,勾选信任的SSL自我签署证书,登录信息不填-应用-使用你的地址,这是注册表会显示了,在搜索栏中输入映像名称,搜索结果在每一页的最后一个,你需要划到最后一个进行下载,实测可正常下载安装。 以上供网友参考。
多乐士 多乐士 还有一个比较简单的方法,只是需要一些外部工具。 1、讲损毁硬盘取出,装入外部移动硬盘 2、打开Diskgenius,定位到硬盘 3、格式化系统分区 4、重新插入硬盘 5、存储池->修复存储池即可
多乐士 多乐士 写的不错的文章
辞了老衲 辞了老衲 这个确实有帮助。
渋驀 渋驀 当然任何时候都可以用curl命令和crontab来实现动态更新DDNS的ip地址: 1、安装crontab之后为root用户创建文件/var/spool/cron/root 2、创建并配置ddnsupdate.sh,放到/usr/bin/文件下,文件内容(以he.net为例): Autodetect my IPv4/IPv6 address: IPV4:curl -4 "http://dyn.example.com:password@dyn.dns.he.net/nic/update?hostname=dyn.example.com" IPV6:curl -6 "http://dyn.example.com:password@dyn.dns.he.net/nic/update?hostname=dyn.example.com" 3、添加执行权限chomod +x /usr/bin/ddnsupdate.sh 4、编辑root用户的crontab:*/10 * * * * /usr/binddnsupdate.sh,每10分钟执行一次。好了,可以享受你的DDNS了
21410 21410 请问下载链接在那里?
madkylin madkylin 不错,不错,谢谢分享了,好东西啊 :lol:
feilung feilung 求方法
zengsuyi zengsuyi 应该挺不错的
zise zise 看看是怎么操作的。。 :oops: