如何把我们发布的库制作成安装包,直接百度“制作安装包工具”有许多软件推荐,比如说NSIS、SetupFactory、InstallShield等等;
这些软件大同小异,添加我们的库文件,提供交互界面设置基本参数,比如说软件名称、版本号、默认安装路径等等,如果界面操作无法满足当前需求的话,可以结合它提供的脚本来做更多的事情,比如写注册表、修改addin文件等等;
学会一种制作安装包的工具并且能灵活应用挺好的,能快速的打包自己的程序,而且这些软件大部分提供了保存项目的功能,也就是一个模板,而且脚本基本通用,也就是说,制作完一个revit插件安装包后,其他的插件只需要把它的库文件替换即可;
不过今天,我们来说说怎么自己写安装包
原理:把我们的程序压缩成zip包,把该zip嵌入安装程序exe中。用户安装时,解析exe中的文件流(zip)到本地,最后解压到用户选择的安装目录。
具体流程细节:
1、整理程序目录(release编译、初始化配置文件,准备addin文件等等),最后压缩成lib.zip包;
2、创建一个控制台程序Setup,把lib.zip注入到Setup项目中,注意,lib.zip文件的生成操作设置为“嵌入的资源”;
3、在program入口中写主要逻辑,比如:判断当前系统是否安装了对应版本revit、解析并且解压zip包、修改addin文件、写注册表、注册卸载程序等等,我的测试代码中没有这些逻辑,主要用作演示,其他各位自己写,也挺简单的;
这里关于zip包使用方式有两种:
第一种方式:如上直接嵌入到程序中打包,优点是可做离线安装包,缺点就是当zip很大时,编译的exe文件也很大,而且每次程序有更新,都需要发布新的安装包;
第二种方式:配合web服务器,zip包在安装程序中实时下载,优点就是用户可以下载一个相对很小的安装包,而且不需要更新安装包就能安装最新的程序。缺点显而易见,需要网络;
Demo
这是一个控制台程序,主要演示核心流程如何写
一般的安装程序是桌面应用程序,如WPF应用程序,可创建自己想要的UI提供各种信息的输入等等,怎么写的操作性就多了。
class Program
{
static void Main(string[] args)
{
const string zip = @"WXVisual.FamilyLibrary.Setup.lib.zip";
const string dest = @"C:\ProgramData\Autodesk\Revit\Addins\2018\企业族库V1.0";
const string addin = "WXVisual.Revit.Lib.addin";
if (Directory.Exists(@"C:\ProgramData\Autodesk\Revit\Addins\2018"))
{
var isRunRevit = System.Diagnostics.Process.GetProcessesByName("revit").Length > 0;
if (!isRunRevit)
{
try
{
if (Directory.Exists(dest)) Directory.Delete(dest, true);
var stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(zip);
var extractFilePath = ExtractZipStreamToTemp(stream);
System.IO.Compression.ZipFile.ExtractToDirectory(extractFilePath, dest);
var ori = Path.Combine(dest, addin);
var de = Path.Combine(Path.GetDirectoryName(dest), addin);
File.Copy(ori, de, true);
Console.WriteLine("安装 企业族库系统 成功, 快启动 Revit2018 试试吧。");
}
catch (Exception ex)
{
Console.WriteLine($"安装失败, 请联系管理员 [{ex.Message}]");
}
}
else
Console.WriteLine("revit正在运行, 请关闭revit再进行安装!");
}
else
Console.WriteLine("当前系统未安装revit2018!");
Console.ReadKey();
}
static string ExtractZipStreamToTemp(Stream stream)
{
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
stream.Seek(0, SeekOrigin.Begin);
string strFileName = Guid.NewGuid().ToString() + ".zip";
string strFilePath = Path.Combine(Path.GetTempPath(), strFileName);
using (var fs = new FileStream(strFilePath, FileMode.Create))
using (var bw = new BinaryWriter(fs))
{
bw.Write(bytes);
bw.Close();
fs.Close();
}
return strFilePath;
}
}