浏览器调用本地DLL的方法

news2024/11/26 21:47:26

要在浏览器中调用本地DLL,常见的方法是使用插件。但是为了安全,现在有的浏览器对插件开发做了限制,不让插件调用外部DLL。比如说Chrome,为了调用外部的DLL,我们只能使用早期的chrome版本。
还有一种方法就是在电脑上安装一个助手程序,浏览器通过HTTP GET请求调用助手程序,助手程序再调用本地DLL,并把调用结果反馈到浏览器中。今天我们就来讨论这种方法。
首先助手程序应该是一个WEB服务器,因为只有WEB服务器才能处理浏览器发过来的HTTP GET请求。
第二个问题:浏览器怎么发送HTTP GET请求?答案是JavaScript。如果您熟悉JQuery, 那么让浏览器发送HTTP GET请求只需要几行代码:

$.get("http://localhost/",function(data,status){ 
alert("数据: " + data + "\n状态: " + status); 
});

如果您不了解JQuery,使用的代码会多一些,如下所示:

        //创建XMLHttpRequest对象       
        var httpRequest
		try{ // Firefox, Opera 8.0+, Safari
			httpRequest=new XMLHttpRequest();
		}
		catch (e){
			try{// Internet Explorer
				httpRequest=new ActiveXObject("Msxml2.XMLHTTP");
			}
			catch (e){
				try{
					httpRequest=new ActiveXObject("Microsoft.XMLHTTP");
				}
				catch (e){}
			}
		}
		

        httpRequest.open('GET',
		'http://localhost/',
		true);
        httpRequest.send();//发送请求
        
         // 获取数据后的处理程序
         httpRequest.onreadystatechange = function () {
            if (httpRequest.readyState == 4 && httpRequest.status == 200) {
                var str = httpRequest.responseText;//获取到助手程序返回的字符串
               	alert(str);				
            }
        };

因为浏览器和助手程序都在同一台电脑上,所以代码中HTTP GET的url就是http://localhost

第三个问题:其实浏览器不仅可以用HTTP GET请求调用助手程序,还可以使用HTTP POST,WebSocket协议。
下面我们来看一看流程图:

流程图很简单。这里最麻烦的地方就在于我们要自己写助手程序,还要安装在每一台电脑上。所以我觉得这个方法比较适合企业内部信息管理系统。助手程序可以用来在网页中操作控制本地的读卡器、打印机、扫描仪、高拍仪、U盾等各种硬件设备。
好,原理部分讲完了,如果您看不太懂,问题也不大,现在我们写几个助手程序的实例,估计写完实例大家就会理解了。每个人会的编程语言是不同的,所以我们写的实例,有JAVA版,PHP版和C++版。
所有实例都提供了源代码,源代码放在github上:https://github.com/Dengxd/SimpleDllHelper
DllHelperCpp目录是C++版
DllHelperJava目录是JAVA版
DllHelperPhp目录是PHP版,comATL目录是C++写的com组件,专门给PHP版使用的
TestDll目录是测试用的DLL
test.html文件是浏览器使用的网页JavaScript代码 

编写一个测试用的DLL

既然要调用DLL,我们就先写一个测试用的DLL,JAVA和PHP写不了DLL,所以只能用C++
我的开发环境:
Windows 7 旗舰版 SP1 x64
Microsoft Visual Studio Community 2022 (64 位)
主要代码解读:
主要代码就一个函数

__declspec(dllexport) int __stdcall sum(int a, int b)
{
    return a + b;
}

这是个求和函数,两个输入参数a和b, 返回a+b
我们的助手程序要调用的就是这个函数
这个项目可以编译出x64和Win32(x86)版本的DLL。Visual Studio自动生成的项目也是奇葩,在主界面上Win32程序叫做x86:

但是到了项目属性配置页面,又变成了Win32:

 

很容易把初学者搞得无所适从。其实在这两个地方x86和Win32是一回事。一般我们都是编译成Release版本的,如果要编译成64位的,就在主界面选择x64,如果要编译成32位的,就在主界面选择x86
如果您不会C++和Microsoft Visual Studio, 不知道怎么编译出DLL, 源码里面提供了编译好的DLL,Release x64版的TestDll.dll在文件夹TestDll\x64\Release中,Debug x64版的TestDll.dll在文件夹TestDll\x64\Debug中, Release Win32版的TestDll.dll在文件夹TestDll\Release中,Debug Win32版的TestDll.dll在文件夹TestDll\Debug中,一般情况下我们会使用Release版本的DLL,如果操作系统是64位的,最好使用x64版,如果操作系统是32位的,只能使用Win32版。如果您手痒很想自己编译的话,可以参考一下这篇文章:https://www.freesion.com/article/6443438938/ 。声明一下,这篇文章不是我写的,只是我搜索到的文章。 

