การยุติสคริปต์ใน PowerShell


394

ฉันกำลังมองหาวิธีที่จะยุติสคริปต์ PowerShell (PS1) เมื่อเกิดข้อผิดพลาดที่ไม่สามารถกู้คืนได้ภายในฟังก์ชัน ตัวอย่างเช่น:

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

$host.Exit()แน่นอนไม่มีสิ่งเช่น มี$host.SetShouldExit()แต่สิ่งนี้จริงปิดหน้าต่างคอนโซลซึ่งไม่ใช่สิ่งที่ฉันต้องการ สิ่งที่ฉันต้องการคือสิ่งที่เทียบเท่ากับ Python sys.exit()ที่จะหยุดการทำงานของสคริปต์ปัจจุบันโดยไม่ต้องลาก่อน

แก้ไข:exitใช่มันเป็นเพียง ดุจ


8
หากคุณต้องการหลีกเลี่ยงการปิดหน้าต่าง PowerShell หรือ ISE ในกรณีของฉัน ใช้ "return" แทน มันเพิ่งจบบริบทการทำงานปัจจุบัน "คนใหม่" อธิบายตัวเลือกทั้งหมดเพื่อการศึกษาอย่างละเอียด คุณอาจต้องการพิจารณาเปลี่ยนคำตอบที่ยอมรับ (ปัจจุบันมีคะแนนเสียงมากขึ้นต่อไป) สำหรับผู้ใช้ StackOverflow ในอนาคต มันจะช่วยให้คุณสามารถดีบักสคริปต์ได้เช่นกัน
ZaxLofful

สิ่งนี้ตอบคำถามของคุณหรือไม่ "ทางออก" ใน PowerShell คืออะไร
Mark Schultheiss

คำตอบ:


389

คุณควรใช้คำหลักexit


15
อึศักดิ์สิทธิ์ถ้าฉันไม่ได้พยายามที่จะคิดออกว่าจะทำสิ่งเหล่านี้อย่างชาญฉลาดฉันอาจจะพยายามที่จะเริ่มต้นด้วยและคิดว่ามันได้ผล :) ขอบคุณ
kprobst

118
นี่เป็นคำตอบที่ยอมรับได้อย่างไร มันเป็นการเฉพาะ "ปิดหน้าต่างคอนโซล" ซึ่งผู้ถามพูดว่า "ซึ่งไม่ใช่สิ่งที่ฉันต้องการ"
claudekennilol

3
@claudekennilol มีเพียงผู้ถามคำถามเท่านั้นที่สามารถยอมรับคำตอบได้ ไม่ว่าพวกเขาจะพลาดความจริงที่ว่าทางออกควรจะปิดหน้าต่างหรือเปลี่ยนใจและถือว่ายอมรับได้สำหรับวัตถุประสงค์ของพวกเขา
Iszi

3
มันไม่ปิดหน้าต่างคอนโซลใน v3 หรือ v4 ซึ่งฉันใช้ มันจะถ้าคุณเรียกใช้สคริปต์จาก explorer แต่ไม่ว่าคุณจะจบสคริปต์มันก็จะทำเช่นนั้น หากเรียกใช้จากหน้าต่างคำสั่ง PowerShell จะไม่ปิดหน้าต่าง
Joshua Nurczyk

14
คำตอบของ New Guy นั้นละเอียดกว่ามากและสมควรถูกทำเครื่องหมายว่าเป็นที่ยอมรับ
จิม Aho

585

ฉันรู้ว่านี่เป็นโพสต์เก่า แต่ฉันพบว่าตัวเองกลับมาที่กระทู้นี้มากเพราะเป็นหนึ่งในผลการค้นหาอันดับต้น ๆ เมื่อค้นหาหัวข้อนี้ อย่างไรก็ตามฉันมักจะสับสนมากขึ้นแล้วเมื่อฉันมาเนื่องจากข้อมูลที่ขัดแย้งกัน ท้ายที่สุดฉันต้องทำการทดสอบด้วยตัวเองเสมอ ดังนั้นเวลานี้ฉันจะโพสต์สิ่งที่ค้นพบของฉัน

TL; DRคนส่วนใหญ่จะต้องการใช้Exitเพื่อยุติสคริปต์ที่กำลังทำงานอยู่ อย่างไรก็ตามหากสคริปต์ของคุณเป็นเพียงการประกาศฟังก์ชั่นเพื่อใช้ในเชลล์ในภายหลังคุณจะต้องใช้Returnคำจำกัดความของฟังก์ชั่นดังกล่าว

