如何用Python win32clipboard获取并还原UniLogic非标准剪贴板数据
解决UniLogic梯形图梯级剪贴板数据保存与还原问题
问题背景
从PLC编程环境UniLogic中复制多个梯形图梯级后,尝试通过win32clipboard库保存并还原剪贴板数据时遇到异常:
- 枚举剪贴板格式得到值49161(十六进制
C009),格式名称为DataObject - 执行
win32clipboard.GetClipboardData(49161)返回全空字节串b'\x00\x00\x00\x00\x00\x00\x00\x00' - 将该空数据设置回剪贴板后,无法在UniLogic中粘贴梯级
核心原因
这是Windows剪贴板**延迟渲染(Delayed Rendering)**机制导致的。UniLogic这类专业编程软件为了优化性能,不会在复制时立即把完整的梯形图数据写入剪贴板,仅注册自定义格式并提供一个数据回调指针。当其他程序调用GetClipboardData()时,如果没有触发原程序的数据渲染逻辑,拿到的只是占位的空数据;即使原程序保持运行,直接复用指针也无法生效——因为剪贴板指针的有效性受进程上下文限制,跨进程无法直接使用。
可行解决方法
1. 捕获实际渲染后的剪贴板数据
在复制梯级后立即触发数据渲染并捕获完整二进制:
- 用Python的
ctypes调用Windows原生API,通过OpenClipboard配合GlobalLock直接读取剪贴板内存中的实际数据 - 使用剪贴板监控工具(如ClipSpy),在复制操作后立即查看
DataObject格式对应的完整二进制内容,保存后再用该数据还原剪贴板
2. 逆向UniLogic的自定义数据格式
通过对比不同复制场景的数据,解析DataObject的格式规则:
- 分别复制单个梯级、多个梯级,捕获对应的剪贴板二进制数据,对比差异找出结构规律
- 用调试工具(如x64dbg)跟踪UniLogic写入剪贴板的逻辑,获取数据序列化的具体方式
- 查看UniLogic安装目录下的相关DLL文件,寻找与数据序列化相关的函数或结构定义
3. 通过OLE DataObject接口获取真实数据
放弃win32clipboard的直接调用,改用Python的pythoncom模块操作OLE DataObject,触发延迟渲染获取真实数据:
import pythoncom import win32api from win32com.client import Dispatch pythoncom.CoInitialize() # 获取剪贴板的OLE数据对象 clipboard = Dispatch("Clipboard") data_obj = clipboard.GetDataObject() # 构造目标格式的FORMATETC结构 fmt = pythoncom.FORMATETC() fmt.cfFormat = 49161 # 对应C009自定义格式 fmt.dwAspect = pythoncom.DVASPECT_CONTENT fmt.lindex = -1 fmt.ptd = None fmt.tymed = pythoncom.TYMED_HGLOBAL if data_obj.QueryGetData(fmt): # 获取实际数据存储对象 storage = data_obj.GetData(fmt) # 从HGLOBAL内存块读取二进制内容 ptr = win32api.GlobalLock(storage.data) data_size = win32api.GlobalSize(storage.data) real_data = win32api.PyGetMemory(ptr, data_size) win32api.GlobalUnlock(storage.data) print(real_data)
4. 改用UniLogic原生导出/导入功能
最稳定的替代方案:直接使用UniLogic的导出功能将梯级保存为专用格式文件(如.ulx或XML),需要还原时通过导入功能加载到项目中,完全绕开剪贴板的兼容性问题。
内容的提问来源于stack exchange,提问作者Maksiss
相关产品推荐
相关产品推荐

