将消息从浏览器中运行的 Javascript 发送到 Windows 批处理文件



由于我必须使用的架构可能会破坏许多非常好的软件设计规则,我需要从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解决方案可以满足你的需要。 取自这里。

最新更新