惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

K
Kaspersky official blog
罗磊的独立博客
F
Fortinet All Blogs
人人都是产品经理
人人都是产品经理
量子位
V
Visual Studio Blog
Blog — PlanetScale
Blog — PlanetScale
M
MIT News - Artificial intelligence
B
Blog RSS Feed
腾讯CDC
博客园_首页
aimingoo的专栏
aimingoo的专栏
博客园 - 三生石上(FineUI控件)
博客园 - Franky
S
SegmentFault 最新的问题
N
Netflix TechBlog - Medium
小众软件
小众软件
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
L
LINUX DO - 热门话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Martin Fowler
Martin Fowler
D
Docker
P
Privacy & Cybersecurity Law Blog
S
Securelist
V
V2EX
Jina AI
Jina AI
阮一峰的网络日志
阮一峰的网络日志
T
Tor Project blog
The Hacker News
The Hacker News
Microsoft Azure Blog
Microsoft Azure Blog
AWS News Blog
AWS News Blog
The GitHub Blog
The GitHub Blog
有赞技术团队
有赞技术团队
T
The Exploit Database - CXSecurity.com
Help Net Security
Help Net Security
酷 壳 – CoolShell
酷 壳 – CoolShell
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - 叶小钗
Recent Announcements
Recent Announcements
Cloudbric
Cloudbric
Y
Y Combinator Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Latest news
Latest news
MongoDB | Blog
MongoDB | Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Recorded Future
Recorded Future
V2EX - 技术
V2EX - 技术

博客园 - 好好学习,天天进步

