ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

SOLIDWORKS Manage二次开发Day2:C#查询业务对象与权限坑实战记录

SOLIDWORKS Manage二次开发Day2:C#查询业务对象与权限坑实战记录 很多做SOLIDWORKS二次开发的朋友入门时都是从零件建模、装配体自动化这类“建模脚本”开始的但真到了企业数据管理这个层面面对SOLIDWORKS Manage整个思路完全是另一套逻辑。我Day1已经把环境搭好客户端能正常登录SDK文档也翻了个大概但真正动手用C#去连服务器、查业务数据时才发现要补的功课比想象中多得多。这篇就是我的Day2学习记录从梳理对象模型、搞定登录连接到第一个查询功能平稳落地再到一个把我卡住三小时的权限坑全部分享出来给同样在做SOLIDWORKS Manage二次开发的人做个参考。1. 从“能启动客户端”到“敢写第一行API”Day2该补的知识差1.1 我理解的SOLIDWORKS Manage对象地图Day1我干了一件事把Manage客户端的界面挨个点了一遍从仪表盘到数据卡片从业务对象列表到工作流配置同时把官方SDK文档里的对象层级做了个初步标记。Day2我才真正意识到如果不先把对象模型理清楚后面写代码会非常茫然因为你不知道自己要操作的数据在API里到底属于哪一层。我梳理出来的核心地图是这样的最顶层是应用程序对象代表一个Manage客户端会话负责登录、连接、获取全局配置往下是数据源层也就是服务器和库别名再往下是业务对象定义层对应Manage里的“项目”“物料”“变更单”这一级的业务对象业务对象下面才是记录层也就是具体的一条实例记录下面挂的是字段层比如项目名称、负责人、状态这些具体值旁边还挂着文件层和工作流层分别处理关联的CAD文档和审批流转。这套结构我用一个生活化的类比来理解业务对象就像一张Excel表记录就是表里的一行字段就是单元格。Manage API做的事情大部分就是通过程序去读写这些“单元格”。但难点在于它不是一张普通的Excel表每个单元格背后都有权限、版本、校验逻辑和业务规则直接硬读硬写是行不通的。1.2 业务对象、数据卡片、记录这三者的关系在Manage客户端界面里你看到最多的是一张张数据卡片卡片上摆着很多字段输入框。Day1我还以为二次开发就是去操作这些卡片Day2才发现这个理解有偏差。数据卡片只是表单是给人看和输入的界面真正的数据存在底层数据库里API操作的是业务对象和字段不是卡片本身。这个理解直接影响写代码的方式。比如界面上有一个“项目负责人”输入框你想通过API读取它不能按卡片名字去搜而是先拿到“项目”这个业务对象定义拿到某个具体记录再按字段的内部标识去读值。卡片布局和字段绑定关系可以通过API枚举出来但你不能反向用卡片名当查询条件。我在学习中最容易犯的错就是把界面上的显示名称当成API里的字段标识。实际项目中“显示的时候叫项目名称程序里内部名可能是ProjectName甚至可能是Project_Name_EN”这种差异非常常见。所以每次写代码前先去字段定义里把映射关系确认清楚比自己拍脑袋猜要靠谱得多。1.3 和PDM Professional二次开发的对比如果你之前接触过SOLIDWORKS PDM Professional的二次开发会发现两者的API思路有相似之处都要登录到库都有文件夹和文件对象都能做查询。但Manage多出来的核心概念就是业务对象层。PDM解决的是“文件在哪、版本是什么、谁签出了”Manage解决的则是“这个项目走到哪个阶段、这个变更单关联了哪些零件、BOM现在应该是什么样、这些业务数据怎么走审批流程”。所以做Manage二次开发前思维上要做一个转换不要一上来就找打开文档的API而是先想清楚三个问题——我要操作的业务对象是什么我要用哪个字段来过滤记录我需要读写哪些字段值Day2我最大的认知反转就在这里之前总觉得二次开发就是“调接口操作文件”现在才明白Manage二次开发的重心是操作业务数据文件反而成了附属内容。2. 搭建一个能跑的C#开发骨架引用配置与登录坑2.1 该引用哪个程序集为什么SOLIDWORKS Manage安装之后在安装目录下可以找到API相关的程序集通常以Manage.API命名或者是一套Interop互操作程序集。不同版本、不同安装选项程序集的名字和路径都会有差异。我踩过的最快入门路径是打开官方SDK自带的示例工程看它引用了哪个dll、配置了哪些依赖照着抄而不是自己凭记忆推断。在Visual Studio里添加引用的操作有几个细节容易忽略。首先是“嵌入互操作类型”这个选项我建议默认不要勾选因为Manage API很多底层走的是COM/Interop路线勾选之后可能会出现版本绑定问题程序集明明在运行时却找不到类型。其次是复制本地属性如果API程序集依赖其他dll最好把依赖一起复制到输出目录避免在别的机器上运行时莫名其妙报错。还有一点要特别注意如果引用的是COM组件开发机必须已经完成了组件注册。这个注册通常在Manage客户端安装时自动完成但如果你像我一样在单独的开发环境上只装了SDK、没装完整客户端编译虽然能过运行时会直接报“尚未注册”的COM错误。遇到这种问题先别怀疑代码回开发机上确认有没有装对应的客户端组件。2.2 登录参数分解服务器、库别名、账号类型连接Manage几乎是所有二次开发的第一步也是坑最多的第一步。登录方法Connect或者Login名称以你装的SDK为准通常需要四类信息服务器名、库别名、账号、密码/认证方式。其中库别名不是数据库名而是在Manage里配置的连接别名相当于一个逻辑名称指向真正的数据库和文件库服务。我调试时习惯先把同一套参数在Manage客户端里手动输入一遍分两步排错如果客户端能正常登录说明网络、账号、别名、服务都没问题问题出在API调用方式如果客户端也登录不了那就先排查数据库服务和文件库服务是否启动再检查账号密码。这个“先用客户端验证”的习惯帮我省下大量时间因为API报错信息有时候非常笼统你根本分不清是参数错了还是服务没起。登录常见的报错大概有三类第一类是完全连不上服务器多半是服务器名、端口配错或者防火墙挡了第二类是别名不存在需要到服务端管理工具里核对别名配置第三类是账号或认证方式错误有些Manage库配置的是Windows认证有些是数据库认证两边不匹配就会一直登录失败。2.3 目标框架与平台位数这个隐性门槛这个坑值得单独拿出来说因为太隐蔽了。SOLIDWORKS Manage客户端组件有的版本是32位进程有的是64位。如果API底层依赖的是32位COM组件而你的C#工程用AnyCPU编译在64位操作系统上进程默认以64位方式运行加载32位COM组件时就会碰到“Retrieving the COM class factory for component with CLSID”之类的经典错误或者加载DLL失败。我Day2就在这个坑里转了小半天。新建工程一时顺手选了AnyCPU代码逻辑完全没问题一运行就崩。后来把解决方案平台改成x86重新编译世界清净了。如果你的SDK明确支持x64可以改成x64但不要图省事用AnyCPU。另一个相关的坑是.NET目标框架老版本的Manage API程序集可能只支持.NET Framework 4.x我用.NET 6新建项目引用后各种不兼容退回.NET Framework 4.7.2就一切正常了。所以确认版本兼容性时不仅要看API版本还要看程序集的目标运行库。3. 第一个落地功能查询业务对象并读取字段数据3.1 查询接口的调用顺序我把Day2的目标定为一个非常具体的小工具WinForm界面登录Manage选择某个业务对象按条件查询记录并在表格里展示。这个功能虽然简单但覆盖了API最核心的调用链路。查询的调用顺序我总结为六步获取业务对象定义、创建查询对象、设置返回列、添加过滤条件、执行查询、遍历结果集读取字段值。用伪代码来表示大概是这样的// 示例代码类名/接口名以本地SDK版本为准 var app new MwsApplication(); app.Connect(Server01, ManageAlias, domain\\user, password); var boDef app.Data.BusinessObjects.GetByName(Project); var query boDef.CreateQuery(); query.AddField(ProjectName); query.AddField(Owner); query.Filter.Add(Status, , Active); var result query.Execute();这里有一个容易理解错的地方查询对象创建后不是直接把所有字段都查出来。你只选择界面展示需要的字段可以减少网络传输和内存占用尤其是业务对象下面挂了大量字段时全量查询的性能差别非常大。另外如果业务数据量很大查询接口通常会支持分页或分批获取不要在一个查询里指望把所有历史数据一次拿完服务端不一定允许。3.2 从查询结果到DataGridView展示查询结果拿到之后WinForm里最直接的做法是把结果装进DataTable再绑定到DataGridView。这个写法做C#上位机的朋友应该很熟悉跟从串口或PLC采集数据后展示到表格是同一套路先建DataTable按字段名加列遍历结果集添加行最后把DataTable赋给DataGridView的DataSource属性。var dt new DataTable(); dt.Columns.Add(项目名称); dt.Columns.Add(负责人); dt.Columns.Add(状态); for (int i 0; i result.RowCount; i) { var row dt.NewRow(); row[项目名称] result.GetFieldValueAsString(i, ProjectName); row[负责人] result.GetFieldValueAsString(i, Owner); row[状态] result.GetFieldValueAsString(i, Status); dt.Rows.Add(row); } dataGridView1.DataSource dt;字段少的时候直接手写就行字段一多就建议做一个“界面列名-API字段名”的映射配置用配置文件或数据库表存起来。这样以后换业务对象、改查询字段只改配置不改代码整个工具复用性会强很多。我在写这个小工具时就感受到了好处后面测试新的业务对象完全不用编译把配置一换就行。3.3 字段内部名与显示名的坑这块必须单独讲因为搜索里很多人也在问类似的问题查找一条记录字段数据时界面上明明白白写着“项目负责人”代码里用这个中文字符串去读就是读不到。原因其实很简单你用了显示名称而API要求的是字段的内部名。显示名称是给人看的内部名才是给程序用的两者经常不一样。解决这类问题有两个常用办法。第一个是去数据卡片设计器或者字段配置界面查字段属性把内部名复制出来。第二个是通过API枚举字段定义把每个字段的显示名和内部名都打印出来生成一张对照表。我强烈推荐第二种因为做对照表的过程本身就能帮你发现哪些字段在API里是不可见的哪些字段类型比较特殊。字段类型是另一个容易踩的点。日期、数字、枚举值在API返回时可能是字符串也可能是一个对象直接ToString()可能会得到意料之外的结果。比如日期字段可能带时区信息数字字段可能受系统区域设置影响出现小数点差异。我的处理方式是全部先转成字符串再用TryParse去解析解析失败就记录日志而不是让程序直接崩掉。4. 一次把进度卡死三小时的联调经历4.1 问题现象Day2最难忘的不是写代码而是一个让我反复怀疑人生的错误。我的查询工具可以正常执行结果集也有行数但循环读取记录字段时程序到了某一行就抛异常。异常信息大概意思是“值不在预期范围内”或者“指定的字段在当前记录上不存在”。一开始我以为是SDK版本有问题或者是查询对象没写对反复重启程序、重新编译白白浪费了很多时间。更让人困惑的是不是所有记录都报错。同一个查询前两行能正常读取第三行就挂了。我打开Manage客户端单独看那条记录字段明明有值显示得清清楚楚。这就奇怪了客户端能看到API却读不到问题到底出在哪4.2 完整排查链路这次排查我用了比较系统的思路分享出来给卡住的朋友一个参考。第一件事是缩小范围单独查那条出错的记录单独读那个字段确认是不是必现问题。结果发现必现那就说明不是偶发的资源竞争。第二件事是检查字段内部名是否正确。我用枚举字段定义的方式把这条记录上的所有字段名和当前代码里手写的字段名做了对比确认拼写没有错误。第三件事是检查字段类型。我以为可能是枚举类型和日期类型处理方式不对于是在调试器里看了返回值和内部异常HRESULT没发现明显的类型不匹配。第四件事也是关键一步我抱着试一试的心态切换当前Windows用户换成管理员账号跑同一个查询结果奇迹般不报错了。到这里基本可以锁定问题不是代码逻辑而是权限策略。第五步回到客户端去看该字段的访问控制果然发现当前账号对部分记录的字段没有读取权限。API返回的异常虽然没直接写明“权限不足”但本质就是这个。4.3 根因与解决方案根因是Manage的数据级安全策略在起作用。字段在某些记录上对当前用户不可见时API不会返回null或空字符串而是直接抛异常。这跟普通数据库读取的直觉完全不一样我第一次遇到时毫无心理准备。解决方案实际上有两条路。第一条是换一个有足够权限的账号来运行集成工具企业做系统对接时通常会专门申请一个服务账号按最小授权原则分配业务对象和字段的读取权限。第二条是代码层面做兜底读取字段时加try-catch遇到不可读字段就记录日志继续处理下一条记录不要让一条数据权限问题导致整个导入导出流程中断。try { value result.GetFieldValueAsString(i, ProjectName); } catch (Exception ex) { Log.WriteLine($第{i}行字段ProjectName读取失败{ex.Message}); value ; }这里我要强调一下这个try-catch不是偷懒而是必须做的防御性设计。因为数据权限策略是动态的管理员随时可能调整代码在运行前根本无法预判所有字段是否可读。之前在Day1看文档时我觉得异常处理很简单直到这次联调才发现权限类异常是Manage二次开发最高频的问题之一。5. 给Day2收尾自检清单、调试习惯与Day3方向5.1 Day2自检清单学习二次开发最怕“感觉会了一写就废”所以Day2结束前我给自己列了一个自检清单每一项都有明确的验收标准检查项验收标准环境引用能新建C#工程并成功引用Manage API程序集编译通过登录连接能用代码连接服务器和库别名和客户端参数一致业务对象枚举能通过API枚举出至少2个业务对象条件查询能按一个字段过滤记录结果与Manage客户端一致字段读取能读取文本、日期、数字字段并正确转换类型异常处理能处理字段不可读、无权限两种异常类型交付物编译出一个可运行的exe能在开发机上独立执行如果以上都通过说明Day2的及格线到了。我自己的状态是刚好及格有几个字段类型转换还不熟练查了一条带多值字段的记录后直接懵了这块打算放到进阶阶段再啃。5.2 我在调试时常开的三个窗口调试Manage API程序我慢慢养成了一个习惯就是固定开三个窗口。第一个是异常详情窗口不要只看Message那一行要看完整的调用堆栈和HRESULT很多线索藏在深层异常里。第二个是API日志输出有些版本的SDK自带跟踪开关打开之后能看到实际执行的请求参数和返回结果对定位登录失败、查询条件错误这类问题帮助极大。第三个是Manage客户端的记录详情窗口。我会把程序读出来的值和客户端界面上的值逐字段对照双端一起看很容易区分到底是API问题还是业务数据本身的问题。代码里我还会在关键接口调用前后打时间戳用来观察性能。二次开发的性能问题很容易被忽略如果在一个循环里反复创建查询对象、反复登录一个批量操作可能跑十几分钟改成一次查询拿回所有数据再在内存里按条件过滤速度往往能提升一个数量级。5.3 Day3打算做什么下一步我的计划分三步走。第一把查询功能扩展成通用“业务对象浏览器”做到可以动态选择业务对象、动态配置字段和过滤条件而不再为每个报表单独写死一套代码这个方向也能顺带把前面说的字段映射配置彻底用起来。第二研究创建和更新记录的API把WinForm里的编辑功能打通。这一步会比查询麻烦不少因为要处理必填字段校验、字段格式合法性、保存事务和版本更新任何一个环节没考虑到都会污染真实业务数据所以我会先在测试库里反复验证。第三尝试通过API读取业务对象关联的文件和BOM信息。我觉得这才是PLM二次开发里真正值钱的部分。查询字段只是入口能把文件、BOM、工作流串起来才算是真正用上了Manage的数据整合能力。这些内容后面我会继续整理遇到新的坑再回来填。最后再分享一个小技巧如果你也是边看文档边摸索记得把每次成功的调用参数组合截图存下来。二次开发最怕的不是不会写而是今天能跑、明天再跑又不行了有一份自己的验证样例排查起来会轻松很多。
返回列表