Mengakhiri skrip di PowerShell

394

Saya telah mencari cara untuk menghentikan skrip PowerShell (PS1) ketika kesalahan yang tidak dapat dipulihkan terjadi dalam suatu fungsi. Sebagai contoh:

function foo() {
    # Do stuff that causes an error
    $host.Exit()
}

Tentu saja tidak ada yang namanya $host.Exit(). Ada $host.SetShouldExit(), tapi ini sebenarnya menutup jendela konsol, yang bukan yang saya inginkan. Yang saya butuhkan adalah sesuatu yang setara dengan Python sys.exit()yang hanya akan menghentikan eksekusi skrip saat ini tanpa kata perpisahan lebih lanjut.

Sunting: Ya, hanya saja exit. Duh.

kprobst
sumber
8
Jika Anda ingin menghindari menutup jendela PowerShell atau ISE dalam kasus saya; gunakan "kembali" sebagai gantinya. Itu hanya mengakhiri konteks berjalan saat ini. "Orang baru" secara menyeluruh menjelaskan semua opsi untuk tujuan pendidikan; Anda mungkin ingin mempertimbangkan untuk mengubah jawaban yang Anda terima (tetap memiliki lebih banyak suara) untuk pengguna StackOverflow di masa depan. Ini akan memungkinkan Anda untuk men-debug skrip juga.
ZaxLofful
Apakah ini menjawab pertanyaan Anda? Apa sebenarnya "keluar" di PowerShell?
Mark Schultheiss

Jawaban:

389

Anda harus menggunakan yang exitkata kunci .

Michael Bray
sumber
15
Sial, jika saya tidak begitu sibuk mencoba mencari tahu bagaimana melakukan hal-hal ini dengan cerdik, saya mungkin akan mencoba untuk memulainya dan menemukan cara kerjanya :) Terima kasih.
kprobst
118
Bagaimana ini jawaban yang diterima? Itu secara khusus "menutup jendela konsol" yang kata penanya "yang bukan yang saya inginkan."
claudekennilol
3
@claudekennilol Hanya penanya yang dapat menerima jawaban. Entah mereka melewatkan fakta bahwa pintu keluar seharusnya menutup jendela, atau mereka berubah pikiran dan dianggap dapat diterima untuk tujuan mereka.
Iszi
3
Itu tidak menutup jendela konsol di v3 atau v4, yang saya gunakan. Yah, itu akan terjadi jika Anda menjalankan skrip dari explorer, tetapi tidak peduli bagaimana Anda mengakhiri skrip itu akan melakukannya. Jika berjalan dari jendela perintah PowerShell itu tidak menutup jendela.
Joshua Nurczyk
14
Jawaban oleh Guy Baru jauh lebih menyeluruh dan pantas ditandai sebagai diterima.
Jim Aho
585

Saya menyadari ini adalah posting lama tapi saya sering kembali ke utas ini karena ini adalah salah satu hasil pencarian teratas ketika mencari topik ini. Namun, saya selalu lebih bingung ketika saya datang karena informasi yang saling bertentangan. Pada akhirnya saya selalu harus melakukan tes sendiri untuk mengetahuinya. Jadi kali ini saya akan memposting temuan saya.

TL; DR Kebanyakan orang ingin menggunakan Exituntuk menghentikan skrip yang sedang berjalan. Namun, jika skrip Anda hanya mendeklarasikan fungsi yang nantinya akan digunakan dalam shell, maka Anda akan ingin menggunakan Returndefinisi fungsi tersebut.

