PoshCode ( http://poshcode.org/3226) 에서 Get-WebFile 스크립트를 살펴보면 다음과 같은 이상한 충돌을 발견했습니다.
$URL_Format_Error = [string]"..."
Write-Error $URL_Format_Error
return
다음과 반대되는 이유는 무엇입니까?
$URL_Format_Error = [string]"..."
Throw $URL_Format_Error
또는 더 나은 :
$URL_Format_Error = New-Object System.FormatException "..."
Throw $URL_Format_Error
내가 이해하는 것처럼 종료하지 않는 오류에는 Write-Error를 사용하고 오류는 종료하는 경우 Throw를 사용해야하므로 Write-Error 다음에 Return을 사용해서는 안됩니다. 차이가 있습니까?
답변
Write-Error
중요하지 않은 오류를 사용자에게 알리려면 사용해야합니다. 기본적으로 콘솔에 오류 메시지가 빨간색 텍스트로 인쇄됩니다. 파이프 라인이나 루프가 계속되는 것을 막지는 않습니다. Throw
반면에 종료 오류라고하는 것을 생성합니다. throw를 사용하면 파이프 라인 및 / 또는 전류 루프가 종료됩니다. 사실 trap
또는 try/catch
구조를 사용하여 종료 오류를 처리 하지 않으면 모든 실행이 종료됩니다.
당신이 설정 한 경우주의 할 점은있다 $ErrorActionPreference
로"Stop"
하고 사용 Write-Error
이됩니다 종료 오류를 생성 .
당신이 링크 한 스크립트에서 우리는 이것을 발견합니다 :
if ($url.Contains("http")) {
$request = [System.Net.HttpWebRequest]::Create($url)
}
else {
$URL_Format_Error = [string]"Connection protocol not specified. Recommended action: Try again using protocol (for example 'http://" + $url + "') instead. Function aborting..."
Write-Error $URL_Format_Error
return
}
해당 함수의 작성자가 해당 함수의 실행을 중지하고 화면에 오류 메시지를 표시하려고하지만 전체 스크립트의 실행을 중지하지 않으려는 것처럼 보입니다. 스크립트 작성자가 사용할 수는 throw
있지만 try/catch
함수를 호출 할 때 를 사용해야한다는 의미 입니다.
return
함수, 스크립트 또는 스크립트 블록 일 수있는 현재 범위를 종료합니다. 이것은 코드로 가장 잘 설명됩니다.
# A foreach loop.
foreach ( $i in (1..10) ) { Write-Host $i ; if ($i -eq 5) { return } }
# A for loop.
for ($i = 1; $i -le 10; $i++) { Write-Host $i ; if ($i -eq 5) { return } }
두 가지에 대한 출력 :
1
2
3
4
5
여기에 하나 개 잡았다 사용 return
하여 ForEach-Object
. 예상대로 처리를 중단하지 않습니다.
추가 정보:
$ErrorActionPreference
: about_Preference_Variablestry/catch
: about_Try_Catch_Finallytrap
: about_Trapthrow
: about_Throwreturn
: about_Return
답변
쓰기 오류 의 주요 차이점 cmdlet 및 던져 PowerShell의 키워드는 전자가 단순히이다 인쇄 받는 텍스트 표준 오류 스트림 (표준 오류) 후자는 실제로 동안 종료 된 실행 명령이나 함수의 처리, 후 처리를 오류 정보를 콘솔에 보내 PowerShell에 의해.
제공 한 예제에서 두 가지의 다른 동작을 관찰 할 수 있습니다.
$URL_Format_Error = [string]"..."
Write-Error $URL_Format_Error
return
이 예에서는 오류 메시지가 콘솔로 전송 된 후 스크립트 실행 return
을 명시 적으로 중지 하기 위해 키워드가 추가 되었습니다. 반면 두 번째 예에서는return
종료가 암시 적으로 수행되므로 키워드가 필요하지 않습니다 throw
.
$URL_Format_Error = New-Object System.FormatException "..."
Throw $URL_Format_Error
답변
중요 : 두 가지 유형의 종료 오류 가 있으며 현재 도움말 항목이 불행히도 충돌합니다 .
-
문 -terminating 오류, 특정 복구 할 수없는 상황에서 cmdlet에 의해 및 .NET 예외가 / PS 런타임 오류가 발생하는 식으로보고; 진술 만 종료 되고 기본적으로 스크립트 실행이 계속됩니다 .
-
스크립트는 -terminating : (더 정확하게 오류 실행 영역-종료를 중 하나에 의해 트리거 등)
Throw
또는 에러 동작 환경 변수 / 파라미터 값을 통해 오차 다른 유형 중 하나를 확대하여이Stop
.
잡히지 않으면 현재 런 스페이스 (스레드)를 종료합니다. 즉, 현재 스크립트뿐만 아니라 해당하는 경우 모든 호출자도 종료합니다.
PowerShell의 오류 처리에 대한 포괄적 인 개요는 이 GitHub 설명서 문제를 참조하십시오. .
이 포스트의 나머지 부분은 비 종료 대 진술 종결 에 중점을 둡니다. 오류 .
질문의 핵심에 중점을 둔 기존의 유용한 답변을 보완하려면 : 문장 종결 또는 비 종료 오류 보고 방법을 어떻게 선택 합니까 ?
Cmdlet 오류보고 에는 유용한 지침이 포함되어 있습니다. 실용 요약을 시도하겠습니다 .
비 종료 오류의 기본 개념 은 대규모 입력 세트의 “내결함성”처리를 허용 하는 것 입니다. 입력 객체 의 하위 세트 를 처리 하지 못하면 기본적으로 장기 실행 프로세스 를 전체적으로 중단해서는 안됩니다 . 자동 변수로 수집 된 오류 레코드를 통해보고 된대로 나중에 오류를 검사하고 실패한 개체 만 재 처리 할 수 있습니다 $Error
.
-
cmdlet / 고급 기능인 경우 NON-TERMINATING 오류를 보고 하십시오.
- 파이프 라인 입력 및 / 또는 배열 값 매개 변수를 통해 MULTIPLE 입력 객체를 받아들입니다.
- 오류 SPECIFIC 입력 개체 발생 , AND
- 이러한 오류는 원칙적으로 추가 입력 개체의 처리를 예방하지 않습니다 ( 상황 에 따라 입력 개체가 없거나 이전 입력 개체가 이미 성공적으로 처리되었을 수 있음).
- 고급 기능에서
$PSCmdlet.WriteError()
종료Write-Error
하지 않는 오류를보고하는 데 사용 합니다 ( 불행히도 호출자의 범위 에서$?
설정 되지 않음 – 이 GitHub 문제 참조 ).$False
- 처리 종료되지 않는 오류 것은 :
$?
가장 최근의 명령이보고 여부를 알려줍니다 적어도 하나의 종료되지 않는 오류가 발생했습니다.- 따라서,
$?
존재$False
한다는 것은 (빈이 아닌) 서브셋을 입력 개체가 올바르게 아마도 전체 세트를 처리하지 않았다. - 기본 설정 변수
$ErrorActionPreference
및 / 또는 공통 cmdlet 매개 변수-ErrorAction
는 오류 출력 동작 및 종료되지 않는 오류를 스크립트 종료 오류로 에스컬레이션해야하는지 여부에 따라 종료되지 않는 오류의 동작 (만)을 수정할 수 있습니다.
- 따라서,
- 고급 기능에서
-
다른 모든 경우에는 STATEMENT-TERMINATING 오류를 보고하십시오 .
- 특히 SINGLE 또는 NO 입력 개체 만 허용하고 NO 또는 SINGLE 출력 개체를 출력하거나 매개 변수 입력 만 가져 오고 주어진 매개 변수 값이 의미있는 작업을 방해 하는 cmdlet / 고급 기능에서 오류가 발생하는 경우 .
- 고급 기능에서는
$PSCmdlet.ThrowTerminatingError()
명령문 종료 오류를 생성하기 위해 사용해야합니다 . - 반대로
Throw
키워드 는 전체 스크립트 (기술적으로는 현재 스레드 ) 를 중단 시키는 스크립트 종료 오류를 생성합니다 . - 취급 성명 – 종료 오류를하십시오
try/catch
핸들러 또는trap
문을 사용할 수 있습니다 (이 수 와 함께 사용할 수 비 종료 오류)하지만, 참고 심지어 문 기본적으로 -terminating 오류가 실행 스크립트의 나머지 부분을 방지하지 않습니다. 종료하지 않는 오류 와 마찬가지로 이전 명령문이 명령문 종료 오류를 트리거했는지 여부를$?
반영$False
합니다.
- 고급 기능에서는
- 특히 SINGLE 또는 NO 입력 개체 만 허용하고 NO 또는 SINGLE 출력 개체를 출력하거나 매개 변수 입력 만 가져 오고 주어진 매개 변수 값이 의미있는 작업을 방해 하는 cmdlet / 고급 기능에서 오류가 발생하는 경우 .
안타깝게도 모든 PowerShell 자체 핵심 cmdlet이 다음 규칙에 따라 작동하는 것은 아닙니다 .
-
실패 할 가능성은 없지만
New-TemporaryFile
(PSv5 +)는 파이프 라인 입력을 수락하지 않고 하나의 출력 개체 만 생성하더라도 실패하면 종료되지 않는 오류를보고합니다 . 그러나 최소한 PowerShell [Core] 7.0에서 수정되었습니다. 그러나이 GitHub를 참조하십시오. 문제 . -
Resume-Job
의 도움이 주장이 지원되지 않는 작업 유형을 (통과 등으로 생성 된 작업으로Start-Job
지원되지 않습니다, 때문에Resume-Job
워크 플로 작업 에만 적용 작업)을 전달하면 종료 오류가 발생하지만 PSv5.1에서는 사실이 아닙니다.
답변
Write-Error
함수 소비자가 -ErrorAction SilentlyContinue
(또는 -ea 0
)로 오류 메시지를 표시하지 않도록합니다 . throw
필요한 동안try{...} catch {..}
try … catch를 Write-Error
다음 과 함께 사용하려면
try {
SomeFunction -ErrorAction Stop
}
catch {
DoSomething
}
답변
Andy Arismendi의 답변에 추가 :
쓰기 오류 가 프로세스를 종료 할지 여부 는 $ErrorActionPreference
설정에 따라 다릅니다 .
사소한 스크립트의 경우 빠르게 실패 $ErrorActionPreference = "Stop"
하도록 권장되는 설정 입니다.
“오류와 관련하여 PowerShell의 기본 동작은 오류가 계속됩니다 … VB6″다음 오류시 이력서 다시 시작 느낌 “-ish”
( http://codebetter.com/jameskovacs/2010/02/25/the-exec-problem/에서 )
그러나 Write-Error
통화가 종료됩니다.
사용하려면 쓰기 오류 에 관계없이 다른 환경 설정의 비 종료 명령으로, 당신이 사용할 수있는 공통 매개 변수 -ErrorAction
값 Continue
:
Write-Error "Error Message" -ErrorAction:Continue
답변
코드를 읽는 것이 정확하면 맞습니다. 종료 오류는을 사용해야 throw
하며 .NET 유형을 처리하는 경우 .NET 예외 규칙을 따르는 것이 좋습니다.