Exit vs Return vs Break

  • ออก:นี่จะเป็นการ "ออก" บริบทที่กำลังทำงานอยู่ หากคุณเรียกคำสั่งนี้จากสคริปต์คำสั่งนี้จะออกจากสคริปต์ ถ้าคุณเรียกคำสั่งนี้จากเชลล์มันจะออกจากเชลล์

    หากฟังก์ชั่นโทรออกคำสั่ง Exit มันจะออกจากสิ่งที่เคยเรียกใช้บริบทดังนั้นหากฟังก์ชั่นนั้นถูกเรียกใช้จากภายในสคริปต์ที่กำลังทำงานเท่านั้นมันจะออกจากสคริปต์นั้น อย่างไรก็ตามหากสคริปต์ของคุณประกาศฟังก์ชั่นเพื่อให้สามารถใช้งานได้จากเชลล์ปัจจุบันและคุณเรียกใช้ฟังก์ชั่นนั้นจากเชลล์มันจะออกจากเชลล์เนื่องจากเชลล์เป็นบริบทที่ฟังก์ชันต่อเนื่องExitคำสั่งที่ทำงานอยู่

    หมายเหตุ:โดยค่าเริ่มต้นหากคุณคลิกขวาที่สคริปต์เพื่อเรียกใช้ใน PowerShell เมื่อสคริปต์ทำงานเสร็จแล้ว PowerShell จะปิดโดยอัตโนมัติ สิ่งนี้ไม่เกี่ยวข้องกับExitคำสั่งหรือสิ่งอื่นใดในสคริปต์ของคุณ มันเป็นเพียงพฤติกรรมเริ่มต้นของ PowerShell สำหรับสคริปต์ที่กำลังเรียกใช้โดยใช้วิธีการเฉพาะนี้ในการเรียกใช้สคริปต์ เช่นเดียวกับไฟล์แบตช์และหน้าต่างบรรทัดคำสั่ง

  • กลับ:สิ่งนี้จะกลับไปที่จุดโทรก่อนหน้า ถ้าคุณเรียกคำสั่งนี้จากสคริปต์ (นอกฟังก์ชั่นใด ๆ ) มันจะกลับไปที่เชลล์ หากคุณเรียกคำสั่งนี้จากเชลล์มันจะกลับไปที่เชลล์ (ซึ่งเป็นจุดโทรก่อนหน้านี้สำหรับคำสั่งเดียวที่รันจากเชลล์) ถ้าคุณเรียกใช้คำสั่งนี้จากฟังก์ชันมันจะกลับไปยังตำแหน่งที่เคยเรียกใช้ฟังก์ชัน

    การดำเนินการคำสั่งใด ๆ หลังจากจุดโทรที่ถูกส่งกลับไปจะดำเนินการต่อจากจุดนั้น ถ้าสคริปต์ถูกเรียกจากเปลือกและมันก็มีReturnคำสั่งออกไปข้างนอกฟังก์ชั่นใด ๆ แล้วเมื่อมันกลับไปที่เปลือกมีไม่มีคำสั่งในการเรียกใช้จึงทำให้การใช้วิธีนี้หลักเช่นเดียวกับReturnExit

  • ทำลาย:สิ่งนี้จะแยกออกจากลูปและสลับเคส ถ้าคุณเรียกใช้คำสั่งนี้ในขณะที่ไม่ได้อยู่ในลูปหรือกรณีสวิตช์มันจะแตกออกจากสคริปต์ หากคุณโทรBreakภายในลูปที่ซ้อนอยู่ภายในลูปมันจะแยกออกจากลูปที่ถูกเรียกเท่านั้น

    นอกจากนี้ยังมีคุณสมบัติที่น่าสนใจBreakที่คุณสามารถใส่คำนำหน้าวนซ้ำด้วยป้ายกำกับและจากนั้นคุณสามารถแยกวงวนกำกับนั้นแม้ว่าBreakคำสั่งจะถูกเรียกภายในกลุ่มที่ซ้อนกันหลายกลุ่มภายในวงที่ติดป้ายกำกับนั้น

    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
นอกจากนี้ยังเห็นว่าคุ้มค่าExitสามารถนำรหัสการส่งคืนเป็นพารามิเตอร์ (ค่าเริ่มต้น 0) - Exit 3เช่น
aucuparia

2
ฉันเห็นด้วยนี่เป็นคำตอบที่ดีกว่ามาก "ตัวแบ่ง" อาจมีผลที่ไม่ตั้งใจ
iagomartinez

