会话中断后接续本任务时:先读本文件 +
Docs/ARCHITECTURE.md,从「待续」小节继续。 最终状态:✅ 全解决方案编译通过(MSBuild CLI,BUILD_OK)。三平台子流程容器(Halcon/VPP/VM)+ 闪退修复全部落地;功能运行时验证待人工进行。
DllNotFoundException: 无法加载 DLL"halcon"(HSmartWindowControlWPF.OnRender 首帧触发 HHandleBase 静态构造;首次异常被吞、二次渲染异常直接致命闪退)。桌面副本同样有 Runtime\dll\x64\halcon.dll 但 HALCON 原生运行时是 DLL 家族,孤立拷贝无效。HSmartWindowControlWPF,改为 code-behind 防御式创建:先 HOperatorSet.GetSystem("version") 原生探测,可用才创建控件并挂事件/右键菜单;不可用显示"HALCON 原生运行库不可用"占位提示(画布/属性编辑不受影响,进程不闪退)。右键菜单 MyMenu 一并改为代码构建。Plugins.Vpp\VppFlowNodes.cs:VppFlowPlugin + VppFlowModel/VppFlowInput/VppFlowOutput + VppEditorPreview(BeginRunCycle 换 RunStamp+ClearAll;Show 发布图层)。Plugins.Vm\VmFlowNodes.cs:VmFlowPlugin + VmFlowModel/VmFlowInput/VmFlowOutput(镜像;VM 图层发布留待 VmWindow.RefreshImage 平台对象对接)。Plugins.Vpp\Views\VppFlowEditorView.*(大显示窗=VppWindow(1)+RefreshImageDisplay(ICogImage))、Plugins.Vm\Views\VmFlowEditorView.*(大显示窗=VmWindow);左侧画布工具箱分别用 FlowToolboxScope.VisionVpp/VisionVm;均实现 IPluginViewSave/IPluginRunFeedback/IPluginViewTip + ParentGroupModel 注入(子节点公式树可见 &{输入.*})。FlowToolboxScope 增加 VisionVpp=2/VisionVm=3;FlowEditorViewModel.InitCommands 子流程工具箱按 IsSubFlowNode && Group=={Halocn模块|Vpp模块|Vm模块} 过滤后按 VisionPlugin 分组——各平台算子互不串台;OpenNodeEditor 的 keepParent(保留容器输入变量)推广到全部平台子流程。IsSubFlowNode=true(不再出现在主流程工具箱,只在各自平台子流程内;旧流程已放置的节点不受影响)。Vp 算子运行后经 VppEditorPreview.Show(Model, cogImage) 发布输入图像图层(GenImage→CogImage 只转一次,喂图/发布共用)。AssemblyScanner.CreateInstances 实例化失败从静默改为 AppLogger.Warning("模块 xxx 实例化失败,已跳过")——直接暴露"引擎没起来/主页画面空白"这类静默降级的原因。C:\Program Files\Microsoft Visual Studio\18\Insiders\MSBuild\Current\Bin\MSBuild.exe TeamAAS.sln /p:Configuration=Debug /p:Platform=x64(BUILD_OK),不再依赖 VS GUI。首轮 4 处 CS0246 FormulaBound(缺 using PropertyGridLib.Controls;)已修复。Runtime\Plugins\Plugins.Halcon.dll(09-04 旧版,会因同名去重抢先加载、使闪退修复失效);保留 HalconPlugins\ 内最新版。删除杂物 EXE\win-x64\AwakenGPUToolLog.txt、EXE\win-x64\images_v2.db(仓库根目录已干净;ExE.zip(167MB, 当日) 疑似用户打包桌面副本用,未动)。ContentControl x:Name=NodeInfoSlot 插槽 + 新 API ReplaceNodeInfoPanel(UIElement)(null=恢复默认,仅影响本实例);三个编辑器 XAML 把视觉面板(视觉显示标题+图层 ComboBox+大显示窗+运行状态行)定义为折叠的 VisionPanel,构造函数里 EditorRoot.Children.Remove(VisionPanel) 后注入(渲染前完成,无闪烁),面板 MinHeight=320、宽度随右侧面板列(320 起,画布分隔条可拖宽)。HKCU\Software\Microsoft\Avalon.Graphics 新建 DWORD DisableHWAcceleration=1(仅 WPF 改用软件渲染,即时生效、无需重启)。已启动 TeamAAS 截屏验证渲染正常。reg delete "HKCU\Software\Microsoft\Avalon.Graphics" /v DisableHWAcceleration /f节点 · 图层 · #批次。节点名.图像/.区域 → 图像/区域(节点归属由条目结构表达,不再冗余前缀)。CogRecordDisplay.RenderEngine 默认硬件加速渲染在本机(向日葵远程+显卡环境)不 painting,切 GDI 渲染引擎(CogRenderEngineConstants.CogGDIRenderEngine=1)立即恢复。注意该属性只能在句柄创建后读写(否则抛 InvalidOperationException)。落地 Plugins.Vpp\Views\CogGdiRender.cs(递归扫描容器内所有 Cog 显示控件、HandleCreated 时机切换):VppWindow(主页+VPP流程编辑器显示)直接 Apply;ToolBlockEdit(工具块编辑器,内部面板动态创建)用 600ms×40 次定时器重扫兜底。HalconEditorPreview.Current 经典通路,每个算子跑完直接推图覆盖图层筛选结果 → 已移除该挂接(图层总线为唯一显示驱动);区域类算子(形状筛选/连通域/形态学)发布时无底图 → LayerComboHelper 增加底图回退:节点没发过图像层时取全流程最近发布的图像层垫底("区域附带原图",不再黑底孤立区域)。HalconOperatorModelBase([Button 高级编辑])+ HalconToolAdvancedEditor 专用窗体(左 PropertyGrid 参数 + 右 HalconWindow 大显示窗 + 加载测试图像注册「图像」输入变量 + 后台单步执行,执行挂当前流程注册表);8 个现有算子模型全部翻转到新基类;新增算子 H边缘提取(Sobel+阈值,检测识别分类)。后续新算子继承基类即自动获得高级编辑入口。Runtime\Vpp9.0\ 运行时目录当初只拷了 ToolBlock 需要的 DLL,缺经典工具程序集(Cognex.VisionPro.Blob/PMAlign/Caliper 及其 .Controls —— 它们在 VisionPro 安装的 ReferencedAssemblies 里,bin 目录没有);② VisionPro 程序集是懒加载的,应用没显式用到之前不在 AppDomain,反射按名扫描永远找不到。C:\Program Files\Cognex\VisionPro\ReferencedAssemblies 补齐 6 个 DLL 到 Vpp9.0(Blob/PMAlign/Caliper ×2 含编辑控件);② VpToolSupport 增加 EnsureCognexAssembliesLoaded(Assembly.Load 触发 AssemblyResolve → Runtime 递归解析),FindToolType/FindControlType 找不到时先预载再重扫。OpenNativeEditor 同时修复了:编辑控件与工具跨程序集查找、[NonSerialized] 委托反序列化后为 null 的兜底、内部显示控件 GDI 渲染修复。GenImageConverter.Grey8ToCogImage 用 CogImage8Root.Initialize 包裹 GenImage.Data 托管数组后立即解除固定——GC 挪动/回收数组后 CogImage 读到悬空指针 → 显示黑图(有暗噪点)、Blob 数量恒 0。修复:改走 ToBitmap() → new CogImage8Grey(bmp) 拷贝路径(SetRootCopier/Freeze 在该版 VisionPro 中不存在,编译器证实)。CogToolBase.CreateLastRunRecord() 把整棵记录树发布为图层(VppEditorPreview.ShowRecord:RecordKey 命名、ContentType 判定图像层、根记录=默认合成视图、深度限 3 层防环);编辑器图层级选中直接 VppWindow.RefreshRecordDisplay(record) 用 Cognex 原生渲染(图像+图形叠加原样呈现,如 BlobImageUnfiltered 的绿色轮廓)。ICogRecord 成员名是 RecordKey/Content/ContentType/SubRecords(无 Name)。VppWindow.RefreshRecordDisplay 去除每帧 GC.Collect(连续运行卡顿)。Dictionary<图层名, 记录对象>(树序)。Results.Count、Results.GetBlobs[0].CenterOfMassX、SearchRegion...)作为输出终端,输出名=路径末段(重名自动 _2/_3)。可选项运行后由 VpToolSupport.LearnTerminalPaths 自动学习(递归公共属性、深度≤3、集合展开首元素标 [0]、封顶 80 条、跳过 Name/RunStatus/System 命名空间),随流程持久化;取值走既有 GetPath 反射路径解析(支持索引与 0 参方法)。OutputField 名字属性为 Key(非 Name)。VpTerminalEditorWindow 专用弹窗:工具对象树(属性/结果,带实时值,如 CenterOfMassX = 123.4;集合展开首元素标 [0];复杂对象可勾选整对象且可继续展开;深度≤4/节点≤400),勾选任意节点 → 确定 → 写回 OutputTerminals(作为输出终端,输出名=路径末段)。弹窗实时读工具对象(EnsureTool 兜底创建),勾选状态按已存路径回显。VpToolPluginBase.PresetTerminals(virtual,返回 VpPresetTerminal[名称,路径])——DeclareOutputs 自动声明 + PluginRun 自动赋值(GetPath 容错取 null)。全部 Vp 算子共用此封装。VpToolPluginBase 实现 IVpResultSource(GetResultKeys=DeclareResultFields 名单 + PresetTerminals);VpResultKeyMultiProvider 候选=两者合集;留空=全部输出,勾选后 DeclareOutputs 按勾选声明、PluginRun 剪裁 res(图层/输出图像/输出终端不受筛选影响)。预设终端输出名可能与类型化结果重名(如 分数),重名项以筛选勾选为准。IVpPresetSource.GetPresetPaths()(模型实现,经 PluginLoader 按工具名反射取插件 PresetTerminals);VpToolPluginBase.PresetTerminals 改 public(接口对齐)。GetPathStrict(区分"路径不存在"与"值为 null/空集合");首次预勾选时逐条验证,只保留工具结果对象上真实存在的路径——Blob 未启用测量时 Area 类预设不会出现在勾选里(启用后下次运行自动可勾)。= null 且可勾选(输出 null),不再直接隐藏。CogBlobResult 上没有 Area/CenterMassX 属性——官方机制是 GetMeasure(CogBlobMeasureConstants)(40 项枚举:Label/Area/Perimeter/CenterMassX/Y/Inertia/Elongation/Angle/Acircularity/BoundingBox*×3族/NotClipped),未启用的测量抛 CogBlobMeasureNotComputedException。反射扫属性永远扫不到 → 这就是"树里找不到 Area"的真正原因。GetMeasure(枚举) 方法的对象自动注入「测量项 (GetMeasure)」分支——40 项全量列出(未启用的标"(未启用)"但仍可勾选,勾选输出 null),路径格式 Results.GetBlobs[0]@Measure:Area。VpToolSupport.GetMeasureValue(TryParseMeasurePath 解析 @Measure: 标记 → GetPath 定位对象 → GetMeasure(枚举));PluginRun 输出环节对测量路径走专用取值。MeasureMarker 常量在 public VpPresetTerminal 上(分类工程可访问)。()(如 GetBlobs() (CogBlobResultCollection) [3 项]),路径按方法名(GetPath 支持无参方法调用,下游绑定同样有效);值渲染复用 WalkValue 统一管线(标量/集合/复杂对象)。树可以一路钻到与官方终端树同样的深度。Results.GetBlobs[0]@Measure:Area),新树生成方法式路径(Results.GetBlobs()[0]...)——字符串对不上,勾选框全空。VpToolSupport.NormalizePath(索引段方法化:GetBlobs[0] → GetBlobs()[0]);① GetPresetPaths 返回前规范化;② PluginRun 对已存 OutputTerminals 做一次性规范化迁移(旧流程数据兼容);③ LearnTerminalPaths 输出统一规范化(学习清单与树一致)。树 Tag=规范化路径 → 勾选回显精确对应。() 的名字("GetBlobs()")——属性/字段/方法全都查不到,中途断链返回 null。()(成员查找用裸名);GetMember 增加"属性不存在时尝试同名 GetXxx() 方法"兜底(GetBlobs/GetBlobMeasure 等);MemberExists 同步剥 ()(严格验证不再误判)。另注意:测量值为 null 的另一情形是测量未在 Blob 原生编辑器 Measurements 页启用(GetMeasure 抛"未计算"被容错为 null)。Results.GetBlobs[0]...),而 NormalizePath/预设存储是带括号的(Results.GetBlobs()[0]...)——树 Tag 与存储字符串又不一致。()(prefix + "." + name + "()"),其下所有子节点路径自动继承;GetPath 运行时剥 () 兼容两种。至此树 Tag=存储格式=取值格式,三方一致。节点 · #批次。修复:① InitPlugin 立即返回 true,编译转 Task.Run 后台(引擎预热/引用/编译全在后台,_engineGate 串行化与 PluginRun 的竞争);② 新增 ScriptCompiler.TryGetEntry/TryCreateCached(纯缓存查询,绝不触发编译);③ DeclareOutputs 只用缓存命中结果(该方法在 UI 线程被调用),未命中回空——后台编译完成后,下次打开属性/保存/运行即按脚本声明输出;④ PluginRun 保持同步编译(在 FlowExecutor 工作线程,不卡 UI)。WarmupEngine 公开供预热调用。
git checkout -b feature/modularization 即可把全部改动带进分支(无需合并操作)。TeamAAS.Core\TeamAAS.SDK\bin\x64\Debug\TeamAAS.SDK.dll ✓TeamAAS.Core\TeamAAS.Motion\bin\x64\Debug\TeamAAS.Motion.dll ✓EXE\win-x64\Plugins\HalconPlugins\:Plugins.Halcon.dll、Plugins.Halcon.ImageProcessing.dll、Plugins.Halcon.Detection.dll、Plugins.Halcon.Measurement.dll、Plugins.Halcon.Logic.dll ✓(+halcondotnet.dll 随主插件复制)Plugins.<平台>.<功能>.dll + Plugins\{HalconPlugins,VmPlugins,VppPlugins}\ 部署目录)、图层管线、迁移规则。Plugins\**\Plugins.*.dll(同名 DLL 去重)。Plugins.Vpp.Vision\Plugins.Vpp.Detection:VpBlob分析 / Vp模板匹配;Plugins.Vpp.Measurement:Vp卡尺测量 / Vp找圆 / Vp找直线。基建=主工程新增 VpToolSupport.cs(反射创建/运行 Cog 工具、结果路径取值 Results[0].Score 等、原生编辑器 EditV2 控件 WinForms 弹出);基类 VpToolModelBase(Tool 随流程序列化不丢配置 + 输入图像绑定 + [Button]高级编辑)+ VpToolPluginBase(取图→喂图→运行→提取)。部署到 Plugins\VppPlugins\。✓ 产物已核实Plugins.Vm.Vision\Plugins.Vm.Module:VM模块 节点(方案/流程/结果键声明 → 运行读取模块结果 GetOutputImageV2 等;高级编辑调起 VisionMaster 客户端打开方案);VmRuntime 增加 GetModuleOutput。部署到 Plugins\VmPlugins\。✓ 产物已核实git checkout -b feature/modularization 分 7 段提交;删 _explore.ps1。git checkout -b feature/modularization 分段提交(全部改动仍在工作区)