Welcome to Our Website

모든 것을 당신에 대해 알고 싶어 예외

  • 05/23/2020
  • 14 분 읽
    • j
    • f

오류 처리하는 정당한 부분의 생활에 올 때 쓰는 코드입니다. 우리는 종종 확인하고 유효성을 검사 할 수 있습니다.예상되는 행동에 대한 조건. 예기치 않은 일이 발생하면 예외 처리로 전환합니다., 할 수 있습니다 쉽게 처리 예외는 다른 사람에 의해 생성 된 코드를 생성할 수 있습니다 당신의 ownexceptions 다른 사람을 위해 처리합니다.

참고

이 기사의 원본 버전은@KevinMarquette 가 작성한 블로그에 나타났습니다. ThePowerShell 팀은이 콘텐츠를 우리와 공유해 주신 Kevin 에게 감사드립니다. 을 확인하시기 바랍니 그의 블로그 atPowerShellExplained.com.

기본적인 용어

우리는 몇 가지 기본적인 기간 전에 우리는 이 하나입니다.

예외

예외는 정상적인 오류 처리로 문제를 처리 할 수 없을 때 생성되는 이벤트와 같습니다.,숫자를 0 으로 나누려고하거나 메모리가 부족한 것은 anexception 을 만드는 무언가의 예입니다. 때로는 사용중인 코드의 작성자가 특정 문제에 대한 예외를 만듭니다.그들이 일어날 때.

Throw And Catch

예외가 발생하면 예외가 발생한다고 말합니다. 던져진 예외를 처리하려면그것을 잡을 필요가있다. 예외가 발생하고 무언가에 의해 잡히지 않으면 스크립트가 중지됩니다.

호출 스택

호출 스택은 목록의 기능이 있는 호출됩니다., 함수가 호출 될 때 스택 또는 목록의 맨 위에 추가됩니다. 함수가 종료되거나 반환되면 제거됩니다.스택에서.

예외가 발생하면 예외 처리기가 catchit 하기 위해 해당 호출 스택이 검사됩니다.

종료 및 비 종료 오류

예외는 일반적으로 종료 오류입니다. Throw 된 예외는 catch 또는 itterminates 현재 실행 중 하나입니다. 기본적으로 비 종료 오류는Write-Error에 의해 생성되며 예외를 던지지 않고 출력 스트림에 오류를 추가합니다.,

Write-Error및 기타 비 종료 오류가catch를 트리거하지 않기 때문에이를 지적합니다.

예외를 삼키는 것

이것은 단지 그것을 억제하기 위해 오류를 잡을 때입니다. 만들 수 있으므로주의하여이 작업을 수행하십시오.매우 어려운 문제를 해결하십시오.

기본 명령 구문

간략히 요약하면 다음과 같습니다 기본적인 예외 처리에 사용되는 구문에 있습니다.

Throw

자체 예외 이벤트를 만들려면throw키워드로 예외를 던집니다.,

function Start-Something{ throw "Bad thing happened"}

이것은 종료 오류 인 런타임 예외를 만듭니다. Acalling 함수에서catch에 의해 처리되거나 이와 같은 메시지로 스크립트를 종료합니다.

Write-Error-ErrorAction Stop

Write-Error는 기본적으로 종료 오류를 발생시키지 않는다고 언급했습니다. 을 지정하는 경우-ErrorAction Stop,Write-Error생성한 종료는 오류를 처리할 수 있으로catch.,

Write-Error -Message "Houston, we have a problem." -ErrorAction Stop

감사합니 Lee 데일리기 위해 사용에 대해-ErrorAction Stop이다.

Cmdlet-ErrorAction 중지

경우 지정한-ErrorAction Stop에 고급 기능 또는 cmdlet,그것은 모든Write-Error문으로 종료하는 오류를 실행을 중단하거나 처리할 수 있는catch.,

Start-Something -ErrorAction Stop

Try/잡기

방법 예외 처리 작품에서 PowerShell(그리고 많은 다른 언어)에는 당신이 첫 번째tryasection 코드의 경우 오류가 발생할 수 있습catch니다. 다음은 빠른 샘플입니다.

catch스크립트는 종료 오류가있는 경우에만 실행됩니다. try가 올바르게 실행되면catch를 건너 뜁니다.,

Try/Finally

때로는 오류를 처리 할 필요가 없지만 exceptionhappens 가 아닌 경우 실행하는 코드가 여전히 필요합니다. Afinally스크립트는 정확하게 수행합니다.

이 예제를 살펴보십시오.

리소스를 열거 나 연결할 때 언제든지 닫아야합니다. ExecuteNonQuery()throwsan 예외 인 경우 연결이 닫히지 않습니다. 여기에try/finally블록 안에 동일한 코드가 있습니다.이 예에서는 오류가 있으면 연결이 닫힙니다. 또한 noerror 가 있으면 닫힙니다., finally스크립트는 매번 실행됩니다.

