PowerShell'de bir komut dosyasını sonlandırma


394

Bir işlev içinde kurtarılamayan bir hata oluştuğunda bir PowerShell (PS1) komut dosyasını sonlandırmak için bir yol arıyordum. Örneğin:

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

Tabii ki diye bir şey yok $host.Exit(). Var $host.SetShouldExit(), ama bu aslında konsol penceresini kapatıyor, ki istediğim bu değil. Ihtiyacım olan şey sys.exit()sadece geçerli komut dosyası yürütmek durmadan durur Python's eşdeğer bir şeydir .

Düzenleme: Evet, sadece exit. Duh.


8
Benim durumumda PowerShell penceresini veya İMKB'yi kapatmaktan kaçınmak istiyorsanız; bunun yerine "return" kullanın. Sadece geçerli çalışan içeriği sonlandırır. "Yeni adam" eğitim amaçlı tüm seçenekleri ayrıntılı olarak açıklar; gelecekteki StackOverflow kullanıcıları için kabul edilen cevabınızı (şu anda zaten daha fazla oy var) değiştirmeyi düşünebilirsiniz. Senaryoda da hata ayıklamanızı sağlar.
ZaxLofful

Yanıtlar:


389

Sen kullanmalıdır anahtar kelime .exit


15
Kutsal bok, bu şeyleri nasıl akıllıca yapacağımı anlamaya çalışırken bu kadar yakalanmasaydım, muhtemelen bunu başlatabilirdim ve işe yaradığını anladım :) Teşekkürler.
kprobst

118
Bu kabul edilen cevap nasıl? Özellikle "konsolun penceresini kapatır" demişti ki, "bu istediğim şey değil."
claudekennilol

3
@claudekennilol Sadece soru asker cevap alabilir. Ya çıkışın pencereyi kapatması gerektiği gerçeğini kaçırdılar ya da fikrini değiştirdiler ve bunu amaçları için kabul edilebilir buldular.
Iszi

3
Kullandığım v3 veya v4'teki konsol penceresini kapatmaz. Komut dosyasını explorer'dan çalıştırırsanız çalışacaktır, ancak komut dosyasını nasıl bitirdiğiniz önemli değil. Bir PowerShell komut penceresinden çalıştırılıyorsa pencereyi kapatmaz.
Joshua Nurczyk

14
New Guy'ın cevabı çok daha ayrıntılı ve haklılar kabul edilmiş olarak işaretlendi.
Jim Aho

585

Bu eski bir yazı olduğunu biliyorum ama kendimi bu konuya çok geri geliyor bulmak gibi bu konuyu ararken en iyi arama sonuçlarından biridir. Ancak, çelişkili bilgiler nedeniyle geldiğimden sonra her zaman daha karışık kalıyorum. Sonuç olarak bunu anlamak için her zaman kendi testlerimi yapmak zorundayım. Bu sefer bulgularımı yayınlayacağım.

TL; DR Çoğu insan Exitçalışan bir komut dosyasını sonlandırmak için kullanmak isteyecektir . Ancak, betiğiniz yalnızca daha sonra bir kabukta kullanılacak Returnişlevleri bildiriyorsa, söz konusu işlevlerin tanımlarında kullanmak isteyeceksiniz .