编写JavaScript代码

我们建立一个文件,文件名text.html, 内容如下:

<!doctype html>
<html>
  <head>
	<meta http-equiv="Content-Type" content="text/html;charset=utf-8">

  </head>
  <body>
     <form action="" enctype="application/x-www-form-urlencoded">
          <input type="button" name="ok" id="ok" value="HTTP GET">
      </form>
  </body>
  <script type="text/javascript" >
	window.onload = function () {
		document.getElementById("ok").onclick = function () {
        
        //创建XMLHttpRequest对象       
        var httpRequest
		try{ // Firefox, Opera 8.0+, Safari
			httpRequest=new XMLHttpRequest();
		}
		catch (e){
			try{// Internet Explorer
				httpRequest=new ActiveXObject("Msxml2.XMLHTTP");
			}
			catch (e){
				try{
					httpRequest=new ActiveXObject("Microsoft.XMLHTTP");
				}
				catch (e){}
			}
		}
		

        httpRequest.open('GET',
		//'http://localhost/cgi-bin/dllhelpercpp.cgi',
		'http://localhost/',
		true);
        httpRequest.send();//发送请求
        
         // 获取数据后的处理程序
         
        httpRequest.onreadystatechange = function () {
            if (httpRequest.readyState == 4 && httpRequest.status == 200) {
                var str = httpRequest.responseText;//获取到助手程序返回的字符串
               	alert(str);				
            }
        };

    }
	
}		
  </script>
</html>

这代码熟悉JavaScript的同学都能看得懂,我就不解释了。
我们用浏览器打开这个文件,会显示一个按钮“HTTP GET”,点击这个按钮,浏览器就会向助手程序发送HTTP GET请求

编写JAVA版的助手程序

我的开发环境:
Windows 7 旗舰版 SP1 x64
IntelliJ IDEA 2021.2.1(Ultimate Edition)
java version "1.8.0_121" Java(TM) SE Runtime Environment (build 1.8.0_121-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.121-b13, mixed mode)
我们使用JNA来调用DLL,关于JNA,网络上文章很多了,大家可以自己去搜一搜,我就不献丑了。大家可以参考一下这篇文章:https://www.freesion.com/article/6443438938/
前面我们说过,助手程序应该是一个WEB服务器,所以我们就使用spring boot框架,这货自带了一个TOMCAT,省了不少麻烦
主要代码解读:

public interface Mydll extends Library {
   Mydll instance = Native.load("C:\\TestDll.dll", Mydll.class);

   int sum(int a,int b);

}
@RequestMapping("/")
@ResponseBody
public int dll(HttpServletResponse resp) {

   int ret=Mydll.instance.sum(1,2);
   resp.setHeader("Access-Control-Allow-Origin","*");
   return ret;
}

"C:\\TestDll.dll" 是DLL文件所在的路径,要改成您相应的文件路径
int sum(int a,int b);声明了DLL中对应的函数
int ret=Mydll.instance.sum(1,2); 就是调用DLL中的sum函数
resp.setHeader("Access-Control-Allow-Origin","*"); 这句是为了解决跨域问题的

修改application.yml
把端口改为80
server:
  port: 80

特别注意:如果您的WINDOWS是32位的,只能使用Win32版的DLL和32位的JDK。如果您的WINDOWS是64位的,可以使用x64版的DLL和64位的JDK,也可以使用Win32版的DLL和32位的JDK。归纳为一句话: DLL和JDK位数要一致。

现在我们运行这个JAVA程序,然后在浏览器中打开前面写的test.html文件,点击“HTTP GET”按钮:

成功调用DLL

编写PHP版的助手程序 

我的开发环境:

Windows 7 旗舰版 SP1 x64

PHPStudy 8.1.1.3 ,  Nginx 1.15.11, PHP 7.3.4nts

Microsoft Visual Studio Community 2022 (64 位)

PHP调用普通的DLL有两种方法,一种是开发一个PHP扩展,再由PHP扩展调用DLL,第二种是开发一个com组件,php先调用com组件,再由com组件调用DLL。我们采用的是第二种方法。

Php是写不了com组件的,所以我们用C++来写一个com组件。

开发com组件

可以参考这个网页:https://blog.csdn.net/weixin_33507838/article/details/115411281

