浏览器调用本地DLL的方法

要在浏览器中调用本地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

  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
4 浏览器网络编程(共两周) 4.1 浏览器工作原理(老师讲解1学时,学生理解1学时) 浏览器工作原理如图4-1所示。 图4-1 浏览器工作原理 (1) 浏览器分析超链指向页面的 URL。 (2) 浏览器向 DNS 请求解析 www.tsinghua.edu.cn 的 IP 地址。 (3) 域名系统 DNS 解析出清华大学服务器的 IP 地址。 (4) 浏览器与服务器建立 TCP 连接 (5) 浏览器发出取文件命令: GET /chn/yxsz/index.htm。 (6) 服务器 给出响应,把文件 index.htm 发给浏览器。 (7) TCP 连接释放。 (8) 浏览器显示“清华大学院系设置”文件 index.htm 中的所有文本 4.2 浏览器功能结构(老师讲解1学时,学生理解1学时) 浏览器程序功能结构如图4-2所示。 图4-2 浏览器功能结构 1) 浏览器有一组客户、一组解释程序,以及管理这些客户和解释程序的控制程序。 2) 控制程序是其中的核心部件,它解释鼠标的点击和键盘的输入,并调用有关的组件来执行用户指定的操作。 3) 例如,当用户用鼠标点击一个超链的起点时,控制程序就调用一个客户从所需文档所在的远地服务器上取回该文档,并调用解释程序向用户显示该文档 4) HTML 解释程序是必不可少的,而其他的解释程序则是可选的。 5) 解释程序把 HTML 规格转换为适合用户显示硬件的命令来处理版面的细节。 6) 许多浏览器还包含 FTP 客户,用来获取文件传送服务。 7) 一些浏览器也包含电子邮件客户,使浏览器能够发送和接收电子邮件 8) 浏览器将它取回的每一个页面副本都放入本地磁盘的缓存中。 9) 当用户用鼠标点击某个选项时,浏览器首先检查磁盘的缓存。若缓存中保存了该项,浏览器就直接从缓存中得到该项副本而不必从网络获取,这样就明显地改善浏览器的运行特性。 10) 但缓存要占用磁盘大量的空间,而浏览器性能的改善只有在用户再次查看缓存中的页面时才有帮助。 11) 许多浏览器允许用户调整缓存策略。 4.3 浏览器设计(老师讲解2学时,学生设计2学时) (1)浏览器功能设计 浏览器功能设计主要确定设计好的浏览器需要具备哪些功能,以及这些功能是以什么方式进行实现,这个步骤相当于软件设计中的“需求分析”,其中必须保证基本功能的具备,即浏览器必须能够浏览Web页面。 (2)浏览器界面设计 浏览器界面设计主要确定浏览器的页面布局,设定浏览器窗口上设置哪些功能菜单项、设置哪些功能按钮、设置哪些状态栏,它们各自的位置如何、属性如何、对应的变量如何等等。 (3)浏览器代码设计 浏览器代码设计主要是确定对上述的设计的功能在代码上怎样实现,包括选用的程序语言和编程平台选择、程序代码的编写、程序代码的调试、程序功能的测试等等。 4.4 浏览器编程设计平台(老师讲解2学时,学生理解4学时) (1)VS2005编程平台 (2)WebBrowser类及其使用 (3)一些浏览器程序的代码分析 4.5 浏览器开发步骤(8天) (1)熟悉VS2005平台,建立项目(半天) 打开VS2005选择“创建项目”,进入“新建项目”对话框,如图4-1所示。 图4-1 “新建项目”对话框 在“新建项目”对话框的项目类型窗口中选中“Visual C#”作为项目开发语言,在模板窗口中选中“Windows 应用程序”作为项目开发模板,在“名称”、“位置”编辑框中输入自己设定的项目名字和项目存储位置,本讲义使用“CSharp浏览器”作为项目名称,如图4-2所示。 图4-2 输入新建项目的属性 完成输入内容后,单击“确定”按钮,进入项目VC#开发窗口“Form.cs[设计]”,如图4-3所示。 图4-3 VC#开发窗口“Form.cs[设计]” (2)界面设计(1天) ○1设计菜单栏如图4-4所示。(半天) 图4-4 设计菜单栏 设计“文件”菜单如4-5所示。 图4-5 设计“文件”菜单 设计“编辑”菜单如图4-6所示。 图4-6 设计“编辑”菜单 设计“查看”菜单如图4-7所示。 图4-7 设计“查看”菜单 设计“收藏”菜单如图4-8所示。 图4-8 设计“收藏”菜单 设计“工具”菜单如图4-9所示。 图4-9 设计“工具”菜单 ○2设计工具栏、用户区和状态栏如图4-10所示(半天) 图4-10 工具栏和状态栏 (3)功能代码编辑 ○1初始化代码(半天) 双击“Form”设计页面进入代码编写页面,如图4-11所示。 图4-11 代码编写页面 初始化页面代码如下: ////////////////////////////////////////////////////////
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值