PowerShellスクリプトの起動バッチつくってみた


はじめに

自分はPowerScriptで簡単なツールを作るさいにバッチファイルのクリックから実行できるようにすることが多いです。

こうすることで、ショートカット化してスタートメニューに置いておくことで簡単に呼び出せたり、コンソールを自分で開いたり閉じたりする必要がなくなるのでそこそこ便利だと思います。

ただ毎回0からバッチファイルやフォルダ構成を準備するのは面倒だな~、ということでテンプレート構成を作ってみました。

この記事では構成や中身について詳しく書いてみようかなと思います。

構成

テンプレートの構成は以下のような形にしてみました。

テンプレート構成
<アプリ名フォルダ>
├ main.lnk
├ README.txt
├ src
│ ├ main.bat
│ └ main.ps1
├ lib
│ └ hoge.ps1
└ img
  └ favicon.ico

main.bat が起動バッチで、PowerShellスクリプトのエントリーポイントが main.ps1 です。

実際の処理内容は直接 main.ps1 に書くか、別スクリプトにまとめて呼び出すことになるかなと思います。
まあ、複雑な処理を書くことは少ないと思うので lib にスクリプトモジュールをいくつか入れて main.ps1 でそれを使って何かする、みたいなコードになることが多い気がします。

main.lnk, src/main.bat

main.lnksrc/main.bat のショートカットです。
アプリっぽくするためにbatファイルにアイコンを設定したかったのですが直接はできないようなので、代わりにショートカットを作ってそれにアイコンを設定する方法をとることにしました。(完全におまけです)

2021-09-21追記
main.ps1の中で管理者権限が必要な処理を記述する場合はmain.batを管理者権限で実行する必要がありますが、main.lnkを管理者権限で実行することはできないので、その時はmain.batをそのままルートディレクトリに配置するとよいと思います。

配布の可能性を考慮して、ショートカットのリンク先は以下のように環境変数・Explorer・相対パスを使って記述しました。こうすることで環境に依存しないショートカットにすることができます。

main.lnkのリンク先
%windir%\explorer.exe ".\src\main.bat"

main.bat の中身は PowerShell でmain.ps1を実行する処理だけです。

main.bat
cd %~dp0/../
powershell -ExecutionPolicy Unrestricted -NoProfile -WindowStyle Hidden ./src/main.ps1

cd %~dp0/../ ではカレントディレクトリをツールのルートディレクトリに設定しています。これによってスクリプト内では Get-Location でツールのルートディレクトリを取得できます。

-ExecutionPolicy Unrestricted ではPowerShellスクリプトの実行ポリシーを制限なしに設定しています。デフォルトの実行ポリシーではスクリプトを実行できないようになっているのでそれをアプリの実行時のみ解除しています。
ちなみに実行ポリシーの種類については こちらの記事 なんかが詳しいです。

-NoProfile では既存プロファイルの読み込みをスキップしています。プロファイルに自作コマンドなどを設定している場合、それがアプリに干渉する可能性があるので念のため設定しています。

-WindowStyle Hidden ではbatとPowerShellを実行するコマンドプロンプトを表示しないよう設定しています。
もし処理内容がコマンドラインベース(コマンドラインの入力を読み取る、コマンドラインにログを表示するなど)の場合はこのオプションを外してください。Start-ProgressInvoke-WebRequest のように進捗がコンソール上に表示されるコマンドを使う場合もこのオプションを外さないと何も表示されないので注意してください。(1敗)

%~dp0/main.ps1 ./src/main.ps1 はエントリーポイントなるPowerShellスクリプトです。1行目でカレントディレクトリを設定しているので ./src/main.ps1 でも十分ですね。

2021-09-21追記
main.ps1を指定するときのパスは相対パスに変更しました。
ツールのパスにスペースが入っている場合、cdは正常に動きますがpowershellの引数はスペースまでの部分しか認識してくれないようでした。他にダブルクォートで囲むなどの対策もある気がします。

README.txt

README.txt はアプリのドキュメントです。

自分の場合、とりあえず以下のことを書くように意識しています。

  • About : どんなアプリなのか
  • Usage : どうやって使うのか

また、ライセンス表記や変更履歴も必要に応じて記述するとよいと思います。(GitHubで管理する場合はコミットログやLICENSEファイルがあるので不要ですね)

src/main.ps1

main.ps1main.bat から呼び出されるエントリーポイントです。

main.ps1 からsrc配下のファイルやlib配下のファイルを読み込むときはカレントディレクトリから取得することができます。

lib配下のスクリプト実行例
$ROOT = (Get-Location).Path
. "${ROOT}/lib/hoge.ps1"

img/favicon.ico

アプリっぽさを出すためのおまけ要素です(笑)。

アイコンをオリジナルなものに変更することでアプリっぽさが格段に向上します。

アイコンは ここ とか ここ で処理内容がわかるような画像を入手して、ここ でico形式に変換する、というのが自分がよくやる手段です。
(アイコンサイズは最低でも16x16と32x32があったほうがいいらしい)

2021-09-21追記
アイコンのパスは絶対パス指定で、対象アイコンを移動させても自動で参照先が変わらないです。なのでディレクトリ名を変えたりツールを配布したときにアイコンが外れてしまいます。それでももし面倒でなければ、個人的に使う場合は適宜アイコンを設定して下さい。また配布を考えている場合は設定したパス名(≒自分のユーザ名など)が配布相手に伝わることに気を付けてください。

さいごに

今回作ったテンプレート構成をベースに自分でもいろいろと作っていて、ある程度まとまった段階でGitHubに挙げているので気になる方はぜひチェックしてみてください。

あと、アプリを作る際に使えそうなスクリプトモジュールもぽつぽつと作っているのでこちらもよろしければどうそ。