プロデルで自分専用SCPクライアントGUIを作る

今日は、プロデルでSCPクライアントを作ってみます。

プロデルには[SFTP機能プラグイン](https://rdr.utopiat.net/files/plugins.html#sftp)でSCPのファイル転送機能が利用できます。[FTPのファイル転送機能](https://docs.utopiat.net/rdr/manual/network/ftpclient.htm)も標準で利用できます。

SCPは、手元のPC(ローカル)とサーバなどのコンピュータ(リモート)との間でファイル転送するときに使われる通信方法です。ウェブサイトやWebアプリなどのファイルをやり取りするとき使います。かつてはFTPが主流でしたが暗号化などのセキュリティが担保されたSCPが今は主流だと思います。

普段WinSCPを使っていて十分使えますが、Windowsでは便利で使い勝手の良いGUIのファイル転送ツールが少ない気がしています。仮想マシンを使う機会も多くなり、またターミナルでコマンド操作でファイル転送する方が便利な場合も多くなってきたからかもしれません。そこで自分で使える使い勝手の良いSCPクライアントをプロデルで作ってみようと思い立ちました。

## SFTP機能プラグインの種類
SFTP機能プラグインに含まれる「SFTPクライアント」「SFTPファイル」種類を使います。種類に定義された手順と設定項目は、次の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101225/9a2f1885-831c-c614-c859-c4d187cf3a7c.png)

なお、プラグインに含まれる種類のツリーは、プロデルデザイナの「表示」メニューの「ライブラリ」から閲覧できます。

## SSH接続する
まずはファイル転送するためのSFTPクライアントを作り、サーバへ接続します。
なお事前に、接続先のサーバでSSHのサービス(デーモン)を起動しておく必要があります。アカウントの登録も必要です。

接続先のサーバのホスト名,ユーザ名,パスワードを指定します。キーファイルで接続する場合にはプライベートキーのファイルを指定します。拡張子は.pemを指定します。

```
SFTPというSFTPクライアントを作る
SFTPのサーバ名は「」
SFTPのユーザ名は「」
SFTPのパスワードは「」
SFTPのプライベートキーファイルは、「private.pem」
SFTPを接続させる
```

実行するとサーバへSSHで接続されます。

## 今日の影の主役: リストビュー部品
リストビュー部品は、データをリストアップするための部品です。エクスプローラーのファイルを列挙する一覧に使われている部品です。今回はリストビュー部品の主要な機能を一通り使います。

リストビューは、プロデルデザイナの「ウィンドウの設計」画面(フォームデザイナ)で貼り付けられます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101225/8b2a8a19-d6b7-258d-dcae-8d46d2fa1dba.png)

## ファイルリストを列挙する
サーバに接続できたら、指定したパスのファイルとディレクトリの一覧をリストビューに列挙させます。

リモートの特定のディレクトリにあるファイルとディレクトリの情報を取得するには「詳細一覧を取得する」手順を使います。その戻り値として「SFTPファイル」種類の配列が代入されます。

```
【アイテム一覧】は、SFTPで[現在パス]から詳細一覧を取得したもの
```

取得したSFTPファイルの配列をもとにして、リストビューへ項目を「追加する」手順で追加します。追加すると「[リストビュー項目](https://docs.utopiat.net/rdr/manual/wincontrol/listviewitem.htm)」種類のオブジェクトが返されます。別途「詳細」設定項目で、リストビューの詳細表示で表示する内容を設定します。
また「タグ」設定項目へ、追加するときに使ったSFTPファイルのオブジェクトを入れておきます。リストビューの項目を選択した時に、それに対応するファイルのSFTPファイルのオブジェクトを調べられるようにするためです。

```
一覧取得する手順
    マウスカーソルは、砂時計
    ファイルリストビューをクリアする
    ファイルリストビューを更新開始する
    【アイテム一覧】は、SFTPで現在パスから詳細一覧を取得したもの
    もしアイテム一覧が無でなければ
        アイテム一覧のすべてのアイテムについてそれぞれ繰り返す
            もしアイテムのディレクトリなら
                ディレクトリ名は、アイテムのファイル名のファイル名だけ
                もしディレクトリ名が「.」なら繰り返しを続ける
                ファイルリストビューにディレクトリ名をフォルダアイコンで追加する
                    そのタグをアイテムに変える
            他でもしアイテムのファイルなら
                ファイル名は、アイテムのファイル名のファイル名だけ
                拡張子アイコンは、ファイル名からアイコン画像を抽出する
                もし拡張子アイコンが無なら拡張子アイコンは、ファイルアイコン
                ファイルリストビューにファイル名を拡張子アイコンで追加する
                    その詳細を｛アイテムのサイズ, アイテムの最終更新日時｝に変える
                    そのタグをアイテムに変える
            もし終わり
        繰り返し終わり
    もし終わり
    ファイルリストビューを更新終了する
    マウスカーソルは、標準
    パス欄の内容は、現在パス
終わり
```

リストビューの項目に表示するアイコンは、Windows標準のリソースから取得します。
```
ファイルアイコンは「shell32.dll」の0番目からアイコン画像を抽出したもの
フォルダアイコンは「shell32.dll」の3番目からアイコン画像を抽出したもの
```
また、ファイル名を指定すると、その拡張子に対応するアイコン画像を取得できます。
```
拡張子アイコンは、[ファイル名]からアイコン画像を抽出する
```

### 処理中にマウスカーソルを変える
ファイル転送は、リモートと通信するので各操作に多少の時間がかかります。
ユーザに処理中であることがわかるように、マウスカーソルを砂時計に変えます。

```
マウスカーソルは、砂時計
```
処理が終わり、マウスカーソルを元に戻すには次のように書きます。
```
マウスカーソルは、標準
```

ちょっとした工夫で使っているときのストレスや違和感を和らげられます。

## ダウンロード/アップロード機能を実装する

「SFTPクライアント」の「ダウンロードする」手順と「アップロードする」手順を使います。

- SFTPで【リモートファイル名】を【ダウンロード先ファイル名】へダウンロードする
- SFTPで【ローカルファイル名】を【アップロード先ファイル名】へアップロードする

### ダウンロード
リストビューをダブルクリックした時に、リモートからファイルをダウンロードします。リストビューをダブルクリックした時に選択したリストビュー要素は「選択項目」設定項目で調べられます。

```
ファイルリストビューがダブルクリックされた時の手順
    アイテムは、ファイルリストビューの選択項目のタグ
    もしアイテムのファイルなら
        パス欄の内容は、アイテムのファイル名
        保存画面のファイル名は、アイテムのファイル名のファイル名だけ
        保存画面のフィルタを「すべてのファイル|*.*」に変える
        ファイル名は、保存するファイルを選択したもの
        もしファイル名が無でなければ
            SFTPでアイテムのファイル名をファイル名へダウンロードする
        もし終わり
    もし終わり
終わり
```

なお、ダブルクリックした時のイベント手順は、「イベント手順の選択」で作れます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101225/1917a8f3-ee64-9234-bfcf-63e6f975cde9.png)

### アップロード
エクスプローラーからドラッグ&ドロップされたファイルを、リモートへアップロードします。ファイルがドラッグ&ドロップされると「ドラッグドロップされた時」のイベント手順が発生します。

なお、イベントを発生させるためには、ファイルファイルリストビューの「ドラッグドロップ」設定項目を〇にしておく必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101225/42bcd623-b4fe-6056-7e4c-c5055c89e91f.png)


ドラッグされたファイルは、「この時のファイル一覧」で配列で取得できます。配列ですので「それぞれ繰り返す」文で、ファイルをアップロードします。つまり複数ファイルがドラッグされた場合には、ひとつずつアップロードされます。

```
ファイルリストビューがドラッグドロップされた時の手順
    もし現在パスが空なら返す
    【一覧】は、この時のファイル一覧
    マウスカーソルは、砂時計
    一覧のすべてのファイルについてそれぞれ繰り返す
        SFTPでファイルを「[現在パス]/[ファイルのファイル名だけ]」へアップロードする
    繰り返し終わり
    マウスカーソルは、標準
    一覧取得する
終わり
```

## 削除/名前の変更機能を実装する

- SFTPで【ファイル名】を削除する
- SFTPで【ディレクトリ名】を削除する
- SFTPで【対象ファイル名】を【変更後パス】へ変更する
(なお「変更する」手順はファイルの移動も兼ねるためディレクトリ名も含むフルパスで指定します)

### コンテキストメニュー
GUIの各部品には、右クリックしたときに表示するコンテキストメニューを作ることができます。「削除」機能は、コンテキストメニューから呼び出せるようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101225/c798d612-4469-ebad-109b-3d8a30dd04be.png)


コンテキストメニューを表示するには、「コンテキストメニュー」部品をウィンドウに作ります。「ここへ入力」の部分をクリックするとメニュー項目が追加できます。

