PowerShellスクリプトの配置場所を基準にしたパス指定による安全性の向上

PowerShell スクリプト (.ps1) ファイルが配置されているフォルダのパスを格納した $PSScriptRoot 自動変数を用いることで、外部のバッチなどからその .ps1 ファイルが呼び出す際の相対パスによるエラーの発生を防ぐスクリプトと実行の例を紹介します。

PowerShell スクリプトの配置場所を基準にしたパス指定による安全性の向上2

※ Windows PowerShell PSVersion 5.1.19041.6093 を使用します。

サンプル a.ps1 スクリプトの説明

PowerShell (.ps1) ファイル a.ps1 は、同じフォルダにある、相対パスで指定した 1.txt$PSScriptRoot による絶対パスで指定した 2.txtC:\temp フォルダにコピーするスクリプトです。

この a.ps1 ファイルを、同じフォルダの run.bat から呼び出した場合と、違う場所(例では .\sub\)の run_from_sub.bat から呼び出した場合で、相対パス・絶対パスでコピーが正しく行われるかを確認します。

PowerShell スクリプトの配置場所を基準にしたパス指定による安全性の向上3

以下は a.ps1 スクリプトファイルの中身です。
Copy-Item コマンドレットにより、 -Path で指定したファイルを -Destination で指定したフォルダにコピーします。

# 相対パス指定
Copy-Item -Path ".\1.txt" -Destination "C:\temp\"

# スクリプトの場所基準
Copy-Item -Path "$PSScriptRoot\2.txt" -Destination "C:\temp\"

項目をある場所から別の場所にコピーします。

-Path
文字列配列として、コピーする項目へのパスを指定します。 ワイルドカード文字を使用できます。

-Destination
新しい場所へのパスを指定します。 既定値は、現在のディレクトリです。
コピーする項目の名前を変更するには、 Destination パラメーターの値に新しい名前を指定します。

Copy-Item (Microsoft.PowerShell.Management) – PowerShell | Microsoft Learn

2つ目の Copy-Item では、コピー元ファイルのパスを $PSScriptRoot 自動変数で、このスクリプトファイルのあるフォルダを絶対パスで指定しています。

$PSScriptRoot

実行中のスクリプトの親ディレクトリの完全なパスが含まれています。

PowerShell 2.0 では、この変数はスクリプト モジュール (.psm1) でのみ有効です。 PowerShell 3.0 以降では、すべてのスクリプトで有効です。

about_Automatic_Variables – PowerShell | Microsoft Learn #$PSScriptRoot

.ps1 と起動する .bat が同じフォルダの場合


同じフォルダにある run.bat をダブルクリックすることで、 a.ps1 スクリプトファイルを実行します。

@echo off
powershell -ExecutionPolicy Bypass -File "%~dp0a.ps1"
pause

a.ps1 の前の %~dp0 は、カレントディレクトリを指します。

%~dp0」は、現在自分がいるフォルダ(カレントディレクトリ)のパスを取得します。

バッチファイルで「cd /d %~dp0」コマンドでカレントディレクトリを変更する | 技術的特異点

実行結果

実行すると、以下のメッセージが表示されたコマンドプロンプトが表示されます。

続行するには何かキーを押してください . . .

相対パスで指定した 1.txt$PSScriptRoot 自動変数による絶対パスで指定した 2.txt も C:\temp フォルダにコピーできました。

PowerShell スクリプトの配置場所を基準にしたパス指定による安全性の向上1

コピー先フォルダがない場合のエラー

コピー先フォルダ C:\temp が存在しない場合は、 Copy-Item コマンドレットが失敗して、以下のエラーメッセージがバッチファイルを起動して表示されたコマンドプロンプトに表示されます。

このときは、コピーはどちらのファイルも行われません。

Copy-Item : ファイル名、ディレクトリ名、またはボリューム ラベルの構文が間違っています。
発生場所 G:\Dev\PowerShell\Study-PSScriptRoot\a.ps1:2 文字:1
+ Copy-Item -Path ".\1.txt" -Destination "C:\temp\"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Copy-Item], IOException
    + FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.CopyItemCommand

Copy-Item : ファイル名、ディレクトリ名、またはボリューム ラベルの構文が間違っています。
発生場所 G:\Dev\PowerShell\Study-PSScriptRoot\a.ps1:5 文字:1
+ Copy-Item -Path "$PSScriptRoot\2.txt" -Destination "C:\temp\"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Copy-Item], IOException
    + FullyQualifiedErrorId : System.IO.IOException,Microsoft.PowerShell.Commands.CopyItemCommand

続行するには何かキーを押してください . . .

.ps1 と起動する .bat が異なるフォルダの場合

異なるフォルダ(例では .\sub\)にある run_from_sub.bat をダブルクリックすることで、別のフォルダにある a.ps1 スクリプトファイルを実行します。

以下は、run_from_sub.bat の内容です。
バッチファイルのカレントディレクトリを指す %~dp0 のあとに ..\ を加えて上位の a.ps1 を実行します。

@echo off
powershell -ExecutionPolicy Bypass -File "%~dp0..\a.ps1"
pause

.ps1 と異なるフォルダから実行した際の相対パスの不具合

a.ps1 ファイルと異なる場所から実行すると、カレントディレクトリが .ps1 のあるフォルダと異なるため、 a.ps1 のスクリプト内の相対パスで指定したファイルの位置が a.ps1 のあるフォルダと異なるため、コピー失敗します。

$PSScriptRoot 自動変数による絶対パスで指定した 2.txt はコピーが成功しています。

PowerShell スクリプトの配置場所を基準にしたパス指定による安全性の向上2
Copy-Item : パス 'G:\Dev\PowerShell\Study-PSScriptRoot\sub\1.txt' が存在しないため検出できません。
発生場所 G:\Dev\PowerShell\Study-PSScriptRoot\a.ps1:2 文字:1
+ Copy-Item -Path ".\1.txt" -Destination "C:\temp\"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (G:\Dev\PowerShe...tRoot\sub\1.txt:String) [Copy-Item], ItemNotFoundExce
   ption
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand

続行するには何かキーを押してください . . .

相対パスだと呼び出されるディレクトリによって結果が変わる

以上のことから、相対パスを用いる .ps1 スクリプトは、呼び出されるディレクトリ(カレントディレクトリ)によって結果が異なることがわかりました。
$PSScriptRoot 自動変数による絶対パスは、カレントディレクトリの影響を受けないため、より安全に動作することがわかりました。

まとめ

今回は、PowerShell スクリプト (.ps1) ファイルが配置されているフォルダのパスを格納した $PSScriptRoot 自動変数を用いることで、外部のバッチなどからその .ps1 ファイルが呼び出す際の相対パスによるエラーの発生を防ぐスクリプトと実行の例を紹介しました。

参照サイト Thank You!

記事一覧 → Compota-Soft-Press

コメント

Ads Blocker Image Powered by Code Help Pro

お願い - Ads Blocker Detected

このサイトは広告を掲載して運営しています。

ポップアップを閉じて閲覧できますが、よろしければ

このサイト内の広告を非表示にする拡張機能をオフにしていただけませんか?

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

We have detected that you are using extensions to block ads. Please support us by disabling these ads blocker.

タイトルとURLをコピーしました