예외를 잡는 것이 아니기 때문에 여전히 호출 스택 위로 전파됩니다.

Try/Catch/Finally

catchfinally를 함께 사용하는 것이 완벽하게 유효합니다. 대부분의 경우 하나 또는다른,하지만 당신은 당신이 둘 다 사용하는 시나리오를 찾을 수 있습니다.

$PSItem

이제 우리는 기초를 가지고 밖의 방법으로,우리는 할 수 있습합니다.,

안에catch블록이 자동적인 변수($PSItem또는$_)의 유형ErrorRecord포함된 정보에 대한 예외는 아니다. 다음은 키 프로퍼티 중 일부에 대한 간략한 개요입니다.

이 예제에서는ReadAllText에서 잘못된 경로를 사용하여이 예외를 생성했습니다.

::ReadAllText( '\\test\no\filefound.log')

PSItem.ToString()

이렇게하면 로깅 및 일반 출력에 사용할 가장 깨끗한 메시지가 제공됩니다., ToString()isautomatically 경우 호출$PSItem문자열 안에 배치.

catch{ Write-Output "Ran into an issue: $($PSItem.ToString())"}catch{ Write-Output "Ran into an issue: $PSItem"}

$PSItem.InvocationInfo

이 속성에는 예외가 throw 된 함수 또는 scriptwhere 에 대해 PowerShell 에서 수집 한 추가 정보가 포함되어 있습니다. 다음은 Icreated 샘플 예외에서InvocationInfo입니다.

중요한 정보를 여기에서 보여주는ScriptName,Line코드의ScriptLineNumber어디서 호출을 시작했다.피>

$PSItem.,ScriptStackTrace

이 속성은 예외가 생성 된 코드로 가져온 함수 호출 순서를 보여줍니다.

나는 같은 스크립트의 함수에 대한 호출 만하고 있지만 다중 스크립트가 관련된 경우 호출을 추적합니다.피>

$PSItem.예외

이것은 던져진 실제 예외입니다.피>

$PSItem.예외.Message

이것은 예외를 설명하는 일반적인 메시지이며 좋은 출발점입니다. 대부분의 예외에는 기본 메시지가 있지만 예외가 발생했을 때 사용자 정의 된 것으로 설정할 수도 있습니다.,

PS> $PSItem.Exception.MessageException calling "ReadAllText" with "1" argument(s): "The network path was not found."

이것은 또한 메시지를 반환할 때 전화$PSItem.ToString()가 아니었다면 중 하나에 설정ErrorRecord.피>

$PSItem.예외.Innerexception

예외에는 내부 예외가 포함될 수 있습니다. 이것은 종종 호출하는 코드가 예외를 캐치하고 다른 예외를 throw 하는 경우입니다. 원래 예외는 내부에 배치됩니다.새로운 예외.

PS> $PSItem.Exception.InnerExceptionMessageThe network path was not found.

나중에 예외를 다시 던지는 것에 대해 이야기 할 때 다시 방문 할 것입니다.피>

$PSItem.예외.,Stacktrace

예외에 대한StackTrace입니다. 위의ScriptStackTrace를 보여 주었지만,이 코드는 관리 코드에 대한 호출입니다.

at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost)at System.IO.StreamReader..ctor(String path, Encoding encoding, Boolean detectEncodingFromByteOrderMarks, Int32 bufferSize, Boolean checkHost)at System.IO.File.InternalReadAllText(String path, Encoding encoding, Boolean checkHost)at CallSite.Target(Closure , CallSite , Type , String )

이벤트가 관리 코드에서 던져 질 때만이 스택 추적을 얻습니다. 나는 전화하고있다.NETframework 기능 직접 그래서 우리는이 예에서 볼 수있는 모든 것입니다. 일반적으로 스택 추적을 수행 할 때 코드가 멈추고 시스템 호출이 시작되는 위치를 찾고 있습니다.

예외 작업

기본 구문 및 예외 속성보다 예외에 더 많은 것이 있습니다.,

형식화 된 예외 잡기

당신이 잡는 예외와 함께 선택적 일 수 있습니다. 예외에는 유형이 있으며 지정할 수 있습니다.잡으려는 예외 유형.

제외 유형은 체크에 대한 각catch블록할 때까지 중 하나입니다 찾을과 일치하는 예외는 아니다.그것은 깨닫는 것이 중요하다는 예외 수 있는 상속에서 다른 예외가 있습니다. 위의 예에서FileNotFoundExceptionIOException에서 상속됩니다. 따라서IOException가 처음이라면 대신 호출됩니다., 일치하는 항목이 여러 개인 경우에도 하나의 캐치 블록 만 호출됩니다.