主要代码解读:

STDMETHODIMP CATLSimpleObject::atlsum(LONG a, LONG b, LONG* c)
{
    // TODO: 在此处添加实现代码
	HINSTANCE hinstLib;
	hinstLib = LoadLibrary(TEXT("c:\\TestDll.dll"));
	if (hinstLib != NULL)
	{
		typedef int(__stdcall* SUM)(int, int);
		SUM sum;
		sum = (SUM)GetProcAddress(hinstLib, "sum"); //这是获取dll里面的sum函数

		if (NULL != sum)
		{
			int ret = sum(a, b);  //调用dll的sum函数
			* c = ret;  //这是设置返回值
		}
		FreeLibrary(hinstLib);
	}
    return S_OK;
}

"C:\\TestDll.dll" 是DLL文件所在的路径,要改成您相应的文件路径
特别注意:TestDll.dll 和 com组件的位数要一致。要么都是x64 ,要么都是Win32(x86)。千万不能一个x64,另一个Win32(x86)
Com组件编译出来之后,需要注册,注册需要使用命令行:regsvr32 D:\doc\code\SimpleDllHelper\comATL\x64\Release\comATL.dll
这里D:\doc\code\SimpleDllHelper\comATL\x64\Release\comATL.dll是com组件所在的路径,应该改成您本机上实际的文件路径

开发php代码

总共三行代码:

header('Access-Control-Allow-Origin:*'); //这句是为了解决跨域问题的
$com = new COM("ComATL.ATLSimpleObject") or die("无法调用ComTest");  //初始化com组件
echo $com->atlsum(1, 2);  //调用com组件的接口

如果说程序代码是美女们的超短裙,那么我最喜欢的就是PHP了,因为越短越好!
还有一点很重要,修改php配置文件,加上一行extension=php_com_dotnet.dll

如果没有这一行, PHP无法调用com组件
最后我们在浏览器中打开前面写的test.html文件,点击“HTTP GET”按钮,将会看到和java助手程序一样的结果

编写C++版的助手程序

我的开发环境:
Windows 7 旗舰版 SP1 x64
Microsoft Visual Studio Community 2022 (64 位)

介绍一下我们的思路:先安装一个APACHE HTTPD服务器,然后写一个CGI的程序,由这个CGI程序来调用DLL,最后把CGI程序部署到APACHE HTTPD服务器里面

安装一个APACHE HTTPD服务器

官网下载地址:https://archive.apache.org/dist/httpd/binaries/win32/ 这里面有很多版本,我下载的是这个:httpd-2.2.18-win32-x86-no_ssl.msi

安装的时候,就按照缺省的设置安装,安装完会自动启动apache2.2服务,系统托盘区也会多一个apache的图标:

 

 打开浏览器,输入网址http://localhost/,显示如下:

 出现It works! 就说明已经安装成功。

写一个CGI的程序

由这个CGI程序来调用DLL
主要代码如下:

#include <windows.h> 
#include <stdio.h> 

int main()
{
	HINSTANCE hinstLib;

	printf("Access-Control-Allow-Origin:*\n");
	printf("Content-type: text/html\n\n");

	hinstLib = LoadLibrary(TEXT("c:\\TestDll.dll"));



	if (hinstLib != NULL)
	{
		typedef int(__stdcall* SUM)(int, int);
		SUM sum;
		sum = (SUM)GetProcAddress(hinstLib, "sum");

		if (NULL != sum)
		{
			int ret = sum(1,2);
			printf("%d", ret);
		}
		else
		{
			printf("can not find function sum ");
		}

		FreeLibrary(hinstLib);
	}
	else
	{
		printf("load library fail!");
	}
	return 0;
}

"C:\\TestDll.dll" 是DLL文件所在的路径,要改成您相应的文件路径
printf("Access-Control-Allow-Origin:*\n");这句是为了解决跨域问题的
printf("Content-type: text/html\n\n");  \n\n这个说明HTTP响应头部结束

printf("%d", ret); 这句是真正在网页上显示的内容

注意事项,因为我们安装的APACHE HTTPD是Win32版本的,所以我们使用的TestDll.dll也必须是Win32(x86)版的,这个CGI程序在编译的时候也要选择Win32(x86)版的。

把CGI程序部署到APACHE HTTPD服务器

我们把编译好的exe文件改名为dllhelpercpp.cgi, 复制到APACHE HTTPD的CGI-BIN目录里面。
打开浏览器,打开网址http://localhost/cgi-bin/dllhelpercpp.cgi,如果出现一个数字3,就说明部署成功了。

