RevitAPI 隐藏UI读取Revit文件

在项目中需要读取rvt文件,但是因为该格式为非公开格式,其数据需要revit的支持,但批量读取不可能一个一个用revit软件去打开。不过该方法还是需要revit的依赖,速度比开软件快了知道多少

1.1. 新建一个控制台项目

RevitAPI 隐藏UI读取Revit文件

1.2. 添加Revit API引用

我们找到revit安装目录下的这两个DLL添加到项目引用中

  • RevitNET.dll
  • RevitAPI.dll

RevitAPI 隐藏UI读取Revit文件

修改属性:复制本地:FALSE

RevitAPI 隐藏UI读取Revit文件

1.3. 为MAIN函数添加STAThread特性

        [STAThread]//一定要有
        static void Main(string[] args)
        {
        }

如果未添加则报错:

异常:SEHException: 外部组件发生异常。

1.4. 修改控制台项目为64位

由于revit为64位程序,所以我们的控制台程序一定要为64位才可正常使用。

RevitAPI 隐藏UI读取Revit文件

1.5. 添加封装好的revitContext类

可以直接使用,可以根据自己需要去修改,其中的Application就是revit主要的

    public class RevitContext
    {
        #region private fields

        Product _revitProduct;
        private static bool isLoadEnv = false;//是否已添加过环境变量

        #endregion

        #region public fields

        /// <summary>
        /// revit程序目录
        /// </summary>
        public static string RevitPath;

        #endregion
        #region event

        public event EventHandler<Product> InitRevitFinished;

        #endregion
        #region public properties
        /// <summary>
        /// 打开REVIT文件时的设置
        /// </summary>
        public OpenOptions OpenOptions { get; set; }
        /// <summary>
        /// Revit Application
        /// </summary>
        public Autodesk.Revit.ApplicationServices.Application Application => this._revitProduct?.Application;
        #endregion
        #region constructors
        /// <summary>
        /// 
        /// </summary>
        /// <param name="revitPath">revit安装目录</param>
        public RevitContext(string revitPath)
        {
            RevitPath = revitPath;
            AddEnv();
        }
        /// <summary>
        /// 使用此构造方法前需要调用 RevitContext.AddEnv();
        /// </summary>
        public RevitContext()
        {
           
        }

        #endregion

        #region public methods
        public void InitRevit()
        {
            this.OpenOptions = new OpenOptions
            {
                Audit = true,
                AllowOpeningLocalByWrongUser = false,
                DetachFromCentralOption = DetachFromCentralOption.DetachAndDiscardWorksets //从中心模型分离
            };
            _revitProduct = Product.GetInstalledProduct();
            var clientApplicationId = new ClientApplicationId(Guid.NewGuid(), "RevitContext", "BIM");
            _revitProduct.SetPreferredLanguage(Autodesk.Revit.ApplicationServices.LanguageType.Chinese_Simplified);
            _revitProduct.Init(clientApplicationId, "I am authorized by Autodesk to use this UI-less functionality.");
            OnInitRevitFinished();
        }
        public Document OpenFile(string filename, OpenOptions options = null)
        {
            if (options == null)
            {
                options = this.OpenOptions;
            }
            ModelPath model = new FilePath(filename);
            return this._revitProduct.Application.OpenDocumentFile(model, options);
        }
        /// <summary>
        /// 获取默认三维视图
        /// </summary>
        /// <param name="document">文档</param>
        /// <returns></returns>
        public View3D GetView3D(Document document)
        {
            if (document.ActiveView is View3D view3D && !view3D.IsPerspective && view3D.CanBePrinted)
            {
                return view3D;
            }
            FilteredElementCollector filter=new FilteredElementCollector(document);
            return (View3D) filter.OfClass(typeof(View3D)).FirstElement();
        }

        /// <summary>
        /// 获取指定三维视图
        /// </summary>
        /// <param name="document">文档</param>
        /// <param name="viewName">指定视图名称</param>
        /// <returns></returns>
        public View3D GetView3D(Document document,string viewName)
        {
            FilteredElementCollector filter = new FilteredElementCollector(document);
            return (View3D)filter.OfClass(typeof(View3D)).FirstOrDefault(x => x.Name==viewName);
        }

        public IList<Element> GetElementsWithView(View3D view)
        {
            FilteredElementCollector collector=new FilteredElementCollector(view.Document,view.Id);
            return collector.ToElements();
           
        }

        #endregion

        #region public static methods
        /// <summary>
        /// 添加revit安装路径到环境变量以便加载相应的DLL
        /// </summary>
        /// <param name="revitPath">添加revit安装路径</param>
        public static void AddEnv(string revitPath=null)
        {
            if (isLoadEnv)
            {
                return;
            }

            if (revitPath!=null)
            {
                RevitPath = revitPath;
            }
            AddEnvironmentPaths(RevitPath);
            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
        }



        #endregion

        #region private static methods

        /// <summary>
        /// 添加环境变量
        /// </summary>
        /// <param name="paths">revit安装路径</param>
        static void AddEnvironmentPaths(params string[] paths)
        {
            string[] first = {
                Environment.GetEnvironmentVariable("PATH") ?? string.Empty
            };
            string value = string.Join(Path.PathSeparator.ToString(), first.Concat(paths));
            Environment.SetEnvironmentVariable("PATH", value);
        }
        /// <summary>
        /// 动态加载revit相关的dll
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
        {
            var assemblyName = new AssemblyName(args.Name);
            var text = $"{Path.Combine(RevitPath, assemblyName.Name)}.dll";
            Assembly result;
            if (File.Exists(text))
            {
                Console.WriteLine($"Load Revit Dll Path:{text}");
                result = Assembly.LoadFrom(text);
            }
            else
            {
                result = null;
            }
            return result;
        }

        #endregion
        #region private methods

        private void OnInitRevitFinished()
        {
            this.InitRevitFinished?.Invoke(this, this._revitProduct);
        }



        #endregion

    }

1.6. 使用并测试

class Program
    {
        static RevitContext revit;
        static Program()
        {
            RevitContext.AddEnv(@"D:\Program Files\Autodesk\Navisworks Manage 2020\Loaders\Rx\");
        }
        [STAThread]//一定要有
        static void Main(string[] args)
        {
            revit = new RevitContext();
            revit.InitRevitFinished += InitRevitFinished;
            revit.InitRevit();
            Console.ReadKey();
        }

        private static void InitRevitFinished(object sender, Product revitProduct)
        {
            Console.WriteLine("当前使用Revit版本为:" + revitProduct.Application.VersionName);

            Document document = revit.OpenFile(@"E:\test\2019\经典小文件\2020.rvt");

            View3D view = revit.GetView3D(document);
            if (view!=null)
            {
                Console.WriteLine(view.Name);
                var elements =revit.GetElementsWithView(view);
                foreach (var element in elements)
                {
                    Console.WriteLine(element.Name);
                }
            }

        }
    }

完成!

RevitAPI 隐藏UI读取Revit文件

1.7. 留下的坑:

  • 如何在不指定revit路径的情况下加载(动态获取revit安装路径)
  • 根据revit文件版本加载相应的revit路径
  • 一个程序动态支持多版本revit

以上问题本人已有相应的方法。

源码

RevitAPI 隐藏UI读取Revit文件

上一篇:windows10下Bad owner or permissions on .ssh/config的解决办法


下一篇:.NET Core 3时代!如何使用DevExpress WPF创建应用