경우리System.IO.PathTooLongException,IOException가 일치하지만 경우에는InsufficientMemoryException아무것도 잡을 것이고 그 전파하는 것까지 합니다.

한 번에 여러 유형 잡기

동일한catch문을 가진 여러 예외 유형을 잡을 수 있습니다.

이 추가를 제안 해 주셔서 감사합니다/u/Sheppard_Ra.

형식화 된 예외 던지기

PowerShell 에서 형식화 된 예외를 던질 수 있습니다., 을 호출하는 대신throw문자열

throw "Could not find: $path"

를 사용하여 예외가 가속기 like this:

throw "Could not find: $path"

하지만 당신은 메시지를 지정할 때 당신이 그것입니다.

던져 질 예외의 새 인스턴스를 만들 수도 있습니다. 할 때 메시지는 선택 사항입니다.시스템에 모든 기본 제공 예외에 대한 기본 메시지가 있기 때문입니다.

throw ::new()throw ::new("Could not find path: $path")

를 사용하지 않는 경우 PowerShell5.0 이상을 사용해야 합니다 나New-Object접근 방식이다.,

를 사용하여 입력한 예외를 제외하고(또는 다른 사람)을 잡을 수 있는 예외를 유형에 의해 언급했듯이에서는 이전 섹션입니다.

쓰기 오류-제외

추가할 수 있습니다 이러한 형식의 예외를Write-Error우리는 여전히catch오류를 exceptiontype. 사용Write-Error에서 같은 이러한 예제:

그리를 잡을 수 있습 it like this:

catch { Write-Log $PSItem.ToString()}

큰 목록이다.NET 예외

I 컴파일 목록의 도움으로 레딧/r/PowerShell 커뮤니티는 containshundreds 습니다.,순 예외는이 게시물을 보완합니다.

  • 큰 목록이다.NET 예외

시작 검색하여 그 목록에 대한 예외처럼 느끼는 그런 것에 적합한 mysituation. 기본System네임 스페이스에서 예외를 사용하려고합니다.

예외는 객체

형식화 된 예외를 많이 사용하기 시작하면 객체임을 기억하십시오. 다른 예외다른 생성자와 속성이 있습니다., System.IO.FileNotFoundException에 대한 FileNotFoundExceptiondocumentation 을 보면 메시지와 filepath 를 전달할 수 있음을 알 수 있습니다.

::new("Could not find file", $path)

FileName속성이 있는 노출하는 파일 경로.

catch { Write-Output $PSItem.Exception.FileName}

다른 생성자 및 객체 속성에 대해서는.NET 설명서를 참조해야합니다.

재 던지는 예외

경우 모든 일을 할 겁에서 당신의catch블록throw같은 예외지 않는catch니다., catchithappens 때 일부 작업을 처리하거나 수행하려는 예외 만 있어야합니다.

예외에 대한 작업을 수행 할 때가 있지만 예외를 다시 던지면 다운 스트림이 처리 할 수 있습니다. 우리는 메시지를 작성하거나 문제를 해결할 위치에 가깝게 기록 할 수 있지만 문제를 스택 위로 더 처리 할 수 있습니다.

catch{ Write-Log $PSItem.ToString() throw $PSItem}

충분히 흥미롭게,우리는 전화throw내에서catch그리고 다시 발생합 currentexception.,

catch{ Write-Log $PSItem.ToString() throw}

우리는 다시 throw 예외를 유지 원래의 실행과 같은 정보를 원 scriptand 니다. 이 시점에서 새로운 예외를 던지면 예외가 시작된 곳을 숨 깁니다.

새 예외를 다시 던지기

예외를 잡지만 다른 예외를 던지려면 originalexception 을 새 예외 안에 중첩해야합니다. 이렇게하면 스택 아래의 누군가가$PSItem.Exception.InnerException로 액세스 할 수 있습니다.

catch{ throw ::new('Could not access field',$PSItem.Exception)}

$PSCmdlet.,ThrowTerminatingError()

한 것은 내가 좋아하지 않 사용에 대해throwraw 예외는 오류 messagepoints 에서throw문을 나타냅니다 라는 문제입니다.

는 오류 메시지가 나에게 말하는 내가 스크립트가 깨지기 때문에 나라는throw선 31 아바드 메시지 사용자를 위한 스크립트를 참조하십시오. 그것은 그들에게 유용한 것을 말하지 않습니다.

Dexter Dhami 는ThrowTerminatingError()를 사용하여 수정할 수 있다고 지적했습니다.,

고 가정하는 경우ThrowTerminatingError()이라는 기능 안에 라는Get-Resource,thenthis 는 오류를 우리는 것입니다.