ฉันไม่แน่ใจว่าความคิดเห็นของคุณเกี่ยวกับ "ออก" ถูกต้องสมบูรณ์แม้ว่านี่จะเป็นคำตอบที่ดีโดยรวม ทางออกดูเหมือนว่าจะทำให้ ISE ปิดตัวลงในลักษณะที่ดูเหมือนจะไม่มีอะไรทำ เพียงออกจากบริบท (ตัวอย่างเช่นการทำให้สคริปต์สมบูรณ์) ไม่ได้ทำเช่นนี้
Bill K

1
@ บิลล์แน่นอน ฉันได้อัพเดตคำตอบแล้ว เมื่อฉันเขียนสิ่งนี้ครั้งแรกฉันจำไม่ได้ว่าพบเอกสารอย่างเป็นทางการเกี่ยวกับทางออก ฉันทำแล้วGet-Command ExitและGet-Alias Exitไม่มีผลลัพธ์ จากนั้นฉันดูเพื่อดูว่ามันเป็นคำหลักและไม่พบเอกสารอย่างเป็นทางการของมัน อย่างไรก็ตามในตอนนี้ฉันไม่ทราบว่าฉันมาถึงข้อสรุปได้อย่างไร ชัดเจนว่าเป็นคำหลัก ( technet.microsoft.com/en-us/library/hh847744.aspx ) อาจเป็นเพราะการออกเป็นหนึ่งในคำหลักเดียวที่ไม่มีหัวข้อ help_ ของตัวเองดังนั้นรายการของหัวข้อในแถบด้านข้างซ้ายจึงไม่รวม
Guy ใหม่

6
แล้วเรื่องการโยนล่ะ?
JDC

80

Exitจะออกจาก PowerShell ด้วย หากคุณต้องการที่จะ "แยก" ออกจากฟังก์ชั่นหรือสคริปต์ปัจจุบัน - ใช้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
โปรดอย่าใช้breakเมื่อต้องการแยกฟังก์ชั่นปัจจุบันออก ... สคริปต์การโทรสามารถถูกรบกวนได้เช่นกัน!
DannyMeister

49

เขียนข้อผิดพลาดคือความผิดพลาดที่ไม่ยุติและโยนสำหรับการยุติข้อผิดพลาด

cmdlet การเขียนข้อผิดพลาดประกาศข้อผิดพลาดที่ไม่สิ้นสุด โดยค่าเริ่มต้นข้อผิดพลาดจะถูกส่งในสตรีมข้อผิดพลาดไปยังโปรแกรมโฮสต์ที่จะแสดงพร้อมกับเอาต์พุต

ข้อผิดพลาดที่ไม่สิ้นสุดจะเขียนข้อผิดพลาดไปยังสตรีมข้อผิดพลาด แต่จะไม่หยุดการประมวลผลคำสั่ง หากมีการประกาศข้อผิดพลาดที่ไม่สิ้นสุดในหนึ่งไอเท็มในการรวบรวมไอเท็มอินพุตคำสั่งยังคงประมวลผลไอเท็มอื่นในการรวบรวม

