如何在TwinCAT中用Ads.NET读取NCTOPLC_AXIS_REF并解决执行引擎异常?
解决读取PLC NCTOPLC_AXIS_REF时的System.ExecutionEngineException异常
排查方向1:结构体与PLC数据定义严格对齐
- 逐字段核对C#结构体与PLC中
NCTOPLC_AXIS_REF的数据类型、字节长度、字节序:比如PLC的DWord对应C#的uint,Word对应ushort,若PLC用大端字节序,需手动转换字段值。 - 数组部分确认
SizeConst与PLC数组元素数量完全一致,且数组元素类型匹配PLC定义。
排查方向2:内存对齐参数调整
- 尝试修改
StructLayout的Pack值:虽然用了Pack=1,但部分PLC结构体要求2或4字节对齐,可切换后测试是否恢复正常。 - 计算结构体总字节数:用
Marshal.SizeOf(typeof(你的结构体类型))获取C#结构体长度,和PLC侧数据块的字节数对比,确保两者完全相等。
排查方向3:验证ReadAny的输入参数
- 确认
handle指向的PLC数据块地址、偏移量完全正确,避免指向非法内存区域。 - 检查
client连接状态:读取时确保PLC在线、连接未中断,且当前账号有数据块访问权限。
排查方向4:绕过自动Marshal,手动解析字节
System.ExecutionEngineException多和非托管内存访问错误相关,可尝试先读取原始字节再手动转换,排查是否是ReadAny自动Marshal的问题:
// 先读取原始字节数组 byte[] rawData = new byte[Marshal.SizeOf(typeof(NCTOPLC_AXIS_REF))]; client.ReadBuffer(handle, rawData, 0, rawData.Length); // 手动将字节数组转换为结构体 GCHandle pinnedHandle = GCHandle.Alloc(rawData, GCHandleType.Pinned); try { NCTOPLC_AXIS_REF axisData = (NCTOPLC_AXIS_REF)Marshal.PtrToStructure(pinnedHandle.AddrOfPinnedObject(), typeof(NCTOPLC_AXIS_REF)); } finally { pinnedHandle.Free(); }
如果手动解析成功,说明ReadAny的自动Marshal逻辑和你的结构体定义存在冲突,需调整结构体属性。
排查方向5:检查PLC数据块配置
- 确认
NCTOPLC_AXIS_REF所在数据块未开启优化块访问:部分PLC的优化块无法通过常规结构体Marshal读取,需关闭优化访问,或使用PLC官方库提供的专属读取方法。
内容的提问来源于stack exchange,提问作者Roald
相关产品推荐
相关产品推荐

