异常信息“OpenClipboard HRESULT:0x800401D0 (CLIPBRD_E_CANT_OPEN
WPF本身对Clipboard处理的问题,在.Net4.0及之前的版本中都有问题,在.Net4.5中修复了,但XP下安装不了.NET4.5,而我的程序又必须在XP下运行。
问题主要是由于:在程序访问剪切板的时候,有其他程序正在占用剪切板,导致自己的程序无法访问,从而抛出异常。
剪切板处理的那句代码不变,还是使用SetText方法。
void Application_DispatcherUnhandledExcep 4.使用winform剪贴板
System.Windows.Forms.Clipboard.SetText(txt2.Text);
看一下WinForm和WPF的代码 WinForm的SetText()最终会调用SetDataObject(data, copy, 10, 100),这个是SetDataObject()的签名:
[UIPermission(SecurityAction.Demand, Clipboard=UIPermissionClipboard.OwnClipboard)]
public static void SetDataObject(object data, bool copy, int retryTimes, int retryDelay) { if (Application.OleRequired() != ApartmentState.STA) { throw new ThreadStateException(SR.GetString("ThreadMustBeSTA")); } if (data == null) { throw new ArgumentNullException("data"); } if (retryTimes < 0) { object[] args = new object[] { "retryTimes", retryTimes.ToString(CultureInfo.CurrentCulture), 0.ToString(CultureInfo.CurrentCulture) }; throw new ArgumentOutOfRangeException("retryTimes", SR.GetString("InvalidLowBoundArgumentEx", args)); } if (retryDelay < 0) { object[] objArray2 = new object[] { "retryDelay", retryDelay.ToString(CultureInfo.CurrentCulture), 0.ToString(CultureInfo.CurrentCulture) }; throw new ArgumentOutOfRangeException("retryDelay", SR.GetString("InvalidLowBoundArgumentEx", objArray2)); } DataObject obj2 = null; if (!(data is IDataObject)) { obj2 = new DataObject(data); } bool flag = false; try { IntSecurity.ClipboardRead.Demand(); } catch (SecurityException) { flag = true; } if (flag) { if (obj2 == null) { obj2 = data as DataObject; } if (!IsFormatValid(obj2)) { throw new SecurityException(SR.GetString("ClipboardSecurityException")); } } if (obj2 != null) { obj2.RestrictedFormats = flag; } int num2 = retryTimes; IntSecurity.UnmanagedCode.Assert(); try { int num; do { if (data is IDataObject) { num = UnsafeNativeMethods.OleSetClipboard((IDataObject) data); } else { num = UnsafeNativeMethods.OleSetClipboard(obj2); } if (num != 0) { if (num2 == 0) { ThrowIfFailed(num); } num2--; Thread.Sleep(retryDelay); } } while (num != 0); if (copy) { num2 = retryTimes; do { num = UnsafeNativeMethods.OleFlushClipboard(); if (num != 0) { if (num2 == 0) { ThrowIfFailed(num); } num2--; Thread.Sleep(retryDelay); } } while (num != 0); } } finally { CodeAccessPermission.RevertAssert(); } } 而WPF的SetText(),虽然签名一样,但是具有完全不同的实现:
[SecurityCritical]
public static void SetDataObject(object data, bool copy) { SecurityHelper.DemandAllClipboardPermission(); CriticalSetDataObject(data, copy); } [FriendAccessAllowed, SecurityCritical]
internal static void CriticalSetDataObject(object data, bool copy) { IDataObject obj2; if (data == null) { throw new ArgumentNullException("data"); } if (data is DataObject) { obj2 = (DataObject) data; } else if (data is IDataObject) { SecurityHelper.DemandUnmanagedCode(); obj2 = (IDataObject) data; } else { obj2 = new DataObject(data); } int num2 = 10; while (true) { int hr = OleServicesContext.CurrentOleServicesContext.OleSetClipboard(obj2); if (NativeMethods.Succeeded(hr)) { break; } if (--num2 == 0) { Marshal.ThrowExceptionForHR(hr); } Thread.Sleep(100); } if (copy) { Thread.Sleep(10); Flush(); } } |
|