CSharp Tips:让DotNet实现的COM对象支持IObjectSafety接口

CSharp Tips:调用Win32 API如何处理指针类型的参数   0、前言从VB到C#,被人诟病比较多的就是交互性比较差,又集中表现在调用Win32 API上。如果说C/C++调用API只是调用函数这类轻松的活,在C#下却成了阻挡入门者的技术活。之所以产生这么大区别在于数据类型的差异,就是因为C#这类采用了“安全”的类型,我们避免了内存释放和内存访问错误的一些困扰,但是不得不面对调用API时的繁琐。有得必有失,关键看你选择了什么。在调用API时, 阅读详情
当我们实现的COM对象,或者ActiveX控件在浏览器中调用的时候,往往会出现警告框,提示不安全的控件正在运行。这是因为浏览器安全策略所限定的,浏览器认为只有“安全的对象”才能够被执行。
所谓安全的对象就是指那些不访问本地资源的对象,例如不会去读注册表,不会写文件等等。一个满足条件的对象通过支持IObjectSafety接口告诉浏览器,自己是合法的。
下面就简单的介绍一下怎么在C#中实现对于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] DWORD * 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
}
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 class MyControl : System.Windows.Forms.UserControl,IObjectSafety
实现
  // implement functions of IObjectSafety
  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)
  {
        ...    
  }
    一切正常编译通过,但是通过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);
 }
实现
  // implement functions of IObjectSafety
  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)
  {
        ...    
  }
    编译通过,不错;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);
 }
    其余代码不变,重新编译,通过;察看导出类型库,果然少了很多垃圾;调用测试页面,正确。激动中...
 
怎样让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)
  {
  }
    只要这么些,就不会再有讨厌的对话框弹出了。
 
    如果你的组件是在客户端安装,在浏览器中调用,那么所有的工作已经完成;所以是希望通过Codebase的方式下载发布,你还需要去搞一个数字签字,已经不是本文讨论的范围了,就到这里,结束了。
 
 
