如何在Node.js中注册URL协议处理程序

27
我正在开发一个命令行node模块,并希望能够通过网站上的链接启动它。 我想注册一个自定义协议my-module://,使链接具有以下格式:my-module://action:some-action,点击它们将启动node包。 如果没有针对此的Node API(我确定不会有),那么我是否可以通过调用系统命令从Node中完成呢? 它必须在Windows,Linux和MacOS上工作。

这不是一个 Node API,而是一个浏览器设置。 - hexacyanide
1
@hexacyanide URL协议由操作系统而不是浏览器处理,我已经在Windows上成功实现了它(你需要添加一些注册表键),但想知道是否有跨平台的Node API,而不是分别实现每个平台。 - Daniel Chatfield
这似乎是不一致的,因为协议处理程序可以在Chrome和Firefox中仅通过设置添加。 - hexacyanide
1
@hexacyanide 他们有自己的系统协议包装器,因此网站可以注册自己(然后Chrome会注册自己作为处理程序)。如果您查看Chrome或Firefox处理程序,它只会显示从其中一个内部定义的处理程序 - 如果处理程序不在其内部设置中,则将使用系统处理程序。例如,Spotify、GitHub和iTunes不会在其中列出。 - Daniel Chatfield
我很困惑,您说这是由操作系统完成的。这与node.js有什么关系?这个问题是否类似于https://dev59.com/DnRC5IYBdhLWcg3wFdJx中的自定义协议? - user568109
你不能只是在默认浏览器中打开一个 HTML 文件,然后运行 registerProtocolHandler() 命令吗?或者如果 file:/// 不行的话,在你控制的 URL 上打开...我相信 #start "http://..." 在 Windows 中可行... - dandavis
3个回答

28

这是一个有趣的想法。我认为目前还没有跨平台的node.js解决方案。我找到了一些人询问同样问题的帖子:

https://github.com/rogerwang/node-webkit/issues/951

Electron现在支持使用app.setAsDefaultProtocolClient API(自v0.37.4起)在macOS和Windows上设置默认协议客户端。

编写此库不会很困难。

Windows:

在Windows方面,您需要将应用程序注册为处理该URI方案的应用程序。

您需要为应用程序设置注册表条目:

HKEY_CLASSES_ROOT
   alert
      (Default) = "URL:Alert Protocol"
      URL Protocol = ""
      DefaultIcon
         (Default) = "alert.exe,1"
      shell
         open
            command
               (Default) = "C:\Program Files\Alert\alert.exe" "%1"

然后,在Windows运行您的应用程序时,您应该能够在process.argv[]中看到参数。确保启动一个shell来运行node,而不仅仅是直接运行您的应用程序。

原始MSDN文章

请注意,这需要管理员权限并在系统范围内设置处理程序。要按用户进行设置,您可以使用HKEY_CURRENT_USER\Software\Classes,因为Electron的实现这样做

Apple:

在github评论中引用的“OS X”文章实际上是针对iOS的。我建议查看以下编程指南,了解如何注册应用程序以处理URL方案:

Apple Dev文档

简而言之,您需要创建一个启动服务并使用CFBundleURLTypes填充.plist文件,此字段是数组,应仅填充协议名称,即http

以下Super User问题提供了更好的解决方案,但是它是每个用户的设置。

“您要查找的文件是〜/ Library / Preferences / com.apple.LaunchServices.plist。”

它保存了一个名为LSHandlers的数组,定义LSHandlerURLScheme的Dictionary子元素可以相应地进行修改,以便与LSHandlerRole配合使用。

Linux:

据我所知,在Linux中有几种方法可以完成这个任务(惊喜?)

Gnome有一个工具,可以让您注册一个url处理程序w3 archives

gconftool-2 -t string -s /desktop/gnome/url-handlers/tel/command "bin/vonage-call %s"
gconftool-2 -s /desktop/gnome/url-handlers/tel/needs_terminal false -t bool
gconftool-2 -t bool -s /desktop/gnome/url-handlers/tel/enabled true

