[powershell] PowerShell의 외부 프로세스에서 변수로 출력을 어떻게 캡처합니까?

외부 프로세스를 실행하고 PowerShell의 변수에 대한 명령 출력을 캡처하고 싶습니다. 나는 현재 이것을 사용하고있다 :

$params = "/verify $pc /domain:hosp.uhhg.org"
start-process "netdom.exe" $params -WindowStyle Hidden -Wait

명령이 실행되고 있음을 확인했지만 출력을 변수로 캡처해야합니다. 이것은 파일로만 리디렉션되기 때문에 -RedirectOutput을 사용할 수 없음을 의미합니다.



답변

시도해 보셨습니까?

$OutputVariable = (Shell command) | Out-String


답변

참고 : 질문의 명령은을 사용 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 /ccmd.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 {
    $_
  }
}


답변

오류 출력을 리디렉션하려면 다음을 수행해야합니다.

$cmdOutput = command 2>&1

또는 프로그램 이름에 공백이있는 경우 :

$cmdOutput = & "command with spaces" 2>&1


답변

아니면 이것을 시도하십시오. 출력을 변수 $ scriptOutput으로 캡처합니다.

& "netdom.exe" $params | Tee-Object -Variable scriptOutput | Out-Null

$scriptOutput


답변

또 다른 실제 예 :

$result = & "$env:cust_tls_store\Tools\WDK\x64\devcon.exe" enable $strHwid 2>&1 | Out-String

이 예에는 경로 (환경 변수로 시작)가 포함되어 있습니다. 따옴표는 경로와 EXE 파일을 둘러싸 야하지만 매개 변수는 포함하지 않아야합니다!

참고 :& 명령 앞의 문자를 잊지 말고 따옴표 외부의 문자를 잊지 마십시오 .

오류 출력도 수집됩니다.

이 조합을 작동시키는 데 시간이 걸렸으므로 공유하기로 생각했습니다.


답변

나는 대답을 시도했지만 내 경우에는 원시 출력을 얻지 못했습니다. 대신 PowerShell 예외로 변환되었습니다.

내가 얻은 원시 결과 :

$rawOutput = (cmd /c <command> 2`>`&1)


답변

나는 다음을 작동시켰다.

$Command1="C:\\ProgramData\Amazon\Tools\ebsnvme-id.exe"
$result = & invoke-Expression $Command1 | Out-String

$ result 는 당신에게 필요한 것을 제공합니다