참고 : 질문의 명령은을 사용 Start-Process
하여 대상 프로그램의 출력을 직접 캡처하지 못하게합니다. 일반적으로 콘솔 응용 프로그램을 동기식으로 실행 하는 Start-Process
데 사용하지 마십시오 . 쉘에서와 같이 직접 콘솔 응용 프로그램을 호출 하십시오. 이렇게하면 응용 프로그램이 호출 콘솔의 표준 스트림에 연결되어 $output = netdom ...
아래에 설명 된대로 간단한 할당으로 출력을 캡처 할 수 있습니다.
기본적 으로 외부 유틸리티의 출력 캡처 는 PowerShell 기본 명령과 동일하게 작동합니다 ( 외부 도구를 실행하는 방법에 대한 새로 고침이 필요할 수 있음).
$cmdOutput = <command> # captures the command's success stream / stdout
$cmdOutput
하나 이상의 출력 객체를 생성하는 경우 객체 배열 을 수신합니다 . 외부 프로그램 의 경우 프로그램의 출력 라인을 포함하는 문자열 배열을 의미합니다 .
당신이 원하는 경우 항상받을 하나의 잠재적 멀티 라인 - - 문자열을 사용<command>
$cmdOutput
$cmdOutput = <command> | Out-String
하려면 캡처 변수에 출력 하고 화면에 인쇄 :
<command> | Tee-Object -Variable cmdOutput # Note how the var name is NOT $-prefixed
경우 또는, <command>
A는 cmdlet을 또는 고급 기능, 당신이 사용할 수있는 공통 매개 변수를
-OutVariable
/-ov
:
<command> -OutVariable cmdOutput # cmdlets and advanced functions only
와 그주의 -OutVariable
다른 시나리오에서, 달리 $cmdOutput
입니다 항상 수집 에만하더라도, 하나의 객체가 출력됩니다. 특히, 배열과 같은 [System.Collections.ArrayList]
유형 의 인스턴스 가 반환됩니다. 이 불일치에 대한 설명은 이 GitHub 문제 를
참조하십시오 .
의 출력 캡처하려면 여러 명령 , 사용 중 서브 표현식을 ( $(...)
) 또는 (스크립트 블록을 전화 { ... }
로) &
또는 .
:
$cmdOutput = $(<command>; ...) # subexpression
$cmdOutput = & {<command>; ...} # script block with & - creates child scope for vars.
$cmdOutput = . {<command>; ...} # script block with . - no child scope
참고가 있음을 접두사로 일반 필요 &
(전화 연산자) 이름이 개인 명령이 / 경로가됩니다 인용 - 예를 들어, $cmdOutput = & 'netdom.exe' ...
- 그 자체로 외부 프로그램과 관련이 없습니다 (이 동등하게 PowerShell 스크립트에 적용), 그러나입니다 구문 요구 사항 : PowerShell을 기본적으로 표현식 모드 에서 따옴표로 묶인 문자열로 시작하는 명령문을 구문 분석 하지만 인수 모드 는 명령 (cmdlet, 외부 프로그램, 함수, 별명)을 호출하는 데 필요합니다.&
합니다.
$(...)
와 & { ... }
/ 사이의 주요 차이점 . { ... }
은 전자 가 전체 입력을 반환하기 전에 메모리의 모든 입력을 수집하는 반면, 후자 는 1 대 1 파이프 라인 처리에 적합한 출력을 스트리밍 한다는 것입니다.
리디렉션 은 기본적으로 동일하게 작동하지만 아래주의 사항을 참조하십시오.
$cmdOutput = <command> 2>&1 # redirect error stream (2) to success stream (1)
그러나 외부 명령의 경우 다음과 같이 예상대로 작동 할 가능성이 높습니다.
$cmdOutput = cmd /c <command> '2>&1' # Let cmd.exe handle redirection - see below.
외부 프로그램과 관련된 고려 사항 :
외부 프로그램 은 PowerShell의 유형 시스템 외부에서 작동하기 때문에 성공 스트림 (stdout)을 통해서만 문자열 을 반환 합니다.
출력에 둘 이상의 줄이 포함되어 있으면 PowerShell은 기본적으로 출력 을 문자열 배열 로 분할합니다 . 보다 정확하게, 출력 라인은 [System.Object[]]
요소가 문자열 ( [System.String]
) 인 유형 의 배열에 저장됩니다 .
당신이 경우 출력이되고 싶어 하나 , 잠재적으로 여러 줄의 문자열을 , 파이프Out-String
:
$cmdOutput = <command> | Out-String
2>&1
성공 스트림의 일부로 캡처하기 위해 stderr를 stdout으로 리디렉션 하면 다음과 같은 경고 가 있습니다 .
하려면 2>&1
병합 표준 출력과 표준 에러를 소스에서 , 하자 cmd.exe
리디렉션을 처리하는 다음과 같은 관용구를 사용하여 :
$cmdOutput = cmd /c <command> '2>&1' # *array* of strings (typically)
$cmdOutput = cmd /c <command> '2>&1' | Out-String # single string
cmd /c
cmd.exe
명령으로 호출 하고 <command>
이후에 종료<command>
완료되었습니다.
- 주위에 작은 따옴표
2>&1
를 사용하면 리디렉션이 전달됩니다.cmd.exe
PowerShell에서 해석하지 않고 .
포함 cmd.exe
한다는 것은 기본적으로 PowerShell 자체 요구 사항 외에도 캐릭터를 이스케이프하고 환경 변수를 확장 하는 규칙이 적용됨 을 의미합니다 . PS v3 +에서는 특수 매개 변수 --%
(소위 중지 구문 분석 기호 )를 사용하여 cmd.exe
와 같은 스타일 환경 변수 참조를 제외하고 PowerShell에 의해 나머지 매개 변수의 해석을 해제 할 수 %PATH%
있습니다.
이 접근 방식으로 소스에서 stdout과 stderr 을 병합하므로 PowerShell에서 stdout-originated 라인과 stderr-originated 라인을 구별 할 수 없습니다 . 이 구분이 필요한 경우 PowerShell 자체 2>&1
리디렉션을 사용 하십시오 (아래 참조).
PowerShell의 2>&1
리디렉션을 사용 하여 어떤 스트림에서 어떤 라인이 나왔는지 알 수 있습니다 .
STDERR 출력으로 캡처 오류 기록 ( [System.Management.Automation.ErrorRecord]
소위)가 아닌 문자열 출력 어레이가 포함될 수 믹스 의 문자열 과 (a 표준 출력 라인 각각 나타내는 문자열) 오류 기록 (a 열려진 행을 나타내는 각 레코드) . 에서 요청한대로 2>&1
문자열과 오류 레코드는 PowerShell의 성공 출력 스트림을 통해 수신됩니다 ).
콘솔에서 오류 기록에 인쇄 빨간색 , 그리고 1 기본적으로 하나의 생산 멀티 라인 cmdlet에의 종료되지 않는 오류가 표시 것 같은 형식으로 표시; 후속 오류 레코드도 빨간색으로 인쇄되지만 오류 메시지 만 한 줄 에 인쇄 됩니다 .
콘솔에 출력 할 때 문자열은 일반적으로 출력 배열에서 가장 먼저 나오고 그 뒤에 오류 레코드 (적어도 "동시에"stdout / stderr 출력 일괄 처리 중)가옵니다. 그러나 다행히도 출력 을 캡처 할 때 , 그것 없이 얻을 수있는 것과 같은 출력 순서를 사용하여 올바르게 인터리브된다2>&1
; 다시 말해 , 콘솔로 출력 할 때 캡처 된 출력은 외부 명령에 의해 stdout 및 stderr 행이 생성 된 순서를 반영하지 않습니다.
이 경우 A의 전체 출력 캡처 하나 와 문자열을Out-String
, PowerShell은 추가 할 것이다 여분의 줄을 오류 레코드의 문자열 표현은 위치 (같은 추가 정보가 포함되어 있기 때문에, At line:...
) 및 카테고리를 ( + CategoryInfo ...
); 흥미롭게도 이것은 첫 번째 오류 레코드 에만 적용됩니다 .
- 이 문제를 해결하려면 다음
.ToString()
방법으로 파이프하는 대신 각 출력 개체 에이 방법을 적용하십시오 Out-String
.
$cmdOutput = <command> 2>&1 | % { $_.ToString() }
;
PS v3 +에서는 다음과
$cmdOutput = <command> 2>&1 | % ToString
같이 단순화 할 수 있습니다 . 보너스로 출력을 캡처하지 않으면 콘솔로 인쇄 할 때에도 인터리브 된 출력이 생성됩니다.
또한, 오류 기록 필터링 아웃 과 함께 PowerShell에서의 에러 스트림로 보낼Write-Error
(출력이 캡처되지 않은 경우 콘솔에 인쇄 할 때 보너스로,이조차 제대로 인터리브 출력을 생성) :
$cmdOutput = <command> 2>&1 | ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) {
Write-Error $_
} else {
$_
}
}
Start-Process
데 사용하지 마십시오 . 쉘에서와 같이 직접 실행 하십시오. 재치 :netdom /verify $pc /domain:hosp.uhhg.org
. 이렇게하면 응용 프로그램이 호출 콘솔의 표준 스트림에 연결되어 유지되므로 간단한 할당으로 출력을 캡처 할 수 있습니다$output = netdom ...
. 아래에 주어진 대부분의 답변은 암시 적Start-Process
으로 직접 실행을 선호합니다.