Çıkış vs Dönüş vs Break

  • Çıkış: Bu, çalışmakta olan bağlamdan "çıkacaktır". Bu komutu bir komut dosyasından çağırırsanız, komut dosyasından çıkar. Bu komutu kabuktan çağırırsanız kabuktan çıkar.

    Bir işlev Exit komutunu çağırırsa, çalıştığı bağlamdan çıkar. Bu işlev yalnızca çalışan bir komut dosyasından çağrılırsa bu komut dosyasından çıkar. Ancak, komut dosyanız yalnızca geçerli kabuktan kullanılabilmesi için işlevi bildirirse ve bu işlevi kabuktan çalıştırırsanız, kabuk komuttan ayrılan işlevin çalıştığı bağlam olduğu için kabuktan çıkar Exit.

    Not: Varsayılan olarak PowerShell'de çalıştırmak için bir komut dosyasına sağ tıklarsanız, komut dosyası çalıştıktan sonra PowerShell otomatik olarak kapanır. Bunun Exitkomutla veya komut dosyanızdaki başka bir şeyle ilgisi yoktur . Bu belirli bir komut dosyası çalıştırma yöntemi kullanılarak çalıştırılan komut dosyaları için varsayılan bir PowerShell davranışıdır. Aynı şey toplu iş dosyaları ve Komut Satırı penceresi için de geçerlidir.

  • Dönüş: Bu, bir önceki çağrı noktasına dönecektir. Bu komutu bir komut dosyasından çağırırsanız (herhangi bir işlev dışında) kabuğa geri döner. Kabuktan bu komutu çağırırsanız, kabuğa geri döner (tek bir komut için önceki çağrı noktası olan kabuktan). Bu komutu bir işlevden çağırırsanız, işlevin çağrıldığı yere dönecektir.

    Geri döndürüldüğü çağrı noktasından sonra tüm komutların yürütülmesi bu noktadan itibaren devam eder. Kabuktan bir komut dosyası çağrılırsa ve Returnherhangi bir fonksiyonun dışındaki komutu içeriyorsa, kabuğa geri döndüğünde çalıştırılacak başka komut yoktur, böylece Returnbu şekilde kullanılan esasen aynı şekilde kullanılır Exit.

  • Break: Bu, döngülerden çıkacak ve vakaları değiştirecektir. Bir döngü veya anahtar durumunda değilken bu komutu çağırırsanız, komut dosyasından kopacaktır. BreakBir döngü içinde iç içe yerleştirilmiş bir döngü içine çağırırsanız , yalnızca çağrıldığı döngüden çıkar.

    Ayrıca, Breakbir döngüyü etiketle ön ekleyebileceğiniz ve ilginç bir Breakkomut da etiketli döngü içindeki birkaç iç içe grup içinde çağrılsa bile etiketli döngüden çıkabilirsiniz .

    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
    }

39
Ayrıca Exitparametre olarak bir dönüş kodu alabileceğinizi belirtmek gerekir (varsayılan 0'dır) - örn Exit 3.
aucuparia

2
Katılıyorum, bu çok daha iyi bir cevap. "Break" in istenmeyen sonuçları olabilir.
iagomartinez

Genel olarak harika bir cevap olmasına rağmen "Çıkış" hakkındaki yorumunuzun tamamen doğru olduğundan emin değilim. Çıkış, İMKB'nin başka hiçbir şey yapmayacak şekilde kapanmasına neden oluyor gibi görünüyor. Sadece bağlamdan çıkmak (örneğin, komut dosyası tamamlama) bunu yapmaz.
Bill K

1
@BillK Gerçekten. Cevabı güncelledim. Bunu ilk yazdığımda, Exit hakkında hiçbir resmi belge bulamadığımı hatırlıyorum. Daha sonra Get-Command Exitve sonuçsuz yaptım Get-Alias Exit. Sonra bir anahtar kelime olup olmadığını görmek için baktım ve resmi bir belge bulunamadı. Ancak şimdi baktığımda, bu sonuca nasıl geldiğimi bilmiyorum. Açıkçası bu bir anahtar kelimedir ( technet.microsoft.com/en-us/library/hh847744.aspx ). Belki de Exit, kendi about_ yardım konusuna sahip olmayan tek anahtar kelimelerden biri olduğundan ve bu nedenle sol kenar çubuğundaki konuların listesi içermiyor olabilir.
Yeni Guy

6
Ya atın?
JDC

80

ExitPowerShell'den de çıkacaktır. Sadece geçerli işlev veya komut dosyasından "kırmak" istiyorsanız - kullanın 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..."
}

5
Lütfen breakşu anki işlevden çıkmak istediğinizde kullanmayın ... arama komut dosyaları da bozulabilir!
DannyMeister

49

Yazma Hatası sonlandırma hataları içindir ve atma hataları sonlandırma içindir

Write-Error cmdlet'i sonlanmayan bir hata bildirir. Varsayılan olarak hatalar, hata akışında görüntülenecek ana programla birlikte çıktıyla birlikte gönderilir.

Sonlandırılmayan hatalar hata akışına bir hata yazar, ancak komut işlemeyi durdurmazlar. Bir girdi öğeleri koleksiyonundaki bir öğe üzerinde sonlanmayan bir hata bildirilirse, komut koleksiyondaki diğer öğeleri işlemeye devam eder.

