PowerShell에서 Start-Process: 직관적인 프로세스 시작

이해하려면 먼저 Start-Process 및 다른 명령이 제한되는 이유를 일반적인 EXE 파일의 작동 방식을 이해해야 합니다. EXE 파일이 실행되면 설계된 작업을 수행합니다. 어떤 것을 핑하거나 (ping), 소프트웨어 설치 프로그램을 시작하거나 (setup), 일부 DNS 레코드를 조회하거나 (nslookup) 등등. 여기에 part 및 Start-Process and와 같은 명령을 사용하여 프로세스를 시작하는 것은 훌륭합니다. 간단합니다. 그러나 그 EXE가 일부 출력을 반환할 때 제한이 발생합니다.

우리는 PowerShell 에서 여러 가지 방법으로 프로세스를 시작할 수 있습니다. PowerShell Start-Process 및 Invoke-Expression cmdlet을 사용하거나 실행 파일을 직접 호출하거나 앰퍼샌드 (&)를 사용하여 표현을 호출할 수 있습니다. 가장 일반적인 방법은 아마도 가장 직관적인 Start-Process를 사용하는 것입니다. PowerShell은 명령의 명명에 대한 직관적인 접근으로 알려져 있으며 Start-Process는 훌륭한 선택입니다. 그러나 해당 명령에는 제한이 있습니다.

스트림

Windows에 한정되지 않은 여러 다른 실행 가능한 파일과 마찬가지로 EXE 파일에는 표준 스트림 개념이 있습니다. 표준 스트림은 실행 가능한 파일이 출력을 반환하는 방법입니다. 이러한 스트림은 stdin, stdout 및 stderr의 세 가지 유형으로 나뉩니다. Stdin은 실행 가능한 파일에 전달할 수 있는 스트림으로 여기에 중점을 두지 않겠습니다. Stdout은 실행 가능한 파일이 정상적인 오류가 아닌 출력을 보내는 데 사용하는 스트림입니다.

PowerShell 용어로 생각해보면, stdout는 Write-Output이 반환하는 것으로 생각할 수 있습니다. 오류가 발생할 때 (실행 파일의 개발자가 제대로 작성했는지에 따라), 실행 파일은 stderr를 통해 출력을 반환해야 합니다. 이는 오류 정보를 반환하기 위해 예약된 스트림입니다.

이러한 스트림을 사용하면 실행 파일의 사용자는 일반적인 출력과 오류를 구분할 수 있습니다. 스트림은 수십 년 동안 사용되어 왔으며, Windows 및 PowerShell은 스트림에 대해 잘 알고 있으며 자체적으로 채택하고 있습니다.

종료 코드

종료 코드, 반환 코드 또는 결과 코드는 실행 파일이 종료될 때 사용자에게 상태를 신호로 알리기 위해 사용되는 또 다른 오래된 개념입니다. 종료 코드는 실행 파일이 종료될 때 사용자에게 상태를 알리는 정수입니다.

일반적으로 프로그램이 따라야 하는 몇 가지 표준 종료 코드가 있습니다. 종료 코드가 0이면 모든 것이 정상이고, 종료 코드 3010은 재부팅이 필요함을 나타내는 등의 의미를 갖습니다. PowerShell은 $LastExitCode 자동 변수를 사용하는 등 다양한 방법으로 이 종료 코드를 캡처할 수 있습니다. 종료 코드는 실행 파일이 사용자에게 전달하는 또 다른 방법입니다.

스트림 및 종료 코드 캡처

이제 우리가 다루는 내용을 이해했으니 예제를 사용해보겠습니다. 간단하게 ping.exe를 사용하겠습니다. 먼저 google.com에 ping을 보내 성공적인 결과를 반환합니다. PowerShell 시작 프로세스는 사용하지 않습니다.

PS C:\> ping google.com
Pinging google.com [2607:f8b0:4004:80b::200e] with 32 bytes of data:

