「ssh〜」というスキームを要求した時、ターミナルエミュレータが起動するようにする

Last-modified: 2014-08-16 (土) 12:41:50 (1992d)

(独自プロトコルスキームの関連付けを定義する)

Windowsは、例えばクリッカブルURL機能のついたテキストエディタやメーラーで「http://〜」というプロトコルスキームを持つリンクをクリックすると、ブラウザが起動しそのページが表示されます。同様に、「ファイル名を指定して実行」(Windowsキー+R)に、例えば 「http://google.co.jp/」と入力すると、規定のブラウザが起動してそのページが表示されます。

この使用感はとっても便利で、いろいろと融通が利きそうです。今回は、新たに「ssh://〜」というプロトコルスキームが要求されたとき、ターミナルエミュレータ(PuttyやPoderosa等)を起動し、そのsshサーバへアクセスを行うようにします。

レジストリの編集

スキームの関連付けは、レジストリの[HKEY_CLASSES_ROOT\ssh]というキーを追加して行います。

このキーを追加することで、「ファイル名を指定して実行」の中で「ssh://〜」が入力されたとき、[HKEY_CLASSES_ROOT\ssh\shell\open\command]キーのプログラムが起動するようになります。

ただし、ここにそのままターミナルエミュレータの実行ファイルを指定したとしても、引数で与えられた「ssh://〜」を解析できず、サーバに接続できないと思います。そのため、このURLを解析するスクリプトを用意し、このスクリプトが解析したURLをコマンドライン引数として構築し、端末エミュレータへ渡すようにします。ただし、Poderosaの場合はコマンドライン引数を指定しての実行はできない(私が知らないだけか?)と思いますので、一旦XMLファイルを構築し、それをPoderosaに渡すようにします。

url-ssh-handler.reg

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\ssh]
@="URL: SSH プロトコル"
"EditFlags"=dword:00000002
"URL Protocol"=""
"FriendlyTypeName"="@ieframe.dll,-909"

[HKEY_CLASSES_ROOT\ssh\DefaultIcon]
@=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,74,00,25,\
  00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,75,00,72,00,\
  6c,00,2e,00,64,00,6c,00,6c,00,2c,00,30,00,00,00

[HKEY_CLASSES_ROOT\ssh\shell]

[HKEY_CLASSES_ROOT\ssh\shell\open]

[HKEY_CLASSES_ROOT\ssh\shell\open\command]
@=hex(2):77,00,73,00,63,00,72,00,69,00,70,00,74,00,2e,00,65,00,78,00,65,00,20,\
  00,22,00,25,00,55,00,53,00,45,00,52,00,50,00,52,00,4f,00,46,00,49,00,4c,00,\
  45,00,25,00,5c,00,75,00,72,00,6c,00,2d,00,73,00,73,00,68,00,2d,00,68,00,61,\
  00,6e,00,64,00,6c,00,65,00,72,00,2e,00,77,00,73,00,66,00,22,00,20,00,25,00,\
  31,00,00,00

[HKEY_CLASSES_ROOT\ssh\shell\open\command_sub]
@="wscript.exe \"C:\\windows\\url-ssh-handler.wsf\" %l"

拡張子を.reg にしてテキストファイルに保存後、ダブルクリックでレジストリに追加されます。

[HKEY_CLASSES_ROOT\ssh\shell\open\command]キーは、REG_SZ 形式形式でURL解析スクリプトへの絶対パスを指定するか、REG_EXPAND_SZ形式で、環境変数を展開させるかのどちらかが良いと思います。

今回のサンプルでは、REG_EXPAND_SZで、wscript.exe "%USERPROFILE%\url-ssh-handler.wsf" %1 を指定しています(バイナリなので読めませんが)。REG_SZ形式のサンプルは、[HKEY_CLASSES_ROOT\ssh\shell\open\command_sub]キーの中にあります(実際には使わないキーです)。なお、第一引数を表す文字列は、%1でも%lでも(%dでも?)いいようです。どう違うのか、詳しくはわかりません。

URL解析スクリプトの作成

解析するスクリプトは、Windows Scripting Host (wsfファイル) で書きます。環境が用意されているのであれば、pythonやperl、powershellなどでも良いでしょう。今回、私が作成したものはこのようなものです。

url-ssh-handler.wsf

<job>
<script language="JScript">
/*
url-ssh-handler.wsf
ytyng.com

引数で与えられた ssh://user@pass:host:port/ を解析し、
それらの値を引数として端末エミュレータを起動する。

*/

// =====================================================================
// Configuration
// ---------------------------------------------------------------------

APP = "putty"; // putty | teraterm | poderosa
//プログラムの絶対パス。\" で囲う必要は無い。
COMMAND_PUTTY    = "C:\\Program Files\\putty\\putty.exe";
COMMAND_TERATERM = "C:\\Program Files\\teraterm\\ttermpro.exe";
COMMAND_PODEROSA = "C:\\Program Files\\Poderosa\\Poderosa.exe";

// =====================================================================

function die(strExitMessege){
	if(strExitMessege) WScript.Echo(strExitMessege);
	WScript.Quit();
}

//★引数が無い場合は終了
if(!WScript.Arguments.length) die("「ssh://サーバ名」という形で引数を指定してください。");