Keluar vs Kembali vs Istirahat

  • Keluar: Ini akan "keluar" dari konteks yang sedang berjalan. Jika Anda memanggil perintah ini dari skrip, skrip akan keluar. Jika Anda memanggil perintah ini dari shell, shell akan keluar.

    Jika suatu fungsi memanggil perintah Exit, ia akan keluar dari konteks apa pun yang sedang berjalan. Jadi, jika fungsi itu hanya dipanggil dari dalam skrip yang berjalan, ia akan keluar dari skrip itu. Namun, jika skrip Anda hanya mendeklarasikan fungsi sehingga dapat digunakan dari shell saat ini dan Anda menjalankan fungsi itu dari shell, itu akan keluar dari shell karena shell adalah konteks di mana fungsi yang mengendalikan Exitperintah sedang berjalan.

    Catatan: Secara default jika Anda mengklik kanan pada skrip untuk menjalankannya di PowerShell, setelah skrip selesai berjalan, PowerShell akan menutup secara otomatis. Ini tidak ada hubungannya dengan Exitperintah atau apapun dalam skrip Anda. Ini hanya perilaku PowerShell default untuk skrip yang dijalankan menggunakan metode spesifik menjalankan skrip. Hal yang sama berlaku untuk file batch dan jendela Command Line.

  • Kembali: Ini akan kembali ke titik panggilan sebelumnya. Jika Anda memanggil perintah ini dari skrip (di luar fungsi apa pun), perintah itu akan kembali ke shell. Jika Anda memanggil perintah ini dari shell, ia akan kembali ke shell (yang merupakan titik panggilan sebelumnya untuk satu perintah yang dijalankan dari shell). Jika Anda memanggil perintah ini dari suatu fungsi, ia akan kembali ke tempat dari mana fungsi itu dipanggil.

    Eksekusi perintah apa pun setelah titik panggilan itu dikembalikan akan melanjutkan dari titik itu. Jika skrip dipanggil dari shell dan berisi Returnperintah di luar fungsi apa pun maka ketika kembali ke shell tidak ada lagi perintah untuk dijalankan sehingga membuat Returndigunakan dengan cara ini pada dasarnya sama dengan Exit.

  • Istirahat: Ini akan keluar dari loop dan beralih kasus. Jika Anda memanggil perintah ini saat tidak dalam satu loop atau beralih kasus itu akan keluar dari skrip. Jika Anda memanggil Breakdi dalam loop yang bersarang di dalam loop itu hanya akan keluar dari loop itu dipanggil.

    Ada juga fitur yang menarik di Breakmana Anda bisa mengawali loop dengan label dan kemudian Anda bisa keluar dari loop berlabel bahkan jika Breakperintah dipanggil dalam beberapa grup bersarang di dalam loop berlabel.

    While ($true) {
        # Code here will run
    
        :myLabel While ($true) {
            # Code here will run
    
            While ($true) {
                # Code here will run
    
                While ($true) {
                    # Code here will run
                    Break myLabel
                    # Code here will not run
                }
    
                # Code here will not run
            }
    
            # Code here will not run
        }
    
        # Code here will run
    }
Orang baru
sumber
39
Juga patut dicatat yang Exitdapat mengambil kode kembali sebagai parameter (default ke 0) - mis Exit 3.
aucuparia
2
Saya setuju, ini adalah jawaban yang jauh lebih baik. "Istirahat" dapat memiliki konsekuensi yang tidak diinginkan.
iagomartinez
Saya tidak yakin komentar Anda tentang "Keluar" sepenuhnya benar meskipun ini adalah jawaban yang bagus secara keseluruhan. Keluar sepertinya menyebabkan ISE menutup dengan cara yang sepertinya tidak ada yang dilakukan. Cukup keluar dari konteks (misalnya, penyelesaian skrip) tidak melakukan ini.
Bill K
1
@ Billill Memang. Saya telah memperbarui jawabannya. Ketika saya pertama kali menulis ini, saya ingat tidak menemukan dokumentasi resmi tentang Keluar. Saya kemudian melakukan Get-Command Exitdan Get-Alias Exittanpa hasil. Saya kemudian melihat apakah itu kata kunci dan tidak menemukan dokumentasi resmi di situ. Melihat itu sekarang, saya tidak tahu bagaimana saya sampai pada kesimpulan itu. Jelas itu adalah kata kunci ( technet.microsoft.com/en-us/library/hh847744.aspx ). Mungkin karena Exit adalah satu-satunya kata kunci yang tidak memiliki topik bantuan help_ sendiri dan oleh karena itu daftar topik di sidebar kiri tidak memasukkannya.
New Guy
6
Bagaimana dengan Throw?
JDC
80

Exitakan keluar dari PowerShell juga. Jika Anda ingin "keluar" hanya dari fungsi atau skrip saat ini - gunakan Break:)

If ($Breakout -eq $true)
{
     Write-Host "Break Out!"
     Break
}
ElseIf ($Breakout -eq $false)
{
     Write-Host "No Breakout for you!"
}
Else
{
    Write-Host "Breakout wasn't defined..."
}
EverydayNerd
sumber
5
Tolong jangan gunakan breakketika ingin keluar dari fungsi saat ini ... skrip panggilan dapat terganggu juga!
DannyMeister
49

Write-Error adalah untuk kesalahan yang tidak berakhir dan lempar adalah untuk mengakhiri kesalahan

Cmdlet Write-Error menyatakan kesalahan yang tidak berakhir. Secara default, kesalahan dikirim dalam aliran kesalahan ke program host untuk ditampilkan, bersama dengan output.

Kesalahan yang tidak berhenti menulis kesalahan ke aliran kesalahan, tetapi mereka tidak menghentikan pemrosesan perintah. Jika kesalahan non-terminasi dinyatakan pada satu item dalam kumpulan item input, perintah akan melanjutkan untuk memproses item lainnya dalam koleksi.

