首页 / 资讯中心 / 文章详情

RevitLookup 2020完全指南:addin加载、Snoop调试与源码改造

RevitLookup 2020完全指南:addin加载、Snoop调试与源码改造 ★ FEATURED ARTICLE
简介面向Revit 2020二次开发者的RevitLookup表格查找工具包内含可直接部署的插件注册文件与完整程序源码。RevitLookup用于查看和检索Revit数据库中的元素、参数与关系帮助开发者直观检查接口数据结构、定位插件问题是实施Revit二次开发时常用的调试辅助工具。压缩包共161个文件以78个C#源码文件为主另含编译好的动态库、addin注册文件、resx资源文件以及多种图标素材整体仅1.05MB源码工程、配置与图像资源彼此配套按模块分离适合阅读实现脉络。已有1652人学习下载。工具包兼顾开箱即用和源码修改两种方式既满足日常调试需要也适合在Visual Studio中调整项目引用后重新编译以便匹配本机环境并进一步按业务场景定制查找功能。1. RevitLookup 2020把Revit API的黑匣子撬开二开调试从盲猜变成翻树写过Revit插件的朋友多半有过这种经历自己写的命令跑完没报错但构件属性没变或者拿到一个Element却不知道里面到底挂了多少参数、几何数据长什么样。这时候最笨的办法是往代码里临时塞TaskDialog.Show()一行行打日志打完了再删删完发现还有别的要查又得重新编译一遍。RevitLookup 2020就是来终结这种盲猜的它是一个开源的外部应用以addin清单文件的形式挂进Revit 2020装上之后你可以在Revit界面里直接窥探任意元素、任意文档对象把API对象的属性、参数、几何、依赖关系一层层展开成树。它尤其适合两类人一类是刚接触Revit二次开发、连Parameter和ElementId都没摸熟的新手另一类是写复杂逻辑时被API文档绕晕、需要立刻确认对象真实结构的熟手。源码就在本地顺着编译一遍你还能按自己的需求改菜单、加命令。2. 先从成品入手addin加载、菜单入口和Snoop的三个用法2.1 addin文件是什么Revit 2020只认这一份XML清单Revit本身不扫描DLL它只扫描后缀为.addin的XML清单文件再由清单里写的Assembly路径去定位你的插件程序集。Revit 2020里addin文件放在两个位置程序数据级C:\ProgramData\Autodesk\Revit\Addins\2020对所有Windows用户生效用户级C:\Users\用户名\AppData\Roaming\Autodesk\Revit\Addins\2020只对当前用户生效。我一般优先放用户级避免在公司电脑上因为没有ProgramData写权限而加载失败。RevitLookup编译产物是一个DLL配套的addin内容大致是这样?xml version1.0 encodingutf-8? RevitAddIns AddIn TypeApplication NameRevitLookup 2020/Name AssemblyC:\LookupOutput\RevitLookup.dll/Assembly FullClassNameRevitLookup.App/FullClassName ClientId8D2A8C4F-0000-4000-8000-123456789ABC/ClientId VendorIdADSK/VendorId VendorDescriptionRevitLookup for Revit 2020/VendorDescription /AddIn /RevitAddIns这份清单里有三个关键点。Type必须写Application而不是Command因为RevitLookup的入口是IExternalApplication它要在Revit启动时注册菜单FullClassName要和你源码里的入口类完全一致包括命名空间写错一个字加载就会静默失败ClientId是一个GUID不能和本机其他插件重复重复的后果是Revit只加载其中一个。把这段XML存成RevitLookup.addin编码建议用UTF-8带BOM或者ANSI纯UTF-8无BOM在某些中文系统上会被误读这是addin加载失败里最玄学的一条后面避坑章节还会再提。2.2 加载之后去哪找Developer选项卡与入口菜单addin放好、Revit 2020启动后默认界面里看不到任何入口。很多人以为加载失败其实Revit把外部应用的工具藏在了附加模块里。正确做法是打开Revit点左上角文件菜单→选项→界面在工具分组里勾上Developer开发工具。确定后界面上方会多出一个Developer选项卡RevitLookup的菜单就挂在这里。展开后你会看到一组以Snoop开头的命令。Snoop直译是窥探它干的事就是把Revit内存里的对象抓出来用树形结构展示给你看。这个窗口和Visual Studio的调试器局部变量窗口很像但它是独立于代码运行的哪怕你的插件已经关闭只要Revit进程还开着就能继续查对象。初次打开Snoop窗口时左侧是对象层级右侧是当前选中节点的属性明细底部的搜索框支持按名称过滤成员查找海量属性时非常管用。2.3 Snoop Current / Snoop DB / Snoop Pick 三种调试路径怎么选RevitLookup在2020版本里最常见的三个入口对应三种完全不同的使用场景。Snoop Current Selection当前选择 先在Revit视图里选中一个墙体、族实例或者标高再点这个命令它会直接定位到你选中的Element。这是日常用得最多的入口查这个构件到底有什么参数它的Location是LocationCurve还是LocationPoint都靠它。Snoop DB数据库 不看具体构件而是看Revit文档本身。它从Document开始展开你能翻到ElementSet、ParameterSet、项目信息、族列表等文档级对象。适合查当前文档里有哪些族项目的ProjectInfo参数被塞了什么值这类整库问题。缺点是树很大加载略慢展开时要有点耐心。Snoop Pick点选 点击命令后光标变成拾取状态你在视图中点哪个构件它就Snoop哪个构件不用提前选中。在深嵌套的族里一层层点进去查内部几何时比先选中再切换命令顺手得多。我的习惯是明确要查某个选中构件用Current不确定对象在哪就用Pick怀疑是文档级数据问题就直接上DB。三个入口背后的Snoopable对象模型是同一套区别只是起点不同所以你从哪个入口进去最终看到的结构都一样。3. 源码编译从仓库拉到F5能跑差在哪几步3.1 项目结构sln、一个主项目、两个Revit引用把RevitLookup 2020的源码下载下来解压之后你最先看到的是一个sln解决方案文件和一个主项目文件夹。整个源码的组织并不复杂核心逻辑是一个类库项目入口是IExternalApplicationSnoop窗口用的是Windows Forms没有依赖第三方UI框架所以还原起来比很多商业插件省心。打开项目文件后第一件事是检查引用。Revit二次开发的项目只需要两个关键程序集RevitAPI.dll和RevitAPIUI.dll。前者管文档、元素、几何等底层对象后者管UI、UIDocument、选择集。RevitLookup两个都要用所以都会引用。如果你的项目里引用的DLL版本和本机Revit 2020不一致编译能过但一加载就报试图加载格式不正确的程序集或API版本不匹配这一条值得记进避坑手册。3.2 引用环境HintPath、目标框架、x64打开csproj文件重点检查三处配置。第一处是目标框架Revit 2020基于.NET Framework 4.7.2运行所以TargetFrameworkVersion要对应v4.7.2或更低比如4.6.1也能跑但不要选netcore或net5.0以上Revit 2020不认识。第二处是平台目标必须x64Revit 2020只有64位版本你把项目设成AnyCPU在运行时也可能踩雷。第三处是引用路径Reference IncludeRevitAPI HintPathC:\Program Files\Autodesk\Revit 2020\RevitAPI.dll/HintPath PrivateFalse/Private /Reference Reference IncludeRevitAPIUI HintPathC:\Program Files\Autodesk\Revit 2020\RevitAPIUI.dll/HintPath PrivateFalse/Private /ReferenceHintPath写死的是你本机的Revit安装路径不同机器装的盘符不同这里极容易编译失败。Private设为False表示不把RevitAPI拷贝到输出目录因为运行期Revit自己会加载这些程序集拷出去反而可能出现多份程序集导致的类型冲突。如果源码给的HintPath已经指向某个特定路径你先看本机有没有没有就改成你自己的实际路径。这里分享一个我自己常用的替代方案不直接改csproj里的HintPath而是在项目里建一个RevitDll文件夹把RevitAPI.dll和RevitAPIUI.dll复制进去引用指到相对路径..\RevitDll\RevitAPI.dll。好处是换电脑、换Revit版本时只要替换这个文件夹里的文件不用重新改工程配置。前提是这两份DLL只能本机使用别想着再分发。3.3 附加调试让VS把断点打进Revit进程编译完成后按F5能不能直接跑起来默认不行因为你的启动项目是一个类库没有exe入口。你需要告诉Visual Studio启动时帮我拉起Revit 2020。在项目属性→调试选项卡里选启动外部程序填C:\Program Files\Autodesk\Revit 2020\Revit.exe命令行参数可以不填。这个配置其实写在.csproj.user文件里直接改文件也行Project PropertyGroup StartProgramC:\Program Files\Autodesk\Revit 2020\Revit.exe/StartProgram StartArguments/StartArguments StartActionProgram/StartAction /PropertyGroup /Project保存后F5Visual Studio会先编译然后启动Revit并自动把调试器附加到Revit进程上。这时打开Developer选项卡里的命令点一下就会命中你在源码里下的断点。注意一个细节附加调试器的Revit实例会变得明显卡顿这是.NET调试器跟踪托管代码的正常代价不是插件死循环。RevitLookup源码本身就是一套很好的调试目标——你可以在Snoop命令的Execute方法第一行打断点然后去点一个构件逐步走一遍它收集对象的完整路径。如果不想每次F5都启动全新Revit也可以手动打开Revit和你的项目再用VS的调试→附加到进程选中Revit.exe。我更喜欢这种模式因为项目改完只要重新编译生成DLL再重启Revit就能看效果不需要让VS接管整个Revit生命周期。4. RevitLookup 2020避坑排查addin不生效、Snoop没反应、加载就闪退这一章是血泪经验汇总。RevitLookup本身是一个成熟工具但成熟指的是它的逻辑不是你的电脑环境。下面几条是群里和论坛里反馈最集中、我自己也翻过车的场景全部按现象→原因→解决来写。4.1 现象Developer选项卡打开了菜单里却没有RevitLookupaddin文件放对了Revit也重启了但附加模块里空空如也。原因按概率排序第一addin文件名或扩展名不对放进去的是RevitLookup.addin.txt第二XML内容里Assembly路径指向的DLL不存在Revit启动时扫码发现目标缺失就跳过了第三ClientId和已有插件重复被Revit当成同一插件去重。解决先确认文件扩展名是.addin而不是.txt在资源管理器里把查看文件扩展名打开看一眼再用记事本打开addin检查Assembly路径的盘符和目录是否真实存在并确认目标DLL文件名和编译输出一致最后用PowerShell跑一句[guid]::NewGuid().ToString()生成全新GUID替换ClientId以后新插件都用这个办法生成别手抄网上复制的GUID。4.2 现象addin路径正确但Revit 2020启动时弹插件加载错误这个比静默失败好一点至少给了弹窗。弹窗内容一般会提示加载哪个程序集失败。原因多数是DLL引用了Revit 2020不存在的程序集或者编译目标是x86。RevitLookup源码默认是x64但如果你在旧电脑上拿到的源码被前人改过平台目标编译出来的DLL一进Revit进程就会因为位数不匹配被拒。解决用CorFlags.exe或者直接在VS里打开项目属性→生成→平台目标确认是x64然后在项目引用列表里删掉所有带黄色感叹号的项目重新添加RevitAPI和RevitAPIUI再编译一次。黄感叹号代表引用找不到目标文件删掉重加比手动改HintPath更快。4.3 现象Snoop命令能点但弹出的窗口里只显示一行Object这种情况常发生在Snoop某个构件时窗口打开却看不到期望的参数列表只返回一个简单的Object节点展开也什么都没有。原因一般是Snoop的对象不是Element而是ElementId或某个内嵌对象RevitLookup没法从ElementId反查到可用元素——它需要你先真正选中元素才能拿到完整对象。另一个常见原因是你用了Snoop Pick但点到的是视图像素而不是构件图元。解决改回Snoop Current Selection先在视图里框选或Tab键切换选中你要查的墙、门、族实例确认状态栏出现图元高亮后再执行命令如果还是空检查你的选择集里是否混入了Group或ImportedInstance这类复合对象先点选单个族实例再试。4.4 现象Snoop《某属性》时Revit直接崩溃连错误日志都没有这是最让人血压高的一条。通常发生在展开GeometryElement下的Solid、Face或Edge节点时尤其是复杂体量、链接模型里的构件。原因RevitLookup在读取某些几何数据时调用的是API的get_Geometry()或ComputeDerivedGeometry链接模型或未加载的图元会触发Revit的内部几何计算异常进程直接挂掉。这不是你代码的问题是Revit几何引擎的脾性。解决习惯性先隔离变量——Snoop同一个构件时先展开Parameters确认数据能读再展开Geometry如果复现崩溃换一个简单构件比如普通墙体再试确认是构件本体的几何特殊性导致让Revit先完全加载链接模型再Snoop实在要查复杂几何先配合源码在SnoopGeometry相关方法里临时包一层try-catch把异常文本写进日志文件不用弹窗——这一步需要你会改源码正好用得上项目里自带的那份代码。4.5 现象自己编译的DLL在别的机器上加载失败你在A机器上编译通过把RevitLookup.dll和addin复制到B机器B机器Revit 2020启动后什么反应都没有。原因B机器可能没装对应的.NET Framework运行时或者你的编译环境安装了某个高版本.NET库DLL依赖了B机器没有的程序集还有可能是Assembly绝对路径失效——你写的是C:\Users\A机器用户名\...B机器根本没有这个目录。解决发布时带上编译用的目标框架安装包用Dependencies工具查看DLL的依赖列表把非系统程序集一并拷走addin里Assembly路径保持相对路径风格。RevitLookup官方发布的addin模板里路径也都是绝对路径但这属于能跑但不好搬的做法真正跨机器分发给同事时请先老老实实改成通用路径并测试一遍。5. 把RevitLookup改造成自己的新增菜单项和自定义Snoop逻辑5.1 读懂入口ExternalApplication的OnStartup里做了什么源码在手值得先读一遍入口类。App类继承IExternalApplication在OnStartup里拿到UIControlledApplication然后调用RibbonPanel相关方法创建按钮把几个Snoop命令绑到PushButtonData上。整个注册菜单的过程不超过30行代码逻辑很直白创建面板→为每个命令创建按钮→绑定命令类。读懂这段有一个直接收益你可以把它的面板从附加模块移到自己项目的专属选项卡里或者给按钮换图标。做法是改OnStartup里的CreateRibbonTab把application.CreateRibbonTab(MyTools)加在创建面板之前再让面板归属到这个选项卡。这样打开Revit你自己的工具和原版Snoop并列团队里分发时也比埋在附加模块里显眼得多。5.2 加一个自定义命令Snoop当前视图的所有选中族实例RevitLookup原版只Snoop当前选择、DB和Pick对象但它没有一次性把当前视图所有图元列出来的入口。当你处理大模型、想确认某面墙上到底挂了多少实例时原版会让你一个个点。这个需求完全可以在源码里扩展——新增一个IExternalCommand[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.ReadOnly)] public class SnoopActiveViewInstances : IExternalCommand { public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { var doc commandData.Application.ActiveUIDocument.Document; var view commandData.Application.ActiveUIDocument.ActiveGraphicalView; var collector new FilteredElementCollector(doc, view.Id); var instances collector .OfClass(typeof(FamilyInstance)) .CastFamilyInstance() .ToList(); using (var form new SnoopForms.SnoopForm(instances)) { form.ShowDialog(); } return Result.Succeeded; } }这段代码做了三件事用FilteredElementCollector传入视图Id限定只收集当前可见视图里的元素再通过OfClass(typeof(FamilyInstance))过滤族实例最后把它们整体塞进Snoop窗口让用户按常规方式展开查看。TransactionMode.ReadOnly声明这个命令不修改文档Revit会允许它在只读状态下快速执行。不要小看这一小段它展示了Revit二次开发里最常用的收集器写法先限定范围、再过滤类型、最后转成可操作列表。你以后写任何批量处理工具骨架都是一模一样的。新增命令之后还要在addin里补一段注册让它出现在菜单里AddIn TypeCommand NameRevitLookup.SnoopActiveView/Name AssemblyC:\LookupOutput\RevitLookup.dll/Assembly FullClassNameRevitLookup.SnoopActiveViewInstances/FullClassName ClientIdD7F7D7A0-0000-4000-8000-ABCDEF123456/ClientId VendorIdADSK/VendorId /AddIn注意这里Type从Application变成了Command因为这段命令直接挂在外部工具按钮下不依赖外部应用启动。一个addin文件里可以同时包含多个AddIn节点你之前的Application节点别删两者共存。重新编译后重启Revit新命令会出现在外部工具列表里点一下就能看到当前视图所有族实例的集合。5.3 给Snoop窗口加一个归属类型列如果你经常在大量构件间跳转会发现原版Snoop窗口里对象列表没有显示每个元素的Category和Name翻树查起来效率低。这个也可以在源码里改SnoopForm的数据源绑定处给每个节点加两个自定义属性展示Element.GetType().Name和Category?.Name。改完编译窗口列表会直观很多。这一步不是必须的但做过一次你就明白拿着源码改工具比在外围用AutoCAD式的命令行取巧要可靠得多——因为你动的是数据源本身。6. 让Lookup替你验收代码参数写入前后对比的三步验收法工具不只是用来查这是什么还能反过来验证你写的代码到底有没有生效。我这两年养成的一个习惯是写任何会修改元素参数的插件时先用RevitLookup把手术前的状态记录下来跑完代码再Snoop同一根元素对比参数值的变化。流程很短先在视图里选中目标构件Snoop Current Selection找到你要改的参数名记下旧值然后运行你的外部命令命令跑完后不关闭Revit重新选同一根构件再次Snoop看参数值是否按预期改变。如果值变了但类型不对比如本该写double却写成了intSnoop窗口的参数类型列会直接暴露类型不匹配。这个方法比在代码里加Debug.Assert更贴近真实运行结果因为它验证的是Revit数据库落库后的最终状态。我还经常在Snoop里展开Geometry节点核对写完参数后几何是否跟着更新——比如改了一个族实例的OffsetLocation点和Solid的Transform应当同步变化如果几何没有跟随说明你的参数改动没有触发Regenerate这是Revit API里非常隐蔽的静默失败光靠看返回值发现不了。这种时候我会在Execute方法末尾先调一次doc.Regenerate()再重新Snoop对比。需要注意Snoop窗口展示的是内存态数据如果命令在一个事务里改了值又回滚了Snoop看到的仍然是原值这是正常现象——不要误判为代码没执行。最后分享一个我踩过的坑早期我用Snoop检查某构件参数发现值没变就认定是插件逻辑错了调了半天才发现Snoop出来的是Parameter的AsValueString()格式而这个格式是带单位后缀的2500显示成2500.0 mm我呢拿字符串做了精确匹配当然一直失败。从那以后我养成了一个习惯看参数值时先区分StorageType是Integer、Double还是String再用对应的AsInteger()、AsDouble()或AsString()去读。这个习惯被我从RevitLookup带到了所有Revit二开项目里希望你也能顺手用上。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站