var wshShell = new ActiveXObject("WScript.Shell");

//URLをパース
url=WScript.Arguments(0);
url=url.replace(/^ssh\:\/\//,""); // ssh://を除去
url=url.split(/\//)[0];           // /以降を除去

// サーバ名とポートを分離
if(url.match(/^(.+)\:(\d+)$/)){
	host = RegExp.$1;
	port = RegExp.$2;
}else{
	host = url;
	port = "";
}

// サーバ名とユーザー名を分離
if(host.match(/^(.+)\@(.+)$/)){
	user = RegExp.$1;
	host = RegExp.$2;
}else{
	user = "";
}
// ユーザー名とパスワードを分離
if(user && user.match(/^(.+)\:(.+)$/)){
	user = RegExp.$1;
	pswd = RegExp.$2;
}else{
	pswd = "";
}

switch(APP){
case "putty": //puttyの場合
	command  = "\""+COMMAND_PUTTY+"\" ";
	if(port) command += "-P " +port+" ";
	if(user) command += "-l " +user+" ";
	if(pswd) command += "-pw "+pswd+" ";
	command += host;
	break;
	//Puttyの場合、デフォルトの設定が自動的に読み込まれる。
	//文字コードや色、ウインドウサイズなどはデフォルト設定が使われる。
case "teraterm": //teratermの場合
	command  = "\""+COMMAND_TERATERM+"\" ";
	command += host+" ";
	if(port) command += "/P " +port+" ";
	command += "/ssh2 ";
	if(user){
		command += "/auth=password ";
		command += "/user="+user+" ";
		if(pswd){
			command += "/passwd="+pswd+" ";
		}else{
			command += "/ask4passwd ";
		}
	}
	command += "/KT=UTF8 /KR=UTF8 ";
	break;

case "poderosa": //poderosaの場合
	command  = "\""+COMMAND_PODEROSA+"\" ";
	//XMLファイルを作成する
	gtsFile = wshShell.SpecialFolders("Desktop")+"\\url-ssh-handler.gts";
	//↑ Desktop もしくは MyDocuments のスペシャルフォルダを使うと良い
	var fso = new ActiveXObject("Scripting.FileSystemObject");
	var fp = fso.CreateTextFile(gtsFile,true);
	fp.WriteLine('<?xml version="1.0" encoding="shift_jis"?>');
	fp.WriteLine('<poderosa-shortcut version="4.0">');
	fp.WriteLine('<Poderosa.Terminal.TerminalSettings encoding="utf-8" transmit-nl="LF" caption="'+host+'" />');
	fp.Write('<Poderosa.Protocols.SSHLoginParameter destination="'+host+'" ');
	if(port) fp.Write('port="'+port+'" ');
	if(user) fp.Write('account="'+user+'" ');
	if(pswd) fp.Write('passphrase="'+pswd+'" ');
	fp.WriteLine('/>');
	fp.WriteLine('</poderosa-shortcut>');
	fp.close();
	command += "-open \""+gtsFile+"\"";
	//ここで作ったファイルは自動的に削除はしない。
	//パスワードを指定して接続した場合、パスワードが平文テキストで残ることになるので注意すること。
	//パスワード接続については http://ja.poderosa.org/faq/15.html
}

//die("host="+host+"\nport="+port+"\nuser="+user+"\npassword="+pswd+"\ncommand="+command); //デバッグ用

wshShell.Run(command);

</script>
</job>

プログラムのパスは各自の環境で異なると思いますので、変更してください。\→\\ となります。後々ダブルクォーテーションで囲うので、上部の定義箇所では空白が含まれるパスでもダブルクォーテーション(\")は必要ありません。

これを、%USERPROFILE% ディレクトリ、つまり、各ユーザーのホームディレクトリに配置します([HKEY_CLASSES_ROOT\ssh\shell\open\command]が指定する場所、ということです)。 WindowsXPの場合は、C:\Documents and Settings\ユーザー名 になる場合が多いと思います。詳しくは、set コマンドや echo %USERPROFILE% で確認できます。

これらの作業により、以下のようなことが実現できます。

  • IEやFirefoxなどのブラウザで、ssh://〜 というリンクをクリックした時、端末エミュレータが起動して接続できる。社内ページなどで便利。
  • SSHのパスワードをパスワード管理ソフトに保存している場合が多いと思いますが、パスワード管理ソフトのURLリンク機能でsshにそのままログインできる。例えば、僕はKeePass?を使っているのですが、KeePass?のURL欄に ssh://ユーザーID:パスワード@ホスト名(IPアドレス)/ の形式で記述しておけば、一覧表示の際にそのURL欄をダブルクリックするだけでSSHサーバにログイン可能。これも激しく便利。
  • Windowsキー+R → ssh://〜 の入力でSSH接続可能。以前のコマンド候補が表示されて、これも便利。ただ、上記には劣る。
  • Windowsのショートカット機能で、ssh://〜 のショートカットを作っておけば、ダブルクリックで起動可能。(PoderosaやTeraTerm?のマクロ機能や、puttyのコマンド引数をしっかり書いたショートカットを作っておけば実現可能なため、アドバンテージはそれほど無い。ソフトウェアを一括切り替えできるのが強みか)

など、地味に快適になります。

ssh接続を1日に何度も行う人は、お試しあれ。