CSharp Tips:讓DotNet實現的COM物件支援IObjectSafety介面 (轉)
CSharp Tips:讓DotNet實現的COM物件支援IObjectSafety介面 (轉)[@more@]
當我們實現的COM,或者在中的時候,往往會出現警告框,提示不的控制元件正在執行。這是因為瀏覽器安全策略所限定的,瀏覽器認為只有“安全的物件”才能夠被。
所謂安全的物件就是指那些不訪問本地資源的物件,例如不會去讀登錄檔,不會寫等等。一個滿足條件的物件透過支援ISafety介面告訴瀏覽器,自己是合法的。
下面就簡單的介紹一下怎麼在中實現對於IObjectSafety介面的支援。
思路
C/C++d的可以直接在SDK中找到IObjectSafety的定義,所以需要支援的話非常容易。C#比較麻煩,因為我們沒有辦法獲得IObjectSafety的定義,不過沒有問題,我們可以按照IObjectSafety在SDK中的定義,在C#的工程中重新定義該介面。
如果大家瞭解COM機制一定會知道,所謂藉口的定義之出現在型別庫中,與實現無關。而判斷一個介面唯一性就是定義介面時指定的UUID。此外自己重新定義時需要保證介面中沒有的引數與返回值必須與原定義一致即可。
我們的做法就是,找到ObjSafe.idl,然後複製其中的UUID,利用這個UUID在C#中定一個interface IObjectSafety,並且申明其中的兩個函式;定義完成之後,讓需要檢查安全介面的繼承該介面,並在該元件內部實現IObjectSafety的兩個函式,按照要求做適當的返回,那麼用這個元件包裝的COM物件在IE中呼叫就被認為是安全的了。
第一次嘗試
按照上面的思路,我們開始進行嘗試
idl中的介面定義
[
object,
uuid(CB5BDC81-93C1-11cf-8F20-00805F2CD064),
pointer_default(unique)
]
interface IObjectSafety : IUnknown
{
HRESULT GetInterfaceSafetyOptions(
[in] REFIID riid, // Interface that we want options for
[out] D * pdwSupportedOptions, // Options meaningful on this interface
[out] DWORD * pdwEnabledOptions); // current option values on this interface
object,
uuid(CB5BDC81-93C1-11cf-8F20-00805F2CD064),
pointer_default(unique)
]
interface IObjectSafety : IUnknown
{
HRESULT GetInterfaceSafetyOptions(
[in] REFIID riid, // Interface that we want options for
[out] D * pdwSupportedOptions, // Options meaningful on this interface
[out] DWORD * pdwEnabledOptions); // current option values on this interface
HRESULT SetInterfaceSafetyOptions(
[in] REFIID riid, // Interface to set options for
[in] DWORD dwOptionSetMask, // Options to change
[in] DWORD dwEnabledOptions); // New option values
}
[in] REFIID riid, // Interface to set options for
[in] DWORD dwOptionSetMask, // Options to change
[in] DWORD dwEnabledOptions); // New option values
}
IObjectSafety介面定義
因為介面中存在指標,所以直接採用Int32的整型形式,用到了unsafe code。
[Guid("CB5BDC81-93C1-11cf-8F20-00805F2CD064")]
public interface IObjectSafety
{
// methods
unsafe void GetInterfacceSafyOptions(
System.Int32 riid,
System.Int32* pdwSupportedOptions,
System.Int32* pdwEnabledOptions);
void SetInterfaceSafetyOptions(
System.Int32 riid,
System.Int32 dwOptionsSetMask,
System.Int32 dwEnabledOptions);
}
繼承
public interface IObjectSafety
{
// methods
unsafe void GetInterfacceSafyOptions(
System.Int32 riid,
System.Int32* pdwSupportedOptions,
System.Int32* pdwEnabledOptions);
void SetInterfaceSafetyOptions(
System.Int32 riid,
System.Int32 dwOptionsSetMask,
System.Int32 dwEnabledOptions);
}
繼承
public class MyControl : System..Forms.UserControl,IObjectSafety
實現
// implement functions of IObjectSafety
public unsafe void GetInterfacceSafyOptions(System.Int32 riid,System.Int32* pdwSupportedOptions,System.Int32* pdwEnabledOptions)
{
public unsafe void GetInterfacceSafyOptions(System.Int32 riid,System.Int32* pdwSupportedOptions,System.Int32* pdwEnabledOptions)
{
...
}
public void SetInterfaceSafetyOptions(System.Int32 riid,System.Int32 dwOptionsSetMask,System.Int32 dwEnabledOptions)
{
}
public void SetInterfaceSafetyOptions(System.Int32 riid,System.Int32 dwOptionsSetMask,System.Int32 dwEnabledOptions)
{
...
}
}
一切正常編譯透過,但是透過IE呼叫測試頁面,在裝載頁面的時候卻產生了一個關閉應用程式異常,仔細察看內容Error Report是的地址訪問。無語中...
第二次嘗試
由於是非法的記憶體地址訪問,很自然的聯想到是介面定義的問題,因為存在unsafe code,查查文件發現根本無需使用unsafe code這麼誇張,可以透過out這個引數修飾符解決。
修改定義和實現如下
IObjectSafety介面定義
[Guid("CB5BDC81-93C1-11cf-8F20-00805F2CD064")]
public interface IObjectSafety
{
// methods
void GetInterfacceSafyOptions(
System.Int32 riid,
out System.Int32 pdwSupportedOptions,
out System.Int32 pdwEnabledOptions);
void SetInterfaceSafetyOptions(
System.Int32 riid,
System.Int32 dwOptionsSetMask,
System.Int32 dwEnabledOptions);
}
public interface IObjectSafety
{
// methods
void GetInterfacceSafyOptions(
System.Int32 riid,
out System.Int32 pdwSupportedOptions,
out System.Int32 pdwEnabledOptions);
void SetInterfaceSafetyOptions(
System.Int32 riid,
System.Int32 dwOptionsSetMask,
System.Int32 dwEnabledOptions);
}
實現
// implement functions of IObjectSafety
public unsafe void GetInterfacceSafyOptions(System.Int32 riid,out System.Int32 pdwSupportedOptions,out System.Int32 pdwEnabledOptions)
{
public unsafe void GetInterfacceSafyOptions(System.Int32 riid,out System.Int32 pdwSupportedOptions,out System.Int32 pdwEnabledOptions)
{
...
}
public void SetInterfaceSafetyOptions(System.Int32 riid,System.Int32 dwOptionsSetMask,System.Int32 dwEnabledOptions)
{
}
public void SetInterfaceSafetyOptions(System.Int32 riid,System.Int32 dwOptionsSetMask,System.Int32 dwEnabledOptions)
{
...
}
編譯透過,不錯;IE呼叫測試頁面,同樣的錯誤!鬱悶,無鬥志,回家。
}
編譯透過,不錯;IE呼叫測試頁面,同樣的錯誤!鬱悶,無鬥志,回家。
第三次嘗試
睡了一覺,飽餐戰飯,繼續思考。
自己比較了生成的型別庫,發現一些很奇怪的現象,在型別庫中IObjectSafety居然被定義了兩次interface IObjectSafety : IUnknown,以及dispinterface IObjectSafety : IDispatch。而偏偏MyControl是從dispinterface IObjectSafety上繼承的。這就與正確的IObjectSafety的介面說明相違背,問題應該出在這裡。
MSDN,查文件。System.Runtime.InteropService下有很多關於描述介面的屬性,從中可以找到產生問題的原因。有一個屬性InterfaceTypeAttribute,就是用來說明定義的介面是從IUnknown繼承還是IDispatch繼承,預設情況下是Dual的,所以是兩份。
再次定義如下:
[Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064"),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
// methods
void GetInterfacceSafyOptions(
System.Int32 riid,
out System.Int32 pdwSupportedOptions,
out System.Int32 pdwEnabledOptions);
void SetInterfaceSafetyOptions(
System.Int32 riid,
System.Int32 dwOptionsSetMask,
System.Int32 dwEnabledOptions);
}
其餘程式碼不變,重新編譯,透過;察看匯出型別庫,果然少了很多垃圾;呼叫測試頁面,正確。激動中...
public interface IObjectSafety
{
// methods
void GetInterfacceSafyOptions(
System.Int32 riid,
out System.Int32 pdwSupportedOptions,
out System.Int32 pdwEnabledOptions);
void SetInterfaceSafetyOptions(
System.Int32 riid,
System.Int32 dwOptionsSetMask,
System.Int32 dwEnabledOptions);
}
其餘程式碼不變,重新編譯,透過;察看匯出型別庫,果然少了很多垃圾;呼叫測試頁面,正確。激動中...
怎樣讓IE認為你的物件安全
實現了這個介面,剩下的事情就很簡單了。前面提到過如果按照正規的途徑你需要確保你的程式碼沒有訪問系統的本地自然,然後按照文件要求,當該物件被不同的介面呼叫查詢的時候,做不同的反饋。具體實現可以在MSDN的Sample中找到。
當然我們可以寫一個物件讀寫本地檔案,但是支援IObjectSafety介面,並且始終宣告自己是合法的,這樣來欺騙瀏覽器,那麼程式碼就很簡單了,如下:
// implement functions of IObjectSafety
public void GetInterfacceSafyOptions(System.Int32 riid,out System.Int32 pdwSupportedOptions,out System.Int32 pdwEnabledOptions)
{
pdwSupportedOptions = CLsObjectSafety.INTERFACESAFE_FOR_UNTRUSTED_CALLER;
pdwEnabledOptions = CLsObjectSafety.INTERFACESAFE_FOR_UNTRUSTED_DATA;
}
public void SetInterfaceSafetyOptions(System.Int32 riid,System.Int32 dwOptionsSetMask,System.Int32 dwEnabledOptions)
{
}
只要這麼些,就不會再有討厭的對話方塊彈出了。
public void GetInterfacceSafyOptions(System.Int32 riid,out System.Int32 pdwSupportedOptions,out System.Int32 pdwEnabledOptions)
{
pdwSupportedOptions = CLsObjectSafety.INTERFACESAFE_FOR_UNTRUSTED_CALLER;
pdwEnabledOptions = CLsObjectSafety.INTERFACESAFE_FOR_UNTRUSTED_DATA;
}
public void SetInterfaceSafetyOptions(System.Int32 riid,System.Int32 dwOptionsSetMask,System.Int32 dwEnabledOptions)
{
}
只要這麼些,就不會再有討厭的對話方塊彈出了。
如果你的元件是在客戶端,在瀏覽器中呼叫,那麼所有的工作已經完成;所以是希望透過Codebase的方式釋出,你還需要去搞一個數字簽字,已經不是本文討論的範圍了,就到這裡,結束了。
參考文件
1、HOWTO: Implement IObjectSafety in Controls(.com/default.x?scid=kb;EN-US;q182598">)
2、Exposing Components to (/html/cpconexposietframeworkcomponentstocom.asp">)
3、System.Runtime.InteropServices()
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752019/viewspace-962632/,如需轉載,請註明出處,否則將追究法律責任。
請登入後發表評論
登入
全部評論
相關文章
- COM 物件 和 介面 (轉)物件
- MFC對COM介面編寫的支援分析 (轉)
- Activex控制元件的IObjectSafety介面問題控制元件Object
- VC開發多語言介面支援----INI實現(轉)
- 讓 @HystrixCommand 支援Spring EL實現動態更新commandKey,groupKey,threadPoolKeySpringthread
- Comparable介面的實現和使用
- rhel 6.5讓KVM支援中文介面
- dotnet 委託的實現解析
- ActiveX學習筆記二 ActiveX在IE中安全級別問題-實現IObjectSafety介面筆記Object
- JAVA 將介面的引用指向實現類的物件Java物件
- Lock物件Condition介面實現等待/通知物件
- jQuery物件和DOM物件之間的轉換實現jQuery物件
- Missing Microsoft.CompactFramework.CSharp.targetsROSFrameworkCSharp
- DotNet Dictionary 實現簡介
- 『現學現忘』Git物件 — 17、Commit物件Git物件MIT
- 讓VC++支援中文 (轉)C++
- Python實現支援JSON儲存和解析的物件PythonJSON物件
- Metasploit技巧命令支援tips
- ASP實現多語言支援 (轉)
- 程式介面多模式顯示的實現 (轉)模式
- 使用 RxJs 實現一個支援 infinite scroll 的 Angular ComponentJSAngular
- 【轉】【譯】讓你的網站更炫酷的一些小 tips網站
- 從java內建類和自定義類比較Comparable介面和Comparator介面實現排序的不同Java排序
- keycloak~正確讓api介面支援跨域API跨域
- 讓WPS Office也能實現多語言支援
- 高效能USB轉串列埠介面卡,讓USB和序列介面輕鬆實現雙向通訊!串列埠
- 用C#建立COM物件 (轉)C#物件
- 讓你的Mozilla支援XML資料島 (轉)XML
- 讓VisualBasic實現隱藏Mouse (轉)
- C#動態建立介面的實現例項物件C#物件
- DDD的實體、值物件、聚合根的基類和介面:設計與實現物件
- 從現場實施到技術支援的轉折
- Dotnet Core多版本API共存的優雅實現API
- 使用Microsoft Agent的COM介面程式設計(轉)ROS程式設計
- .net webapi 實現 介面版本控制並打通swagger支援WebAPISwagger
- [WPF] 離線環境實現支援拼音模糊搜尋的AutoCompleteBox
- 使用ATL建立支援IClassFactory2的COM元件 (轉)元件
- 讓linux支援你的DMA66硬碟(轉)Linux硬碟