Sonlandırma hatası bildirmek için Throw anahtar sözcüğünü kullanın. Daha fazla bilgi için, bkz. About_Throw ( http://go.microsoft.com/fwlink/?LinkID=145153 ).


4
Hatalı bir etkinliği sonlandırmanın en doğru yolu budur. Sadece aniden sonlandırmaya çalışmaktan çok daha iyi olan hatayı ele almaya teşebbüs eder.
Paul Turner

Benim için, en azından modül işlevlerinde, çıkışları atın, ancak bir çıkış kodu belirlemez. Bu, CLI örn powershell -command "& module-function ...". Ben aslında bir hata çıkış kodu çıktısı için bir sarma try-catch atmak ve bu sarma catch çıkmak için bu fonksiyonları dönüştürmek gerekiyordu.
Josh

2
$PSCmdlet.ThrowTerminatingError()throw
Atmanın

33

Bu işlemi sonlandırır ve temel alınan işletim sistemine belirtilen çıkış kodunu verir.

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

[Environment]::Exit(1)

Bu, arayandan alınabilecek belirli bir çıkış koduyla çıkmanıza olanak tanır.


3
PowerShell'de bunun için yerleşik Çıkış'ı kullanabilirsiniz, örn Exit 1.
Jonas

3
yerleşik Çıkış her zaman beklediğiniz gibi çalışmaz. Bunu powershell'de deneyin: "Exit 5"> test1.ps1 powershell.exe. \ Test1.ps1 $ lastexitcode "[Çevre] :: Çıkış (5)"> test2.ps1 powershell.exe. \ Test2.ps1 $ lastexitcode
gabriwinter

1
[Environment]::Exit(1)bir komut dosyasında çağırdığımda powershell penceremden çıkmanın yan etkisi var, burada kullanıldığında exitgörünmüyor.
Josh Desmond

25

Bence sen Returnyerine onu arıyorsun Break. Break genellikle döngüler için kullanılır ve yalnızca en içteki kod bloğundan kopmalar olur. Bir işlev veya komut dosyasından çıkmak için Return tuşunu kullanın.


7
Bu doğru değil - OP özellikle bir fonksiyonun içinden bir betikten çıkmayı ister . Returnkomut dosyasından değil, işlevden dönecektir. ( bir betiğin Returnen üst düzeyinde betiği sonlandıracaktır, ancak soru bu değildi.)
Michael Sorens

1
Bu 'cevap' aslında EverydayNerd cevabı hakkında yorumlar mıydı?
tkokasih

22

Bir istisna atmak, özellikle hata nedenini açıklığa kavuşturmak istiyorsanız iyi olacaktır:

throw "Error Message"

Bu bir sonlandırma hatası oluşturur.


3
Bunun yaklaşık bir yıl önce Greg Bray'nin cevabından daha fazla bir şey kattığını düşünmüyorum stackoverflow.com/a/20556550/695671
Jason S

12

Belki "tuzak" kullanmak daha iyidir. PowerShell tuzağı, bir sonlandırma veya hata oluştuğunda çalıştırılacak kod bloğunu belirtir. tip

Get-Help about_trap

tuzak ifadesi hakkında daha fazla bilgi edinmek için.


10

Ben tesadüfen öğrendim (örneğin basitçe , etiket nereye does not var ) (hatta bir işlev içinde) tüm senaryonun patlak görünüyor ve canlı dizi tutar. Bu şekilde, geçerli kapsamı bilmeden (ve etiketler oluşturmadan) komut dosyasını herhangi bir yerden (örneğin özyinelemeli bir döngü) kesen bir işlev oluşturabilirsiniz:Break <UnknownLabel>Break ScriptScript

Function Quit($Text) {
    Write-Host "Quiting because: " $Text
    Break Script
} 

1
Cevabınız doğrudur, ancak betiğin tüm arayanlarından çıkma isteğinize katılmamaları durumunda betiğinizin arayanları için sorunlara neden olabileceğini unutmayın: stackoverflow.com/questions/45746588/…
DannyMeister

5

Bunu bir programı yeniden çalıştırmak için kullandım. Yardımcı olur mu bilmiyorum, ama sadece iki farklı giriş gerektiren basit bir if ifadesidir. Benim için powershell'de çalıştı.

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

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

Bu yardımcı olur bilmiyorum, ama ben bunu çalıştırdıktan sonra bir programı sonlandırma hatları boyunca inanıyorum. Ancak bu durumda, tanımlanan her girdi listelenmiş ve kategorize edilmiş bir çıktı gerektirir. Ayrıca çıkmanın yeni bir bilgi istemi satırı çağırmasını ve programı bu şekilde sonlandırmasını sağlayabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.