Revit二次开发——独立进程内读取、写入Revit文件
详解
不开启Revit,读取、写入Revit文件
要点:需要引入RevitNET.dll,RevitAddInUtility.dll和RevitAPI.dll三个dll到项目中
RevitAddInUtility.dll
此dll是Autodesk Revit 提供,用于方便开发者进行安装包的制作。使用此dll无需读注册表,可针对Revit版本,安装位置等信息的获取,也可以轻松的操控AddIn插件注册文件。此dll具体chm帮助文档,与此dll统一存在于Revit安装目录下。
RevitNET.dll
RevitNET.dll 在Revit安装目录下即可找到。此dll是Autodesk 用于开启一个简易版本 、无任何UI界面的小型化 Revit 所进行封装的。也就是使用此dll可做到无需启动Revit便可进行创建、修改、读取等等操作。并且因为是无界面操作,其效率要比Revit更高。其具体使用方法,如下代码所示。Navsiworks 即是使用了此dll。感兴趣的朋友可以进行尝试研究。
public class Program{static readonly string WorkPath = Path.GetDirectoryName(typeof(Program).Assembly.Location);static Program(){RevitCoreContext.Instance.Run();}/// <summary>/// Revit 内核必须加 STAThread 标签/// </summary>/// <param name="args"></param>[STAThread]static void Main(string[] args){var app = RevitCoreContext.Instance.Application;// Todo ...var projectrTemplate = app.DefaultProjectTemplate;if (!File.Exists(projectrTemplate)){throw new FileNotFoundException("默认项目路径不存在 , 请指定 !");}var document = app.NewProjectDocument(projectrTemplate);if (document == null){throw new InvalidOperationException();}// create wall demo ...var p1 = XYZ.Zero;var p2 = p1 + XYZ.BasisX * 10;var p3 = p2 + XYZ.BasisY * 10;var p4 = p1 + XYZ.BasisY * 10;var points = new XYZ[] { p1, p2, p3, p4 };document.Invoke(m =>{var level0 = document.QueryByType<Level>().OfType<Level>().FirstOrDefault(x => Math.Abs(x.Elevation - 0.0) <= 1e-7);if (level0 == null){level0 = Level.Create(document, 0);document.Regenerate();}for (int i = 0; i < points.Length; i++){var a = points[i];var b = i == points.Length - 1 ? points[0] : points[i + 1];Wall.Create(document, Line.CreateBound(a, b), level0.Id, false);}});document.SaveAs(Path.Combine(WorkPath, "demowall.rvt"));RevitCoreContext.Instance.Stop();}}
public class RevitCoreContext{// 此路径为动态反射搜索路径 、 此路径可为任意路径(只要路径下有RevitNET 所需依赖项即可,完整依赖项可在 Naviswork 2016 下面找到)static readonly string[] Searchs = RevitProductUtility.GetAllInstalledRevitProducts().Select(x => x.InstallLocation).ToArray();static readonly object lockobj = new object();static RevitCoreContext _instance;private Product _product;public Application Application { get => _product.Application; }public static RevitCoreContext Instance{get{if (_instance == null){lock (lockobj){if (_instance == null){_instance = new RevitCoreContext();}}}return _instance;}}static RevitCoreContext(){AddEnvironmentPaths(Searchs);AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;}public void Run(){_product = Product.GetInstalledProduct();var clientId = new ClientApplicationId(Guid.NewGuid(), "DotNet", "BIMAPI");// I am authorized by Autodesk to use this UI-less functionality. 必须是此字符串。 Autodesk 规定的._product.Init(clientId, "I am authorized by Autodesk to use this UI-less functionality.");}public void Stop(){_product?.Exit();}static void AddEnvironmentPaths(params string[] paths){var path = new[] { Environment.GetEnvironmentVariable("PATH") ?? string.Empty };var newPath = string.Join(System.IO.Path.PathSeparator.ToString(), path.Concat(paths));Environment.SetEnvironmentVariable("PATH", newPath);}private static Assembly OnAssemblyResolve(object sender, ResolveEventArgs args){var assemblyName = new AssemblyName(args.Name);foreach (var item in Searchs){var file = string.Format("{0}.dll", System.IO.Path.Combine(item, assemblyName.Name));if (File.Exists(file)){return Assembly.LoadFile(file);}}return args.RequestingAssembly;}}
public static class DocumentExtension{public static void Invoke(this Document doc, Action<Transaction> action, string name = "default"){using (var tr = new Transaction(doc, name)){tr.Start();action(tr);var status = tr.GetStatus();switch (status){case TransactionStatus.Started:tr.Commit();return;case TransactionStatus.Committed:case TransactionStatus.RolledBack:return;case TransactionStatus.Error:tr.RollBack();return;default:return;}}}public static TResult Invoke<TResult>(this Document doc, Func<Transaction, TResult> func, string name = "default"){using (var tr = new Transaction(doc, name)){tr.Start();var result = func(tr);var status = tr.GetStatus();switch (status){case TransactionStatus.Started:tr.Commit();return result;case TransactionStatus.Committed:case TransactionStatus.RolledBack:return result;case TransactionStatus.Error:tr.RollBack();return result;default:return result;}}}public static void InvokeSub(this Document doc, Action<SubTransaction> action){using (var tr = new SubTransaction(doc)){tr.Start();action(tr);var status = tr.GetStatus();switch (status){case TransactionStatus.Started:tr.Commit();return;case TransactionStatus.Committed:case TransactionStatus.RolledBack:break;case TransactionStatus.Error:tr.RollBack();return;default:return;}}}public static TResult InvokeSub<TResult>(this Document doc, Func<SubTransaction, TResult> func){using (var tr = new SubTransaction(doc)){tr.Start();var result = func(tr);var status = tr.GetStatus();switch (status){case TransactionStatus.Started:tr.Commit();return result;case TransactionStatus.Committed:case TransactionStatus.RolledBack:return result;case TransactionStatus.Error:tr.RollBack();return result;default:return result;}}}public static void InvokeGroup(this Document doc, Action<TransactionGroup> action, string name = "default"){using (var tr = new TransactionGroup(doc, name)){tr.Start();action(tr);var status = tr.GetStatus();switch (status){case TransactionStatus.Started:tr.Commit();return;case TransactionStatus.Committed:case TransactionStatus.RolledBack:break;case TransactionStatus.Error:tr.RollBack();return;default:return;}}}public static TResult InvokeGroup<TResult>(this Document doc, Func<TransactionGroup, TResult> func, string name = "default"){using (var tr = new TransactionGroup(doc, name)){tr.Start();var result = func(tr);var status = tr.GetStatus();switch (status){case TransactionStatus.Started:tr.Commit();return result;case TransactionStatus.Committed:case TransactionStatus.RolledBack:return result;case TransactionStatus.Error:tr.RollBack();return result;default:return result;}}}public static FilteredElementCollector QueryByType<T>(this Document doc) where T : Element{return new FilteredElementCollector(doc).OfClass(typeof(T));}}
问题总结
1,异常:SEHException: 外部组件发生异常
解决方法:Revit 内核必须加 STAThread 标签
RevitCoreContext.Instance.Run();
2,在Windows应用程序提示无法加载RevitNET.dll。
可能的原因是:目标平台为Any CPU,首先32位。
应该取消首先32位的对勾,或者更改为X64 。
目标框架注意与引用的项目一致(主要针对其它dll)
3,如何跨线程访问吗?
将RevitNet封装为一个控制台应用程序(Revit启动程序),然后通过命令行去启动Revit启动程序。
在启动过程可以传入参数。
Process process=new Process();//AppDomain.CurrentDomain.BaseDirectory +
process.StartInfo.FileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory ,"ExportStart.exe");//执行的exe路径
process.StartInfo.UseShellExecute = false;//不显示shell
process.StartInfo.CreateNoWindow = true;//不创建窗口
process.StartInfo.RedirectStandardInput = true;//打开流输入
process.StartInfo.RedirectStandardOutput = true;//打开流输出
process.StartInfo.RedirectStandardError = true;//打开错误流
process.StartInfo.Arguments = "" + revitCmd + " \"" + filePathList.First() + "\"";//输入参数,多个参数使用空间分割,如果一个参数包含空格,使用""包括此参数
process.Start();//执行
string msg = process.StandardOutput.ReadToEnd();//读取输出
process.WaitForExit();//等待执行完成
process.Close();//结束
4,未能加载由“RevitNET.dll”导入的过程?
解决办法:
查看环境变量,将RevitInstallPath的path放至第一位。
5,不启动获取Revit文件的版本
/// <summary>/// 获取Revit文件的版本/// </summary>/// <param name="path">文件路径</param>/// <returns></returns>public static string GetRevitVision(string path){string revitVision = null;FileStream stream = new FileStream(path, FileMode.Open);int size = 1024 * 1024;byte[] bytes = new byte[size]; while (stream.Read(bytes, 0, size) > 0){string str = Encoding.Unicode.GetString(bytes);string pattern = @"Autodesk Revit \d{4}";var match = Regex.Match(str, pattern);if (match.Success){revitVision = match.Value.Substring(match.Length - 4, 4);//File.WriteAllText(@"D:\abc.txt", str);break;}}return revitVision;}
6,程序运行目录(OutputDll)能否删除RevitAPI.dll或RevitAPIUI.dll等相关dll
可以,设置环境变量后,Revit会去Revit安装目录下查找以上dll。
注意:如果如果程序运行目录(OutputDll)存在Revit相关的dll,版本必须正确,否则会报错。(如果不能保证版本正确,不如将Revit相关dll全部删除)
7,RevitNet启动程序,能否取消RevitAddInUtility.dll的引用?
可以取消,RevitAddInUtility.dll 此dll的作用是用于获取Revit的安装目录,可以手动指定Revit的安装目录。从而取消此dll的引用。(完全可以不安装Revit,只复制Revit需要的dll,但区别那些dll是Revit需要的会很麻烦。不过可以将Revit安装目录下的文件全部复制到指定位置)
Revit二次开发——独立进程内读取、写入Revit文件相关推荐
- Revit二次开发01——环境搭建(附Revit 2018 + Visual Studio 2017下载地址)
目录 1.准备工作 1.1 安装Revit 2018 1.2 安装Revit 2018 SDK 1.3 安装Visual Studio 2017 2.配置Addin Manager 3.测试 3.1 ...
- Revit二次开发之获取当前电脑所有Revit版本
一.背景 小伙伴们在做Revit插件安装包时,是否需要获取当前电脑已经安装了哪些版本的Revit呢? 二.解决思路 主要有两种思路 通过注册表 通过revit提供的方式 这里推荐第2种方式,因为这种方 ...
- Revit二次开发之通过命令ID调用Revit自有命令
参考一: PostableCommand Enumeration 参考二: 修改----ID_BUTTON_SELECT----MD----创建->选择;插入->选择;注释->选择; ...
- Revit二次开发——三角面创建
Revit二次开发--三角面创建 文章目录 Revit二次开发--三角面创建 前言 一.三角面是什么? 二.三角网 三.使用步骤 1.引入库 2.开启事务 3.创建 总结 前言 三角面是创建实体的基础 ...
- 关于Revit二次开发的些许事
关于Revit二次开发的些许事 关于Revit二次开发的些许事 Revit二次开发方向 岗位需求 哪些公司在招聘Revit研发岗位? 招聘的普遍岗位职责是什么? 岗位要求有哪些? 待遇是不是美丽?! ...
- Revit二次开发从入门到精通学习之路, (含Revit二次开发教程下载)
Revit二次开发从入门到精通学习之路 Autodesk Joe Ye叶雄进 2. 18 2014 yexiongjin@hotmail.com Revit在国内的应用越来越广泛, Revit ...
- 再谈Revit二次开发的可靠性和前景
接到一个问题咨询如下信息. Revit本身的开发规范吗?Revit发展前景如何?听说了一些Revit的身世,老担心它本身的代码就不规整.严谨,程序不够稳定,在这个平台上开始大规模二次开发有很大风险.公 ...
- Revit二次开发笔记
Revit二次开发笔记: 配置:以revit 2021为例 Visual studio中的配置 以下是如果要翻成EnergyPlus模型需要的配置 如何安装Addin Manger和lookup插件 ...
- Revit二次开发加载RevitLookup.dll程序集
Revit二次开发加载RevitLookup.dll程序集 Revit二次开发环境搭建(Revit 2019+Visual Studio 2017) 更正加载RevitLookup.dll: 编译出R ...
最新文章
- 百万数据报表导出:需求以及思路分析
- 内核 读写 flash mtd_2D动作卷轴《Lost Epic》公布 少女外表魂系内核|游民星空
- junit 预期错误_谨慎使用JUnit的预期异常
- 机箱硬盘指示灯不亮_安钛克DF600 FLUX机箱:FLUX平台第一款机箱,为全民电竞热“降温”...
- 舞动的桥 阿里云首个百万IOPS云盘的背后
- android 编译c代码吗,在Android手机上编译C代码
- java读取tif文件_java读取TIF,TIFF文件方法
- python语义分析_Python自然语言分析
- 高级气泡图——R语言简单实现
- 使用Certbot为nginx配置免费的https证书
- 微信、公总号、企业微信开发
- tomcat--catalina
- Vue-pdf实现在线预览PDF文件
- 百度云盘群组下载,细节操作让你摸不着头脑?
- 第四章 开始Unity Shader学习之旅(1)
- 中小企业网管管理完全篇 [转]
- 复现实验:文本数据的分类与分析
- 【BIM+GIS】ArcGIS Pro2.8如何打开Revit模型,BIM和GIS融合?
- 如何生成小程序太阳码
- 高一物理借助传感器用计算机测速度,【2-2讲义·习题】第4节 实验:用打点计时器测速度...
热门文章
- 单目图像深度估计 - 迁移篇:Depth Extraction from Video Using Non-parametric Sampling
- 让我们一起开发【菜谱系统】吧,滚雪球学 Python 第三轮项目计划
- USB Full-Speed 控制传输
- 有赞 java_响应式架构与 RxJava 在有赞零售的实践
- 抢红包代码 php,ASP.NET代码轻松实现微信抢红包
- 计算机n位数的表示范围,计算机组成原理——原码、反码、补码的表示范围
- 【随笔】AI+眼镜行业
- 猎聘Q1营收毛利齐增,在线招聘的“春天”要来了么?
- Barcode读取之barcode_para_contrast_min.hdev
- 守株待兔都赚钱了,几十个IP怎么比几万IP还赚钱