用VB6写在线更新程序(上篇)(2/3)

前端之家收集整理的这篇文章主要介绍了用VB6写在线更新程序(上篇)(2/3)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

到这里又遇到问题了,命令行参数是拆分到数组里的,如果不指定命令参数时,则数组保持为“空数组”。而对“空数组”的任何操作(包括UBound函数测长度)都会引发错误,这个问题困扰了我很久。怎么才能将这种情况区分出来呢?没办法,最终还是只能借助API函数SafeArrayGetDim,其实这个函数的真正作用是:取得 OLE Variant 数组元素的数组维度,不过,勉强解决问题吧。

从命令行参数得到XML配置文件地址后,接着是解析XML文件获取更新信息与文件列表。当然,在解析XML配置信息之前,得先定好XML配置文件的格式,如下面的代码

<?xml version="1.0" encoding="gb2312" ?>

<update>

<publish>

<force>0</force>

<publishDate>20090902 19:51:32</publishDate>

<version>1.0.0.0</version>

<remark />

<run />

</publish>

<paths>

<configUrl url="Update.xml" />

<configPath path="D:/Current/VBUpdate/Publisher/" />

<baseUrl url="http://localhost/update/" />

<localPath url="D:/Current/VBUpdate/Publisher/" />

<remotePath url="D:/Current/VBUpdate/Publisher/" />

</paths>

<files>

<file name="Publisher.exe" main="1" version="1.0.0.0" />

<file name="../Update/Update.exe" version="1.0.0.0" />

<file name="../Update/olelib.tlb" version="20040201 22:54:16" />

<file name="../Update/SetSys.ico" version="20090813 10:38:54" />

</files>

</update>

其中,publish结点描述的上所发布程序的基本信息,包括以下子结点:

序号

结点名称

用途

可能值

备注

1

force

指明是否强制更新。

0(可取消更新)或1(强制更新)

0值均解析为1(强制更新)

2

publishDate

表示发布时间。

发布当时时间。

3

version

主程序版本号。

主程序文件版本号。

通过比较这个版本号决定是否需要更新。

4

remark

发布说明。

历次发布的修订内容

每次的修订内容占一行,新的在上面。

5

run

更新后运行命令。

DOS命令。

一般为调用批处理。

paths结点描述与更新及发布相关的路径,包括以下子结点:

序号

结点名称

用途

可能值

备注

1

configUrl

指定XML配置文件URL

包括XML文件名的完整URL

要与主程序中读取的URL一致。

2

configPath

保存XML配置文件的远程地址。

文件路径,以“/”结束。

不支持FTP路径。

3

baseUrl

指定下载基地址。

http://路径,以“/”结束。

4

localPath

指定本地路径。

本地待发布程序路径,以“/”结束。

一般以主程序路径为基准。

5

remotePath

指定远程路径。

程序发布到的路径,以“/”结束。

不运行FTP路径。

files描述要更新文件列表,每个文件以一个子结点表示,结点为固定为“file”,“name属性指定源文件名,以上述的下载基地址(baseUrl)为基准,支持相对路径;“target属性指定目的文件名,以主程序所在路径为基准,支持相对路径,缺省时直接使用源文件名;“version属性表示该文件发布的版本号,如果文件包括版本信息,则用“date属性指定其最后修改时间,“version”或“date”决定了该文件的新旧、是否需要更新;“main属性指定该文件是否主程序,1(或非0)表示是,0表示否。

XML配置文件格式清楚了,下面要开始VB读取XML之旅了,好XML解析用的是MicrosoftXML分析器组件,而且在Delphi中已经用过,写起来还不是很太吃力。MSXML分析器有很多版本,但为了安全起见还是引用了较低的版本:2.0(Microsoft XML,version 2.0)

要解析XML配置之前,首先需要创建XML文档处理对象,由于习惯了OOP,当然在VB里也要这样用好一点,所以将XML配置解析写成了类:XmlConfiguration,在构造函数(我自认为Class_Initialize过程应该就等同于构造函数吧?)中创建XML文档实例:

Set XmlDoc = New DOMDocument

XmlDoc.preserveWhiteSpace = False 这句感觉是多余的,本来是想让它自动缩进、换行的,但就是没找到适合的属性,保存得到的XML文件乱糟糟的。

创建XML文档实例后,开始装载XML配置文件,用到Load方法

XmlDoc.Load(ConfigFile)

Delphi中不同的是,这里的Load是异步执行的,调用后尚不能立即读取结点,需要监测其状态,等待装载完成后才行。我是通过Timer定时(100毫秒)检测的,当XmlDoc.readyState = 4时即开始解析XML配置。首先写一个Analysis方法,依次读取update(根结点)下的每一个子结点,然后再处理每一个子结点:

'{ 解析每个子结点的值到各个属性Cable Fan 2009-08-14 }

Public Sub Analysis()

Dim i As Integer

Dim Root As IXMLDOMNode

Dim Node As IXMLDOMNode

Set Root = XmlDoc.documentElement

If Root Is Nothing Then

MsgBox "无法读取XML配置!"

Else

For i = 0 To Root.childNodes.Length - 1

Set Node = Root.childNodes(i)

Select Case Node.nodeName

Case "publish"

LoadPublish Node '发布信息。

Case "paths"

LoadPaths Node ' 装载下载路径。

Case "files"

LoadFiles Node ' 装载文件列表。

End Select

Next

End If

End Sub

'{ 装载下载路径。Cable Fan 2009-08-14 }

Private Sub LoadPublish(PNode As IXMLDOMNode)

On Error GoTo CATCH

' 遍历所有文件子结点。

Dim Node As IXMLDOMNode

Dim Attr As IXMLDOMNode

Dim i As Integer

For i = 0 To PNode.childNodes.Length - 1

Set Node = PNode.childNodes(i)

Select Case Node.nodeName

Case "force"

m_Force = (Node.Text = "1")

Case "publishDate"

m_PublishDate = CDate(Node.Text)

Case "version"

m_Version = Node.Text

Case "remark"

m_Remark = Node.Text

Case "run"

m_RunCmd = Node.Text

End Select

Next

Exit Sub

CATCH:

Err.Raise MODULEID + 12, "XMLConfiguration.LoadPublish"

Err.Clear

End Sub

'{ 装载下载路径。Cable Fan 2009-08-14 }

Private Sub LoadPaths(PNode As IXMLDOMNode)

On Error GoTo CATCH

' 遍历所有文件子结点。

Dim Node As IXMLDOMNode

Dim Attr As IXMLDOMNode

Dim i As Integer

For i = 0 To PNode.childNodes.Length - 1

Set Node = PNode.childNodes(i)

Select Case Node.nodeName

Case "configUrl"

Set Attr = Node.Attributes.getNamedItem("url")

If Not Attr Is Nothing Then m_ConfigUrl = Attr.nodeValue

Case "configPath"

Set Attr = Node.Attributes.getNamedItem("path")

If Not Attr Is Nothing Then m_ConfigPath = Attr.nodeValue

Case "baseUrl"

Set Attr = Node.Attributes.getNamedItem("url")

If Not Attr Is Nothing Then m_BaseUrl = Attr.nodeValue

Case "localPath"

Set Attr = Node.Attributes.getNamedItem("path")

If Not Attr Is Nothing Then m_LocalPath = Attr.nodeValue

Case "remotePath"

Set Attr = Node.Attributes.getNamedItem("path")

If Not Attr Is Nothing Then m_RemotePath = Attr.nodeValue

End Select

Next

Exit Sub

CATCH:

' Err.Raise MODULEID + 12,"XMLConfiguration.LoadPaths"

' Err.Clear

End Sub

'{ 装载下载路径。Cable Fan 2009-08-14 }

Private Sub LoadPaths(PNode As IXMLDOMNode)

On Error GoTo CATCH

' 遍历所有文件子结点。

Dim Node As IXMLDOMNode

Dim Attr As IXMLDOMNode

Dim i As Integer

For i = 0 To PNode.childNodes.Length - 1

Set Node = PNode.childNodes(i)

Select Case Node.nodeName

Case "configUrl"

Set Attr = Node.Attributes.getNamedItem("url")

If Not Attr Is Nothing Then m_ConfigUrl = Attr.nodeValue

Case "configPath"

Set Attr = Node.Attributes.getNamedItem("path")

If Not Attr Is Nothing Then m_ConfigPath = Attr.nodeValue

Case "baseUrl"

Set Attr = Node.Attributes.getNamedItem("url")

If Not Attr Is Nothing Then m_BaseUrl = Attr.nodeValue

Case "localPath"

Set Attr = Node.Attributes.getNamedItem("path")

If Not Attr Is Nothing Then m_LocalPath = Attr.nodeValue

Case "remotePath"

Set Attr = Node.Attributes.getNamedItem("path")

If Not Attr Is Nothing Then m_RemotePath = Attr.nodeValue

End Select

Next

Exit Sub

CATCH:

' Err.Raise MODULEID + 12,"XMLConfiguration.LoadFiles"

' Err.Clear

End Sub

Delphi中不同的是,读取一个结点的属性值时,要判断属性的存在性,试图读取返回的空值将引发错误

原文链接:https://www.f2er.com/vb/262700.html

猜你在找的VB相关文章