Reply from 2607:f8b0:4004:80b::200e: time=61ms
Reply from 2607:f8b0:4004:80b::200e: time=65ms
Reply from 2607:f8b0:4004:80b::200e: time=80ms
Reply from 2607:f8b0:4004:80b::200e: time=78ms

Ping statistics for 2607:f8b0:4004:80b::200e:

Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 61ms, Maximum = 80ms, Average = 71ms

PS> $LastExitCode
0
PS> $?
True

I’ll now purposefully ping a host that doesn’t resolve a DNS name and will fail. Notice the value of $LastExitCode.

PS> ping googlllll.com

Ping request could not find host googlllll.com. Please check the name and try again.
PS> $LASTEXITCODE
1

이미 실행 코드가 다른 것을 보았지만 실행 결과가 다르기 때문에 스트림은 보이지 않았습니다. PowerShell은 기본적으로 실행 가능한 파일에 대한 차이를 이해하지 못합니다. 콘솔에서 보이는 텍스트는 당신이 알고 사랑하는 빨간색 오류 텍스트가 아니라 흰색입니다.

다음과 같이 >2>를 사용하여 스트림을 캡처하고 파일로 리디렉션하는 몇 가지 다른 방법이 있습니다. 이것은 옛날 방식입니다.

PS> ping googllll.com > output.msg 2> output.err
PS> Get-Content .\output.err
PS> Get-Content .\output.msg

Ping request could not find host googllll.com. Please check the name and try again.

그러나 이 경우에도 ping.exe가 1의 종료 코드를 반환하더라도 해당 출력은 여전히 표준 출력(stdout)으로 전달됩니다. 이것은 흔한 일입니다. 반환되는 스트림과 종료 코드는 개발자에게 완전히 달려 있으며 많은 다른 스타일로 제공됩니다.

만약 “새로운 방식”으로 가고 싶다면, Start-Process를 사용하고 -RedirectStandardError-RedirectStandardOutput 매개변수를 사용할 수 있지만, 그래도 파일로만 리디렉션됩니다.

Start-Process의 제한 사항

일반적인 출력을 생성하고 프로세스를 시작하는 것은 그렇게 흔한 일은 아닙니다. 게다가 PowerShell은 스트림과 종료 코드를 잘 처리하지 못합니다. ping.exe를 실행하고 결과를 추적하려면 매번 이렇게 해야 합니다. 실행 가능한 파일을 실행하려면.

PS> Start-Process -FilePath -NoNewWindow ping -ArgumentList 'google.com' -RedirectStandardOutput output.txt -RedirectStandardError err.txt
PS> $LastExitCode
PS> Get-Content -Path output.txt
PS> Get-Content -Path err.txt

I still wouldn’t get my error text either!

이 모든 것을 해결해 봅시다. PowerShell 갤러리에서 만든 Invoke-Process라는 작은 함수를 다운로드하세요.

PS> Install-Script 'Invoke-Process'
PS> . Invoke-Process.ps1

이제 유효한 호스트를 사용하여 ping을 실행하고 무슨 일이 일어나는지 확인하세요.

Invoke-Process -FilePath ping -ArgumentList ‘google.com’

같은 결과를 얻는 것을 주목하세요. 이건 좋아요!

이제 잘못된 호스트를 사용하여 ping을 실행하세요.

Invoke-Process -FilePath ping -ArgumentList ‘googlddde.com’

이제 뭔가 잘못되었다면 우리가 예상하는 대로 전형적인 빨간색 오류 텍스트를 얻는 것을 주목하세요. Invoke-Process는 stdout, stderr 및 종료 코드를 캡처하기 위해 내부적으로 Start-Process를 사용하고 그런 다음 출력을 해당하는 스트림으로 보냅니다. 이게 바로 올바른 방법입니다!

PowerShell이 실행 가능한 파일에서 스트림과 종료 코드를 처리하는 것을 더 쉽게 만들지 못한 것은 아쉽지만, 지금은 오픈 소스로 되어 있으므로 이를 추가할 수 있겠죠!

Source:
https://adamtheautomator.com/start-process/