WPF剪切板问题-OpenClipboard HRESULT:0x800401D0 (CLIPBRD_E_CANT_OPEN))
WPF剪切板问题-OpenClipboard HRESULT:0x800401D0 (CLIPBRD_E_CANT_OPEN))
最近碰到一个问题,需要弄个小工具来解决。刚好接触到WPF,于是就想通过WPF来实现。
在这个过程中想通过程序将一些东西复制到剪切板中,代码很简单:Clipboard.SetText(lineTexts[lineIndex]);就这一句,想把lineTexts这个字符串List中的第lineIndex项复制到剪切板中,但是运行的时候就会抛出异常,大致的异常信息是“OpenClipboard HRESULT:0x800401D0 (CLIPBRD_E_CANT_OPEN))”(挺长的一段,注意没写全)。而winform那边之前也用过,没有问题。
上网搜索了一下,看了挺多资料,发现是WPF本身对Clipboard处理的问题,在.Net4.0及之前的版本中都有问题,最近Micorsoft已经在.Net4.5中修复了。问题主要是由于:在程序访问剪切板的时候,有其他程序正在占用剪切板,导致自己的程序无法访问,从而抛出异常。
在.Net4.0上,解决这个问题,我大概总结了一下,有下面几种方法:
这种方法处理过程中UI会有一小段时间的假死。。。可以考虑多线程?
2. 换一种方式设置剪切板
Clipboard.SetDataObject(lineTexts[lineIndex]);
就这一句。。。这种方法不会抛异常,UI也没有假死,非常正常!估计SetDataObject方法跟SetText方法的实现不一样,没有细究。。。
3. 跟方法1类似,不过有点高级
在这个过程中想通过程序将一些东西复制到剪切板中,代码很简单:Clipboard.SetText(lineTexts[lineIndex]);就这一句,想把lineTexts这个字符串List中的第lineIndex项复制到剪切板中,但是运行的时候就会抛出异常,大致的异常信息是“OpenClipboard HRESULT:0x800401D0 (CLIPBRD_E_CANT_OPEN))”(挺长的一段,注意没写全)。而winform那边之前也用过,没有问题。
上网搜索了一下,看了挺多资料,发现是WPF本身对Clipboard处理的问题,在.Net4.0及之前的版本中都有问题,最近Micorsoft已经在.Net4.5中修复了。问题主要是由于:在程序访问剪切板的时候,有其他程序正在占用剪切板,导致自己的程序无法访问,从而抛出异常。
在.Net4.0上,解决这个问题,我大概总结了一下,有下面几种方法:
- 自行截获异常,进行处理
for (int i = 0; i < 10; i++) { try { Clipboard.SetText(lineTexts[lineIndex]); break; } catch { System.Threading.Thread.Sleep(10);//这句加不加都没关系 } }
这种方法处理过程中UI会有一小段时间的假死。。。可以考虑多线程?
2. 换一种方式设置剪切板
Clipboard.SetDataObject(lineTexts[lineIndex]);
就这一句。。。这种方法不会抛异常,UI也没有假死,非常正常!估计SetDataObject方法跟SetText方法的实现不一样,没有细究。。。
3. 跟方法1类似,不过有点高级
剪切板处理的那句代码不变,还是使用SetText方法。
在App.xaml文件中添加下面代码中红色的部分在App.xaml.cs文件中添加代码:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
DispatcherUnhandledException="Application_DispatcherUnhandledException">
void Application_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
var comException = e.Exception as System.Runtime.InteropServices.COMException;
if (comException != null && comException.ErrorCode == -2147221040)///OpenClipboard HRESULT:0x800401D0 (CLIPBRD_E_CANT_OPEN))
e.Handled = true;
}
这种方法中剪切板动作会自动多次尝试,由于抛出的异常被App中的异常处理给截获了,所以会不断的尝试直到成功。方法三也有一定程度的UI假死。对于方法三,具体原理可以到MSDN上搜一下DispatcherUnhandledException或相关内容,这里一时半会说不清楚。
方法三使用范围广,可以类似的处理其他的异常。而方法二只能是自己的代码才能解决,如果用到WPF控件或者其他第三方控件就不行了。所以推荐方法三,但如果是自己写的代码,用方法二就简单方便的多。