博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
VB.NET 自动打包程序
阅读量:6824 次
发布时间:2019-06-26

本文共 14215 字,大约阅读时间需要 47 分钟。

hot3.png

因为每次将编译好的程序提交时都要花费很多时间用来打包,因此我需要有一个让程序自动完成这些琐碎的工作。

首先说一下我的目标。我的C#程序(在本文中暂时称作Example.exe)编译后暂时存放在Debug目录中,该程序有两种形态:平台端和客户端,它们分别给不同的用户使用,这两个客户端的不同之处仅在与App.config(可以被看做一个XML文件)中的配置不同。打包时需要先使用NSIS脚本对Debug目录下的内容制作成安装包,再使用WinRAR将安装包进行压缩。除了两个安装包外,还需要提供一些文件放置到自动更新的目录下,这些文件需要单独打成安装包。

为此我使用VB.NET写了一个小程序(暂时取名叫SoftwareRelease),来实现这个功能。

配置文件如下:

D:\Example\bin\Debug
D:\ObjectPath
D:\NSIS\makensis.exe
D:\WinRAR\rar.exe

将这个文件放置在编译好的EXE文件相同路径下即可。

因为程序中要使用WinRAR和NSIS编译工具,因此在配置文件中要写明这两个程序可执行文件的绝对路径。

程序代码如下:

