C# WPF 访问剪切板报错
如果剪贴板操作失败(例如 HRESULT 0x800401D0 (CLIPBRD_E_CANT_OPEN) 错误),则会引发相应的 ExternalException (,这是一种 ExternalException) 。
由于 Win32 OpenClipboard
API 全局运行,因此编写良好的应用程序应在完成剪贴板操作后立即调用相应的 CloseClipboard
API。 否则,在同一会话中运行的其他应用程序将无法访问剪贴板函数。
在 WPF 中,通常以无提示方式忽略对剪贴板的访问。 However, applications can opt to receive an ExternalException
upon failure by setting the ShouldThrowOnCopyOrCutFailure flag to true
. 但是,选择接收异常还要求应用程序通过 a CommandBinding处理Cut和 Copy RoutedUICommands,然后将该绑定应用到应用程序中的所有 TextBoxBase 控件 (TextBox和RichTextBox) 。 应用程序应确保处理 CommandBinding 执行处理程序中复制和剪切操作产生的 ExternalException。
以上来自微软官方解释
代码:
[DllImport("user32.dll")]
private static extern IntPtr CloseClipboard();
注:调用此方法时,最好做个1秒的等待,因为调用之后真正的释放是有时间的,或者做一个Retry
/// <summary> /// /// </summary> public static class ClipboardHelper { [DllImport("user32.dll")] private static extern IntPtr CloseClipboard(); [DllImport("user32.dll", SetLastError = true)] static extern IntPtr GetOpenClipboardWindow(); [DllImport("user32.dll", SetLastError = true)] static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId); /// <summary> /// 获取进程信息 /// </summary> /// <returns></returns> public static Process GetProcessLockingClipboard() { int processId; GetWindowThreadProcessId(GetOpenClipboardWindow(), out processId); return Process.GetProcessById(processId); } /// <summary> /// 清理剪切板,避免异常 /// </summary> public static void ClearClipboard() { try { CloseClipboardMethod(); } catch (Exception ex) { //记录日志 try { CloseClipboardMethod(); } catch (Exception ex2) { //忽略 } } } public static void CloseClipboardMethod() { CloseClipboard(); System.Windows.Clipboard.Clear(); } /// <summary> /// /// </summary> /// <param name="image"></param> /// <returns></returns> public static void SetImage(BitmapSource image) { try { SetImageMethod(image); } catch (Exception ex) { //记录日志 try { var process = GetProcessLockingClipboard(); if (process != null) { var msg =$"占用剪切板的进程:{process.Id}、{process.ProcessName}"; //记录占用剪切板的进程信息 } SetImageMethod(image); } catch (Exception ex1) { //忽略 } } } /// <summary> /// 复制逻辑 /// </summary> /// <param name="image"></param> /// <returns></returns> private static void SetImageMethod(BitmapSource image) { ClearClipboard(); //结束之后等待一下,等进程真正的结束再继续下一步 Thread.Sleep(1000); //将图片放入到剪切板 System.Windows.Clipboard.SetImage(image); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
2020-08-16 转载——EntiyFrameWork教程