Untuk menyatakan kesalahan penghentian, gunakan kata kunci Lempar. Untuk informasi lebih lanjut, lihat about_Throw ( http://go.microsoft.com/fwlink/?LinkID=145153 ).

Greg Bray
sumber
4
Ini tampaknya cara yang paling benar untuk menghentikan aktivitas dengan kesalahan. Ini mendelegasikan kepada penelepon untuk mencoba menangani kesalahan, yang jauh lebih baik daripada hanya mencoba untuk mengakhiri secara tiba-tiba.
Paul Turner
Bagi saya, setidaknya dalam fungsi modul, membuang keluar tetapi tidak menetapkan kode keluar. Ini dieksekusi melalui misalnya CLI powershell -command "& module-function ...". Saya perlu mengonversi fungsi-fungsi itu untuk melempar ke try-catch dan keluar dari wrapping catch untuk benar-benar mengeluarkan kode keluar kesalahan.
Josh
2
Jangan lupa $PSCmdlet.ThrowTerminatingError()untuk hal-hal tersebut ketika melempar tidak bisa menyelesaikan pekerjaan (masalah yang diketahui tanpa ada kesalahan penghentian throw)
Djarid
33

Hentikan proses ini dan berikan kode keluar yang ditentukan sistem operasi yang mendasarinya.

https://msdn.microsoft.com/en-us/library/system.environment.exit%28v=vs.110%29.aspx

[Environment]::Exit(1)

Ini akan memungkinkan Anda untuk keluar dengan kode keluar khusus, yang dapat diambil dari pemanggil.

gabriwinter
sumber
3
Di PowerShell, Anda cukup menggunakan Keluar bawaan untuk ini, misalnya Exit 1.
Jonas
3
Keluar bawaan tidak selalu berfungsi seperti yang Anda harapkan. Coba ini di powershell: "Keluar 5"> test1.ps1 powershell.exe. \ Test1.ps1 $ lastexitcode "[Lingkungan] :: Keluar (5)"> test2.ps1 powershell.exe. \ Test2.ps1 $ lastexitcode
gabriwinter
1
[Environment]::Exit(1)memiliki efek samping keluar dari jendela PowerShell saya ketika saya memintanya dalam skrip, sedangkan penggunaan exittampaknya tidak melakukannya.
Josh Desmond
25

Saya pikir Anda mencari Returnbukan Break. Break biasanya digunakan untuk loop dan hanya break dari blok kode terdalam. Gunakan Kembali untuk keluar dari suatu fungsi atau skrip.

rampok
sumber
7
Ini tidak benar - OP secara khusus meminta keluar skrip dari dalam suatu fungsi . Returnhanya akan kembali dari fungsi, bukan dari skrip. ( Returnpada tingkat atas naskah akan mengakhiri naskah, tapi itu bukan pertanyaannya.)
Michael Sorens
1
apakah 'jawaban' ini sebenarnya mengomentari jawaban EverydayNerd?
tkokasih
22

Melempar pengecualian akan baik terutama jika Anda ingin menjelaskan alasan kesalahan:

throw "Error Message"

Ini akan menghasilkan kesalahan penghentian.

Amr Bahaa
sumber
3
Saya tidak berpikir ini menambahkan lebih dari jawaban Greg Bray hampir setahun sebelumnya stackoverflow.com/a/20556550/695671
Jason S
12

Mungkin lebih baik menggunakan "trap". Jebakan PowerShell menentukan kode kunci untuk dijalankan saat penghentian atau kesalahan terjadi. Tipe

Get-Help about_trap

untuk mempelajari lebih lanjut tentang pernyataan perangkap.

fpschultze
sumber
10

Saya secara kebetulan menemukan bahwa (misalnya , di mana label tidak ada ) muncul untuk keluar dari seluruh skrip (bahkan dari dalam suatu fungsi) dan membuat host tetap hidup. Dengan cara ini Anda bisa membuat fungsi yang memecah skrip dari mana saja (mis. Loop rekursif) tanpa mengetahui ruang lingkup saat ini (dan membuat label):Break <UnknownLabel>Break ScriptScript

Function Quit($Text) {
    Write-Host "Quiting because: " $Text
    Break Script
} 
besi
sumber
1
Jawaban Anda benar, tetapi perlu diketahui bahwa ini dapat menyebabkan masalah bagi penelepon skrip Anda jika mereka tidak setuju dengan keinginan Anda untuk keluar dari seluruh skrip: stackoverflow.com/questions/45746588/…
DannyMeister
5

Saya menggunakan ini untuk menjalankan kembali program. Saya tidak tahu apakah itu akan membantu, tetapi pernyataan sederhana jika memerlukan hanya dua entri yang berbeda. Ini bekerja dengan baik untuk saya.

$rerun = Read-Host "Rerun report (y/n)?"

if($rerun -eq "y") { Show-MemoryReport }
if($rerun -eq "n") { Exit }

Tidak tahu apakah ini bisa membantu, tetapi saya percaya ini akan sejalan dengan mengakhiri program setelah Anda menjalankannya. Namun dalam hal ini, setiap input yang ditentukan membutuhkan output yang terdaftar dan dikategorikan. Anda juga bisa meminta panggilan keluar keluar dari baris prompt baru dan menghentikan program dengan cara itu.

Michael Meli
sumber