一些轻量级的管理器看起来允许您创建虚假的MIME类型并将它们注册为URI协议处理程序。
“为具有各种方案的URI创建虚假MIME类型,例如:application/x-xdg-protocol- 支持特定URI协议的应用程序可以将虚假MIME类型添加到其桌面条目文件中的MimeType键中。因此,通过查看mimeinfo.cache文件,可以轻松找到系统上安装的所有支持URI方案的应用程序。同样,defaults.list文件可用于指定特定URI类型的默认程序。”来自wiki.lxde.org KDE还支持他们自己的处理URL协议处理程序的方法:
创建一个文件:$KDEDIR/share/services/your.protocol,并填充相关数据:
[Protocol] exec=/path/to/player "%u" protocol=lastfm input=none output=none helper=true listing= reading=false writing=false makedir=false deleting=false 来自last.fm论坛(居然是这里)。
希望这可以帮助你。

好的,这似乎回答了MacOS和Windows部分。如果您可以提供有关Linux的更多信息,包括它如何在使用较轻桌面环境的系统上运行,例如Linux上的XFCE和LXDE;我将授予悬赏。(此外,这主要是基于链接的,请在链接失效的情况下引用这些资源。) - Brigand
从研究来看,Windows 可能是最好的处理方式,在 Mac 上应该不会太困难。在 Linux 方面,如果你知道最终用户将使用什么,你应该能够找到一个适当的平衡点,并且也许会有一些系统可以工作。如果你最终创建了这样一个 npm 模块,那将是非常棒的,如果你创建了,请私信我,我很想看看它!我甚至愿意提供编码和测试方面的帮助。 - jeremy
太好了!这非常有帮助。我想我会将所有内容封装在一个节点模块中,并在完成后在此处添加另一条评论。不过,我暂时无法完成这个任务。 - Brigand

4

以下是我在Mac OS上使用NW.js应用程序的方法:

  1. Open the app /Applications/Utilities/Script Editor

    type the following code in the editor

    on open location this_URL
       do shell script "/Applications/X.app/Contents/MacOS/x '" & this_URL & "'"
    end open location
    

    Replace X by the name of your App.

    Save the script as an Application Bundle anywhere

  2. Go to the script, right click then 'Show Package Contents' then edit Contents/info.plist

    Add these lines at the end of the file, just before </dict></plist> :

    <key>CFBundleIdentifier</key>
    <string>com.mycompany.AppleScript.AppName</string> <!-- edit here -->
    <key>CFBundleURLTypes</key>
    <array>
      <dict>
        <key>CFBundleURLName</key>
        <string>AppName</string> <!-- edit here -->
        <key>CFBundleURLSchemes</key>
        <array>
          <string>myurlscheme</string> <!-- your url scheme here -->
        </array>
      </dict>
    </array>
    
  3. You can now open a link starting with myurlscheme: and see your app is opening!


那么你是要制作一个应用程序来打开另一个应用程序吗? 为什么不把那些 info.plist 文件放在你想要打开的应用程序的 info.plist 中呢?这样做不会有任何问题吗? - user773737

3

编辑:

看起来这个模块已经永久改变了注册流程:

const path = require('path');

const ProtocolRegistry = require('protocol-registry');

console.log('Registering...');
// Registers the Protocol
ProtocolRegistry.register({
    protocol: 'testproto', // sets protocol for your command , testproto://**
    command: `node ${path.join(__dirname, './tester.js')} $_URL_`, // this will be executed with a extra argument %url from which it was initiated
    override: true, // Use this with caution as it will destroy all previous Registrations on this protocol
    terminal: true, // Use this to run your command inside a terminal
    script: false
}).then(async () => {
    console.log('Successfully registered');
});

原始回答:

有一个适用于此目的的npm模块。

链接:https://www.npmjs.com/package/protocol-registry

所以在nodejs中,您只需要运行以下代码即可:

首先安装它

npm i protocol-registry

然后使用下面的代码来注册您的入口文件。
const path = require('path');

const ProtocolRegistry = require('protocol-registry');

console.log('Registering...');
// Registers the Protocol
ProtocolRegistry.register({
    protocol: 'testproto', // set your app for testproto://**
    command: `node ${path.join(__dirname, './index.js')}`, // this will be executed with a extra argument %url from which it was initiated
}).then(async () => {
    console.log('Successfully registered');
});

假设有人打开了 testproto://test,那么一个新的终端将被启动执行以下命令:
node yourapp/index.js testproto://test

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接