Java调用ocx控件以及dll pongo英雄会-修路题解(z) 那些VisualStudio隐藏的调试功能(转) Android 横屏切换竖屏Activity的生命周期(转) 那些有争议的编程观点 经过完整测试的农历-公历相互转换 windows phone SDK 8.0 模拟器异常 0x89721800解决办法 JavaScript 解析器相关资料 AST Parser。。。 (转)浏览器的工作原理:新式网络浏览器幕后揭秘 中缀表达式转后缀表达式(逆波兰表达式) Windows 8 无法安装 Algorithm Gossip: 中序式轉後序式(前序式) tesseract-ocr训练方法 透明窗口与不规则窗口制作方法总结 检测文件存在的四种方法 C/C++多种方法获取文件大小 Struts 2命令执行漏洞 win7 x64怎么枚举所有快捷键呢 在windbg中测试shadow ssdt , win32k!NtUserGetForegroundWindow , hook shadow ssdt
从浏览器启动客户端程序
好好学习,天天进步 · 2012-07-30 · via 博客园 - 好好学习,天天进步
  • 综述

          现在有很多B/S与C/S相结合的产品,会出现一种需求:从浏览器启动客户端的程序,并且如果客户端未安装相应程序,先提示安装。

          主流的几款产品:腾讯QQ、阿里旺旺、迅雷、PPLive等,都有实现了类似的功能。

          浏览器启动客户端程序可以通过注册自定义的Url协议来实现,而检测客户端是否安装程序需要利用ActiveX控件。

          要额外注意的是,现在只有IE浏览器才支持。

  • 客户端程序

        先准备一个简单的客户端程序,只用来显示传入的命令行参数。

    Client

    复制代码

    1 namespace wuhong.Client
    2 {
    3 class Program
    4 {
    5 static void Main(string[] args)
    6 {
    7 if (args != null && args.Length > 0)
    8 {
    9 Array.ForEach(args, arg => Console.WriteLine(arg));
    10 }
    11
    12 Console.ReadLine();
    13 }
    14 }
    15 }

    复制代码

  • 从浏览器启动

          注册自定义的Url协议,这样当用户点击这个URL协议的链接后,IE就会启动相关URL协议的处理器,使用注册的程序来处理这个协议。

          具体来说,比如现在需要注册“wuhong.client”的Url协议,使得形如“wuhong.client:XXXXYYYY”的链接都由上节的控制台程序来处理。

          这一切只需要在客户端安装控制台程序的同时向注册表添加下面的项就可以实现:

    注册表

    复制代码

    1 [HKEY_CLASSES_ROOT\wuhong.client]
    2
    3 @="wuhong.Client"
    4
    5  "URL Protocol"=""
    6
    7 [HKEY_CLASSES_ROOT\wuhong.client\DefaultIcon]
    8
    9 @=" wuhong.Client.exe "
    10
    11 [HKEY_CLASSES_ROOT\wuhong.client\Shell]
    12
    13 [HKEY_CLASSES_ROOT\wuhong.client\Shell\open]
    14
    15 [HKEY_CLASSES_ROOT\wuhong.client\Shell\open\command]
    16
    17 @="\"[TARGETDIR]wuhong.Client.exe\" \"%1\""

    复制代码

          解释一下其中几项:

    [HKEY_CLASSES_ROOT\wuhong.client]

          默认项和URL Protocol项的值都是设置一个名称。

    [HKEY_CLASSES_ROOT\wuhong.client\DefaultIcon]

          默认项的值是Url协议的图标文件名的路径。简单处理可以省略这一项。

    [HKEY_CLASSES_ROOT\wuhong.client\Shell\open\command]

          默认项的值是用来调用(或者启动)处理这个Url协议的程序。整个Url会作为一个参数传递给处理程序。

  • 检测客户端程序安装

          检测客户端是否安装了上节的控制台程序,需要另外实现一个ActiveX控件,在客户端安装程序的同时一并安装。这样可以利用ActiveX控件的加载情况,来判断控制台程序是否安装。

          作为示例,这里实现一个没有任何其他功能的ActiveX控件。

          首先定义IobjectSafety接口。IobjectSafety接口用来向IE声明自身是脚本安全的。在IE的中级安全级别上,是允许脚本安全的ActiveX控件的创建而不提示警告。

    IobjectSafety接口

    复制代码

    1 namespace wuhong.ActiveX
    2 {
    3 [ComImport, Guid("CB5BDC81-93C1-11CF-8F20-00805F2CD064")]
    4 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    5 public interface IObjectSafety
    6 {
    7 [PreserveSig]
    8 int GetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] ref int pdwSupportedOptions, [MarshalAs(UnmanagedType.U4)] ref int pdwEnabledOptions);
    9
    10 [PreserveSig()]
    11 int SetInterfaceSafetyOptions(ref Guid riid, [MarshalAs(UnmanagedType.U4)] int dwOptionSetMask, [MarshalAs(UnmanagedType.U4)] int dwEnabledOptions);
    12 }
    13 }

    复制代码

          接下来是控件的代码,实现一个“wuhong.client”的控件,本身不添加任何额外的功能。

    UserControl类

    复制代码

    1 namespace wuhong.ActiveX
    2 {
    3 [Guid("9C9701D1-D188-495d-8721-9D246211A27C"), ProgId("wuhong.client"), ComVisible(true)]
    4 public partial class ActiveXObject : UserControl, IObjectSafety
    5 {
    6 public ActiveXObject()
    7 {
    8 InitializeComponent();
    9 }
    10
    11 private const int INTERFACESAFE_FOR_UNTRUSTED_CALLER = 0x00000001;
    12 private const int INTERFACESAFE_FOR_UNTRUSTED_DATA = 0x00000002;
    13 private const int S_OK = 0;
    14
    15 public int GetInterfaceSafetyOptions(ref Guid riid, ref int pdwSupportedOptions, ref int pdwEnabledOptions)
    16 {
    17 pdwSupportedOptions = INTERFACESAFE_FOR_UNTRUSTED_CALLER;
    18 pdwEnabledOptions = INTERFACESAFE_FOR_UNTRUSTED_DATA;
    19
    20 return S_OK;
    21 }
    22
    23 public int SetInterfaceSafetyOptions(ref Guid riid, int dwOptionSetMask, int dwEnabledOptions)
    24 {
    25 return S_OK;
    26 }
    27 }
    28 }

    复制代码

           另外AssemblyInfo.cs中需要修改并添加以下内容:

    AssemblyInfo.cs

    1 using System.Security;
    2 [assembly: AllowPartiallyTrustedCallers()]
    3 [assembly: ComVisible(true)]

           项目生成中也需要选择“为COM互操作注册”。

  • 测试

          将客户端程序、ActiveX控件以及注册Url协议的注册表项制作成安装包。

          使用下面的页面代码测试:

    Test页面

    复制代码

    1 <html xmlns="http://www.w3.org/1999/xhtml" >
    2  <head>
    3 <script type='text/javascript'>
    4 function Start() {
    5 try {//支持
    6   var obj = new ActiveXObject("wuhong.client");
    7 }
    8 catch (e) {//不支持
    9   }
    10 if(null != obj){
    11 delete obj;
    12 window.navigate('wuhong.client:start?HelloWorld');
    13 }
    14 else{
    15 alert("您未安装程序,请安装!");
    16 }
    17 }
    18 </script>
    19 <title></title>
    20  </head>
    21  <body>
    22 <input type="button" onclick="Start()" value="启动"/>
    23  </body>
    24  </html>

    复制代码

          可以看到安装前后点击“启动”按钮的区别。

          安装前:

          安装后: