【TeraTermMacro】ファイルパス半角スペースによるログイン失敗と対策

##概要

下記で作成したTeraTermMacroにおいて、ログインに失敗する事象が発生しました。

https://qiita.com/AnPanda/items/d64e332fe1b18dbba19c

ファイルパスに半角スペースが入っていたことが原因と考え、
解消に至るまでの四苦八苦をアウトプットします。

※経緯はいいから解消法だけ知りたい、という方は**[【こちら】](#解決策)**からどうぞ。

##エラー内容

事象が発生したメンバーからエラー画面のキャプチャを共有してもらったところ、
エラー表示は**「Link macro first. Use 'connect' macro」**でした。
Connectコマンドを実施していない状態で他のコマンドを打とうとしている、というエラーのようです。

###分析①

ttlファイルを確認すると、ファイルパスが下記のようになっていました。
`C:\Users\taro\OneDrive - 株式会社○○\ドキュメント\password.dat`
`C:\Users\taro\OneDrive - 株式会社○○\ドキュメント\id_key`


OneDrive上のフォルダを参照するようになっています。
最近社用PCの交換があり、**OneDriveでのバックアップ機能**がオンになったため、
今までどおりマイドキュメントに置いたつもりでも、OneDrive上に保存されていたようです。

https://support.microsoft.com/ja-jp/office/windows-10-%E3%81%AF%E6%97%A2%E5%AE%9A%E3%81%A7-onedrive-%E3%81%AB%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E4%BF%9D%E5%AD%98%E3%81%99%E3%82%8B-33da0077-770c-4bda-b61e-8c8e8ca70ac7

このファイルパス、**OneDriveと社名の間に半角スペース**が入っています。
一方、エラーが発生しない＝OneDriveバックアップがオフの状態だと、以下のように半角スペースはありません。
`C:\Users\taro\Documents\id_key`

これが怪しいとアタリをつけ、「TeraTermMacro 半角スペース」で検索してみたところ、下記の記事を発見。
**ファイルパスをダブルクォテーションで囲む**ことで解消するとの情報を得ました。

https://ja.osdn.net/projects/ttssh2/ticket/31971


試しに、半角スペースありのファイルパスでid_keyを参照させてみると、エラーを再現できました。
ttlファイル上でファイルパスをダブルクォーテーションで囲うように編集し、
問題なくログインできることも確認できました。
`keyfile = '"C:\Users\anpanda\OneDrive - 株式会社○○\ドキュメント\id_key"'`


###対策①

**ttlファイル作成用のExcelに対してファイルパスにダブルクォーテーションを追記**し、修正版をメンバーに展開しました。

##不具合再発

しかし、別メンバーから修正版でSyntaxエラーが出ると報告がありました。

再度確認してみると、自分の環境でもSyntaxエラーが再現。
ttlファイルに直接ダブルクォーテーションを追加しての検証は行いましたが、
Excelからttlファイルを作成しての検証を怠っていました。(ポンコツ)

###分析②

修正版Excelで作成されたttlファイルを確認したところ、
ファイルパスのダブルクォーテーションが増殖していることがわかりました。

**Excelの関数**
`="keyfile = '"""&$B$5&"""'"`

**Excel上の表示**
`keyfile = '"C:\Users\anpanda\OneDrive - 株式会社○○\ドキュメント\id_key"'`
→これをttlファイルにコピペすれば、うまく動作する

**ttlファイルに出力されたコマンド**
`"keyfile = '""C:\Users\anpanda\OneDrive - 株式会社○○\ドキュメント\id_key""'"`
→先頭がダブルクォーテーションになっており、TeraTermMacroでSyntaxエラーになる

VBAでファイル書き出しをする時に、ダブルクォーテーションが入っている行に対して、
**自動的にダブルクォーテーションが補完される**機能が働いていると推測しました。

###対策②

対策できませんでした。
VBAの問題だと考えて対処法を探したり、エスケープ文字を置いてみたりしましたが、結局解決せず。

ここで、**TeraTermMacroの実行時にダブルクォーテーションが入っていればよい**、と発想を変えます。

###分析③

Excel上にはダブルクォーテーションを書かずに済ませ、
**TeraTermMacroの処理でダブルクォーテーションを補う**方向で再検討しました。

直接書けないなら文字コードで入れてやればいいと考え、
TeraTermMacroの公式ヘルプから文字コードに関する記述を検索して、
ASCIIコード値を文字列に変換する`code2str`を使うことにしました。

https://ttssh2.osdn.jp/manual/4/ja/macro/command/code2str.html

ダブルクォーテーションの文字コードは`$22`なので、
`code2str dq $22` とすることで、**変数dqにダブルクォーテーションを格納**することができます。

###対策③

keyfileのパスの前後にダブルクォーテーションを付与するには、
`変数dq　+　keyfileのパス + 変数dq`とすればいいはずです。

ただし、変数keyfileを直接編集してしまうと再利用ができなくなるので、
**ユーザが入力したファイルパスは新しい変数keypath**に格納させ、
ダブルクォーテーションをつけたあと変数keyfileに格納するようにしました。

```bash
keypath = 'C:\Users\anpanda\OneDrive - 株式会社○○\ドキュメント\id_key'
code2str dq $22
strconcat keyfile dq
strconcat keyfile keypath
strconcat keyfile dq
```

この状態での変数keyfileの中身は、
`'"C:\Users\anpanda\OneDrive - 株式会社○○\ドキュメント\id_key"'`になります。

ttlファイルを直接編集して、この仕組みでkeyfileがうまく動作することを確認できました。
passwdfileにも同じ仕組みを適用して、Excelファイルに反映させ、テストしてみました。

##うまくいかない

Excelからttlファイルへの出力には問題ない(ダブルクォーテーション増殖なし)ことを確認し、
さっそくttlファイルを実行してみたところ、**「Link macro first. Use 'connect' macro」**が再発しました orz

###分析④

さっきは動作してたのに…と思い、試しにpasswdfile絡みの編集をロールバックしてみたところ、
ちゃんと動作するようになりました。
ここでようやく、**passwdfileとkeyfileの動作が異なるのでは**、という可能性に行きつきました。

手を抜かずに、**想定されるパターンを洗い出してしっかり検証**することにしました。
passwdfileとkeyfileそれぞれに対して、
・パスに半角スペースがある/ない
・パスがダブルクォーテーションで囲まれている/囲まれていない
の計4パターンを検証してみた結果が下記の表です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464218/80b2c429-3da9-a1e6-7654-c240ce4ee22f.png)
**全然別物でした…！**