追加したメニュー項目をダブルクリックすると、そのメニューをクリックしたときの手順が定義されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101225/1aa22d5e-83ad-ff5e-f1d4-6e3812e35c24.png)

またそのメニューを表示させたい部品で「コンテキストメニュー」設定項目に、そのメニューを設定します。この設定項目を設定した部品を右クリックすると、対応するコンテキストメニューが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101225/5e1a1f71-decc-6184-4a75-fa2f00c37e3f.png)

### ファイルの削除
リストビューで選択したファイルを削除できるようにします。
リストビューでは複数の項目を選択できるので、選択したすべてのファイルを調べるためには「選択項目一覧」設定項目を使います。そして「それぞれ繰り返す」文を使って順番にファイルを削除していきます。

```
削除メニューがクリックされた時の手順
    もしファイルリストビューの選択項目が無なら返す
    
    もし「選択したファイルを削除してもよろしいですか？」を質問したものが×なら返す
    マウスカーソルは、砂時計
    ファイルリストビューの選択項目一覧のすべての項目についてそれぞれ繰り返す
        アイテムは、項目のタグ
        もしアイテムのディレクトリなら
            SFTPでアイテムのファイル名というディレクトリを削除する
        他でもしアイテムのファイルなら
            SFTPでアイテムのファイル名を削除する
        もし終わり
    繰り返し終わり
    マウスカーソルは、標準
    一覧取得する
終わり
```

### ファイル名の変更
ファイル名を変更できるようにします。リストビューではエクスプローラーと同じように名前の編集機能があります。リストビューで「ラベル編集」設定項目を○にすることで項目の名前を編集できるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101225/feaddfea-553a-3ce2-865b-005f9f333683.png)

名前が編集された直後に「ラベルが変更された時」イベント手順が発生します。「この時の編集後」で変更後の名前を調べることができるので、この内容をファイル名にしてリモートのファイル名を変更します。

```
ファイルリストビューのラベルが変更された時の手順
    もしファイルリストビューの選択項目が無なら返す
    アイテムは、ファイルリストビューの選択項目のタグ
    SFTPでアイテムのファイル名を「[アイテムのファイル名のフォルダだけ][この時の編集後]」へ変更する
終わり
```

## 完成したプログラム
ファイル転送に必要な機能が一通り実装できました。

