終端服務的剪貼簿的缺陷,導致WPF呼叫Clipboard.SetText() 失敗
這是一個在實際專案中遇到的問題,在VPN和遠端桌面中,WPF程式對系統剪貼簿進行操作的時候,發生CLIPBRD_E_CANT_OPEN異常。從異常本身來看,很明顯,是COM有問題。
程式碼很簡單 Clipboard.SetText(mSelection); 但是注意,這個是WPF的視窗,所以呼叫的是 System.Windows.Clipboard,而不是WinForm的System.Windows.Forms.Clipboard。
經過一番搜尋,找到了根源:
http://stackoverflow.com/questions/68666/clipbrd-e-cant-open-error-when-setting-the-clipboard-from-net
http://blogs.microsoft.co.il/blogs/tamir/archive/2007/10/24/clipboard-setdata-getdata-troubles-with-vpc-and-ts.aspx
原因是微軟的Terminal Service 的Clipboard有一個bug,解決方法就是用try-catch包一下函式呼叫,然後多呼叫幾次,每次之後呢,Sleep一點時間片,程式碼看上去就是:
for (int i = 0; i < 10; i++) { try { Clipboard.SetText(str); return; } catch { } System.Threading.Thread.Sleep(10); }
而有人也指出,在.Net 2.0 SP1的時候,微軟對Winform的剪下板做了修正,內部就做了這個處理,但是WPF沒有!好,那就來看看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();
}
}
相關推薦
終端服務的剪貼簿的缺陷,導致WPF呼叫Clipboard.SetText() 失敗
這是一個在實際專案中遇到的問題,在VPN和遠端桌面中,WPF程式對系統剪貼簿進行操作的時候,發生CLIPBRD_E_CANT_OPEN異常。從異常本身來看,很明顯,是COM有問題。 程式碼很簡單 Clipboard.SetText(mSelection); 但是注意,這
C#如何儲存剪貼簿內容,在使用後恢復。
C# clipboard類封裝了對剪貼簿的操作,一般使用沒有問題。但由於clipboard封裝的資料型別有限,對於一些自定義型別的剪貼簿資料,如果想佔用剪貼簿並在使用後原樣恢復剪貼簿的資料就會產生問題。試驗了很多方法後,嘗試學習別人C++的思路。使用winapi來處理
delphi 剪貼簿操作,讀取剪貼簿內容
//全域性變數NextClipHwnd:HWND;//剪貼簿觀察鏈中下一個視窗控制代碼 procedure TForm1.FormShow(Sender: TObject);begin //獲得剪貼簿觀察鏈中下一個視窗控制代碼,並將控制代碼註冊到剪貼簿觀察鏈中 Ne
js實現複製到剪貼簿功能,相容所有瀏覽器
前段時間做專案的時候,有點選按鈕複製文字的需求,想使用操作windows剪下板實現,在網上查了些資料,發現目前好像只有IE支援直接訪問剪下板,實現需求的時候也只做了IE中的點選複製功能,其餘瀏覽器: if(window.clipboardData){ window.clip
js複製內容到剪貼簿程式碼,js複製程式碼
例子 <script type="text/javascript"> function jsCopy(){ var e=document.getElementById("contents");//物件是contents
利用python監聽剪貼簿內容,並修改。
前言 由於我在讀論文的時候常常需要複製論文片段,然後論文(pdf格式)中常常有多餘的換行符,所以貼上到txt或者markdown文字中都會很不美觀,我希望能利用python指令碼把換行符去掉,在此記錄過程。 預期要實現的功能: 1)複製一個pdf中的論文片段,
neutron-metadata-proxy無響應,導致windos2003密碼透傳失敗
sha 判斷 agent 系統 process type ado dbf 解決 一、故障現象 在某雲平臺出現指定域指定節點(node-1)上創建windos2003虛擬機無法透傳創建虛擬機時設定的系統登錄密碼,但是可以透傳制作鏡像時設定的密碼創建好windos2003虛擬機
SQL安裝服務起不來,報錯TDSSNICLIENT初始化失敗,錯誤0X80092004
TDSSNIClient初始化失敗,錯誤0x80092004,狀態程式碼0x80。原因:無法初始化SSL支援。 TDSSNIClient初始化失敗,錯誤0x80092004,狀態程式碼0x1。原因:初始化因基礎結構錯誤而失敗。由於網路庫中的內部錯誤,無法啟動網路庫。 經過幾天的搜尋
Dubbo新增服務ip白名單,防止不法呼叫。
1.新增類ValidationFilter繼承阿里巴巴的Filter package com.filter; import java.io.IOException; import java.io.InputStream; import java.util
Win10自動更新,導致的Sql Server連線失敗
Sql Server使用 :常見的【Sql Server連線失敗】問題 -----------------------------------------------------------------------------------------------------
nw.js 實現 剪貼簿的複製copy 貼上功能 --clipboard api
nw.js node-webkit系列(10)Native UI API Clipboard的使用開發文件 clipboard api: http://liuxp.me/nwjs/References/Clipboard/參考網址:http://blog.csdn.net/z
虛擬機移動磁盤中途服務器斷電,導致磁盤鎖定的處理辦法
ovirt可以通過修改數據庫,步驟如下1、OVIRT進入數據庫[root@vmhost2 ~]# su postgres 進入數據庫bash-4.2$ psqlcould not change directory to "/root"psql (9.2.23)Type "help" for help.2、po
NFS服務意外斷開,導致掛載的客戶端“df -Th”命令無法使用,及掛載目錄無法“cd”“ls”
問題處理解決思路:1、強制取消客戶端掛載2、重啟NFS服務,客戶端和服務端都需要重啟3、重新掛載NFS 處理方法:1、強制取消客戶端掛載 # cat /etc/mtab # umount -lf /mnt 2、重啟NFS服務,客戶端和服務端都需要重啟 # systemctl restart nfs # sys
剪貼簿,匿名管道,命名管道,郵槽學習筆記
原始碼在後面 程序間進行通訊的四種方式: 剪貼簿,匿名管道,命名管道,郵槽 1).ClipBoar OpenClipboard() &
針對惠普伺服器SNMP採集頻繁,導致服務停止的解決方案
運維軟體:zabbix採集方式:snmp採集裝置:惠普-DL380_Gen9-伺服器採集週期:根據指標要求頻率有5分鐘到1天主要命令:reset /map1樂維服務中發現,snmp採集惠普伺服器一段時間後,zabbix提示連線失敗,重啟ilo後又可以重新採集,我們可以利用這一點做一
**萬能的“一鍵複製到剪貼簿”,支援IE、火狐、谷歌及移動版瀏覽器**
說到點選按鈕“複製到剪貼簿",大家都可能用過,但是之前的實現方不是隻支援某些瀏覽器,就是要在網頁內嵌swf(Flash)檔案。 這兩種方法:第一種不能很好的相容多數瀏覽器,第二種方式下開發人員可能會擔心Flash的安全性問題。 現在出現了一種新的實現方式:clipboard
TIME_WAIT、NON_ESTABLISHED 連線數過高,導致tomcat服務直接宕機
TCP常見配置參考地址: http://shift-alt-ctrl.iteye.com/blog/1966744;https://www.cnblogs.com/fczjuever/archive/2013/04/05/3000697.html 以上圖最大連線數接近了2000,這個對於單機環境來說基本已
Sqlite表結構讀取工具,word批量轉html,線上雲剪貼簿,檔案批量提取工具;
工欲善其事必先利其器,本週為您推薦工具排行 Sqlite表結構讀取工具,word批量轉html,線上雲剪貼簿,檔案批量提取工具; 本週我們又要發乾貨了,準備好接受了嗎? 為什麼是乾貨,就是因為不是水貨,因為幹了,所以是乾貨,也就是實打實的。當然哈
一次意外:win7 中 DCOM Server Process Launcher 服務意外終止,導致計算機重新啟動
剛遇到這個問題,也是第一次遇到,先描述下問題:在記憶體使用率比較高的情況下,突然彈出對話方塊,提示:DCOM Server Process Launcher 服務意外終止... (當時第一反應就是儲存截圖,結果由於動作慢了點,電腦過了一會就自動關閉程式,重啟了
MFC:使用剪貼簿,怎麼將內容複製到剪貼簿
經常在論壇上見到一些使用者詢問如何在Visual C++中如何實現對剪貼簿的操作,其實在VC++/MFC中是相當簡單的。本文主要介紹瞭如下內容: 1、文字內容的操作 2、WMF資料的操作 3、點陣圖的操作 4、設定使用自定義格式 5、感知剪貼簿內容的改變 6、自動將資料貼上到另一應用程式視窗 一、文字內容的