参考文档
1、HOWTO: Implement IObjectSafety in Visual Basic Controls ( http://support.microsoft.com/default.aspx?scid=kb;EN-US;q182598)
CSharp Tips:怎样创建COM的实例 0、前言C#总的来说不错,Framework也提供了比较丰富的类库,基本上能够满足大部分的需要。但是应用程序难免要和遗留系统打交道,比如说:API函数或者COM组件。C#在Framework环境内部怎么玩都挺好,一旦要和Framework之外的组件函数打交道就需要作一些手脚了。这里主要对在C#中调用COM组件经常遇到的集中情况进行说明。 1、引用一个COM组件,通过New创建大 阅读详情

相关推荐

CSharp Tips:使用OleDb操纵Excel文件(1)

0、前言在进行数据操作的时候经常会碰到这样的要求,“将从数据从Excel文件导入到数据库中”或者“将数据导出到Excel文件中”,这时我们不得不对Excel文件进行操作。一般情况下我们使用Excel自带的一套COM对象对Excel文件进行操作,这套对象模型的功能非常强大,不仅可以通过WorkBook、WorkSheet等一系列对象操纵每一个Cell的数据,而且还可以操作Excel界面中的窗

疾风之狼 7837

将 dotNET组件暴露给COM (下)

将 dotNET组件暴露给COM  小气的神2002-4-23 Article Type: In-Depth  难度等级:6/9        版本:2.32  AutoDispatch参数产生的类型库描述:  coclass dotNETClass {        [default] interface _dotNE

ccBoy的专栏 2353

编码系列--Base32编码的完整示例

 0、前言几年前由于做一些和加密有关的工作,所以写了几个编码的示例,包括Base32和Base24,当年示例代码写得比较随手,而且不是完整的部分,仅演示编码解码的过程,存在不少问题。Blog很少打理,发觉不少朋友对这部分比较感兴趣,不更新一下有误导大家的嫌疑呀,所以重新更新一下示例,希望对大家有帮助,同时也希望和大家讨论是否有更有效的算法。 1、完整的示例再次声明,代码中不保证没有

疾风之狼 3941

IObjectSafety (Interfaces)

 SummaryIObjectSafety is used to mark ActiveX Controls safe for scripting. C# Definition:[ComImport, GuidAttribute("CB5BDC81-93C1-11CF-8F20-00805F2CD064")][InterfaceTypeAttribute(ComInterfaceT

加菲猫的快乐生活--我的理想 795

手把手教你用西门子博图V18配置阿特拉斯PF6000拧紧枪PN通讯(附完整GSD文件与ToolsTalk配置文件)

本文详细介绍了如何使用西门子博图V18配置阿特拉斯PF6000拧紧枪的PN通讯,包括硬件连接、网络参数规划、ToolsTalk软件配置及博图工程设置。通过完整的GSD文件和配置文件,帮助工程师快速实现高精度拧紧设备与PLC的高效通讯,适用于汽车装配和电子制造等工业自动化场景。

weixin_42662293的博客 601

360可视门铃双摄版数据恢复实战:BIN文件解析与视频重组

本文详细解析了360可视门铃双摄版BIN文件的数据恢复过程,包括文件结构分析、双摄像头数据存储机制及视频重组技术。通过Python开发环境和FFmpeg工具链,成功实现了H.265视频流的解析与重组,为智能家居设备数据恢复提供了实用解决方案。

weixin_29196891的博客 908

除了委托和事件,C#中还有其他实现回调机制的方式吗?

这些方式都可以在不同的场景下实现回调机制,开发者可以根据具体的需求和代码的简洁性、可读性等因素来选择合适的方式。

alankuo的专栏 529

Starlink vs Kuiper vs OneWeb:三大低轨卫星网络架构对比与实战应用场景解析

本文对比分析了Starlink、Kuiper和OneWeb三大低轨卫星网络架构的技术差异与商业应用场景。从轨道设计、通信性能到商业落地,详细解析了各系统在近地卫星网络领域的独特优势与挑战,为未来全球宽带服务格局提供专业见解。

weixin_29255731的博客 807

CSharp Tips:让DotNet实现的COM对象支持IObjectSafety接口 (转)

CSharp Tips:让DotNet实现的COM对象支持IObjectSafety接口 (转)[@more@]当我们实现的COM对象,或者ActiveX控件在浏览器中调用的时候,往往会出现警告框,提示不安全的控件正在运行。这是...

ciya3282的博客 185

基于STM32设计的老人防摔倒报警设备(OneNet)_65

本文设计了一种基于STM32单片机的智能老人防摔倒报警设备。该系统结合MPU6050陀螺仪传感器实时监测老人的姿态变化,检测摔倒事件;通过SIM800C通信模块发送短信通知紧急联系人,并将GPS定位信息上传至云端平台,确保家属能够及时了解老人的准确位置。

1万+

人形机器人大语言模型 pi*0.6(π*0.6):最新从经验中学习的VLA

摘要:本文介绍了一种名为Recap的机器人学习方法,通过示范训练、纠错指导和强化学习三个步骤提升机器人执行复杂任务的能力。研究显示,仅依靠模仿学习的机器人难以解决错误累积问题,而Recap方法通过价值函数可视化和优势条件策略训练,使π*0.6模型在咖啡制作、纸箱组装和衣物折叠等任务中的成功率提升超过90%,吞吐量翻倍。该方法突破了传统依赖人工演示的局限,通过自主经验学习实现机器人性能的持续优化,为未来机器人基础模型的发展提供了新方向。

2506_90492529的博客 1317

CSharp Tips:让DotNet实现的COM对象支持IObjectSafet

<!--google_ad_client = "pub-2947489232296736";/* 728x15, 创建于 08-4-23MSDN */google_ad_slot = "3624277373";google_ad_width = 728;google_ad_height = 15;//--><script type="text/javascript"

zgqtxwd的专栏 583

16、Cortex-M7处理器:高性能与复杂架构解析

本文深入解析了Cortex-M7处理器的高性能架构与复杂设计,涵盖AHB总线矩阵优化、超标量六阶段双发射流水线、增强型分支预测单元及双精度浮点支持。重点介绍了其独特的内存层次结构,包括指令与数据TCM、片上缓存和AXI-M 64位总线接口,提升系统并行性与执行效率。通过实际测试对比M4与M7性能差异,并演示如何将代码与数据定位到TCM以实现零等待运行。同时阐述了缓存机制的工作原理及其对系统性能的影响,为开发者提供全面的性能优化指导。

a1b2c3d的博客 126

IObjectSafety接口

都说ActiveX危险,那么为什么XmlHttpRequest以及MediaPlayer都是用ActiveX的方式创建的,却没有问题?原来,这是因为这些ActiveX组件都声明自己是脚本安全的,而IE的中级安全设置上,是允许脚本安全的ActiveX创建,并且不予警告的。IE怎么知道一个插件是脚本安全的?它是通过以下两个办法。一是查询ActiveX组件是否实现了IObjectSafety接口,并且返

QustDong的专栏 1516

【stm32+K210项目】基于K210与STM32协同工作的智能垃圾分类系统设计与实现(完整工程资料源码)

本系统采用SG90舵机Maix Bit摄像头STM32C8T6主控板以及LX_TRIG_MP3_V6.0语音播报模块,构建了一套高效的智能垃圾分类系统,综合运用了图像识别、语音播报及精准控制技术。SG90舵机负责控制垃圾桶的开盖操作。该舵机通过接收PWM信号来实现转动,内部有一个基准电路产生周期为20ms的PWM信号,通过外部脉冲信号的控制(高电平时间在0.5ms至2.5ms之间),使得舵机的输出轴转动到指定位置。舵机内的位置反馈电位计。

嵌入式技术开发 5099

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

再谈IObjectSafety

都说ActiveX危险,那么为什么XmlHttpRequest以及MediaPlayer都是用ActiveX的方式创建的,却没有问题?原来,这是因为这些ActiveX组件都声明自己是脚本安全的,而IE的中级安全设置上,是允许脚本安全的ActiveX创建,并且不予警告的。IE怎么知道一个插件是脚本安全的?它是通过以下两个办法。一是查询ActiveX组件是否实现了IObjectSafety接口,并

optman的专栏 2万+

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

C#学习笔记——回调机制

1.什么是回调函数 回调函数(callbackFunction),顾名思义,用于回调的函数。回调函数只是一个功能片段,由用户按照回调函数调用约定来实现的一个函数。 2.C#回调函数实现机制 ⑴定义一个回调函数; ⑵提供函数实现的一方在初始化的时候,将回调函数的实现函数委托给调用者; ⑶当特定的事件或条件发生的时候,调用者使用委托调用回调函数对事件进行处理。 3. 回调机制应用 使...

weixin_34212189的博客 688

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

C#实现接口回调

通常情况下,我们创建一个对象,并马上直接去使用它的方法。然而,在有些情况下,希望能在某个场景出现后或条件满足时才调用此对象的方法。回调就可以解决这个“延迟调用对象方法”的问题。这个被调用方法的对象称为回调对象。 实现回调的原理简介如下:         首先创建一个回调对象,然后再创建一个控制器对象,将回调对象需要被调用的方法告诉控制器对象.控制器对象负责检查某个场景是否出现或某个条件是

岁月如风的博客 2247

编码系列--Base32编码

0、写在前面这里讨论的编码主要的目的是将不可显示的二进制数组转变为可显示的字符串,包括其逆运算。通过特定的协议传输数据,或者加密解密的时候都会用到类似的方法。在这类运算中用的比较多的是Base64,比如MIME中,DotNET中更是直接提供了Base64 Encode和Decode的方法,相当方便。但是Base64通常由“a-z”、“A-Z”、0-9以及“+”和“=”这些符号组成,当中包含

疾风之狼 2万+

CSharp Tips:在Form中显示动画图片

在Windows Form的程序中有的时候需要显示动画,例如连接网络的动态图标。传统的做法可能是做一组BMP表示不同的状态,然后在Form上添加一个定时器,隔若干毫秒,绘制下一幅图片,如此循环。但是只能是BMP,没法自动支持本身有动画效果的Gif格式的图片。在DotNET中有一个ImageAnimator类,动画处理包含基于时间的帧的图像,这样的在C#中就不需要加载一组图片了,一个Gif轻松搞

疾风之狼 7664

编码系列--Base24编码

0、写在前面Windows和Office的序列号就是在最终换算之后,通过Base24编码转换成为可显示字符串的。写这个系列的目的就是做类似的东东。 1、编码原理在Base32的那篇文章中已经比较详细的说明了,这里只指出与原理相比较,Base24是一个非常奇怪的方案,因为用4个bits作为分码段,只能用到16个,另外8个编码字符用不到,而采用5个bits作为分码段,又少8个字符。这就

疾风之狼 7091

CSharp Tips:Delegate成员变量和Event的区别

简单分析了在定义类的时候,声明Delegate成员变量和Event的区别。

疾风之狼 4514
上一篇: AD & ADSI入门
下一篇: CSharp Tips:引用ActiveX/COM组件时的Strong Name
Mittermeyer
博客等级 码龄25年 60粉丝 28原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值