動作環境:[プロデル1.9.1164](https://rdr.utopiat.net/files/1.9/index.php?type=exe)

```ファイル転送ツール.rdr
「Produire.Network.SSH.dll」を利用する
ファイルアイコンは「shell32.dll」の0番目からアイコン画像を抽出したもの
フォルダアイコンは「shell32.dll」の3番目からアイコン画像を抽出したもの

SFTPというSFTPクライアントを作る
SFTPのサーバ名は「」
SFTPのユーザ名は「」
SFTPのパスワードは「」
SFTPのプライベートキーファイルは、「private.pem」
ホームは「/var/www/html/」

SFTPを接続させる
メイン画面を表示する
待機する

メイン画面とは
	ウィンドウを継承する
	はじめの手順
		初期化する
		ーー貼り付けた部品に対する操作をここに書きます
		現在パスは、ホーム
	終わり
	初期化する手順
	ーー自動生成された手順です。ここにプログラムを書き加えても消える場合があります
		コンテキストメニュー1というコンテキストメニューを作る
			その位置と大きさを｛32,107,121,64｝に変える
			その移動順を1に変える
			その余白を｛33,2,1,2｝に変える
			更新メニューというメニュー項目をコンテキストメニュー1へ追加する
				その内容を「更新」に変える
			削除メニューというメニュー項目をコンテキストメニュー1へ追加する
				その内容を「削除」に変える
		この実質大きさを｛666,394｝に変える
		この初期位置を「中央」に変える
		この内容を「SCPファイル転送ツール」に変える
		初期化開始する
		ファイルリストビューというリストビューを作る
			その位置と大きさを｛0,26,666,368｝に変える
			その表示方法を「詳細」に変える
			その全列選択を○に変える
			その見出し一覧を｛「ファイル名」,「サイズ」,「日付」｝に変える
			その見出し幅を｛252,107,235｝に変える
			そのラベル編集を○に変える
			その移動順を2に変える
			そのドラッグドロップを○に変える
			そのドッキング方向を「全体」に変える
		ツールバー1というツールバーを作る
			その位置と大きさを｛0,0,666,26｝に変える
			その内容を「ツールバー1」に変える
			その移動順を1に変える
			パス欄という選択リスト部品をツールバー1へ作る
				その表示を○に変える
				その大きさを｛121,26｝に変える
		初期化終了する
		この設計スケール比率を｛144,144｝に変える
		ファイルリストビューのコンテキストメニューをコンテキストメニュー1に変える
終わり
	開いた時の手順
		大きさが変化した
		一覧取得する
	終わり

	-現在パス
	一覧取得する手順
		マウスカーソルは、砂時計
		ファイルリストビューをクリアする
		ファイルリストビューを更新開始する
		【アイテム一覧】は、SFTPで現在パスから詳細一覧を取得したもの
		もしアイテム一覧が無でなければ
			アイテム一覧のすべてのアイテムについてそれぞれ繰り返す
				もしアイテムのディレクトリなら
					ディレクトリ名は、アイテムのファイル名のファイル名だけ
					もしディレクトリ名が「.」なら繰り返しを続ける
					ファイルリストビューにディレクトリ名をフォルダアイコンで追加する
						そのタグをアイテムに変える
				他でもしアイテムのファイルなら
					ファイル名は、アイテムのファイル名のファイル名だけ
					拡張子アイコンは、ファイル名からアイコン画像を抽出する
					もし拡張子アイコンが無なら拡張子アイコンは、ファイルアイコン
					ファイルリストビューにファイル名を拡張子アイコンで追加する
						その詳細を｛アイテムのサイズ, アイテムの最終更新日時｝に変える
						そのタグをアイテムに変える
				もし終わり
			繰り返し終わり
		もし終わり
		ファイルリストビューを更新終了する
		マウスカーソルは、標準
		パス欄の内容は、現在パス
	終わり
	ファイルリストビューがダブルクリックされた時の手順
		アイテムは、ファイルリストビューの選択項目のタグ
		もしアイテムのディレクトリなら
			現在パスは、アイテムのファイル名
			一覧取得する
		他でもしアイテムのファイルなら
			パス欄の内容は、アイテムのファイル名
			保存画面のファイル名は、アイテムのファイル名のファイル名だけ
			保存画面のフィルタを「すべてのファイル|*.*」に変える
			ファイル名は、保存するファイルを選択したもの
			もしファイル名が無でなければ
				SFTPでアイテムのファイル名をファイル名へダウンロードする
			もし終わり
		もし終わり
	終わり
	大きさが変化した時の手順
		もし自分の表示でないなら返す
		パス欄の幅を（自分の実質大きさの幅）-20に変える
	終わり
	パス欄が入力された時の手順
		もしこの時のキー番号が13なら
			現在パスは、パス欄の内容
			一覧取得する
			この時の処理済みは、○
		もし終わり
	終わり
	ファイルリストビューがドラッグドロップされた時の手順
		もし現在パスが空なら返す
		【一覧】は、この時のファイル一覧
		マウスカーソルは、砂時計
		一覧のすべてのファイルについてそれぞれ繰り返す
			SFTPでファイルを「[現在パス]/[ファイルのファイル名だけ]」へアップロードする
		繰り返し終わり
		マウスカーソルは、標準
		一覧取得する
	終わり
	削除メニューがクリックされた時の手順
		もしファイルリストビューの選択項目が無なら返す
		
		もし「選択したファイルを削除してもよろしいですか？」を質問したものが×なら返す
		マウスカーソルは、砂時計
		ファイルリストビューの選択項目一覧のすべての項目についてそれぞれ繰り返す
			アイテムは、項目のタグ
			もしアイテムのディレクトリなら
				SFTPでアイテムのファイル名というディレクトリを削除する
			他でもしアイテムのファイルなら
				SFTPでアイテムのファイル名を削除する
			もし終わり
		繰り返し終わり
		マウスカーソルは、標準
		一覧取得する
	終わり
	ファイルリストビューのラベルが変更された時の手順
		もしファイルリストビューの選択項目が無なら返す
		アイテムは、ファイルリストビューの選択項目のタグ
		SFTPでアイテムのファイル名を「[アイテムのファイル名のフォルダだけ][この時の編集後]」へ変更する
	終わり
	更新メニューがクリックされた時の手順
		一覧取得する
	終わり
終わり
```

## まとめ
プロデルを使って150行程度でGUIのSCPクライアントを作ることができました。SCPの基本部分はプラグインで提供されているため、リスト表示やファイル操作のメニューを作れば、GUIツールを作れます。プログラムをさらに改造すれば痒い所に手が届く自分専用のSCPクライアントを作れるはずです。使い勝手の良いファイル転送ツールを求めている方は、ぜひ改造してみてください。

## 関連記事

https://wp.utopiat.net/2020/03/1898/