###解決策

半角スペースの有無によらず正しく動作させる方法は、以下のとおりです。

* **認証鍵ファイル(keyfile)：ダブルクォーテーション<font color="Red">あり**
* **パスワードファイル(passwdfile)：ダブルクォーテーション<font color="Red">なし**

最新版では下記の箇所を修正しました。

```bash
;===変更なし===
passwdfile = 'C:\Users\anpanda\OneDrive - 株式会社○○\ドキュメント\passwd.dat'

;===変数名を変更===
keypath = 'C:\Users\anpanda\OneDrive - 株式会社○○\ドキュメント\id_key'

;===以降、追加===
code2str dq $22
strconcat keyfile dq
strconcat keyfile keypath
strconcat keyfile dq
```

これでExcelからttlファイルを出力して、実行時にエラーが出ないことを検証・確認しました。
旧バージョンでエラーが出ていたメンバーにも確認してもらっているところです。

##まとめ

* OneDriveのフォルダパスには半角スペースが入り、それが悪さをすることがある。
* ファイルパスの読み込み方がすべて同じ挙動とは限らない。
* アタリをつけることは賢明な選択だが、最終的には全パターンを洗い出して検証するべき。
* Excelからファイル出力するときは、ダブルクォーテーションの処理に注意。
* Excelでできないなら、後工程のTeraTermMacroで処理すればいい。