由于我必须使用的架构可能会破坏许多非常好的软件设计规则,我需要从Web浏览器中运行的一些javascript代码向同一台机器上的Windows批处理文件发送消息。 操作系统是 Windows Vista 或更高版本。 使用的浏览器主要是Chrome和Firefox。 jQuery也与javascript一起使用。
浏览器连接到互联网,并且涉及服务器,因此我可以将消息中继到服务器,然后中继到批处理文件。 现在我有一个每分钟左右运行的批处理文件,理论上可以向服务器查询任何消息。 除此之外,我没有任何好主意。
此外,这是一个"封闭"系统。 客户端浏览器、客户端系统和服务器都在我完全控制之下。 这不是公众在浏览器中运行Javascript的情况。 可以操纵客户端计算机以能够接收消息。
发送此消息的好方法是什么?
1. 本地 HTTP 服务器
从 JavaScript 中,将包含您的命令的 AJAX 请求发送到本地 HTTP 服务器。所有现代浏览器都支持跨域 AJAX。服务器可以将命令作为参数传递给批处理文件。确保无法从网络访问服务器。
这种方法的优点是你可以将响应从命令发送回 JavaScript。
-
JavaScript:
$.post('http://localhost:8080', {command: '...'});
-
Bottle.py 服务器:
#!/usr/bin/python from bottle import run, route, request, response import subprocess @route('/', method='POST') def index(): command = request.POST['command'] result = subprocess.check_output(['batchfile.bat', command], shell=True) response.set_header('Access-Control-Allow-Origin', '*') return result run(host='localhost', port=8080, reloader=True)
-
或者 Apache/nginx 下的 PHP:
$result = shell_exec("batchfile.bat " . escapeshellarg($_POST['command']));
-
或者 PHP 中的守护进程:
为了获得额外的乐趣,它具有完整的shell访问权限,并且可以异步运行命令,从而可以在不阻塞的情况下启动桌面应用程序。它不需要Apache。
开始:
php.exe -f batrunner_daemon.php
用途:
$.get('http://localhost:33333/ping -h', function(response) { console.log(response) });
$host = '127.0.0.1'; $port = 33333; $async = false; // enable to run commands without blocking the server (useful for GUI applications) $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); $open = @socket_bind($socket, $host, $port); if ($open) { echo "nListening on http://{$host}:{$port}"; } else { echo "nError. Port {$port} in use"; exit; } socket_listen($socket, 1); while(1) { $connection = socket_accept($socket); $http_request = socket_read($connection, 32768); $command = rawurldecode(substr(strstr($http_request, "rn", true), 5, -9)); echo "nRunning: {$command}..."; if ($async) { $response = pclose(popen('start "" /B ' . $command, 'r')) ? 'error' : 'success'; } else { $response = shell_exec($command); } echo " Done."; socket_write($connection, implode("rn", array( 'HTTP/1.1 200 OK', 'Content-Type: text/plain; charset=UTF-8', 'Connection: close', 'Content-Length: ' . strlen($response), 'Access-Control-Allow-Origin: *', "rn" . $response ))); socket_close($connection); }
为了简单起见,它没有适当的错误处理,并允许任何站点在您的计算机上执行任何操作,使用风险自负。
Access-Control-Allow-Origin: *
意味着任何站点都可以接收来自 shell 的响应。如果没有这个标头,他们显然仍然可以运行命令,但无法接收响应。
2. URI 方案
我尝试了@mamdrood的想法,结果证明它非常简单,比HTTP服务器容易得多。
-
从 HTML 中,您将能够像这样调用批处理文件:
<a href="batrunner://somecommand">Wipe all files</a>
-
以下是
C:mybatfile.bat
中的批处理文件解析命令的方式:@echo off SET command=%1 SET command=%command:batrunner://=% echo %command%
我对批处理文件不是很熟悉,我的命令名称解析代码可能容易受到攻击。如果您知道得更好,请更新此答案。
-
要将批处理文件与
batrunner://
协议关联,请创建batrunner.reg
并运行一次。将C:\mybatfile.bat
替换为脚本,路径应进行转义。Windows Registry Editor Version 5.00 [HKEY_CLASSES_ROOTbatrunner] "URL Protocol"="" [HKEY_CLASSES_ROOTbatrunnershell] [HKEY_CLASSES_ROOTbatrunnershellopen] [HKEY_CLASSES_ROOTbatrunnershellopencommand] @="C:\mybatfile.bat %1"
你也可以创建一个小的Windows应用程序,并使用URI方案来连接信息,就像BitTorrent磁铁或Skype调用一样。
据我所知,在浏览器中运行的 JavaScript 无法与本地文件系统通信。 如果网络上的页面可以在您的系统上读取和写入文件,这对每个人来说都非常非常糟糕。:)
如果你需要生成一个批处理文件,你可以从服务器输出该文件,让用户在本地下载并运行它,但JavaScript在这里没有任何帮助。
我认为您不会找到一种"开箱即用"的方式来使用 javascript 触发本地批处理文件。 我敢肯定,当我完成发布这篇文章时,插件方法已经被提倡,但有很多开发开销。 Chrome也有一些花哨的东西,带有--enable-local-file-access开关,但也有很多警告。(只是把它们扔在那里作为探索的选项)。
您可以考虑只提供一个链接,将.bat文件下载到框中并从那里执行。
编辑我可能说得太早了。 如果你使用的是IE,看起来js/ActiveX解决方案可以满足你的需要。 取自这里。