如果剪贴板操作失败(例如 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); } }
标签:C#,image,应用程序,static,void,剪切板,报错,WPF,public From: https://www.cnblogs.com/JqkAman/p/16591540.html