测试

现在我们修改test.html文件,
把httpRequest.open('GET',    'http://localhost/',true); 
改成httpRequest.open('GET',    'http://localhost/cgi-bin/dllhelpercpp.cgi',true);
用浏览器打开test.html文件,点击“HTTP GET”看看得到的结果是不是和JAVA版本的一样?

CGI程序更进一步的开发

可以参考下面两个网页:
https://blog.csdn.net/u010105970/article/details/41278489
https://blog.csdn.net/weixin_39652658/article/details/116873261

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/180868.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

linux编辑器的使用(gcc,g++)

前言 gcc/g是一个编译器。 我们程序的翻译有四个步骤1.预处理(头文件展开&#xff0c;条件编译&#xff0c;宏替换&#xff0c;去注释)2.编译(c语言汇编语言)3.汇编(汇编->可重定位目标二进制文件&#xff0c;不可以被执行的&#xff0c;bin.obj)----只是把我们自己的代码进…

下载Windows ISO镜像的方法 (超详细 适合新手入门)

前言 &#x1f4dc;“作者 久绊A” 专注记录自己所整理的Java、web、sql等&#xff0c;IT技术干货、学习经验、面试资料、刷题记录&#xff0c;以及遇到的问题和解决方案&#xff0c;记录自己成长的点滴 目录 前言 一、镜像介绍 1、大概介绍 2、详细介绍 二、下载Window…

Solon 1.12.4 发布

一个更现代感的 Java "生态型"应用开发框架&#xff1a;更快、更小、更自由。不是 Spring&#xff0c;没有 Servlet&#xff0c;也无关 JavaEE&#xff1b;新兴独立的开放生态 &#xff08;已有150来个生态插件&#xff09; 。主框架仅 0.1 MB。 相对于 Spring Boot…

JVM学习总结,全面介绍运行时数据区域、各类垃圾收集器的原理使用、内存分配回收策略

参考资料&#xff1a;《深入理解Java虚拟机》第三版 文章目录一&#xff0c;运行时数据区域&#xff08;基础重中之重&#xff09;二&#xff0c;垃圾收集器与内存分配策略1&#xff09;对象已死2&#xff09;再谈引用3&#xff09;对象回收4&#xff09;内存分代收集理论&…

【HBase入门】10. HBase高可用、HBase架构、常见问题汇总

HBase高可用 考虑关于HBase集群的一个问题&#xff0c;在当前的HBase集群中&#xff0c;只有一个Master&#xff0c;一旦Master出现故障&#xff0c;将会导致HBase不再可用。所以&#xff0c;在实际的生产环境中&#xff0c;是非常有必要搭建一个高可用的HBase集群的。 HBase…

【Maven】聚合与继承

目录 1. 聚合工程 2. 聚合工程开发 3. 继承关系 4. 继承关系开发 5. 聚合与继承的区别 1. 聚合工程 什么叫聚合&#xff1f; 聚合&#xff1a;将多个模块组织成一个整体&#xff0c;同时进行项目构建的过程称为聚合 聚合工程&#xff1a;通常是一个不具有业务功能的”空…

如何使用Excel列提取合并器提取多个表格中的一列数据然后合并到一个文件

在我们日常工作中&#xff0c;你可能经常遇到有几十个或更多的Excel文件&#xff0c;每个文件中都包含了相同类型的信息例如姓名、邮箱、地址等等&#xff0c;但它们却在不同文件中不同的列。当你想进行数据汇总或合并的时候&#xff0c;把不同表中同样类型的数据合并在一起&am…

一款用于PE文件绑定免杀的工具: Shellter

简介 Shellter是一种动态二进制程序壳程序&#xff0c;它可以在现有的可执行文件中隐藏恶意软件。它使用动态链接库技术来实现恶意代码的注入&#xff0c;并且可以在不修改现有的可执行文件的情况下进行注入。这使得它非常难以检测&#xff0c;因为它不会改变文件的哈希值或数…

[数据结构基础]排序算法第二弹 -- 选择排序、堆排序和冒泡排序

目录 一. 选择排序 1.1 选择排序的实现思路 1.2 选择排序函数代码 1.3 选择排序的时间复杂度分析 二. 堆排序 2.1 堆排序的实现思路 2.2 堆排序函数代码 2.3 堆排序的时间复杂度分析 三. 冒泡排序 3.1 冒泡排序的基本思想 3.2 冒泡排序函数代码 3.3 冒泡排序的时间…

【微服务】Gateway统一网关

更多内容点击查看微服务学习专栏 一.引入 我们为什么需要网关&#xff1f; 当我们所有的服务摆在那里允许任何人发送请求访问是不是不太安全&#xff1f; 不是所有的业务都是对外公开的&#xff01; Gateway网关是我们服务的守门神&#xff0c;是所有微服务的统一入口&…

机器自动翻译古文拼音 - 十大宋词 - 桂枝香 金陵怀古 王安石

桂枝香金陵怀古 北宋王安石 登临送目&#xff0c;正故国晚秋&#xff0c;天气初肃。 千里澄江似练&#xff0c;翠峰如簇。 归帆去棹斜阳里&#xff0c;背西风&#xff0c;酒旗斜矗。 彩舟云淡&#xff0c;星河鹭起&#xff0c;画图难足。 念往昔、繁华竞逐&#xff0c;叹门外…

【Node.js实战】一文带你开发博客项目之初识Express(安装Express,处理路由,中间件机制)

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;也会涉及到服务端 &#x1f4c3;个人状态&#xff1a; 在校大学生一枚&#xff0c;已拿多个前端 offer&#xff08;秋招&#xff09; &#x1f680;未…

JAVA SE复习(第2章 Java基础语法)

本文笔记来自硅谷柴林燕老师的笔记 只为自己看笔记方便使用 不做他用第2章 Java基础语法2.1 注释&#xff08;annotation&#xff09;&#xff08;掌握&#xff09;注释&#xff1a;就是对代码的解释和说明。其目的是让人们能够更加轻松地了解代码。为代码添加注释&#xff0c;…

2023年web类第一期总结

&#x1f340;本人简介&#xff1a; 吉师大一最爱逃课的网安混子、 华为云享专家、阿里云专家博主、腾讯云自媒体分享计划博主、 华为MindSpore优秀开发者、迷雾安全团队核心成员&#xff0c;CSDN2022年运维与安全领域第15名 &#x1f341;本人制作小程序以及资源分享地址&am…

计算机相关专业混体制的解决方案(国企之银行与券商)

文章目录1、各大银行1.1 银行的分类1.2 信息科技部&#xff08;工作内容&#xff0c;招聘条件&#xff0c;待遇&#xff09;2、各大券商2.1 证券公司待遇2.1 证券公司要求3、其他金融3.1 保险公司3.2 其他金融国企之银行与券商的适用对象&#xff1a; 如果你技术好&#xff0c;…

队列--专题讲解

文章目录模拟队列queue头文件定义基本操作循环队列queue优先队列priority_queue银行大厅排队训练挑战模拟队列 先进先出 队列大概模样 代码截屏&#xff1a; queue 头文件 #include <queue>定义 //队列 queue<int> q;基本操作 //向队尾插入一个元素q.push()…

24考研数学每日一题(带解析)

题目来源于武老师的每日一题&#xff0c;答案是自己做的&#xff0c;不太严谨&#xff0c;仅供参考 2022年11月1日 知识点&#xff1a;函数定义域 答案&#xff1a; 函数定义域是指自变量x的取值范围&#xff0c;不可以把x1作为自变量&#xff0c;x才是自变量&#xff0c;同…

高级数据结构:树状数组详解(c++实现 求解动态数组区间和问题)

文章目录引入树状数组c完整代码引入 什么是树状数组&#xff1f;&#xff1f;&#xff1f; 解决数据压缩里的累积频率&#xff08;Cumulative Frequency&#xff09;的计算问题&#xff0c;现多用于高效计算数列的前缀和&#xff0c; 区间和&#xff0c;这样的问题可以使用树…

蓝桥杯重点(C/C++)(随时更新,更新时间:2023.1.27)

点关注不迷路&#xff0c;欢迎推荐给更多人 目录 1 技巧 1.1 取消同步&#xff08;节约时间&#xff0c;甚至能多骗点分&#xff0c;最好每个程序都写上&#xff09; 1.2 万能库&#xff08;可能会耽误编译时间&#xff0c;但是省脑子&#xff09; 1.3 蓝桥杯return 0…

深度学习:CSPNet

深度学习&#xff1a;CSPNet前言解决的问题Method目前主流网络存在的问题Partial Dense BlockPartial Transition LayerExact Fusion Model实验前言 CSPNet 是作者 Chien-Yao Wang 于 2019 发表的论文 CSPNET: A NEW BACKBONE THAT CAN ENHANCE LEARNING CAPABILITY OF CNN。也…