Setiap kali saya perlu referensi modul atau skrip umum, saya suka menggunakan jalur relatif terhadap file skrip saat ini. Dengan begitu, skrip saya selalu dapat menemukan skrip lain di perpustakaan.
Jadi, apa cara terbaik dan standar untuk menentukan direktori skrip saat ini? Saat ini, saya sedang melakukan:
$MyDir = [System.IO.Path]::GetDirectoryName($myInvocation.MyCommand.Definition)
Saya tahu dalam modul (.psm1) yang dapat Anda gunakan $PSScriptRoot
untuk mendapatkan informasi ini, tetapi itu tidak diatur dalam skrip biasa (yaitu file .ps1).
Apa cara kanonik untuk mendapatkan lokasi file skrip PowerShell saat ini?
powershell
powershell-2.0
Aaron Jensen
sumber
sumber
Jawaban:
PowerShell 3+
PowerShell 2
Sebelum ke PowerShell 3, tidak ada cara yang lebih baik daripada menanyakan
MyInvocation.MyCommand.Definition
properti untuk skrip umum. Saya memiliki baris berikut di bagian atas pada dasarnya setiap skrip PowerShell yang saya miliki:sumber
Split-Path
digunakan di sini?Split-Path
digunakan dengan-Parent
parameter untuk mengembalikan direktori saat ini tanpa nama skrip yang saat ini mengeksekusi.$PSScriptRoot
(Split-Path -Parent
diterapkan ke)$MyInvocation.MyCommand.Path
, tidak$MyInvocation.MyCommand.Definition
, meskipun dalam lingkup tingkat atas dari skrip mereka berperilaku sama (yang merupakan satu-satunya tempat yang masuk akal untuk menelepon dari untuk tujuan ini). Ketika dipanggil di dalam blok fungsi atau skrip , yang pertama mengembalikan string kosong, sedangkan yang kedua mengembalikan definisi fungsi / skrip blok fungsi sebagai string (sepotong kode sumber PowerShell).Jika Anda membuat Modul V2, Anda dapat menggunakan variabel otomatis yang disebut
$PSScriptRoot
.Dari PS> Bantuan automatic_variable
sumber
$PSCommandPath Contains the full path and file name of the script that is being run. This variable is valid in all scripts.
Untuk PowerShell 3.0
Kemudian fungsinya adalah:
sumber
Untuk PowerShell 3+
Saya telah menempatkan fungsi ini di profil saya. Ia bekerja di ISE menggunakan F8/ Run Selection juga.
sumber
Mungkin saya kehilangan sesuatu di sini ... tetapi jika Anda ingin direktori kerja saat ini Anda dapat menggunakan ini:
(Get-Location).Path
untuk string, atauGet-Location
untuk objek.Kecuali jika Anda merujuk pada sesuatu seperti ini, yang saya mengerti setelah membaca pertanyaan itu lagi.
sumber
function Get-Script-Directory { $scriptInvocation = (Get-Variable MyInvocation -Scope 1).Value return Split-Path $scriptInvocation.MyCommand.Path } $hello = "hello" Write-Host (Get-Script-Directory) Write-Host $hello
Simpan itu dan jalankan dari direktori yang berbeda. Anda akan menunjukkan jalur ke skrip.Sangat mirip dengan jawaban yang sudah diposting, tetapi pemipaan tampaknya lebih mirip PowerShell:
sumber
Saya menggunakan variabel otomatis
$ExecutionContext
. Ini akan bekerja dari PowerShell 2 dan yang lebih baru.sumber
Butuh beberapa saat untuk mengembangkan sesuatu yang mengambil jawaban yang diterima dan mengubahnya menjadi fungsi yang kuat.
Saya tidak yakin tentang yang lain, tetapi saya bekerja di lingkungan dengan mesin pada PowerShell versi 2 dan 3, jadi saya harus menangani keduanya. Fungsi berikut menawarkan fallback yang anggun:
Ini juga berarti bahwa fungsi tersebut merujuk pada ruang lingkup Script daripada ruang lingkup orang tua seperti yang diuraikan oleh Michael Sorens di salah satu posting blognya .
sumber
Saya perlu tahu nama skrip dan dari mana itu dijalankan.
Awalan "$ global:" ke struktur MyInvocation mengembalikan path lengkap dan nama skrip ketika dipanggil dari kedua skrip utama, dan baris utama dari file library .PSM1 yang diimpor. Ini juga berfungsi dari dalam fungsi di perpustakaan yang diimpor.
Setelah banyak mengutak-atik, saya memutuskan untuk menggunakan $ global: MyInvocation.InvocationName. Ia bekerja dengan andal dengan peluncuran CMD, Run With Powershell, dan ISE. Kedua peluncuran lokal dan UNC mengembalikan jalur yang benar.
sumber
ParameterArgumentValidationErrorNullNotAllowed
pengecualian.Saya selalu menggunakan potongan kecil ini yang berfungsi untuk PowerShell dan ISE dengan cara yang sama:
sumber
Saya menemukan bahwa solusi lama yang diposting di sini tidak bekerja untuk saya di PowerShell V5. Saya datang dengan ini:
sumber
Anda juga dapat mempertimbangkan
split-path -parent $psISE.CurrentFile.Fullpath
jika salah satu metode lain gagal. Secara khusus, jika Anda menjalankan file untuk memuat banyak fungsi dan kemudian menjalankan fungsi-fungsi dengan-di shell ISE (atau jika Anda menjalankan-dipilih), tampaknyaGet-Script-Directory
fungsi seperti di atas tidak berfungsi.sumber
$PSCommandPath
akan bekerja di ISE selama Anda menyimpan skrip terlebih dahulu dan mengeksekusi seluruh file. Jika tidak, Anda sebenarnya tidak menjalankan skrip; Anda hanya "menempel" perintah ke shell.Menggunakan potongan-potongan dari semua jawaban dan komentar ini, saya menyatukan ini untuk siapa saja yang melihat pertanyaan ini di masa depan. Ini mencakup semua situasi yang tercantum dalam jawaban lain
sumber
sumber