Cara menangani argumen baris perintah di PowerShell

494

Apa cara "terbaik" untuk menangani argumen baris perintah?

Sepertinya ada beberapa jawaban tentang apa cara "terbaik" dan sebagai hasilnya saya terjebak pada bagaimana menangani sesuatu yang sederhana seperti:

script.ps1 /n name /d domain

DAN

script.ps1 /d domain /n name.

Apakah ada plugin yang bisa menangani ini dengan lebih baik? Saya tahu saya menciptakan kembali roda di sini.

Jelas apa yang saya miliki sudah tidak cantik dan tentu saja bukan yang "terbaik", tetapi itu berhasil .. dan itu adalah UGLY.

for ( $i = 0; $i -lt $args.count; $i++ ) {
    if ($args[ $i ] -eq "/n"){ $strName=$args[ $i+1 ]}
    if ($args[ $i ] -eq "-n"){ $strName=$args[ $i+1 ]}
    if ($args[ $i ] -eq "/d"){ $strDomain=$args[ $i+1 ]}
    if ($args[ $i ] -eq "-d"){ $strDomain=$args[ $i+1 ]}
}
Write-Host $strName
Write-Host $strDomain
Aaron Wurthmann
sumber

Jawaban:

917

Anda sedang menciptakan kembali roda. Skrip PowerShell yang normal memiliki parameter yang dimulai dengan -, sepertiscript.ps1 -server http://devserver

Kemudian Anda menangani mereka di parambagian di awal file.

Anda juga dapat menetapkan nilai default ke params Anda, membacanya dari konsol jika tidak tersedia atau menghentikan eksekusi skrip:

 param (
    [string]$server = "http://defaultserver",
    [Parameter(Mandatory=$true)][string]$username,
    [string]$password = $( Read-Host "Input password, please" )
 )

Di dalam skrip Anda dapat dengan mudah

write-output $server

karena semua parameter menjadi variabel yang tersedia dalam cakupan skrip.

Dalam contoh ini, $servermendapat nilai default jika skrip dipanggil tanpa itu, skrip berhenti jika Anda menghilangkan -usernameparameter dan meminta input terminal jika -passworddihilangkan.

Pembaruan: Anda mungkin juga ingin memberikan "flag" (parameter boolean true / false) ke skrip PowerShell. Misalnya, skrip Anda dapat menerima "kekuatan" di mana skrip berjalan dalam mode yang lebih hati-hati saat paksaan tidak digunakan.

Kata kunci untuk itu adalah [switch]tipe parameter:

 param (
    [string]$server = "http://defaultserver",
    [string]$password = $( Read-Host "Input password, please" ),
    [switch]$force = $false
 )

Di dalam skrip maka Anda akan bekerja dengannya seperti ini:

if ($force) {
  //deletes a file or does something "bad"
}

Sekarang, saat memanggil skrip Anda akan mengatur parameter sakelar / panji seperti ini:

.\yourscript.ps1 -server "http://otherserver" -force

Jika Anda secara eksplisit ingin menyatakan bahwa flag tidak disetel, ada sintaks khusus untuk itu

.\yourscript.ps1 -server "http://otherserver" -force:$false

Tautan ke dokumentasi Microsoft yang relevan (untuk PowerShell 5.0; versi 3.0 dan 4.0 juga tersedia di tautan):

kenaifan
sumber
58
Memang salah satu kelebihan besar PowerShell adalah menyediakan infrastruktur parsing parameter standar yang mudah digunakan.
Keith Hill
14
@naivists, dari PowerShell 2.0 bukannya [string]$username = $(throw "-username is required.")ada sintaks untuk parameter wajib: [Parameter(Mandatory=$true)][string]$username. Berikut adalah info lebih lanjut tentang perbedaan antara teknik-teknik ini: blogs.technet.com/b/heyscriptingguy/archive/2011/05/22/…
v.karbovnichy
7
Berhati-hatilah terhadap bug saat arg tidak disediakan; powershell hanya akan mengambil teks tambahan dari baris perintah:. \ yourscript.ps1 -server " serv " -password "mypass" typo Ini secara ajaib akan menetapkan 'salah ketik' untuk $ nama pengguna.
sheamus
4
Menggunakan blok param tampaknya memiliki konsekuensi lain yang tidak disengaja: stackoverflow.com/questions/40940819/…
Logan
1
@sheamus: itu bukan bug! Powershell akan memproses dan menetapkan argumen dalam urutan yang diberikan, kecuali diganti dengan menggunakan nama parameter yang tepat, misalnya, jika daftar blok param Anda: $ user $ pass $ server, dan Anda menjalankan abjad Anda skrip Script Anda, maka akan atur menjadi $ user, b ke $ pass dan c ke $ server, KECUALI Anda tetapkan secara khusus! Jadi, jika Anda mengatakan: yourscript.ps1 -pass abc, $ pass akan ditetapkan ke a, dan parameter (tidak bernama) yang tersisa akan digunakan untuk mengisi yang hilang, dalam urutan yang tercantum dalam blok parameter, jadi $ user = b, $ server = c.
Fernando Madruga