10
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

PowerShell を bat として実行する方法

Last updated at Posted at 2020-03-28

Powershell で作ったツールを簡単に配布してダブルクリックで起動したい

昔(20年くらい?)から私はWSH(VBScript)をよく使っていたのですが、最近の若い者から「今はPowershellですよ。VBScriptなんて、もうすぐ無くなりますよ」と年寄り扱いされたので、去年からPowerShellを使うようになりました。
使ってみるとpowershell は強力なんだけど ps1 ファイルを配布しただけでは、ダブルクリックしても起動しないので、ツールとしては不便を感じていました。

いろいろやってみて WSH(VBScript) みたいにツール単体を配布するだけで簡単に起動できるものが出来たので、投稿します。

.bat にすることで起動方法のバリエーションが増えるので、ツールとしての利便性が格段に上がります。
是非お試しください。
私は powershell で作ったツールは全部この方法で起動してます。一度使ったら止められません。
なお、一回作ったものに機能追加するときは、一旦 .ps1 に変更して ISE でコーディング/デバッグしてから .bat に戻してます。
.ps1 で編集して出来上がったら、.bat をハードリンクで作成しておくと、実行時は .bat 編集時は .ps1 としてエディタで編集できるので便利です。

作り方

  • powershell を普通に(Windows Powershell ISE などで).ps1 で作ります。
  • パラメータで渡したいものは、変数 $parm[0..8] にセットされている前提で作ってください。
  • 以下の HelloWorld.bat の最後の1行(Write-Host の行)以外の部分を .ps1 の頭の部分に挿入します
  • ファイル名を .bat に変更します
  • ファイルをメモ帳で開いてみて UTF-8 だった場合は、ANSI (Shift_JIS) で保存しなおします。
  • 実行用の.bat をハードリンクで作ります。=> DOS 窓を管理者権限で開いて、mklink /H xxxxxx.bat xxxxxx.ps1
HelloWorld.bat
:DUMMY for($i=1;$i -eq 0;$i++) {echo DUMMY} <#
@rem 上の行は batでは(goto されない)ラベル。
@rem パワーシェルでは(条件は常にfalseで実行されない)ラベル付きfor
@rem bat でも パワーシェルでもエラーにならずに、パワーシェルにとってのコメントブロックを開始。
@rem 2行目以降は bat を実行するエリア。パワーシェルから見れば単なるコメントブロック。
@rem /C オプションのときは bat は待たずに終了。オプションがなければ PAUSE で待つ。
@rem bat に渡された引数は、パワーシェルに$parm[0..8]で渡す。

@echo off
set ME=%~dpnx0
rem /C オプションの有無をチェック
if /i CHK%1==CHK/C (
  set CHK=EXIT
  shift
) else (
  set CHK=PAUSE
)
rem パワーシェルを実行。自分自身をコマンドの入ったテキストとして取込んで実行。
powershell -ExecutionPolicy RemoteSigned -Command "Invoke-Expression -Command (@('$parm=@(\"%1\",\"%2\",\"%3\",\"%4\",\"%5\",\"%6\",\"%7\",\"%8\",\"%9\")') + (Get-Content '%ME%') -join \"`n\")"
if /i %CHK%==EXIT exit /b
pause
exit /b
bat のエリアは、exitまで。ここから先は(exit後なので)bat にとっては単なるゴミ #>
# ここから下はパワーシェルの領域

Write-Host "Hello World!"

.bat の中にコメント(rem 文)を入れてあります。何をやっているのかは、そちらをご覧ください。

最大のポイントは1行目。powershell のブロックコメント <# を始めたかったのですが、不用意に書くと bat でリダイレクトとして認識されてしまうので、これを避けるために工夫してます。
これ以外の書き方もあると思います。誰か、もっとカッコいい方法があったら教えてください。

パラメータ渡しのサンプル tail.bat

(長いログファイルの最後の部分だけ見たかったので作りました)
powershell へのパラメータの渡し方のサンプルとして、tailコマンドの例を以下に添付します。
サンプルでは input のファイルをパラメータとして渡してます。

tai.bat の使い方は以下の通り、いろいろな起動方法で実行できるので、ps1 より格段に便利です。

  • tail.bat をダブルクリックして実行して、コマンドラインからファイル名を手で入力する
  • 入力のtxtファイルをマウスでドラッグして、tail.bat の上にドロップする
  • コマンドラインからコマンド入力=> [パス]tail [/C] [/N 行数] [ファイル名]
  • バッチファイルの中から呼ぶ=> CALL [パス]tail.bat /C [/N 行数] ファイル名
tail.bat
:DUMMY for($i=1;$i -eq 0;$i++) {echo DUMMY} <#
@rem 上の行は batでは(goto されない)ラベル。パワーシェルでは(条件は常にfalseで実行されない)ラベル付きfor
@rem bat でも パワーシェルでもエラーにならずに、パワーシェルにとってのコメントブロックを開始したかっただけ。
@rem 2行目以降は bat を実行するエリア。パワーシェルから見れば単なるコメントブロック。
@rem /C オプションのときは待たずに終了。オプションがなければ PAUSE で待つ。
@rem bat に渡された引数は、パワーシェルに$parm[0..8]で渡す。

@echo off
set ME=%~dpnx0
rem /C オプションの有無をチェック
if /i CHK%1==CHK/C (
  set CHK=EXIT
  shift
) else (
  set CHK=PAUSE
)
rem パワーシェルを実行。自分自身をコマンドの入ったテキストとして取込んで実行。
powershell -ExecutionPolicy RemoteSigned -Command "Invoke-Expression -Command (@('$parm=@(\"%1\",\"%2\",\"%3\",\"%4\",\"%5\",\"%6\",\"%7\",\"%8\",\"%9\")') + (Get-Content '%ME%') -join \"`n\")"
if /i %CHK%==EXIT exit /b
pause
exit /b
bat のエリアは、exitまで。ここから先は(exit後なので)bat にとっては単なるゴミ #>
# ここから下はパワーシェルの領域

# Write-Host "受け取ったパラメータ" ($parm[0..8] -join ", ")
# パラメータから /N スイッチをチェックして行数をセット。デフォルトは10行
$idx=0
if ($parm[$idx] -eq "/N") {
  $idx++
  $num=$parm[$idx]
  $idx++
} else {
  $num=10
}
# ファイル名を取得
if ($parm[$idx] -eq "") {
  $mymsg = "`r`ntail [/C] [/N 行数] [ファイル名] : ファイルの最後のn行(デフォルト10行)を出力。/C でpauseせずに画面を閉じます`r`n`r`n"
  $current=Get-Location
  $mymsg = "$mymsg `r`nカレントフォルダ $current `r`n`r`n対象ファイルの PATH を入力してください"
  $input = Read-Host $mymsg
} else {
  $input = $parm[$idx]
}
if ($input -eq ""){
  Write-Host "`r`nファイル名が空です`r`n`r`n"
  exit
}
if (Test-Path $input) {
  $fullpath = $input
} else {
  Write-Host "`r`n$input が見つかりません`r`n`r`n"
  exit
}

# ファイルの最後のn行を取得
Get-Content -Path $fullpath -Tail $num

##あとがき

昔これと同じ発想で perl を起動していました。当時は perl 結構流行ってたんですよね。最近あまり見かけませんね。
Power shell は何でもできるのは運用周りのスクリプトとして優れてますが、やっぱりとっつきにくいですよね。コマンドが独特で。

こちらのwebsiteもよろしくお願いします。
[初心者のためのWEBシステムのインフラ構築]

10
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?