PowerShellを埋め込んだバッチファイルをネットワーク上から管理者権限で実行する

会社でちょっとした便利スクリプトを作ったのだが、ユーザにはネットワーク上に置いたものをそのままダブルクリックで実行できるようにしたかった。

バッチファイルにPowerShellを埋め込んで1ファイルにした上で管理者権限で起動するものは既存のものが見つかったのだが、 管理者権限でネットワークの資格情報が引き継がれない場合に管理者権限での起動に失敗してしまうため、自分自身をローカルドライブにコピーしてから起動するようにするスニペットを作成した。

参考にさせてもらったサイトをもとに、

  • 管理者権限無しでバッチファイルを起動したときに、ユーザのデスクトップフォルダに自分自身をコピーしてからデスクトップ上のバッチファイルを管理者権限で起動する
  • 自分自身の11行目以降をPowerShellコードとして実行した後、最後に自分自身を削除する

という動作するコードが以下。

@ECHO OFF
cd /d %~dp0
whoami /priv | find "SeDebugPrivilege" > nul
if %errorlevel% neq 0 (
 COPY /Y "%~0" "%USERPROFILE%\Desktop\%~nx0"
 @powershell start-process "%USERPROFILE%\Desktop\%~nx0" -verb runas
 exit
)
@powershell -NoProfile -ExecutionPolicy Unrestricted "$s=[scriptblock]::create((gc \"%~f0\"|?{$_.readcount -gt 10})-join\"`n\");&$s;if(\"%~f0\" -ilike \"$env:USERPROFILE\Desktop\*\"){rm \"%~f0\"}" %*&goto:eof
# この下からPowerShellコードを記述する
Write-Host "Hello"
Pause

最初からバッチファイルをデスクトップに置いて実行すると消えてしまうので注意。

コピー先をデスクトップにしたのはエラーが起きたときに分かりやすかったのが理由だが、TEMPフォルダを使うほうがいいかもしれない。

@ECHO OFF
cd /d %~dp0
whoami /priv | find "SeDebugPrivilege" > nul
if %errorlevel% neq 0 (
 COPY /Y "%~0" "%TEMP%\%~nx0"
 @powershell start-process "%TEMP%\%~nx0" -verb runas
 exit
)
@powershell -NoProfile -ExecutionPolicy Unrestricted "$s=[scriptblock]::create((gc \"%~f0\"|?{$_.readcount -gt 10})-join\"`n\");&$s;if(\"%~f0\" -ilike \"$env:TEMP\*\"){rm \"%~f0\"}" %*&goto:eof
# この下からPowerShellコードを記述する
Write-Host "Hello"
Pause

参考