用C#开发ActiveX控件我主要参考红马的三篇文章,入门都是按照其文章上的步骤来的,几乎没有什么问题。但是要注意的是文章中的实现IObjectSafety接口有些问题,实现其接口后还是弹出窗口说ActiveX控件不是安全的。网上有正确的实现方法,我将其整理如下如下:
1
[ComImport, GuidAttribute("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]2
[InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]3
interface IObjectSafety4
{5
[PreserveSig]6
int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);7
[PreserveSig()]8
int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);9
}10

然后让你的ActiveX控件实现其接口,代码如下:
1
#region 实现IObjectSafety接口2
private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";3
private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";4
private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";5
private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";6
private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}";7

8
private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;9
private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;10
private const int S_OK = 0;11
private const int E_FAIL = unchecked((int)0x80004005);12
private const int E_NOINTERFACE = unchecked((int)0x80004002);13

14
private bool _fSafeForScripting = true;15
private bool _fSafeForInitializing = true;16
//使ActiveX控件成为安全的控件17
public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)18
{19
int Rslt = E_FAIL;20
string strGUID = riid.ToString("B");21
pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;22
switch (strGUID)23
{24
case _IID_IDispatch:25
case _IID_IDispatchEx:26
Rslt = S_OK;27
pdwEnabledOptions = 0;28
if (_fSafeForScripting == true)29
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;30
break;31
case _IID_IPersistStorage:32
case _IID_IPersistStream:33
case _IID_IPersistPropertyBag:34
Rslt = S_OK;35
pdwEnabledOptions = 0;36
if (_fSafeForInitializing == true)37
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;38
break;39
default:40
Rslt = E_NOINTERFACE;41
break;42
}43

44
return Rslt;45
}46

47
public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)48
{49
int Rslt = E_FAIL;50

51
string strGUID = riid.ToString("B");52
switch (strGUID)53
{54
case _IID_IDispatch:55
case _IID_IDispatchEx:56
if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true))57
Rslt = S_OK;58
break;59
case _IID_IPersistStorage:60
case _IID_IPersistStream:61
case _IID_IPersistPropertyBag:62
if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true))63
Rslt = S_OK;64
break;65
default:66
Rslt = E_NOINTERFACE;67
break;68
}69

70
return Rslt;71
}72
#endregion73

到此为止,用C#开发ActiveX控件基本上算是完成了,通过IE查看,可以看到效果。细节部分我没有写全,如有需要,可以参考红马文章:
http://www.cnblogs.com/homer/archive/2005/01/04/86473.html
http://www.cnblogs.com/homer/archive/2005/01/08/88780.html
http://www.cnblogs.com/homer/archive/2005/01/26/97822.html


