PowerShellでps1を実行するのに、いちいち実行ポリシーを気にしながら使うのが面倒で、cmd(bat)でラッパーを作ったので、置いておく。
もくじ
ps1ファイルはそのままでは実行できない
Powershellのスクリプトは.ps1ファイルに書く。しかしそのままでは実行ポリシーによりスクリプトの実行は制限されている。
実行ポリシーについて – PowerShell | Microsoft Learn
ProcessスコープのExecutionPolicyを変更すれば、一時的にスクリプトの実行を許可できる。そのプロセスが終了すれば、設定に残ることもないので環境を変えずに使える。
PowerShellのExecutionPolicyのスコープとかについて詳しく #PowerShell – Qiita
要するに…
環境変数 PSExecutionPolicyPreference に Bypass(実行可能なスコープなら何でもOK)をセットして、powershellからps1を呼び出す
set PSExecutionPolicyPreference=Bypass
powershell .\hello.ps1
あるいはpowershellに -ExecutionPolicy Bypass ってオプションを付けて実行すれば良い。
powershell -ExecutionPolicy Bypass .\hello.ps1
毎回入力出来なくはないけど、ちょっと面倒くさい。
面倒なのは嫌なのでcmdで自動化することにしました
これをいちいちコマンドラインで実行するのも面倒なので、cmdでラッパーを作った。
出来ることはこんな感じ
- 引数にps1ファイルを渡すと、Processスコープで実行ポリシーを変更して、スクリプトを実行
- -adminオプションを付けると、非管理者の場合、管理者権限への昇格を要求
- 相対パスでファイルを指定した際、ファイル名から始まる場合は先頭に.\を自動補完
→ cmdコンテキストで、Tabキーで補完入力した場合もそのまま実行可能! - 引数%1にps1ファイルを渡すだけで動くので、 ps1ファイルをこのcmdにD&Dでも使用可能
こいつを…
こうぢゃ!
作ってみた
@echo off
setlocal
set PSExecutionPolicyPreference=Bypass
set Version=20240825
:optioncheck
IF /i "%~1" == "-?" (shift & goto help)
IF /i "%~1" == "-help" (shift & goto help)
IF /i "%~1" == "-command" (set PS1=%~2& shift & shift & goto optioncheck)
IF /i "%~1" == "-admin" (set ADMIN=1& shift & goto optioncheck)
IF /i "%~x1" == ".ps1" (set PS1=%~1& shift & goto optioncheck)
:optionCheckFinished
rem ps1ファイルチェック
IF "%PS1%" == "" (echo .ps1ファイルが指定されていません & goto finish)
IF NOT EXIST "%PS1%" (echo 存在しない.ps1ファイルが指定されました & goto finish)
rem 入力値チェック (?: | \\ | .\ | ..\) で始まらない場合、先頭に .\ を付与
echo %PS1% | findstr /r /v "^.: ^\\\\ ^\.\\\\ ^\.\.\\\\" >NUL
if "%ERRORLEVEL%"=="0" (
set PS1=.\%PS1%
)
:run
echo Running "%PS1%"
if "%ADMIN%"=="1" (CALL:admin "%PS1%") else ( powershell.exe ^&'%PS1%' )
goto finish
:help
echo ps1ファイル実行支援
echo Version: %Version%
echo.
echo psrun [-command] ps1 file [-admin]
echo.
echo -command 実行するps1ファイルを指定します。引数を省略して直接ファイルを指定することも可能。
echo -admin 管理者権限を持たない場合、昇格を要求します。
echo.
goto finish
:admin
rem 管理者権限実行サブルーチン
rem 1. powershellコンテキストに切り替え
rem 2. Start-Processで管理者権限のpowershellを呼び出し
rem 3. %PSExecutionPolicyPreference% を管理者権限のpowershellに引き継ぎ
rem 4. 現在のディレクトリに移動(やらないと相対パスでの実行がエラー)
rem 5. %~1(PS1)を実行
whoami /priv | find "SeDebugPrivilege" > NUL
if %ERRORLEVEL% neq 0 (
powershell.exe "Start-Process powershell.exe -ArgumentList '-ExecutionPolicy %PSExecutionPolicyPreference% -Command cd ''%CD%'' ; &''%~1''' -Verb runas"
) else (
powershell.exe ^&'%~1'
)
exit /b
:finish
endlocal
使い方
psrun.cmd -help
ps1ファイル実行支援
Version: 20240825
psrun [-command] ps1 file [-admin]
-command 実行するps1ファイルを指定します。引数を省略して直接ファイルを指定することも可能。
-admin 管理者権限を持たない場合、昇格を要求します。
あとがき
管理者権限で実行する時に、引数を入れ子にする関係で、”と’の処理が地味に面倒くさかった。
「ScopeがBypassなのはどうなのか?」と思うかもしれないが、そもそもcmdコンテキストを実行する権限があるなら、環境変数やpowershellの引数はいくらでも弄れるはずなので、気にするならそれ以外の部分を気にすべきと思う。
冒頭でも書いたが、変更するのはProcessスコープだけなので、元の環境は一切変えないのがこのやり方の良いところ。
参考文献
管理者権限への昇格プロンプトの出し方
バッチを自動で管理者権限で実行する方法 #Windows – Qiita
ps1のパスにスペースが入る場合、シングルクォーテーションで囲って先頭にアンパサンドを付ける必要がある