Windows Terminalを導入した話の続き。
-
Windows Terminal 導入してみた
もともと PowerShell? あの絶望的配色とコマンドレットとかいうよくわかんないやつでしょ? Git BashでLinuxコマンド使うから別にいいやー と無視し続けてきたのですけども。 AWSの ...
続きを見る
普通使いするのもいいけど、どうせなら自動化でタブがモリモリ開いてくようにしたい。
ということでちょこっと動かしてみたけど詰まりました。。。
Windows TerminalというよりはPowerShellの問題な気がするので詳しい人教えてください。
コマンドライン引数
外部から動かすのに必須のコマンドライン引数。
それぞれのドキュメントを見ながらそれっぽいものを探します。
Windows Terminal
公式ドキュメントはこちら。
Windows Terminalということで呼び出すときは
wt.exe
となります。
exeは省略してwtだけでもOK。
Windows Terminalはあくまで各種Terminalの箱なので、引数はタブなどのレイアウトを操作するものが中心になります。
PowerShell
公式ドキュメントはこちら。
PowerShellの呼び出しはそのまま
powershell.exe
となります。
PowerShellはコマンドの大文字小文字を区別しないので、PowerShellでもPOWERSHELLでもOKです。
exeは同じく省略可。
ちなみにPowerShell ISE(統合スクリプト環境)はPowerShell_Iseで呼び出せます。
自動化で外部から動かす場合はあんまり使わないかも?
事前準備
PowerShellのプロファイルを変更する
恐らく初期設定はWindows PowerShellとなっていると思いますが、スペースが入っていると後々コマンドを実行するときにエラーが出る場合があります。
シングルクォーテーションやダブルクォーテーションで囲むことで回避できないこともないですが、面倒なので最初からスペースは消してしまいましょう。
このプロファイルを管理者として実行する
をONにした場合はWindows Terminalを再起動してください。
PowerShellの実行ポリシーを変更する
defaultの設定だとPowerShellのスクリプトファイル(.ps1)を実行したときにエラーが出ます。
以下のどちらかを実行して実行ポリシーを変更します。
1 2 3 4 5 6 7 8 9 10 11 |
# 永続的に変更する場合 # ポリシーを変更するまで有効 Set-ExecutionPolicy -ExecutionPolicy RemoteSigned # 変更したポリシーを元に戻す Set-ExecutionPolicy -ExecutionPolicy Restricted # 一時的に変更する場合 # ウィンドウを閉じたら元に戻る Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope Process |
セキュリティ的によろしくないので使い終わったら設定を戻せと言いますね。
変更してそのままになってる人も結構いると思いますが自己責任で。
私は毎回コマンド打つのが面倒なのでWindows Terminal側の起動設定に追加しました。
これだとWindows Terminal上のPowerShellに限りポリシーが変更されます。
ただ、Shellで新しくWindows Terminal + PowerShellを開いた場合はここの設定がなぜか効かないみたいなんですけどね。。。
新しいインスタンスの動作を変更する
スタートアップ > 新しいインスタンスの動作を
最近使用したウィンドウに接続する
に変えておきます。
これでShellで新しい画面を起動したときに1つのウィンドウに別タブとして追加されます。
PowerShellでWindows Terminalを操作してみる
前提
今回の実行は
Windows TerminalのPowerShell画面
から行うことにします。
VSCodeのTerminalから実行したらエラー出たので。。。
1ウィンドウに3つのタブを開く
こんな感じでコードを書いて.ps1形式で保存します。
日本語が含まれる場合、文字コードがShift-Jisじゃないと文字化けどころかエラーを吐くので注意。
せっかく前回起動時に文字コード変更処理が走るようにしたのに、なぜかコマンドから起動すると反映されないのでchcp 65001を最初に実行してます。
1 2 3 4 |
# Windows Terminalを起動する wt -w 0 nt -p "PowerShell" --title "タブ1つめ" --tabColor "#FF0000" PowerShell -NoExit -Command {chcp 65001; Write-Host "1つめ";} wt -w 0 nt -p "PowerShell" --title "タブ2つめ" --tabColor "#00FF00" PowerShell -NoExit -Command {chcp 65001; Write-Host "2つめ";} wt -w 0 nt -p "PowerShell" --title "タブ3つめ" --tabColor "#0000FF" PowerShell -NoExit -Command {chcp 65001; Write-Host "3つめ";} |
--tabColor "色コード"までがWindows Terminalで、それ以降が開いたタブで実行する内容です。
今回はPowerShellを指定しているのでPowerShellのコマンドを書いています。
-p "PowerShell"の部分はプロファイルの設定 > 名前と同じものを指定してあげないと、フォントや配色などの設定が引き継がれません。
※スペースがあるとエラーになるので注意
実行すると
別のウィンドウが開いて、そこで3つタブが開きます。
なんでその順番なんだ
と思わないでもないですがツッコんだら負けです。
1タブ内を3ペインに分割する
タブじゃなく画面分割する場合はspを指定します。
ちなみにsp = split-pane、nt = new-tabの省略形です。
なぜか最初の1つを3分割するというのができなかったので、2つ目のタブを分割するようにしてます。
1 2 3 4 5 6 7 |
# 1つ開いておく wt # 別タブで3ペインに分割される wt sp -p "PowerShell" PowerShell -NoExit -Command {chcp 65001; Write-Host "1つめ";} wt sp -p "PowerShell" PowerShell -NoExit -Command {chcp 65001; Write-Host "2つめ";} wt sp -p "PowerShell" PowerShell -NoExit -Command {chcp 65001; Write-Host "3つめ";} |
実行するとこう。
ペインを開く方向を縦・横で指定したり、サイズを変えたりとレイアウトを指定できます。
でも自動化する場合は対象画面の指定が複雑になるからあんまり使わないかなぁ。
変数を渡す
コマンドラインで引数を渡し、Windows Terminal上のPowerShellで出力してみます。
1 2 3 4 5 6 7 8 9 10 11 |
# コマンドライン引数受け取り Param( [parameter(mandatory=$true)][string]$str1, [parameter(mandatory=$true)][string]$str2 ) # ①標準出力 Write-Host "${str1}よりも${str2}が好きです" # ②新しくWindows Terminalを開いて標準出力 wt -w 0 nt -p "PowerShell" --title "変数渡し" PowerShell -NoExit -Command {chcp 65001; Write-Host "${str1}よりも${str2}が好きです";} |
実行すると
①実行元のウィンドウでは変数がちゃんと出力されて
②Windows Terminal上のPowerShellでは変数が空になってしまいました。
通常の渡し方だとダメみたいです。
今度は環境変数に入れて渡してみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# コマンドライン引数受け取り Param( [parameter(mandatory=$true)][string]$str1, [parameter(mandatory=$true)][string]$str2 ) # 環境変数に格納 $Env:TmpStrs = "${str1}よりも${str2}が好きです" # ①標準出力 Write-Host $Env:TmpStrs # ②新しくWindows Terminalを開いて標準出力 wt -w 0 nt -p "Windows PowerShell" --title "変数渡し" PowerShell -NoExit -Command {chcp 65001; Write-Host $Env:TmpStrs;} |
①は問題なく出力されて
②もちゃんと出力されました。
【未解決】配列をループして変数を渡す
引数をただ出力しててもしょうがないので、配列に入れた値をループさせて複数画面を起動してみます。
文字列で結合したのをInvoke-Expressionでコマンドとして実行。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# 配列作成 $domains = @( "google.com", "yahoo.co.jp" ) # 配列を1つずつ取り出してループ # 取り出された値は$_に格納される $domains | ForEach-Object { $Env:TmpCommand = "ping ${_}" Write-Host $Env:TmpCommand wt -w 0 nt -p PowerShell --title $_ PowerShell -NoExit -Command {chcp 65001; Invoke-Expression $Env:TmpCommand} } |
文字列としてのコマンドは正しいことを確認。
google用の画面では、ちゃんとGoogleにpingを飛ばしているので問題なし。
Yahoo!のほうは…
なんでGoogleなんだよ。
これあれか。
batchにあった、誰得かわからない悪魔の仕様…
遅延環境変数
ってやつか。
でもPowerShellだと遅延環境変数ないって話みたいだけどな…?
なぜ…?
とにかく解決法がないか試してみます。
ファイル出力して読み込んでみる
環境変数が更新されないなら、ファイルから読み込んだらいいのでは。
ということで、
- ファイルにコマンドを出力(上書きするので常に1行)
- その1行をWindows Terminal側で読み込み
とする作戦。
1 2 3 4 5 6 7 8 9 10 11 |
$domains | ForEach-Object { # 一旦ファイルに出力 Write-Output "ping ${_}" | Out-File "tmpCommand.txt" # ファイルを読み込んで中身を確認 $tmpCommand = Get-Content "tmpCommand.txt" Write-Host $tmpCommand # Windows Terminal側でもファイルを読み込む wt -w 0 nt -p PowerShell --title $_ PowerShell -NoExit -Command {chcp 65001; $tmpCommand = Get-Content "tmpCommand.txt"; Invoke-Expression $tmpCommand} } |
元のウィンドウでちゃんと2つのドメインが出力されることを確認して…
Yahoo!にちゃんとping飛ばしてることを確認して…
GoogleはYahoo!に…
なんでだよ!!
これはForEach-Objectのループが終わった後にWindows Terminalの起動がまとめて走ってるな。。。
Start-Processで起動してみる
これはちょっと、どう書いてもエラーになってしまってうまく動きませんでした。
難しい。
今の状態だと自動化で使用するのは難しそう
自動化で複数サーバーに同時sshみたいな使い方がしたかったんですけどダメそうですねぇ。
Windows TerminalというよりはPowerShellの問題な気がしますが。
PowerShellが得意な人、解決法があれば教えてください。。。