문제의 근원으로Get-Resource함수를 가리키는 방법을 보십니까? 즉,사용자에게 유용한 것을 알려줍니다.

기 때문에$PSItemErrorRecord,우리 또한 사용할 수 있습니다ThrowTerminatingError이 방법을 다시 throw.,

catch{ $PSCmdlet.ThrowTerminatingError($PSItem)}

이것은 오류의 원인을 Cmdlet 으로 변경하고 Cmdlet 의 사용자로부터 함수의 내부를 숨 깁니다.

Try 는 종료 오류를 만들 수 있습니다.

Kirk Munro 는try/catch블록 내에서 실행될 때 일부 예외는 종료 오류라고 지적합니다. 여기 그가 나에게 준 예제는 0 런타임 예외로 나누기를 생성합니다.

function Start-Something { 1/(1-1) }

한 다음 호출이 그것을 참조를 생성 오류가하고 여전히 출력한 메시지입니다.,

&{ Start-Something; Write-Output "We did it. Send Email" }

지에 의해 배치하는 동일한 코드 안에try/catch,우리는 다른 뭔가가 일어난다.

try{ &{ Start-Something; Write-Output "We did it. Send Email" }}catch{ Write-Output "Notify Admin to fix error and send email"}

오류가 종료 오류가되어 첫 번째 메시지를 출력하지 않는 것을 볼 수 있습니다. 내가 무엇을 하지 않 likeabout 이 하나 있는가에 이 코드는 기능과 행동을 다르게하는 경우 someoneis 사용하는try/catch.

나는 이것에 문제가 발생하지 않았지만주의해야 할 코너 케이스입니다.

$PSCmdlet.,ThrowTerminatingError()안에 시도/잡기

하나의 뉘앙스의$PSCmdlet.ThrowTerminatingError()는 만들어지는 종료에 오류가 yourCmdlet 하지만 그것을 종료한 후에도 오류가 나뭇잎의합니다. 이렇게하면 함수의 호출자가 오류를 처리하는 방법을 결정할 수 있습니다. 그들은-ErrorAction Stop를 사용하거나try{...}catch{...}내에서 호출하여 aterminating 오류로 되돌릴 수 있습니다.,

공공 기능 템플릿

중 하나는 지난고 나와 대화를 커크 먼로이었다는 그는try{...}catch{...}주위의 모든begin,processend블록에서 자신의 모든 advancedfunctions. 에 그 일반적인 catch 블록,그는 하나의 라인을 사용하여$PSCmdlet.ThrowTerminatingError($PSItem)과 거래하는 모든 예외를 떠나 자신의 기능입니다.

function Start-Something{ param() process { try { ... } catch { $PSCmdlet.ThrowTerminatingError($PSItem) } }}

기 때문에 모든 것을try진술에서 그의 기능을 모두 역할을합니다., 이것은 또한 생성 된 오류에서 내부 코드를 숨기는 최종 사용자에게 깨끗한 오류를 제공합니다.

트랩

예외의try/catch측면에 중점을 두었습니다. 그러나 언급해야 할 레거시 기능이 하나 있습니다.우리가 이것을 마무리하기 전에.

Atrap는 스크립트 또는 함수에 배치되어 해당 범위에서 발생하는 모든 예외를 포착합니다. 예외가 발생하면trap의 코드가 실행 된 다음 일반 코드가 계속됩니다. 여러 예외가 발생하면 트랩이 반복해서 호출됩니다.,

나 개인적으로 적이 방법을 채택했지만 저는 가치를 볼 수 있는 관리자 또는 컨트롤러 스크립트 thatlog 는 모든 예외를,그리고 여전히 계속 실행됩니다.

닫는 말

추가한 적절한 예외 처리하는 스크립트를 만들 뿐만 아니라 그들을 더 안정적이지만,또한 iteasier 당신을 위해 문제 해결이 그 예외가 있습니다.

I 많은 시간을 보낸 이야기throw기 때문에 그것은 핵심 개념에 대해 이야기 할 때 exceptionhandling., PowerShell 또한 우리에게Write-Error을 처리하는 모든 상황은 당신을 사용하는 것throw. 그래서 이것을 읽은 후에throw를 사용해야한다고 생각하지 마십시오.

이제는 나를 작성하는 시간을 촬영하에 대한 예외 처리에 이 세부사항,나 toswitch 이상을 사용하는Write-Error -Stop를 생성에 오류가 나의 코드입니다. 또한 kirk 의 조언을 받아ThrowTerminatingError모든 함수에 대해 내 goto 예외 처리기를 만들 것입니다.피>

답글 남기기

이메일 주소를 발행하지 않을 것입니다. 필수 항목은 *(으)로 표시합니다