http://www.cnblogs.com/RCFans/archive/2009/06/26/1333982.html
ActiveX控件开发 要使用C#实现一个ActiveX控件,需要解决三个问题: 1.使.NET组件能够被COM调用 2.在客户机上注册后,ActiveX控件能通过IE的安全认证3.未在客户机上注册时,安装包能通过IE的签名认证 本程序的开发环境是.NET Framework 3.5,工具是Visual Studio .NET 2008,在安装.NET Framework 3.5的客户机上通过测试。 下面是实现步骤: (一)创建可从COM访问的程序集 首先实现一个对COM可见的程序集,创建类库工程,AssemblyInfo.cs应包含: using System.Runtime.InteropServices;//使此程序集中的类型对COM组件可见
[assembly: ComVisible(true)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("94882155-3B7C-48e3-B357-234D56D8F15E")]
加入以下代码到AssemblyInfo.cs确保程序集的可访问性:using System.Security;[assembly: AllowPartiallyTrustedCallers()]
注意上面的Guid,如果程序集内部的类未标注Guid,COM注册的Guid是会新生成的,此处的Guid没有作用。创建用户控件(自定义类待测)IdentityKey.cs,加入:using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;namespace KeyActiveX
{
[Guid("94882155-3B7C-48e3-B357-234D56D8F15E")]
public partial class IdentityKey : UserControl
{
}
}这里的Guid和AssemblyInfo.cs一样,它会在COM注册中成为CLSID并被html以clsid调用。类库工程属性中,选择生成,勾选COM注册,在html文件中加入<object id="controlbyid" classid="clsid:{94882155-3B7C-48e3-B357-234D56D8F15E}" ></object>
在IE中启用不安全控件,查看html页面,应能访问到控件,现在一个在发布时对COM注册的程序集开发完成了。使用OLE/COM Object Viewer(安装VC自带)可以在.NET Categories中查看组件和CLSID。 (二)通过IE安全控件认证如果客户机的IE未开启访问非安全标记的ActiveX控件,通过IE浏览上面的步骤开发出的ActiveX控件,发现IE会给出警告:此页上的 ActiveX 对象可能不安全的。 要允许它将初始化并通过脚本访问吗?或禁止访问。这是客户机IE的安全规则设置的,我们应该在控件开发上解决IE安全认证的问题。首先我们要了解IE是如何判断一个ActiveX控件是不安全的,参见Microsoft帮助和支持文档:How Internet Explorer Determines If ActiveX Controls Are Safe There are two ways to a control as safe for scripting and initialization: 1.Implement the IObjectSafety interface. 2.Provide the following registry keys for the control's CLSID under the Implemented Categories section: a.The following key s the control safe for scripting:
{7DD95801-9882-11CF-9FA9-00AA006C42C4} b.The following key s the control safe for initialization from persistent data:
{7DD95802-9882-11CF-9FA9-00AA006C42C4} Microsoft recommends that you implement IObjectSafety to a control as safe or unsafe. This prevents other users from repackaging your control and ing it as safe when it is not.我决定实现IObjectSafety接口来向IE表明ActiveX控件的安全标识,以保证控件再次打包时安全标识不会被被改写。IObjectSafety是一个COM下的接口,对于C++程序来说,只需要实现它就行了,而.NET之下没有这个接口,在这种情况下,我们的ActiveX控件就是一个不带类型库的COM组件,必须使用C#代码重新定义COM接口。这里需要了解一点COM的接口知识。接口是COM的核心,它区分了在客户和对象之间使用的契约和实现。COM的接口有三种类型:定制接口÷分派接口和双重接口。.NET Framework使用ComInterfaceType对它进行了重定义:
namespace System.Runtime.InteropServices
{
// 摘要:
// Identifies how to expose an interface to COM.
[Serializable]
[ComVisible(true)]
public enum ComInterfaceType
{
// 摘要:
// Indicates the interface is exposed to COM as a dual interface, which enables
// both early and late binding. System.Runtime.InteropServices.ComInterfaceType.InterfaceIsDual
// is the default value.
InterfaceIsDual = 0,
//
// 摘要:
// Indicates an interface is exposed to COM as an IUnknown -derived interface,
// which enables only early binding.
InterfaceIsIUnknown = 1,
//
// 摘要:
// Indicates an interface is exposed to COM as a dispinterface, which enables
// late binding only.
InterfaceIsIDispatch = 2,
}
}
关于三个接口的具体描述,可以参考《C#高级编程第三版》28.1.3 接口。在MSDN上查找,可以知道IObjectSafety继承自IUnknown,是一个定制接口;通过上一章节,可以发现向COM注册时,需要提供一个Guid作为CLSID来标识程序集中的C#类,事实上在COM中,接口和类型库都是带有Guid作为唯一标识的,分别为IID和typelib id。这样,通过在C#编写的接口标上需要的COM接口IID,就可以在注册是向COM表明接口身份了。在Microsoft帮助上查找IObjectSafety定义: [
uuid(C67830E0-D11D-11cf-BD80-00AA00575603),
helpstring("VB IObjectSafety Interface"),
version(1.0)
]
library IObjectSafetyTLB
{
importlib("stdole2.tlb");
[
uuid(CB5BDC81-93C1-11cf-8F20-00805F2CD064),
helpstring("IObjectSafety Interface"),
odl
]
interface IObjectSafety:IUnknown {
[helpstring("GetInterfaceSafetyOptions")]
HRESULT GetInterfaceSafetyOptions(
[in] long riid,
[in] long *pdwSupportedOptions,
[in] long *pdwEnabledOptions); [helpstring("SetInterfaceSafetyOptions")]
HRESULT SetInterfaceSafetyOptions(
[in] long riid,
[in] long dwOptionsSetMask,
[in] long dwEnabledOptions);
}
}
其中的uuid(CB5BDC81-93C1-11cf-8F20-00805F2CD064)就是需要的接口IID。使用C#编写IObjectSafety:using System;
using System.Runtime.InteropServices;namespace KeyActiveX
{
[ComImport, Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
[PreserveSig]
void GetInterfacceSafyOptions(
int riid,
out int pdwSupportedOptions,
out int pdwEnabledOptions); [PreserveSig]
void SetInterfaceSafetyOptions(
int riid,
int dwOptionsSetMask,
int dwEnabledOptions);
}
}
InterfaceType中一定要使用ComInterfaceType.InterfaceIsIUnknown,因为IObjectSafety继承自IUnkown。接下来是KeyActiveX的接口实现:namespace KeyActiveX
{
[Guid("94882155-3B7C-48e3-B357-234D56D8F15E")]
public partial class IdentityKey : UserControl, IObjectSafety
{
#region IObjectSafety 成员 public void GetInterfacceSafyOptions(int riid, out int pdwSupportedOptions, out int pdwEnabledOptions)
{
pdwSupportedOptions = 1;
pdwEnabledOptions = 2;
} public void SetInterfaceSafetyOptions(int riid, int dwOptionsSetMask, int dwEnabledOptions)
{
throw new NotImplementedException();
} #endregion
}
}通过返回一个已定值来告诉IE控件是安全的。具体参见如何在 VisualBasic 控件实现 IObjectSafety (三)签名发布C#开发的ActiveX控件发布方式有三种:制作客户端安装包,分发给客户机安装;
制作在线安装包,客户机联机安装;
使用html中object的codebase指向安装包地址。
前两个比较简单,适合在局域网内实施,生成安装包时需要装Register属性设置为vsdrpCOM;最后一种方式,需要在安装包上进行数字签名,以保证客户机的安全信任。受信任的签名证书应该向证书提供商(如Versign)购买,然后使用签名工具对安装包进行签名。下面利用Visual Studio 2008自带的测试证书创建工具MakeCert和签名工具SignTool进行测试,首先创建一个带有公司信息的测试证书,在Visual Studio命令提示符后输入:makecert -sk ABC -n "CN=ABC Corporation" f:\abccorptest.cer
在F盘上创建了测试证书。然后输入signtool signwizard
在Signing Options页面上,选择Custom,定义证书文件的位置,再下一步选择一个加密算法(MD5或SHA1),指定应用程序的名称和描述URL,确认。此时ActiveX控件安装包有了一个被标记为未信任的测试证书,需要将IE设置为启用未信任安装程序,在html中引用<object id="controlbyid" classid="clsid:{94882155-3B7C-48e3-B357-234D56D8F15E}" codebase="setup.exe" ></object>
客户机安装之后就可以使用ActiveX控件了。
ActiveX控件开发 要使用C#实现一个ActiveX控件,需要解决三个问题: 1.使.NET组件能够被COM调用 2.在客户机上注册后,ActiveX控件能通过IE的安全认证3.未在客户机上注册时,安装包能通过IE的签名认证 本程序的开发环境是.NET Framework 3.5,工具是Visual Studio .NET 2008,在安装.NET Framework 3.5的客户机上通过测试。 下面是实现步骤: (一)创建可从COM访问的程序集 首先实现一个对COM可见的程序集,创建类库工程,AssemblyInfo.cs应包含: using System.Runtime.InteropServices;//使此程序集中的类型对COM组件可见
[assembly: ComVisible(true)]
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
[assembly: Guid("94882155-3B7C-48e3-B357-234D56D8F15E")]
加入以下代码到AssemblyInfo.cs确保程序集的可访问性:using System.Security;[assembly: AllowPartiallyTrustedCallers()]
注意上面的Guid,如果程序集内部的类未标注Guid,COM注册的Guid是会新生成的,此处的Guid没有作用。创建用户控件(自定义类待测)IdentityKey.cs,加入:using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Runtime.InteropServices;namespace KeyActiveX
{
[Guid("94882155-3B7C-48e3-B357-234D56D8F15E")]
public partial class IdentityKey : UserControl
{
}
}这里的Guid和AssemblyInfo.cs一样,它会在COM注册中成为CLSID并被html以clsid调用。类库工程属性中,选择生成,勾选COM注册,在html文件中加入<object id="controlbyid" classid="clsid:{94882155-3B7C-48e3-B357-234D56D8F15E}" ></object>
在IE中启用不安全控件,查看html页面,应能访问到控件,现在一个在发布时对COM注册的程序集开发完成了。使用OLE/COM Object Viewer(安装VC自带)可以在.NET Categories中查看组件和CLSID。 (二)通过IE安全控件认证如果客户机的IE未开启访问非安全标记的ActiveX控件,通过IE浏览上面的步骤开发出的ActiveX控件,发现IE会给出警告:此页上的 ActiveX 对象可能不安全的。 要允许它将初始化并通过脚本访问吗?或禁止访问。这是客户机IE的安全规则设置的,我们应该在控件开发上解决IE安全认证的问题。首先我们要了解IE是如何判断一个ActiveX控件是不安全的,参见Microsoft帮助和支持文档:How Internet Explorer Determines If ActiveX Controls Are Safe There are two ways to a control as safe for scripting and initialization: 1.Implement the IObjectSafety interface. 2.Provide the following registry keys for the control's CLSID under the Implemented Categories section: a.The following key s the control safe for scripting:
{7DD95801-9882-11CF-9FA9-00AA006C42C4} b.The following key s the control safe for initialization from persistent data:
{7DD95802-9882-11CF-9FA9-00AA006C42C4} Microsoft recommends that you implement IObjectSafety to a control as safe or unsafe. This prevents other users from repackaging your control and ing it as safe when it is not.我决定实现IObjectSafety接口来向IE表明ActiveX控件的安全标识,以保证控件再次打包时安全标识不会被被改写。IObjectSafety是一个COM下的接口,对于C++程序来说,只需要实现它就行了,而.NET之下没有这个接口,在这种情况下,我们的ActiveX控件就是一个不带类型库的COM组件,必须使用C#代码重新定义COM接口。这里需要了解一点COM的接口知识。接口是COM的核心,它区分了在客户和对象之间使用的契约和实现。COM的接口有三种类型:定制接口÷分派接口和双重接口。.NET Framework使用ComInterfaceType对它进行了重定义:
namespace System.Runtime.InteropServices
{
// 摘要:
// Identifies how to expose an interface to COM.
[Serializable]
[ComVisible(true)]
public enum ComInterfaceType
{
// 摘要:
// Indicates the interface is exposed to COM as a dual interface, which enables
// both early and late binding. System.Runtime.InteropServices.ComInterfaceType.InterfaceIsDual
// is the default value.
InterfaceIsDual = 0,
//
// 摘要:
// Indicates an interface is exposed to COM as an IUnknown -derived interface,
// which enables only early binding.
InterfaceIsIUnknown = 1,
//
// 摘要:
// Indicates an interface is exposed to COM as a dispinterface, which enables
// late binding only.
InterfaceIsIDispatch = 2,
}
}
关于三个接口的具体描述,可以参考《C#高级编程第三版》28.1.3 接口。在MSDN上查找,可以知道IObjectSafety继承自IUnknown,是一个定制接口;通过上一章节,可以发现向COM注册时,需要提供一个Guid作为CLSID来标识程序集中的C#类,事实上在COM中,接口和类型库都是带有Guid作为唯一标识的,分别为IID和typelib id。这样,通过在C#编写的接口标上需要的COM接口IID,就可以在注册是向COM表明接口身份了。在Microsoft帮助上查找IObjectSafety定义: [
uuid(C67830E0-D11D-11cf-BD80-00AA00575603),
helpstring("VB IObjectSafety Interface"),
version(1.0)
]
library IObjectSafetyTLB
{
importlib("stdole2.tlb");
[
uuid(CB5BDC81-93C1-11cf-8F20-00805F2CD064),
helpstring("IObjectSafety Interface"),
odl
]
interface IObjectSafety:IUnknown {
[helpstring("GetInterfaceSafetyOptions")]
HRESULT GetInterfaceSafetyOptions(
[in] long riid,
[in] long *pdwSupportedOptions,
[in] long *pdwEnabledOptions); [helpstring("SetInterfaceSafetyOptions")]
HRESULT SetInterfaceSafetyOptions(
[in] long riid,
[in] long dwOptionsSetMask,
[in] long dwEnabledOptions);
}
}
其中的uuid(CB5BDC81-93C1-11cf-8F20-00805F2CD064)就是需要的接口IID。使用C#编写IObjectSafety:using System;
using System.Runtime.InteropServices;namespace KeyActiveX
{
[ComImport, Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
[PreserveSig]
void GetInterfacceSafyOptions(
int riid,
out int pdwSupportedOptions,
out int pdwEnabledOptions); [PreserveSig]
void SetInterfaceSafetyOptions(
int riid,
int dwOptionsSetMask,
int dwEnabledOptions);
}
}
InterfaceType中一定要使用ComInterfaceType.InterfaceIsIUnknown,因为IObjectSafety继承自IUnkown。接下来是KeyActiveX的接口实现:namespace KeyActiveX
{
[Guid("94882155-3B7C-48e3-B357-234D56D8F15E")]
public partial class IdentityKey : UserControl, IObjectSafety
{
#region IObjectSafety 成员 public void GetInterfacceSafyOptions(int riid, out int pdwSupportedOptions, out int pdwEnabledOptions)
{
pdwSupportedOptions = 1;
pdwEnabledOptions = 2;
} public void SetInterfaceSafetyOptions(int riid, int dwOptionsSetMask, int dwEnabledOptions)
{
throw new NotImplementedException();
} #endregion
}
}通过返回一个已定值来告诉IE控件是安全的。具体参见如何在 VisualBasic 控件实现 IObjectSafety (三)签名发布C#开发的ActiveX控件发布方式有三种:制作客户端安装包,分发给客户机安装;
制作在线安装包,客户机联机安装;
使用html中object的codebase指向安装包地址。
前两个比较简单,适合在局域网内实施,生成安装包时需要装Register属性设置为vsdrpCOM;最后一种方式,需要在安装包上进行数字签名,以保证客户机的安全信任。受信任的签名证书应该向证书提供商(如Versign)购买,然后使用签名工具对安装包进行签名。下面利用Visual Studio 2008自带的测试证书创建工具MakeCert和签名工具SignTool进行测试,首先创建一个带有公司信息的测试证书,在Visual Studio命令提示符后输入:makecert -sk ABC -n "CN=ABC Corporation" f:\abccorptest.cer
在F盘上创建了测试证书。然后输入signtool signwizard
在Signing Options页面上,选择Custom,定义证书文件的位置,再下一步选择一个加密算法(MD5或SHA1),指定应用程序的名称和描述URL,确认。此时ActiveX控件安装包有了一个被标记为未信任的测试证书,需要将IE设置为启用未信任安装程序,在html中引用<object id="controlbyid" classid="clsid:{94882155-3B7C-48e3-B357-234D56D8F15E}" codebase="setup.exe" ></object>
客户机安装之后就可以使用ActiveX控件了。
解决方案 »
- SessionFactory工厂类
- 求助:VS2008设计窗口拖控件的问题,让我很抓狂
- 在水晶报表中使有图片(大小每次都只能固定在2.54cm X 2.54cm大小)
- [咨询]关于VS2005里装上的AJAX工具包的具体使用方法在哪里有说明?
- DataBinder.Eval()最后一个参数
- 小弟第一次用Nhibernate就出现了问题,请大哥们帮忙看一下是什么错误
- 如何获得项目当前文件的工作目录的路径???????
- 表单提交的问题
- 请推荐一个好的.NET空间
- 请问一各位水兄水妹,从ASP转向ASP.NET要做些什么,有那些不同点需要注意的?
- repeater如何绑定两个数据库?
- 谁有dotnettextbox的源代码,发给我好吗?
using System;
using System.Runtime.InteropServices;namespace KeyActiveX
{
[ComImport, Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
[PreserveSig]
void GetInterfacceSafyOptions(
int riid,
out int pdwSupportedOptions,
out int pdwEnabledOptions); [PreserveSig]
void SetInterfaceSafetyOptions(
int riid,
int dwOptionsSetMask,
int dwEnabledOptions);
}
}
InterfaceType中一定要使用ComInterfaceType.InterfaceIsIUnknown,因为IObjectSafety继承自IUnkown。接下来是KeyActiveX的接口实现:
namespace KeyActiveX
{
[Guid("94882155-3B7C-48e3-B357-234D56D8F15E")]
public partial class IdentityKey : UserControl, IObjectSafety
{
#region IObjectSafety 成员 public void GetInterfacceSafyOptions(int riid, out int pdwSupportedOptions, out int pdwEnabledOptions)
{
pdwSupportedOptions = 1;
pdwEnabledOptions = 2;
} public void SetInterfaceSafetyOptions(int riid, int dwOptionsSetMask, int dwEnabledOptions)
{
throw new NotImplementedException();
} #endregion
}
}通过返回一个已定值来告诉IE控件是安全的。
注意:網上有很多版本,根本就不能阻止IE的安全提示,大家請不要使用。
比如下面這個,根本不起作用:
很多網站都是下面的代碼,根本就不起作用,請大家不要使用!!!!
使用C#编写IObjectSafety: using System;
using System.Runtime.InteropServices; namespace KeyActiveX
{ [ComImport, Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IObjectSafety
{
[PreserveSig]
int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions); [PreserveSig]
int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);
}
}InterfaceType中一定要使用ComInterfaceType.InterfaceIsIUnknown,因为IObjectSafety继承自IUnkown。接下来是KeyActiveX的接口实现: namespace KeyActiveX
{
[Guid("94882155-3B7C-48e3-B357-234D56D8F15E")]
public partial class IdentityKey : UserControl, IObjectSafety
{
private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}"; private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
private const int S_OK = 0;
private const int E_FAIL = unchecked((int)0x80004005);
private const int E_NOINTERFACE = unchecked((int)0x80004002); private bool _fSafeForScripting = true;
private bool _fSafeForInitializing = true; #region IObjectSafety 成员 public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
{ int Rslt = E_FAIL; string strGUID = riid.ToString("B");
pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
switch (strGUID)
{
case _IID_IDispatch:
case _IID_IDispatchEx:
Rslt = S_OK;
pdwEnabledOptions = 0;
if (_fSafeForScripting == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
break;
case _IID_IPersistStorage:
case _IID_IPersistStream:
case _IID_IPersistPropertyBag:
Rslt = S_OK;
pdwEnabledOptions = 0;
if (_fSafeForInitializing == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
break;
default:
Rslt = E_NOINTERFACE;
break;
} return Rslt;
} public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
{
int Rslt = E_FAIL;
string strGUID = riid.ToString("B");
switch (strGUID)
{
case _IID_IDispatch:
case _IID_IDispatchEx:
if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_CALLER) && (_fSafeForScripting == true))
Rslt = S_OK;
break;
case _IID_IPersistStorage:
case _IID_IPersistStream:
case _IID_IPersistPropertyBag:
if (((dwEnabledOptions & dwOptionSetMask) == INTERFACESAFE_FOR_UNTRUSTED_DATA) && (_fSafeForInitializing == true))
Rslt = S_OK;
break;
default:
Rslt = E_NOINTERFACE;
break;
} return Rslt;
} #endregion
}
}
網上100%的地方都拼寫錯誤了!(請注意Safy是錯的,應該是Safety!)
不過沒有關係,只要接口和實現保持一致即可!
在此頁面上的ActiveX控件和本頁上的其它部分的交互可能不安全,您想允許這種交互嗎?想必很多朋友在用C#寫ActiveX控件的時候都會遇到這個問題!
再次提醒,您在網上檢索的時候,很多網站給出的都是3樓的寫法,包括很多知名網站,實際上,3樓的代碼根本就不起不到作用!我推測3樓的版本是在某大俠寫的,被N多網站拷貝過去,未經驗證!我的依據是5樓提到的,將Safety錯誤拼寫成Safty,每個網站都拼錯,這不是巧合吧!
所以,大家按照1樓的做法去寫,保證IE不會給出上述的提示框!!
這個網站提供的就是3樓的寫法,沒有作用,不信可以自己試試!
传送门:
http://topic.csdn.net/u/20101028/12/6aca1627-436d-4313-99e8-de9dc2ff9859.html
在用c#开发的ActiveX中调用JavaScript方法
{
pdwSupportedOptions = 1;
pdwEnabledOptions = 2;
}
pdwSupportedOptions應該等於1,pdwEnabledOptions應該等於2,這樣瀏覽器才會認爲這個ActiveX控件是安全的!
3樓錯誤的原因是:
在GetInterfaceSafetyOptions方法中,pdwSupportedOptions的運算結果是3,pdwEnabledOptions運算結果是1,這當然不會起作用了!private const string _IID_IDispatch = "{00020400-0000-0000-C000-000000000046}";
private const string _IID_IDispatchEx = "{a6ef9860-c720-11d0-9337-00a0c90dcaa9}";
private const string _IID_IPersistStorage = "{0000010A-0000-0000-C000-000000000046}";
private const string _IID_IPersistStream = "{00000109-0000-0000-C000-000000000046}";
private const string _IID_IPersistPropertyBag = "{37D84F60-42CB-11CE-8135-00AA004BB851}"; private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
private const int S_OK = 0;
private const int E_FAIL = unchecked((int)0x80004005);
private const int E_NOINTERFACE = unchecked((int)0x80004002); private bool _fSafeForScripting = true;
private bool _fSafeForInitializing = true;public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
{ int Rslt = E_FAIL; string strGUID = riid.ToString("B");
pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER | INTERFACESAFE_FOR_UNTRUSTED_DATA;
switch (strGUID)
{
case _IID_IDispatch:
case _IID_IDispatchEx:
Rslt = S_OK;
pdwEnabledOptions = 0;
if (_fSafeForScripting == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
break;
case _IID_IPersistStorage:
case _IID_IPersistStream:
case _IID_IPersistPropertyBag:
Rslt = S_OK;
pdwEnabledOptions = 0;
if (_fSafeForInitializing == true)
pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
break;
default:
Rslt = E_NOINTERFACE;
break;
} return Rslt;
}
具体文章看我那个帖子吧。
客户端环境又是比较复杂的,用c#写客户端要有.NetFramework 才能运行
所以activex控件开发一般用vb/vc 6.0/dephi写比较合适。