
简介这是一份UG NX外部开发模式的基础入门示例文档面向机械设计自动化或NX二次开发初学者通过一个在外部模式下新建零件并创建Block的完整程序讲解UF_API环境初始化、零件创建、块建模、保存与关闭等关键步骤帮助读者理解NX Open C/C开发的基本流程。示例采用公制单位利用UF_MODL_create_block1并设置原点坐标与边缘ID参数清晰展示了Block特征构造时各参数的传值方式。资源共1个文件为docx格式压缩包约14KB内容精简适合快速查阅与对照练习。文档中直接给出可运行代码并以分步输出说明每项操作的结果对理解UF_PART_new、UF_MODL_create_block1、UF_PART_save等函数调用很有帮助。目前已有619人学习适用于希望从零开始接触UG外部开发、了解API调用结构的入门读者。1. 外部开发模式创建Block批量出坯与自动建模的第一块敲门砖如果只是想在NXUG界面里画个方块谁也不会去写代码。真正需要“UG外部开发模式下创建Block”的往往是这样一批人做模具标准件库的想用脚本把几百个垫块、镶块一次性生成做工艺自动化的想把产品模型转成加工毛坯再交给CAM还有做产线集成的希望调用三方系统里的长宽高参数服务端自动出一个带特征的prt。Block在NX里不是普通草绘矩形而是带历史记录的三维实体特征参数一改后续的倒角、布尔、坐标都要跟着动。外部开发模式意味着程序运行在NX进程之外先写好逻辑再去驱动NX建模。这条路值不值得走只要你有批量、有规律、要交付可追溯的参数化模型它比人肉画图靠谱得多。下面的内容从环境搭建到代码复现再到踩坑复盘按工程落地顺序写。2. 外部开发模式的环境搭建先搞定进程连接再谈Block特征2.1 内部开发和外部开发差在启动方式和职责边界常见误解是把“外部开发”等同于“命令行里跑UG”。严格说二者的代码很相似区别全在进程关系上。内部开发是NX界面里执行DLL被NX主进程加载能直接用UI和当前Part的对象调试方便但NX没开就跑不了外部开发是独立的exe或dll被你的服务调用再用NXOpen API去连接已运行的NX会话适合无人值守和批量任务。我一般推荐新项目优先做外部模式因为它和内部模式的代码比只多了一句会话获取却能摆脱界面对脚本的束缚。下面是两种模式的对比对比项内部开发外部开发启动方式在NX界面内执行独立进程连接NX会话界面操作可以直接驱动UI不依赖UI以建模和存取为主适用场景交互式工具、需要人工看结果批量建模、服务端自动化典型入口直接用WorkPartSession.GetSession() 或 UF_initialize()外部模式也不是万能的它拿到的Part本身就是NX进程里的WorkPart如果你的程序在服务器上连一个无人值守的NX模型树、导航器这些交互能力会弱很多。所以外部模式的正确打开方式是“把建模当函数调”入参出参都做好日志别在UI上较劲。2.2 准备NX Open引用与最小连接代码NX Open对C和.NET都有支持。如果你只用C核心头文件是uf.hpp和nxopen.hpp用.NETC#更省事直接引用NX安装目录下的NXOpen.dll、NXOpen.UF.dll即可。注意版本外部程序的引用DLL要和你机器上的NX主版本对应否则Session连接时会出现程序集版本冲突。运行程序前确认当前NX许可证里包含NX Open模块否则一调API就报许可错误。先跑通下面这段再写Blockusing NXOpen; class ExternalConnectDemo { static void Main() { Session theSession Session.GetSession(); // 连接外部NX进程 Part workPart theSession.Parts.Work; // 当前活动工作部件 if (workPart null) { throw new System.Exception(当前没有打开的工作部件); } System.Console.WriteLine(连接成功 workPart.FullPath); } }Session.GetSession()是外部模式的一道分水岭内部模式里系统会直接给出Session对象不需要你手动连接外部模式则必须靠这一行去绑定NX进程。workPart必须是外部程序运行前已打开的部件如果NX刚启动且没有加载任何prt这里workPart会为空。参数上不要纠结Work是什么它和NX界面左上角看到的Work Part是同一个。调试时如果程序一闪而过建议把Console.WriteLine改成写文本日志或者用Debugger.Launch()强制挂上断点。这一行看起来简单却是外部开发模式能不能真实跑起来的咽喉。2.3 自动化启动NX与附加调试外部程序可以要求NX已经打开也可以在程序里自行启动NX进程。我习惯把第一步做成启动脚本脚本先根据配置找到NX安装目录再启动NX并自动打开一个空模板prt把路径传给程序。这能避免“连不上会话”的第一类翻车。using System.Diagnostics; // 启动NX进程外部程序先拉起一个NX实例并打开目标prt string nxUgraf NX安装目录\UGII\ugraf.exe; string targetPart 绝对路径\blank.prt; Process nxProc Process.Start(nxUgraf, targetPart); if (nxProc null) throw new System.Exception(NX进程启动失败); // 等NX初始化完成再尝试连接会话 System.Threading.Thread.Sleep(20000); Session theSession Session.GetSession();代码里我用尖括号占位是因为真实路径在不同机器上不统一建议从配置文件或环境变量读取。Thread.Sleep只是最简单粗暴的等待方式生产环境更稳的做法是轮询Session.GetSession()每隔两秒尝试一次直到成功或超时。跑批量时没有人工看屏幕图形刷新、报警对话框都会变成坑。后面第4章会专门说刷新和卡死问题。这里先记住跑批量之前先用一个最小程序验证连接、验证许可、验证日志可写三步都过再上复杂任务。3. 用NXOpen创建Block两条代码路线与参数说明3.1 NXOpen API的CreateBlock最短可运行代码创建Block常用API是workPart.Features.CreateBlock返回Feature对象再把特征转成Features.Block。下面是可直接改路径跑的完整程序using System; using NXOpen; using NXOpen.Features; public class BlockCreator { public static void Main(string[] args) { Session theSession Session.GetSession(); // 连接外部NX进程 Part workPart theSession.Parts.Work; // 当前工作部件 if (workPart null) throw new Exception(请先打开一个prt); Point3d origin new Point3d(0.0, 0.0, 0.0); // 左下角原点绝对坐标系 string[] edgeLengths { 100, 60, 40 }; // X、Y、Z三条边的长度 bool isSolid true; // true实体false片体 Features.Feature feature workPart.Features.CreateBlock(origin, edgeLengths, isSolid); Features.Block block feature as Features.Block; if (block null) throw new Exception(创建结果不是Block特征); workPart.Update(); // 更新特征 Console.WriteLine(Block已创建 feature.FeatureName); } }代码逻辑顺序是先拿会话再拿工作部件构造原点Point3d边长用字符串数组调用CreateBlock生成特征用as做类型校验最后Update让模型真正更新。不要把new Point3d和CreateBlock分开太远原点、边长、实体标志这三个要素要保持在一个事务里中途不要做会触发NX重算的操作。CreateBlock默认把块体加入模型历史记录这一步不传布尔运算标志所以它生成的是独立实体不做减法和交集。需要做布尔时第5章会讲Builder方式。3.2 决定Block创建成败的关键参数与控制点参数类型含义与建议originPoint3d绝对坐标系下的左下角点不是WCS坐标edgeLengthsstring[]X/Y/Z三条边长支持100或L*2表达式isSolidbooltrue建实体false建片体建模直接用trueUpdate()void让特征计算落库漏了它模型树可能不刷新最容易被忽略的是单位和参考系。edgeLengths是字符串数组NX会把“100”按当前部件的单位解析在毫米部件里是100mm在英寸部件里就是100英寸。origin却是纯double坐标不带单位这一点和UF函数的double数组一致。如果你在英制部件里想建100mm的块直接把100填进去会得到100英寸想显式指定单位要写成100mm。另外origin用的是绝对坐标系不是WCS很多工程师在WCS里做设计程序里也照抄WCS坐标结果Block飞到了天边。解决方法是先换算以WCS原点加矢量偏置换算到绝对坐标再传给API。3.3 老代码兼容UF_MODL_create_block1的写法如果你维护的工程是多年前的C二次开发很可能用的是UF_MODL_create_block1。它和NXOpen API是两套体系函数名带UF前缀返回tag_t而不是Feature对象。C外部模式入口固定要先UF_initialize()结束再UF_terminate()#include uf.h #include uf_modl.h int CreateBlockWithUF() { int status UF_initialize(); /* 连接外部NX会话标志外部模式开始 */ if (status ! 0) return status; double origin[3] { 0.0, 0.0, 0.0 }; /* 绝对坐标系原点 */ double lengths[3] { 100.0, 60.0, 40.0 }; /* 三条边 */ tag_t block_tag NULL_TAG; status UF_MODL_create_block1(origin, lengths, block_tag); if (status ! 0) { char msg[256]; UF_get_fail_message(status, msg); /* 取错误文本 */ /* 写日志 */ } UF_terminate(); /* 结束外部会话释放资源 */ return status; }UF_MODL_create_block1的入参是double数组默认就建实体想建片体要走另一组builder接口。它也不带表达式能力lengths写的是数值而不是100mm这类字符串所以单位完全跟随部件。新项目我建议优先用NXOpen API对象模型更规整C#写起来省心特征命名、表达式、图层信息都挂在同一套对象树上老工程保留UF调用没问题但不要混用两套接口去建同一个特征否则对象句柄维护起来非常痛苦。4. 外部模式创建Block的高频踩坑与排查清单4.1 现象Session连接失败程序秒退现象外部exe运行后控制台一闪而过或者抛出连接NX会话失败。原因NX进程没启动或者NX Open许可证不完整再或者引用DLL版本与NX版本不一致。解决先手动打开NX和目标prt再跑程序用日志把异常堆栈写进txt检查exe同目录DLL和NX安装目录里的DLL是否版本匹配。最难查的是版本冲突现象千奇百怪“创建Block成功但Update崩溃”也常由它引起。这种问题不要凭感觉改代码先写一个最小连接案例对照跑能过再跑业务逻辑。4.2 现象尺寸明明是100测量变成2540现象用100做边长模型里看着正常CAM编程时一量怎么大了这么多原因当前prt单位是英寸字符串100被解析成100英寸如果你后续又把它导出成毫米格式数字会按换算系数放大约25.4倍。解决创建前读Part单位做分支或者强制带单位写表达式如100mm。这也是UF路径和NXOpen路径行为不一致的地方UF_MODL_create_block1的double数组不带单位永远按当前部件单位解析。很多人升级到NXOpen后沿用double思维反而掉进表达式字符串的坑。4.3 现象重复运行模型树里Block越叠越多现象程序跑一次成功跑第二次时旧Block还在新Block又加进来了。原因CreateBlock是纯增量操作不会自动替换同名特征代码里没有清理旧特征。解决创建前先按特征名遍历当前部件找到旧Block先删除或禁用删除时要小心特征依赖如果后续倒角、布尔都挂在它上面删除会连带报错。我一般会在Block特征名里带上批次号例如BLK_PART_20250211_01重复运行时删除旧批次、新建新批次这样既避免堆积也为出问题留了后悔药。4.4 现象外部模式下Update后视图不刷新像卡死现象程序没报错日志说特征已创建但屏幕上就是看不到新的Block。原因外部模式不依赖界面消息循环模型更新后视图不会主动重绘不是创建失败是没刷新。解决创建后主动刷新视图theSession.Views.Work.ViewRefresh(); // 强制刷新当前工作视图如果是无人值守远程跑批界面都可能不开刷新也看不到那就别依赖视图验证改为读取feature和part的attribute属性汇总到日志。远程或后台运行时不要弹NX对话框去确认一旦弹窗没有人工点整个任务就停在那里。有对话框需求时一律改成自己的日志和错误码。4.5 现象Block建出来后和预期位置差一个WCS现象原点明明传的是(0,0,0)Block却出现在离模型很远的位置。原因API的Point3d是绝对坐标系设计时用的WCS可能已经旋转或平移过了。解决换算坐标时统一走绝对坐标系如果需要对齐WCS用Matrix4x4或UF_CSYS相关函数做变换。不要“看着差不多就行”Block原点是后续所有布尔和装配的基准错一点后面孔位、开槽全乱。5. 从单个Block到批量自动化命名、图层与回滚5.1 用特征名和图层管理几百个Block创建单个Block不是目的批量才是。批量时我会把Block放进指定图层并用有规则的FeatureName方便后续筛选、排序和清理for (int i 0; i paramList.Count; i) { Point3d origin new Point3d(baseX i * 120, 0, 0); Features.Feature f workPart.Features.CreateBlock(origin, edgeLengths, true); f.FeatureName string.Format(BLK_{0:D4}, i); // 统一命名规则 workPart.Layers.SetLayerForFeature(f, 1); // 放进1层 } workPart.Update();命名规则一固定后面按名称删除旧批次、按图层批量设置颜色或属性就都有了抓手。工业自动化里交付的prt不只问“有没有Block”还要问“哪个是毛坯、哪个是余量”。5.2 参数化回滚用表达式而不是死数值CreateBlock的边长接受表达式字符串这是它比UF好用太多的地方。“100/2”、“205”都能解析。想批量调整时不需要重新创建Block改表达式即可Expression expr workPart.Expressions.FindObject(BLK_L_X); expr.SetRightHandSideString(150); workPart.Update();表达式名字要预先规划我习惯在FeatureName外再存一套特征参数属性。这样回滚和复用都简单遇到供应商模型批次差异改一个表达式比重新跑一遍生成脚本安全得多。5.3 给自动化脚本加事务边界外部模式跑批最容易出的事故是跑到一半失败留下一堆半成品。我现在给每批任务加两个固定节点任务开始前记录清理锚点任务结束后统一校验数量与尺寸中途失败就整批删除新建特征。外部开发模式下没有界面给你按撤销删除操作本身要找对对象所以锚点加命名规则就是无人值守的后悔药。有一次我图省事没做清理锚点直接在一个批次的Block上追加了下一个批次的Block结果特征依赖全缠在一起返工花了比写代码更长的时间。从那以后我养成了一个习惯凡是批量创建Block的程序第一步永远是“删干净上一批”第二步才是“建这一批”日志里补全参数快照。希望帮到你。本文还有配套的精品资源点击获取