Imports System.XmlImports System.IO''' ''' SoftwareRelease 软件自动打包工具''' ''' 
Module ModuleMain ''' ''' SoftwareRelease 软件自动打包工具 ''' '''
Sub Main() '设置控制台缓冲区大小 Console.BufferHeight = 5000 '控制台文字颜色 - 青色 Console.ForegroundColor = ConsoleColor.Cyan '程序使用的标准时间 Dim dateTimeUni As DateTime = DateTime.Now Console.WriteLine("SoftwareRelease 软件自动打包工具") Console.WriteLine("版本号:" & System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString()) Console.WriteLine(New String("=", 20)) Console.WriteLine(dateTimeUni.ToString) Console.WriteLine() ' ----------- 1、读入参数即相关准备工作 ----------- ' Dim Args As String() = System.Environment.GetCommandLineArgs() Dim bNeedPlatform As Boolean = False '打包平台端 Dim bNeedClient As Boolean = False '打包客户端 Dim bNeedUpdate As Boolean = False '打包自动更新文件 '分析传入参数 If Args.Contains("/?") Or Args.Length = 1 Then '查看帮助 PrintUsage() Pause() Exit Sub ElseIf Args.Contains("/A") Or Args.Contains("/a") Then '全量包 bNeedPlatform = True bNeedClient = True bNeedUpdate = True Else If Args.Contains("/P") Or Args.Contains("/p") Then '打包平台端 bNeedPlatform = True End If If Args.Contains("/C") Or Args.Contains("/c") Then '打包客户端 bNeedClient = True End If If Args.Contains("/U") Or Args.Contains("/u") Then '打包自动更新文件 bNeedUpdate = True End If End If Console.WriteLine("本次执行任务:") If bNeedPlatform Then Console.WriteLine("打包平台端") End If If bNeedClient Then Console.WriteLine("打包客户端") End If If bNeedUpdate Then Console.WriteLine("打包自动更新文件") End If Console.WriteLine() '编译完毕后程序目录地址 Dim debugDir As String = "" '打包完毕后软件包所在目录地址 Dim objectDir As String = "" '编译器路径 Dim compilerPath As String = "" 'WinRAR压缩工具路径 Dim winRARPath As String = "" '编译脚本所在目录:平台端 Dim scriptDirOfPlatform As String = "" '编译脚本名称:平台端 Dim scriptFileOfPlatform As String = "" '编译脚本所在目录:客户端 Dim scriptDirOfClient As String = "" '编译脚本路径:客户端 Dim scriptFileOfClient As String = "" '读取配置 Console.WriteLine("正在读取配置...") Dim xmlDoc As XmlDocument = New XmlDocument() xmlDoc.Load("Config.xml") Dim xmlRoot As XmlNode = xmlDoc.SelectSingleNode("Config") For Each xmlObj In xmlRoot.ChildNodes If xmlObj.GetType().ToString() = "System.Xml.XmlElement" Then Dim xmlEle As XmlElement = DirectCast(xmlObj, XmlElement) Select Case xmlEle.Name Case "DebugDir" debugDir = xmlEle.InnerText.ToString.Trim Console.WriteLine("编译完毕后程序目录地址:" & debugDir) Case "ObjectDir" objectDir = xmlEle.InnerText.ToString.Trim Console.WriteLine("打包完毕后软件包所在目录地址:" & objectDir) Case "CompilerPath" compilerPath = xmlEle.InnerText.ToString.Trim Console.WriteLine("编译器路径:" & compilerPath) Case "WinRARPath" winRARPath = xmlEle.InnerText.ToString.Trim Console.WriteLine("WinRAR压缩工具路径:" & winRARPath) Case "ScriptList" For Each xmlObj2 In xmlEle.ChildNodes If xmlObj2.GetType().ToString() = "System.Xml.XmlElement" Then Dim xmlEle2 As XmlElement = DirectCast(xmlObj2, XmlElement) If xmlEle2.Name = "Script" And xmlEle2.GetAttribute("Name") = "platform" Then scriptDirOfPlatform = xmlEle2.GetAttribute("Directory").ToString Console.WriteLine("编译脚本所在目录(平台端):" & scriptDirOfPlatform) scriptFileOfPlatform = xmlEle2.GetAttribute("Script").ToString Console.WriteLine("编译脚本名称(平台端):" & scriptFileOfPlatform) End If If xmlEle2.Name = "Script" And xmlEle2.GetAttribute("Name") = "client" Then scriptDirOfClient = xmlEle2.GetAttribute("Directory").ToString Console.WriteLine("编译脚本所在目录(客户端):" & scriptDirOfClient) scriptFileOfClient = xmlEle2.GetAttribute("Script").ToString Console.WriteLine("编译脚本名称(客户端):" & scriptFileOfClient) End If End If Next Case Else End Select End If Next '释放资源 xmlDoc.RemoveAll() xmlDoc = Nothing '判断配置合法性 Dim isConfigLegal As Boolean = True If String.IsNullOrWhiteSpace(debugDir) Then Console.WriteLine("编译完毕后程序目录地址缺失") isConfigLegal = False End If If String.IsNullOrWhiteSpace(objectDir) Then Console.WriteLine("打包完毕后软件包所在目录地址缺失") isConfigLegal = False End If If String.IsNullOrWhiteSpace(compilerPath) Then Console.WriteLine("编译器路径缺失") isConfigLegal = False End If If String.IsNullOrWhiteSpace(winRARPath) Then Console.WriteLine("RAR压缩工具路径缺失") isConfigLegal = False End If If String.IsNullOrWhiteSpace(scriptDirOfPlatform) Then Console.WriteLine("编译脚本所在目录(平台端)缺失") isConfigLegal = False End If If String.IsNullOrWhiteSpace(scriptFileOfPlatform) Then Console.WriteLine("编译脚本名称(平台端)缺失") isConfigLegal = False End If If String.IsNullOrWhiteSpace(scriptDirOfClient) Then Console.WriteLine("编译脚本所在目录(客户端)缺失") isConfigLegal = False End If If String.IsNullOrWhiteSpace(scriptFileOfClient) Then Console.WriteLine("编译脚本名称(客户端)缺失") isConfigLegal = False End If If Not isConfigLegal Then Pause() Exit Sub End If Console.WriteLine("配置读取完毕!") Console.WriteLine() ' ----------- 2、检查Debug目录 ----------- ' If Not Directory.Exists(debugDir) Then Console.WriteLine("待打包程序目录不存在!") Pause() Exit Sub End If If Not File.Exists(debugDir + "\Example.exe") Then Console.WriteLine("待打包程序不存在!") Pause() Exit Sub End If If Not File.Exists(debugDir + "\Example.exe.config") Then Console.WriteLine("待打包程序关键配置文件缺失!") Pause() Exit Sub End If '清理掉所有pdb文件,这些文件是不需要的 Console.WriteLine("正在清理PDB文件") DeleteAllPdb(New DirectoryInfo(debugDir)) Console.WriteLine("正在清理登录信息") '清理登录信息,打包后的登录信息必须是干净的 If File.Exists(debugDir + "\Config\LoginData.xml") Then 'TODO:清理登陆信息 End If Console.WriteLine("待打包程序目录检查完毕") Console.WriteLine() ' ----------- 3、将Debug目录中的程序配置成平台端 ----------- ' If bNeedPlatform Or bNeedUpdate Then Console.WriteLine("将程序设置为平台端") If (SetAppConfig(debugDir + "\Example.exe.config", "platform")) Then Console.WriteLine("设置完毕") Console.WriteLine() Else Console.WriteLine("设置失败!") Pause() Exit Sub End If End If ' ----------- 4、复制一份,用于之后自动更新 ----------- ' If bNeedUpdate Then If (Directory.Exists(objectDir & "\platform")) Then Console.WriteLine("目录【" & objectDir & "\platform】已存在,正在删除该目录") Directory.Delete(objectDir & "\platform", True) Console.WriteLine("删除完毕!") End If Console.WriteLine("正在复制文件到目录【" & objectDir & "\platform】") My.Computer.FileSystem.CopyDirectory(debugDir, objectDir & "\platform", True) Console.WriteLine("复制完毕!") Console.WriteLine("正在删除冗余文件") 'TODO:删除冗余文件(即不用自动更新下来的文件) Console.WriteLine("冗余文件删除完毕!") Console.WriteLine() End If ' ----------- 5、为Debug目录中内容打包 ----------- ' If bNeedPlatform Then Console.WriteLine("正在打包:平台端") Shell(compilerPath & " " & scriptDirOfPlatform & "\" & scriptFileOfPlatform) Console.WriteLine("平台端打包完毕") '压缩到RAR文件 Dim packageName = scriptDirOfPlatform & "\平台端打包后文件.exe" '这里要做对应修改! If File.Exists(packageName) Then Dim rarName As String = dateTimeUni.ToString("yyyyMMdd") & "_PLATFORM.rar" 'a表示压缩文件,-r表示递归,-ep表示忽略路径信息 Shell(winRARPath & " a -ep " & objectDir & "\" & rarName & " " & packageName, AppWinStyle.NormalFocus, True) End If End If ' ----------- 6、将Debug目录中的程序配置成客户端 ----------- ' If bNeedClient Or bNeedUpdate Then Console.WriteLine("将程序设置为客户端") If (SetAppConfig(debugDir + "\Example.exe.config", "client")) Then Console.WriteLine("设置完毕") Console.WriteLine() Else Console.WriteLine("设置失败!") Pause() Exit Sub End If End If ' ----------- 7、复制一份,用于之后自动更新 ----------- ' If bNeedUpdate Then If (Directory.Exists(objectDir & "\client")) Then Console.WriteLine("目录【" & objectDir & "\client】已存在,正在删除该目录") Directory.Delete(objectDir & "\client", True) Console.WriteLine("删除完毕!") End If Console.WriteLine("正在复制文件到目录【" & objectDir & "\client】") My.Computer.FileSystem.CopyDirectory(debugDir, objectDir & "\client", True) Console.WriteLine("复制完毕!") Console.WriteLine("正在删除冗余文件") 'TODO:删除冗余文件(即不用自动更新下来的文件) Console.WriteLine("冗余文件删除完毕!") Console.WriteLine() End If ' ----------- 8、为Debug目录中内容打包 ----------- ' If bNeedClient Then Console.WriteLine("正在打包:客户端") Shell(compilerPath & " " & scriptDirOfClient & "\" & scriptFileOfClient) Console.WriteLine("客户端打包完毕") '压缩到RAR文件 Dim packageName = scriptDirOfPlatform & "\客户端打包后文件.exe" '这里要做对应修改! If File.Exists(packageName) Then Dim rarName As String = dateTimeUni.ToString("yyyyMMdd") & "_CLIENT.rar" 'a表示压缩文件,-r表示递归,-ep表示忽略路径信息 Shell(winRARPath & " a -ep " & objectDir & "\" & rarName & " " & packageName, AppWinStyle.NormalFocus, True) End If End If ' ----------- 9、打包自动更新包 ----------- ' If bNeedUpdate Then Dim rarNameUpdate As String = dateTimeUni.ToString("yyyyMMdd") & "_UPDATE.rar" 'a表示压缩文件,-r表示递归,-ep1表示忽略被压缩的根文件夹 Dim command As String = winRARPath & " a -r -ep1 " & objectDir & "\" & rarNameUpdate & " " & objectDir & "\platform" & " " & objectDir & "\client" Shell(command, AppWinStyle.NormalFocus, True) End If Console.WriteLine("打包工作全部完成!") Pause() End Sub ''' ''' 配置AppConfig中的客户端类型 ''' ''' AppConfig文件路径 ''' 客户端类型字符串 '''
true:修改成功,false:修改失败
'''
Function SetAppConfig(appConfigPath As String, clientType As String) Dim xmlAppConfig As XmlDocument = New XmlDocument xmlAppConfig.Load(appConfigPath) Dim xmlRoot As XmlNode = xmlAppConfig.SelectSingleNode("configuration") 'TODO:更改App.config中配置,更改成功则 GoTo 到 END_CONFIG Return FalseEND_CONFIG: xmlAppConfig.Save(appConfigPath) xmlAppConfig.RemoveAll() xmlAppConfig = Nothing Return True End Function ''' ''' 删除所有PDB文件 ''' ''' '''
Private Sub DeleteAllPdb(dif As DirectoryInfo) '遍历各个子文件夹 For Each di As IO.DirectoryInfo In dif.GetDirectories DeleteAllPdb(di) Next For Each f As System.IO.FileInfo In dif.GetFiles If f.Extension.ToLower = ".pdb" Then f.Delete() End If Next End Sub ''' ''' 打印程序用法 ''' '''
Sub PrintUsage() Dim Usage(7) As String Usage(0) = "程序使用方法" Usage(1) = "SoftwareRelease [ /? | /p | /c | /u | /a ]" Usage(2) = "没有参数:显示帮助,这与键入 /? 是一样的" Usage(3) = "/p:打包平台端" Usage(4) = "/c:打包客户端" Usage(5) = "/u:打包自动更新包" Usage(6) = "/a:打包全部内容,相当于 /p /m /u 同时存在" Console.WriteLine(Join(Usage, vbCrLf)) End Sub ''' ''' 按任意键继续 ''' '''
Sub Pause() Console.WriteLine("按任意键继续") System.Console.ReadKey() System.Console.Write(Chr(8) + " ") '删除按下的“任意键”字符 End SubEnd Module

以上代码需要注意的方面有:

1、打包前要先删除冗余文件,如*.pdb文件。对于自动更新端,还要删除那些可能会随着每次登录发生改变的文件和目录(如本地缓存数据用的文件等)

2、WinRAR程序(rar.exe)和NSIS编译工具(makensis.exe)都提供了功能强大的命令,可以利用这些命令完成很多自动化操作内容。注意NSIS编译工具使用makensis.exe而不是makensisw.exe,后者是一个具备GUI的工具,前者是为命令行提供的工具。

3、本程序接收的命令行参数为 /p(打包平台端)、/c(打包客户端)、/u(打包自动更新)、/a(打包全部)和/?(帮助),如果无参数则默认显示帮助

4、控制台缓冲区大小要设置得大一些,否则Windows的控制台默认只支持保留最后的300行内容

5、为了更方便使用本程序,可以写一个bat脚本直接调用本程序。内容如下:

SoftwareRelease.exe /a

END

转载于:https://my.oschina.net/Tsybius2014/blog/517298

你可能感兴趣的文章
Java并发编程:线程池的使用
查看>>
C++学习笔记01
查看>>
C# 反射机制
查看>>
c++ 2.1 编译器何时创建默认构造函数
查看>>
CentOS6编译LAMP基于FPM模式的应用wordpress
查看>>
30分钟入门正则表达式
查看>>
问题:主从数据库getConnection死循环
查看>>
15、排序:选择类排序和归并排序
查看>>
编程之美 2.16
查看>>
权限模块_分配权限_显示树状结构_页面中的选中效果
查看>>
艺龙旅行网
查看>>
libdvbpsi源码分析(二)main函数
查看>>
[poj2441] Arrange the Bulls
查看>>
Java内存分配、管理小结
查看>>
Redis入门到高可用(二)—— Redis启动及使用
查看>>
网页快捷键
查看>>
一步一步写jQuery插件
查看>>
MySQL(错误1064)
查看>>
js获取请求路径中参数值
查看>>
Asp.net Web Api进行Nunit测试
查看>>