PowerShellスクリプト実行支援cmd

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でも使用可能

 

こいつを…


こうぢゃ!

作ってみた

psrun.cmd

@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のパスにスペースが入る場合、シングルクォーテーションで囲って先頭にアンパサンドを付ける必要がある

PowerShellの使い方 #PowerShell – Qiita

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です