Poderosa 複数自動SSH接続マクロ（パスワード入力フォーム使用）

## はじめに
Poderosaの複数自動SSH接続のマクロです。
パスワードはベタ書きでもいいのですが、セキュリティ上不安なので入力フォームからでも入力できるようにしました。
一度入力したパスワードを次の接続先に使いまわすかどうかも選択できます。
あとは、エラーでも処理が止まらないようにしました。トレースウィンドウを表示し、そこでエラーの内容を確認できます。

## マクロ内容
Poderosaマクロは、JScript.NET などの .NET 対応言語で記述することができます。
以下のマクロファイルの文字コードは UTF-8 で作成してください。（入力フォームが文字化けするため。）
config の HOSTS （接続先リスト）を自身の環境に合わせて変更してください。

```js:autologin.js
/**
 * Poderosa 複数自動SSH接続マクロ
 */
import Poderosa;
import Poderosa.ConnectionParam;
import Poderosa.Terminal;
import Poderosa.Macro;
import System;
import System.Threading;
import System.Windows.Forms;
import System.Drawing;

var env = new Environment();

// <<<<<<<< Config Start
// デフォルト値
//   ENCODING_TYPE : 文字エンコード
//                   EncodingType.ISO8859_1
//                   EncodingType.UTF8
//                   EncodingType.EUC_JP
//                   EncodingType.SHIFT_JIS
//   NEW_LINE      : 改行コード
//                   NewLine.CR   = \r
//                   NewLine.LF   = \n
//                   NewLine.CRLF = \r\n
//   PORT          : ポート番号
//   PROMPT        : コマンドプロンプト
//                   ※この文字が表示されるまでコマンド実行を待機する
//   TIMEOUT       : ReceiveData取得のタイムアウト（秒）
var ENCODING_TYPE = EncodingType.UTF8;
var NEW_LINE      = NewLine.LF;
var PORT          = 22;
var PROMPT        = '$';
var TIMEOUT       = 5;

// 一度入力したパスワードを次の接続先にも使いまわす
var SHARE_PASSWORD = true;

// 完了メッセージの表示
var SHOW_COMPLETION_MESSAGE = true;

// エラー時に表示されたトレースウィンドウを処理終了後に自動で閉じる
var CLOSE_TRACE_WINDOW = true;

// 接続先リスト
//   ※必須項目は title, host, id です。
//   ※ pass が定義されていない場合は入力フォームの入力値を使用します。
//   ※複数のコマンドを実行する場合は && などでつなげてください。
var HOSTS = [
    {
        title : 'Sample',
        host  : '192.168.1.1',
        id    : 'testuser',
        cmd   : 'ls -l'
    },
    {
        title   : 'Sample2',
        host    : '192.168.1.1',
        id      : 'root',
        pass    : 'password',
        port    : 2022,
        cmd     : 'cd /root/work && ls -l',
        prompt  : '#',
        encode  : EncodingType.SHIFT_JIS,
        newline : NewLine.CRLF
    },
];
// >>>>>>>> Config End

// SSH接続処理
ssh_connect();


/**
 * パスワード入力フォーム
 */
class MyForm extends Form
{
    var textbox : TextBox;
    var button  : OKButton;
    var password = '';

    public function MyForm() {
        textbox = new TextBox();
        textbox.Location = new Point(8, 8);
        textbox.Size = new System.Drawing.Size(192, 19);
        textbox.PasswordChar = '*';
        textbox.Text = '';
        Controls.Add(textbox);

        button = new OKButton();
        button.Location = new Point(205, 8);
        button.Size = new System.Drawing.Size(64, 23);
        button.Text = '接続';
        Controls.Add(button);

        ClientSize = new System.Drawing.Size(274, 38);
        StartPosition = FormStartPosition.CenterScreen;
        MaximizeBox = false;
        MinimizeBox = false;
        Text = '';
    }

    // OKボタン
    class OKButton extends Button
    {
        protected function OnClick( e : EventArgs ) {
            password = MyForm( Parent ).textbox.Text;
            MyForm( Parent ).Close();
        }
    }
}


/**
 * SSH接続
 */
function ssh_connect() {
   var f : MyForm = new MyForm();
   var password = '';
   
   // SSH接続
   for (var i = 0; i < HOSTS.length; i++) {
       var port    = (!HOSTS[i].port) ? PORT : HOSTS[i].port;
       var prompt  = (!HOSTS[i].prompt) ? PROMPT : HOSTS[i].prompt;
       var encode  = (!HOSTS[i].encode) ? ENCODING_TYPE : HOSTS[i].encode;
       var newline = (!HOSTS[i].newline) ? NEW_LINE : HOSTS[i].newline;

       var connect_info = HOSTS[i].id + '@' + HOSTS[i].host + ' (port ' + port + ')';

       if (!HOSTS[i].pass) {
           if (!(SHARE_PASSWORD && f.password !== '')) {
               f.textbox.Text = '';
               f.Text = connect_info;
               f.ShowDialog();
           }
           password = f.password;
       } else {
           password = HOSTS[i].pass;
       }

       try {
           var con = connect(
               HOSTS[i].host,
               ConnectionMethod.SSH2,
               port,
               encode,
               newline,
               HOSTS[i].id,
               password,
               HOSTS[i].title
           );
           // コマンドの実行
           if (HOSTS[i].cmd) {
               if (wait(prompt, con)) {
                   con.TransmitLn(HOSTS[i].cmd);
               }
           }
       } catch (e) {
          env.Debug.ShowTraceWindow();
          env.Debug.Trace('SSH失敗 : ' + connect_info);
          env.Debug.Trace(e);
       }
   }

    // 処理完了
    if (SHOW_COMPLETION_MESSAGE) env.Util.MessageBox('Done!');
    if (CLOSE_TRACE_WINDOW) env.Debug.HideTraceWindow();
}


/**
 * ホストに接続
 */
function connect(host, method, port, encoding, newline, id, password, title) {
    var param = new SSHTerminalParam(method, host, id, password);
    param.Caption = title;
    param.Port = port;
    param.Encoding = encoding;
    param.TransmitNL = newline;
    var connection = env.Connections.Open(param);
    return connection;
}


/**
 * 特定の文字が表示されるまで待機
 */
function wait(s, connection) {
    var line = '';
    while(line.indexOf(s) == -1) {
        var data = connection.ReceiveData(1000 * TIMEOUT);
        if (data == null) {
            env.Debug.ShowTraceWindow();
            env.Debug.Trace('Timeout');
            return false;
        }
        line += data;
    }
    return true;
}
```
## 参考URL
以下のコードが参考となりました。ありがとうございます。
- https://github.com/cdesjardins/poderosa/blob/8800a0d76142d586f93d084d667cb419fcc661ea/Macro/TerminalParam.cs
- https://github.com/cdesjardins/poderosa/blob/8800a0d76142d586f93d084d667cb419fcc661ea/TerminalEmulator/TerminalUtil.cs
- https://github.com/cdesjardins/poderosa/blob/8800a0d76142d586f93d084d667cb419fcc661ea/Usability/RenameTabBox.cs
- https://github.com/poderosaproject/poderosa/blob/51aa928aa86ef8155159d8bfddd805803872b05f/Misc/Macro/Sample/run-commands.js
- https://github.com/VirusFree/Poderosa/blob/4a56882fb73ade82d759764f02c256586f7cecd2/Misc/Macro/Sample/run-script.js
- http://goldblog.jp/developer/1182.html
- http://blog.code4u.org/archives/589
- https://blog.gti.jp/post-159
- http://qiita.com/super-hot-engineer/items/ec21bc0785ca17aea1d7
- http://qiita.com/imp954sti/items/87d9226c7771205b5f12