是否可以将 ActiveX 对象标记为安全以便无需更改 IE 设置?
Posted
技术标签:
【中文标题】是否可以将 ActiveX 对象标记为安全以便无需更改 IE 设置?【英文标题】:Is it possible to mark an ActiveX object as safe so that IE settings need not be changed? 【发布时间】:2014-01-15 11:29:04 【问题描述】:我创建了一个启动应用程序的 ActiveX dll 程序集。我在浏览器中通过 javascript 调用了这个 dll。该应用程序在点击 URL 时启动。
要让这个脚本工作,我需要进入 IE 设置并启用“初始化和脚本未标记为安全的 activex 控件”。有没有办法对 ActiveX 对象进行编码以将其标记为安全?
我用SN工具生成了一个key(.snk文件),用这个key编译了DLL。因此,该 dll 已签名,但它不会运行,除非我在 IE 设置中启用“初始化并编写未标记为安全的脚本 Activex 控件”。
这是我已经实现并希望将其标记为安全的文章:- Writing an ActiveX control in C#。
我在 this microsoft link:-
上获得了对安全控制概念 (IObjectSafety) 的参考我无法理解该代码需要放在哪里。任何帮助都会使其更清楚..
【问题讨论】:
【参考方案1】:我从不同的地方收集了一些代码(和知识),这是我的工作版本 - 界面:
[Serializable, ComVisible(true)]
public enum ObjectSafetyOptions
INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001,
INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002,
INTERFACE_USES_DISPEX = 0x00000004,
INTERFACE_USES_SECURITY_MANAGER = 0x00000008
//
// MS IObjectSafety Interface definition
//
[
ComImport(),
Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
]
public interface IObjectSafety
[PreserveSig]
long GetInterfaceSafetyOptions(ref Guid iid, out int pdwSupportedOptions, out int pdwEnabledOptions);
[PreserveSig]
long SetInterfaceSafetyOptions(ref Guid iid, int dwOptionSetMask, int dwEnabledOptions);
和实施:
#region safe for scripting
private ObjectSafetyOptions m_options = ObjectSafetyOptions.INTERFACESAFE_FOR_UNTRUSTED_CALLER | ObjectSafetyOptions.INTERFACESAFE_FOR_UNTRUSTED_DATA;
public long GetInterfaceSafetyOptions(ref Guid iid, out int pdwSupportedOptions, out int pdwEnabledOptions)
pdwSupportedOptions = (int)m_options;
pdwEnabledOptions = (int)m_options;
return 0;
public long SetInterfaceSafetyOptions(ref Guid iid, int dwOptionSetMask, int dwEnabledOptions)
return 0;
#endregion safe for scripting
现在 IE 不会用确认对话框来唠叨我了。
【讨论】:
【参考方案2】:以下链接有一个完美的示例,它是创建以及将 activeX 控件标记为安全的答案:-Creating activex objects with c#
用c#创建activex对象
本指南的目的是提供简单的步骤 创建一个可以在 IE 中加载和使用的简单 ActiveX 控件 托管网页。
背景
ActiveX 是一种 Microsoft 技术,用于创建 可重复使用的组件。这种技术,也称为对象链接和嵌入 (OLE) 以及 COM 在 Microsoft 环境中被大量使用,并且 应用程序开发。在本文中,我将使用该术语 COM 包含所有类似的 Microsoft 相关技术:ActiveX、OLE、 自动化等……因为它是创建组件的框架。任何人 对创建可重用组件感兴趣的应该熟悉 通讯。一个非常好的资源是 Don Box 的“Essential COM”。
COM 背后的想法是允许创建组件 可以被各种客户消费。这意味着我可以创建一个 使用 C++ 的组件,然后可以由用 VB 编写的应用程序使用,或 甚至是我们将很快执行的网页。传统上,ActiveX 对象通常用 C++ 和 VB 编写,但实际上可以用任何 语言,只要它们能够识别 COM。
这意味着我们可以使用 .NET 创建 COM 对象 平台。和 large 只告诉你如何通过 Interop 使用非托管 COM 对象。所以我的目标 本指南旨在展示如何使用这个强大的功能。另外,仅供参考,有 一种 .NET 技术,与下面将要描述的非常相似,它允许 在 IE 中托管 Windows 窗体控件(不知道官方术语/名称 为此)。
废话不多说,让我们开始示例吧。
要求
熟悉 C#。开发环境。我将使用 Visual Studio
-
(2003 应该也可以。不过不知道速成版。)
html、Javascript
IE。 ActiveX 对象不能托管在任何其他 浏览器。创建 ActiveX 控件
第一步是创建一个 C# DLL 项目。这可以是 完成以下步骤:
-
启动 Visual Studio
选择文件 -> 新建项目
为项目类型选择“其他语言”->“Visual C#”
选择“类库”模板
创建项目后,继续重命名 Class1.cs 随心所欲。我将其重命名为 HelloControl.cs
我们将创建的 ActiveX 控件是无处不在的 你好世界!代码和解释如下。
HelloControl.cs
using System;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Collections.Generic;
using System.Text;
namespace csharp.activex.sample
/// <summary>
/// A very simple interface to test ActiveX with.
/// </summary>
[
Guid( "E86A9038-368D-4e8f-B389-FDEF38935B2F"),
InterfaceType( ComInterfaceType.InterfaceIsDual),
ComVisible( true)
]
public interface IHello
[DispId(1)]
string Hello();
[DispId(2)]
int ShowDialog(string msg);
;
[
Guid("873355E1-2D0D-476f-9BEF-C7E645024C32"),
// This is basically the programmer friendly name
// for the guid above. We define this because it will
// be used to instantiate this class. I think this can be
// whatever you want. Generally it is
// [assemblyname].[classname]
ProgId("csharpAx.CHello"),
// No class interface is generated for this class and
// no interface is marked as the default.
// Users are expected to expose functionality through
// interfaces that will be explicitly exposed by the object
// This means the object can only expose interfaces we define
ClassInterface(ClassInterfaceType.None),
// Set the default COM interface that will be used for
// Automation. Languages like: C#, C++ and VB
// allow to query for interface's we're interested in
// but Automation only aware languages like javascript do
// not allow to query interface(s) and create only the
// default one
ComDefaultInterface(typeof(IHello)),
ComVisible(true)
]
public class CHello : IHello
#region [IHello implementation]
public string Hello()
return "Hello from CHello object";
public int ShowDialog(string msg)
System.Windows.Forms.MessageBox.Show(msg, "");
return 0;
#endregion
;
HelloControl.cs 文件由一个类和一个接口组成。 那么让我们从接口定义开始,接着是 CHello 类。
IHello 接口
接口通常被描述为契约。一旦设计了界面 并发布使用它不应该改变。让我重复一遍,它 永远不会改变。
已经为这个接口定义了几个属性。
1) Guid – 这是一个唯一标识符。使用 guidgen.exe 生成自己的 2) InterfaceType – 这决定了向 COM 公开哪个基类。
InterfaceType 属性需要进一步解释。这是它的定义方式。
public enum ComInterfaceType
InterfaceIsDual = 0,
InterfaceIsIUnknown = 1,
InterfaceIsIDispatch = 2,
所有 COM 接口和对象必须至少继承 IUnknown 接口(见附录 A)。该接口允许客户端创建 COM 对象通过 CoCreateInstance() 并搜索其他接口以及 处理对象生命周期管理。
IDispatch 接口只允许在自动化感知中使用对象 像javascript这样的语言(见附录B)。这个接口,允许客户端 应用程序来查询对象在运行时支持的属性和方法- 时间并执行它们。这很像 .Net 中的反射。
Dual 仅表示上述两者的组合。这样做的主要原因是 允许在没有 IDispatch 的所有开销的情况下创建接口 在不需要的情况下。
最后,您会注意到 IHello 中每个方法的 DispId(#) 属性 界面。从 IDispatch 接口调用 Invoke 时需要这样做。
CHello 类
最后要讨论的是 CHello 类。这个类简单实现 IHello 接口仅此而已。 ShowDialog() 只是表明我们可以 执行需要某种 UI 的对象,在本例中为消息框。 属性在 cmets 中进行了描述。
编译和注册
编写完代码后,继续编译 ActiveX 程序集。 该程序集将在项目的 bin 文件夹中称为 [projectname].dll。
下一步是注册。这样做会打开一个命令提示符并转到 dll的位置。注册程序集类型:
C:\Regasm [项目名称].dll /codebase /tlb
确保将“[projectname]”替换为您的 dll 的正确名称。 您应该得到一些输出,表明程序集已正确导出。 类似于以下内容。
Microsoft ® .NET Framework 程序集注册实用程序 2.0.50727.42 版权所有 © 微软公司 1998-2004。版权所有。 类型注册成功 程序集导出到 '[TLB 位置] ',类型库注册成功
要取消注册程序集,请将“/unregister”标志传递给 Regasm。您将需要 当需要对程序集进行更改时,取消注册并关闭 IE。如果你不 在进行代码更改之前取消注册您的程序集,您最终可能会得到虚假 注册表项和清理的痛苦。关闭 IE 的原因是为了确保 对您的程序集的所有引用都已被释放。
创建 HTML 测试页
我们即将完成。我们现在需要做的就是创建一个测试页面。 这应该很简单,但仍然如此。 Javascript 还提供了创建 ActiveX 对象的方法。
Test.html
<html xmlns="http://www.w3.org/1999/xhtml">
<head> <title>C# ActiveX Test</title> </head>
<body onload="myload();">
<h1>This is Our ActiveX Test Page h1>
The message from the ActiveX Control is [
<div id="axmsg"></div>
]
<script type ="text/javascript">
function myload()
var myAx = new ActiveXObject("csharpAx.CHello");
if(myAx != null)
myAx.ShowDialog("hello from asp.net");
var d = document.getElementById("axmsg");
var s = myAx.Hello();
d.outerText = s;
else
lert("NOOOO... we failed");
</script>
</body></html>
要在 Javascript 中创建我们的 ActiveX 对象,我们使用 ActiveXObject()。参数 因为这通常是我们在其定义中指定的 PROGID。如果一个 PROGID 未在其定义中指定,那么我认为您可以传入 “AssemblyName.ClassName”。其余的 javascript 只是简单地调用我们的 ActiveX 对象方法。
就是这样!!!我们应该有一个功能齐全的例子。这种执行 ActiveX 的能力 来自 javascript 的对象非常强大。关于安全的辩论和争论 ActiveX 对象的安全性是众所周知的,我不会再扔更多的饲料 到火。但是,想象一下创建一个 Win32 甚至是 Winform 应用程序 UI 是通过 IWebBrowser2 用 HTML 编写的,并且所有 UI 交互都已处理 与您的 ActiveX 对象,只是深思熟虑。虽然,现在想起来, WPF 已经在这样做了。哦,好吧。
希望这份关于如何使用 C# 创建 ActiveX 对象的指南对您有所帮助。
-skaoth-
进一步修改
上面的例子虽然完整(希望没有错误),但有一个小问题。当html页面是 加载后我们得到一个讨厌的消息框说
“此页面上的 ActiveX 控件可能不安全……等等等等”
那么我们该如何解决这个问题呢?好吧,这真的很简单。我们需要实现一个接口 称为 IObjectSafety。为此,请将新的 .cs 文件添加到项目中。
IObjectSafety.cs
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Text;
namespace csharp.activex.sample
[
Serializable,
ComVisible(true)
]
public enum ObjectSafetyOptions
INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001,
INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002,
INTERFACE_USES_DISPEX = 0x00000004,
INTERFACE_USES_SECURITY_MANAGER = 0x00000008
;
//
// MS IObjectSafety Interface definition
//
[
ComImport(),
Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064"),
InterfaceType(ComInterfaceType.InterfaceIsIUnknown)
]
public interface IObjectSafety
[PreserveSig]
long GetInterfaceSafetyOptions( ref Guid iid, out int pdwSupportedOptions, out int pdwEnabledOptions);
[PreserveSig]
long SetInterfaceSafetyOptions( ref Guid iid, int dwOptionSetMask, int dwEnabledOptions);
;
//
// Provides a default Implementation for
// safe scripting.
// This basically means IE won't complain about the
// ActiveX object not being safe
//
public class IObjectSafetyImpl : IObjectSafety
private ObjectSafetyOptions m_options =
ObjectSafetyOptions.INTERFACESAFE_FOR_UNTRUSTED_CALLER |
ObjectSafetyOptions.INTERFACESAFE_FOR_UNTRUSTED_DATA;
#region [IObjectSafety implementation]
public long GetInterfaceSafetyOptions( ref Guid iid, out int pdwSupportedOptions, out int pdwEnabledOptions)
pdwSupportedOptions = (int)m_options;
pdwEnabledOptions = (int)m_options;
return 0;
public long SetInterfaceSafetyOptions(ref Guid iid, int dwOptionSetMask, int dwEnabledOptions)
return 0;
#endregion
;
然后修改CHello对象,使其继承自IObjectSafetyImpl 类,使其看起来像
public class CHello : IObjectSafetyImpl, IHello
…
;
这样,关于 ActiveX 对象不安全的对话框应该会消失。
参考文献
ATL 内部 - Brent E. Rector,Chris Sells。 Essential COM – Don Box。
http://msdn2.microso...yw6(VS.80).aspx http://msdn2.microso...y/aa768224.aspx http://www.c-sharpco...tiveXInNet.aspx
附录 A:未知
interface IUnknown
virtual HRESULT QueryInterface(REFIID riid, void **ppvObject) = 0;
virtual ULONG AddRef(void) = 0;
virtual ULONG Release(void) = 0;
;
附录 B:IDispatch
interface IDispatch : public IUnknown
virtual ULONG GetTypeInfoCount(unsigned int FAR* pctinfo) = 0;
virtual HRESULT GetTypeInfo(unsigned int iTInfo, LCID lcid, ITypeInfo FAR* FAR* ppTInfo ) = 0;
virtual ULONG GetIDsOfNames(
REFIID riid,
OLECHAR FAR* FAR* rgszNames,
unsigned int cNames,
LCID lcid,
DISPID FAR* rgDispId) = 0;
virtual ULONG Invoke(
DISPID dispIdMember,
REFIID riid,
LCID lcid,
WORD wFlags,
DISPPARAMS FAR* pDispParams,
VARIANT FAR* pVarResult,
EXCEPINFO FAR* pExcepInfo,
unsigned int FAR* puArgErr) = 0;
;
【讨论】:
贴出的链接建议的解决方案对我不起作用,我还是要修改IE配置以上是关于是否可以将 ActiveX 对象标记为安全以便无需更改 IE 设置?的主要内容,如果未能解决你的问题,请参考以下文章