ในการประกาศข้อผิดพลาดการยกเลิกให้ใช้คำหลัก Throw สำหรับข้อมูลเพิ่มเติมดู about_Throw ( http://go.microsoft.com/fwlink/?LinkID=145153 )


4
นี่เป็นวิธีที่ถูกต้องที่สุดในการยุติกิจกรรมที่มีข้อผิดพลาด มันมอบหมายให้ผู้โทรเพื่อพยายามจัดการกับข้อผิดพลาดซึ่งดีกว่าเพียงแค่พยายามที่จะยุติทันที
Paul Turner

อย่างน้อยในโมดูลฟังก์ชั่นการโยนออก แต่ไม่ได้ตั้งรหัสทางออก นี้ได้รับการดำเนินการผ่าน CLI powershell -command "& module-function ..."เช่น ฉันจำเป็นต้องแปลงฟังก์ชั่นเหล่านั้นให้เป็นแบบลองคัพและออกจากการจับแบบห่อนั้นเพื่อที่จะเอาท์พุทรหัสออกจากข้อผิดพลาด
Josh

2
อย่าลืม$PSCmdlet.ThrowTerminatingError()สำหรับกรณีที่เมื่อโยนก็ไม่สามารถได้งานทำ (ฉบับที่รู้จักกันมีข้อผิดพลาดไม่มียุติจากthrow)
Djarid

33

ยุติกระบวนการนี้และให้โค้ดการออกที่ระบุแก่ระบบปฏิบัติการ

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

[Environment]::Exit(1)

วิธีนี้จะช่วยให้คุณสามารถออกด้วยรหัสการออกเฉพาะซึ่งสามารถรับได้จากผู้โทร


3
ใน PowerShell Exit 1คุณก็สามารถใช้ในตัวออกจากนี้เช่น
Jonas

3
การออกในตัวไม่สามารถทำงานได้อย่างที่คุณคาดหวัง ลองใช้สิ่งนี้ใน powershell: "Exit 5"> test1.ps1 powershell.exe \ test1.ps1 $ lastexitcode "[สภาพแวดล้อม] :: ออก (5)"> test2.ps1 powershell.exe \ test2.ps1 $ lastexitcode
gabriwinter

1
[Environment]::Exit(1)มีผลข้างเคียงของการออกจากหน้าต่าง PowerShell ของฉันเมื่อฉันเรียกใช้ในสคริปต์ซึ่งการใช้exitไม่ปรากฏขึ้น
Josh Desmond

25

ฉันคิดว่าคุณกำลังมองหาแทนReturn Breakโดยทั่วไปแล้วตัวแบ่งจะใช้สำหรับการวนซ้ำและการหยุดพักจากบล็อกโค้ดด้านในเท่านั้น ใช้ Return เพื่อออกจากฟังก์ชั่นหรือสคริปต์


7
นี้ไม่ถูกต้อง - OP โดยเฉพาะขอให้ออกจากสคริปต์จากภายในฟังก์ชั่น Returnจะกลับมาจากฟังก์ชั่นไม่ใช่จากสคริปต์ ( Returnที่ด้านบนระดับของสคริปต์จะยุติสคริปต์ แต่ที่ไม่ได้คำถาม.)
ไมเคิล Sorens

1
คำตอบนี้เป็นความคิดเห็นจริง ๆ ในคำตอบ EverydayNerd หรือไม่
tkokasih

22

การโยนข้อยกเว้นจะดีโดยเฉพาะถ้าคุณต้องการชี้แจงเหตุผลข้อผิดพลาด:

throw "Error Message"

สิ่งนี้จะสร้างข้อผิดพลาดการยกเลิก


3
ฉันไม่คิดว่านี่จะเป็นการเพิ่มคำตอบของ Greg Bray ได้มากกว่าหนึ่งปีก่อนหน้านี้stackoverflow.com/a/20556550/695671
Jason S

12

อาจจะเป็นการดีกว่าถ้าใช้ "กับดัก" กับดัก PowerShell ระบุ codeblock ให้ทำงานเมื่อมีการยกเลิกหรือข้อผิดพลาดเกิดขึ้น ชนิด

Get-Help about_trap

เพื่อเรียนรู้เพิ่มเติมเกี่ยวกับคำสั่ง Trap


10

ผมบังเอิญพบว่า(เช่นเพียง, ที่ฉลากไม่อยู่ ) จะปรากฏขึ้นเพื่อแยกออกจากสคริปต์ทั้งหมด (แม้จากภายในฟังก์ชั่น) และช่วยให้เจ้าบ้านยังมีชีวิตอยู่ วิธีนี้คุณสามารถสร้างฟังก์ชันที่ทำลายสคริปต์จากที่ใดก็ได้ (เช่นวนซ้ำซ้ำ) โดยไม่ทราบขอบเขตปัจจุบัน (และการสร้างป้ายกำกับ):Break <UnknownLabel>Break ScriptScript

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

1
คำตอบของคุณเป็นจริง แต่โปรดระวังสิ่งนี้อาจทำให้เกิดปัญหากับผู้โทรหาสคริปต์ของคุณหากพวกเขาไม่เห็นด้วยกับความปรารถนาที่จะออกจากสคริปต์ทั้งหมด: stackoverflow.com/questions/45746588/
......

5

ฉันใช้สิ่งนี้เพื่อรันโปรแกรมอีกครั้ง ฉันไม่รู้ว่ามันจะช่วยได้หรือไม่ แต่มันเป็นเรื่องง่ายถ้าข้อความที่ต้องการเพียงสองรายการที่แตกต่างกัน มันทำงานใน PowerShell สำหรับฉัน

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

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

ไม่ทราบว่าสิ่งนี้จะช่วยได้หรือไม่ แต่ฉันเชื่อว่านี่จะเป็นไปตามแนวทางของการยกเลิกโปรแกรมหลังจากที่คุณเรียกใช้ อย่างไรก็ตามในกรณีนี้ทุกอินพุตที่กำหนดต้องใช้เอาต์พุตที่แสดงรายการและจัดหมวดหมู่ นอกจากนี้คุณยังสามารถให้ทางออกเรียกขึ้นบรรทัดใหม่และยกเลิกโปรแกรมด้วยวิธีนี้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.