ブラウザにはセキュリティを確保するために様々な制約があります。
例えば「ブラウザ上のボタンをクリックするとイラストレータが立ち上がって指定したファイルを開く」という動作をさせたくても出来ません。
「ボタンをクリックすると、ハードディスク上のファイルを別の場所に移動する」ということもできません。
しかしながら、今回の案件ではそれを実現する必要がありまして、なんとかせねばならなくなりました。
もちろん通常の方法では実現できませんので(出来たらとんでもないセキュリティホール)、多少クライアントPCに細工を施して実現しました。
オリジナルの「URLスキーム」をPCに登録して、ブラウザからPCを操作する
スマホでウェブサイトを見ているとき、リンクをタップするとApp StoreやGoogle Palyのアプリが開くことがありますよね。地図のアイコンをタップするとマップアプリが立ち上がったりとか。
あれは、「URLスキーム」という仕組みによるものです。
ウェブサイトへのリンクは「http://~」という記号で始まりますが、この「http://」がURLスキームです。「http://」から始まるアドレスを見つけたら、ウェブサイトから情報を取ってきてブラウザで表示するという風にOSに設定がされています。
ちなみに「comgooglemaps://」はGoogleMapsアプリのURLスキームです。ウェブサイト上にこのURLから始まるリンクを張ると、スマホであればタップするとGoogleMapsアプリが起動します。
あまり知られていないのですが、実はWindowsOSやMacOSでもURLスキームを使うことができます。あいにくMacは詳しくないのですが、Windowsの場合はレジストリに設定を書き込むことで、オリジナルのURLスキームを使用できるようになります。
ブラウザから、ローカルにインストールしたRubyに指令を送る
今回は、独自のURLスキームを登録して、Rubyのスクリプトを実行させることにしました。
例えば「chikuwa://」というURLスキームを登録してみます。
以下の内容のレジストリファイルを作って保存します。
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\chikuwa]
@="URL:Chikuwa Protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\chikuwa\shell]
[HKEY_CLASSES_ROOT\chikuwa\shell\open]
[HKEY_CLASSES_ROOT\chikuwa\shell\open\command]
@="\"wscript.exe\" \"C:\\MyApps\\app.vbs\" \"%1\""
このレジストリファイルをダブルクリックすると、レジストリに情報が書き込まれます。「chikuwa://」というURLスキームがOSに登録され、「chikuwa://」で始まるURLをクリックする度に「C:\MyApps\app.vbs」が実行されるようになります。
なんでRubyじゃなくてVBSなんだと思われるかも知れませんが、これには理由があります。
レジストリに、実行するプログラムのパスを登録する必要があるのですが、フルパスで指定する必要があるのです。もし、Rubyのバージョンアップなどでパスが変わると動かなくなってしまうので、何か対策が必要です。環境変数にRubyのパスを通しておけば良さそうなものですが、残念ながらダメなのです。
いろいろ調べたところ、VBSについてはフルパスで指定する必要がないようです。VBSからRubyを呼び出す場合は、環境変数にRubyのパスが通っていれば問題なく動作するので、 一旦VBSを経由させることで解決しました。
ちなみにapp.vbsの中身はこんな感じです。シェルからrubywを引数付きで呼び出すだけのごくシンプルなプログラムです。
Option Explicit
Dim ws
Set ws = WScript.CreateObject("WScript.Shell")
ws.Run "rubyw ""C:\MyApps\app.rb"" " & WScript.Arguments(0)
Rubyへの引数として、呼び出し元のURLを渡しています。つまり、「chikuwa://」の後に文字情報をつなげれば、スクリプトにパラメータを引き渡すことができます。JavaScriptで配列のパラメータをjsonエンコードし、さらにencodeURIComponentでURIエンコードしたものを「chikuwa://」の後につないで渡してやります。
Rubyでは、以下のようにすればパラメータを受け取ることができます。
require 'uri'
require 'json'
m = ARGV[0].match(/^chikuwa:\/\/(.+)\//)
params = JSON.parse(URI.unescape(m[1]))
あとは、好きなようにファイルの操作をすればOKです。
ホームページの制作(デザイン・コーディング・プログラミング)に加え、ネットショップの販売促進に関するアドバイスも致します。 20年以上に渡って実際にネットショップを運営した経験を生かし、聞きかじりではない実績を伴ったノウハウを、自分の言葉でお伝えいたします。 プログラミングの経験は30年以上。HTML、CSS、JavaScript、TypeScript、Vue、NuxtJS、Node.js、MySQL、MongoDB、Elasticsearch、WordPress、PHP、Docker、Electronなど、幅広く対応します。
コメント