本文提供Revit插件的打包方式,本文着重介绍AddIn文件的动态生成实现方法,安装包制作过程在下一篇文章中介绍,源码及所需文件在文章末尾列出。
一、打包实现逻辑
- 用户点击安装程序,开始执行安装
- 将插件相关数据解压到用户指定目录中
- 根据当前插件安装的位置动态生成addin文件到本机Revit插件加载目录中
- 将资源文件复制到本机Revit安装目录下(项目所需,其它项目请忽略此步骤)
- 安装完成
二、AddIn文件动态生成
1.配置文件
新建一个配置文件存储插件的相关属性,文件为ini格式,内容如下:
[AddInContent]
Type=APP #插件类型 APP外部应用 CMD外部命令
Name=MainAppCS #插件名称
AssemblyName=MainAppCS.dll #插件dll
FullClassName=MainAppCS.MainRun #程序入口类名
VendorId=ADSK #开发商ID
[AddInFile]
FileName=MainAppCS.addin #AddIn文件名称
[PlatForm]
VersionCount=1 #版本数量
Version_0=2016 #版本号
PathX86_0=MainAppCS\2016 #32位程序路径
PathX64_0=MainAppCS\2016 #64位程序路径
2.AddIn动态生成实现
新建一个控制台应用程序,在本机Revit的安装目录下找到RevitAddInUtility.dll,引入到项目中。
读取配置文件信息:
[DllImport("kernel32")]
public static extern int GetPrivateProfileString(string section, string key, string def, StringBuilder retVal, int size, string filePath);
/// <summary>
/// 读取配置文件中属性值(键值对格式)
/// </summary>
/// <param name="section">节名称</param>
/// <param name="key">属性Key值</param>
/// <param name="retVal">属性Value值</param>
/// <param name="filePath">配置文件路径</param>
/// <returns></returns>
public static bool ReadParamINI(string section, string key, ref string retVal, string filePath)
{
int size = 260;
StringBuilder ItemVal = new StringBuilder(size);
GetPrivateProfileString(section, key, "", ItemVal, size, filePath);
retVal = ItemVal.ToString();
if (retVal == "")
{
return false;
}
return true;
}
组织AddIn文件信息,主要是组织插件dll路径与AddIn文件保存路径:
/// <summary>
/// 组织AddIn文件信息
/// </summary>
/// <param name="addInInfo">ini配置文件信息</param>
/// <param name="deployInfo">AddIn文件信息,记录的是路径信息</param>
/// <returns></returns>
public static bool GetAddInInfoFromProduct(AddInInfo addInInfo, ref DeployInfo deployInfo)
{
//获取本机安装的所有Revit信息
IList<RevitProduct> revitProductArray = RevitProductUtility.GetAllInstalledRevitProducts();
if (0 == revitProductArray.Count)
{
Console.WriteLine("在本机上未检测到任何Revit系列软件的安装!");
Console.Read();
return false;
}
bool findProduct = false;
string versionName = "";
DeployPath curDeployPath = new DeployPath();
for (int i = 0; i < addInInfo.versionCount; ++i)
{
VersionInfo versionInfo = addInInfo.versionInfo[i];
foreach (RevitProduct product in revitProductArray)
{
versionName = System.Enum.GetName(product.Version.GetType(), product.Version);
if (!string.IsNullOrEmpty(versionName) && versionName.Contains(versionInfo.appVersion))
{
//根据配置文件中版本信息拼接AddIn文件存储路径
curDeployPath.addInFilePath = Path.Combine(product.AllUsersAddInFolder, addInInfo.manifestFileName);
//拼接安装包解压的dll文件路径
if (AddInArchitecture.OS32bit == product.Architecture)
{
curDeployPath.addInAssemblyPath = Path.Combine(CurAppDir, versionInfo.pathX86, addInInfo.addInAssemblyName);
}
else if (AddInArchitecture.OS64bit == product.Architecture)
{
curDeployPath.addInAssemblyPath = Path.Combine(CurAppDir, versionInfo.pathX64, addInInfo.addInAssemblyName);
}
deployInfo.deployCount++;
deployInfo.deployItem.Add(curDeployPath);
findProduct = true;
}
}
}
if (!findProduct)
{
Console.WriteLine("在本机上未检测到符合当前需要安装版本的Revit系列软件!");
Console.Read();
}
return findProduct;
}
执行安装的操作:
//执行插件安装
//addInInfo:配置文件信息(从上述方法一得出);addInDeployInfo:AddIn文件路径信息(从上述方法二得出)
//获取本机安装的所有Revit
IList<RevitProduct> revitProductArray = RevitProductUtility.GetAllInstalledRevitProducts();
for (int i = 0; i < addInDeployInfo.deployCount; ++i)
{
DeployPath deployPath = addInDeployInfo.deployItem[i];
string addInAssemblyPath = deployPath.addInAssemblyPath;
string manifestPath = deployPath.addInFilePath;
RevitAddInManifest manifest = new RevitAddInManifest();
//外部应用
if (addInInfo.addInType.ToLower().Equals("app"))
{
RevitAddInApplication addInApp = new RevitAddInApplication(addInName, addInAssemblyPath, Guid.NewGuid(), addInAssemblyFullClassName, vendorId);
manifest.AddInApplications.Add(addInApp);
}
//外部命令
else if (addInInfo.addInType.ToLower().Equals("cmd"))
{
RevitAddInCommand addInCmd = new RevitAddInCommand(addInAssemblyPath, Guid.NewGuid(), addInAssemblyFullClassName, vendorId);
addInCmd.Text = addInInfo.addInName;
manifest.AddInCommands.Add(addInCmd);
}
manifest.SaveAs(manifestPath);
}
#region 资源文件添加到Revit安装目录下(项目专用,其它项目请删除此段代码)
string ermsg = null;
string resPath = Path.Combine(CurAppDir, "ProjectResource.dll");
if (revitProductArray?.Count > 0 && addInInfo.versionInfo?.Count > 0 && File.Exists(resPath))
{
foreach (var version in addInInfo.versionInfo)
{
try
{
RevitProduct product = revitProductArray.ToList().Find(x => x.Version.ToString().Contains(version.appVersion));
if (product != null)
{
string curResPath = Path.Combine(product.InstallLocation, "ProjectResource.dll");
if (!File.Exists(curResPath))
File.Copy(resPath, curResPath, true);
}
}
catch (Exception ex)
{
ermsg = "Revit" + version.appVersion + "版本资源文件添加错误";
Console.WriteLine(ermsg);
Console.Read();
}
}
}
#endregion
执行卸载的操作
//执行插件卸载
//addInInfo:配置文件信息(从上述方法一得出);addInDeployInfo:AddIn文件路径信息(从上述方法二得出)
//获取本机安装的所有Revit
IList<RevitProduct> revitProductArray = RevitProductUtility.GetAllInstalledRevitProducts();
for (int i = 0; i < addInDeployInfo.deployCount; ++i)
{
DeployPath deployPath = addInDeployInfo.deployItem[i];
string addInAssemblyPath = deployPath.addInAssemblyPath;
string manifestPath = deployPath.addInFilePath;
if (File.Exists(manifestPath))
{
File.Delete(manifestPath);
}
}
#region 删除Revit安装目录下的资源文件(项目专用,其它项目请删除此段代码)
string ermsg = null;
if (revitProductArray?.Count > 0 && addInInfo.versionInfo?.Count > 0)
{
foreach (var version in addInInfo.versionInfo)
{
try
{
RevitProduct product = revitProductArray.ToList().Find(x => x.Version.ToString().Contains(version.appVersion));
if (product != null)
{
string curResPath = Path.Combine(product.InstallLocation, "ProjectResource.dll");
if (File.Exists(curResPath))
{
File.Delete(curResPath);
}
}
}
catch (Exception ex)
{
ermsg = "卸载时Revit" + version.appVersion + "目录下资源文件删除失败";
Console.WriteLine(ermsg);
Console.Read();
}
}
}
#endregion
将程序生成的exe文件保存备用
项目地址,有需要请自行下载:源代码Git地址(包含打包工具)