노트 :
다음은이 개념 증명을 기반으로 의 직접 사용 System.Diagnostics.Process
및 System.Diagnostics.ProcessStartInfo
캡처 프로세스의 출력 .NET 종류의 메모리 (귀하의 질문에 명시된 바와 같이, Start-Process
그것은 단지 출력을 캡처 지원하기 때문에, 옵션이 아닌 파일 에서와 같이, 이 답변 ) :
노트 :
다른 사용자로 실행하기 때문에이 기능은 Windows (.NET Core 3.1 기준) 에서만 지원 되지만 두 PowerShell 버전 모두에서 지원됩니다 .
다른 사용자로 실행해야하고 출력을 캡처 해야 하므로 .WindowStyle
명령을 숨김 으로 실행하는 데 사용할 수 없습니다 ( .WindowStyle
requires .UseShellExecute
는 be 가 필요 $true
하므로이 요구 사항과 호환되지 않습니다). 그러나 모든 출력이 캡처 되므로 효과적으로 숨겨진 실행을 설정 .CreateNoNewWindow
합니다 $true
.
# Get the target user's name and password.
$cred = Get-Credential
# Create a ProcessStartInfo instance
# with the relevant properties.
$psi = [System.Diagnostics.ProcessStartInfo] @{
# For demo purposes, use a simple `cmd.exe` command that echoes the username.
# See the bottom section for a call to `powershell.exe`.
FileName = 'cmd.exe'
Arguments = '/c echo %USERNAME%'
# Set this to a directory that the target user
# is permitted to access.
WorkingDirectory = 'C:\' #'
# Ask that output be captured in the
# .StandardOutput / .StandardError properties of
# the Process object created later.
UseShellExecute = $false # must be $false
RedirectStandardOutput = $true
RedirectStandardError = $true
# Uncomment this line if you want the process to run effectively hidden.
# CreateNoNewWindow = $true
# Specify the user identity.
# Note: If you specify a UPN in .UserName
# (user@doamin.com), set .Domain to $null
Domain = $env:USERDOMAIN
UserName = $cred.UserName
Password = $cred.Password
}
# Create (launch) the process...
$ps = [System.Diagnostics.Process]::Start($psi)
# Read the captured standard output.
# By reading to the *end*, this implicitly waits for (near) termination
# of the process.
# Do NOT use $ps.WaitForExit() first, as that can result in a deadlock.
$stdout = $ps.StandardOutput.ReadToEnd()
# Uncomment the following lines to report the process' exit code.
# $ps.WaitForExit()
# "Process exit code: $($ps.ExitCode)"
"Running ``cmd /c echo %USERNAME%`` as user $($cred.UserName) yielded:"
$stdout
위의 결과는 다음과 같이 산출되며 주어진 사용자 ID로 프로세스가 성공적으로 실행되었음을 나타냅니다.
Running `cmd /c echo %USERNAME%` as user jdoe yielded:
jdoe
이후 다른 전화하는거야 PowerShell을의 인스턴스를 , 당신은 할 수 의 장점이 걸릴 PowerShell을 CLI 에 출력 직렬화 복원 할 수 있습니다 CLIXML 형식으로 출력 대표의 능력 이 풍부한 객체를 제한 유형 충실도 불구을, 같은 설명, 이 관련 답변 .
# Get the target user's name and password.
$cred = Get-Credential
# Create a ProcessStartInfo instance
# with the relevant properties.
$psi = [System.Diagnostics.ProcessStartInfo] @{
# Invoke the PowerShell CLI with a simple sample command
# that calls `Get-Date` to output the current date as a [datetime] instance.
FileName = 'powershell.exe'
# `-of xml` asks that the output be returned as CLIXML,
# a serialization format that allows deserialization into
# rich objects.
Arguments = '-of xml -noprofile -c Get-Date'
# Set this to a directory that the target user
# is permitted to access.
WorkingDirectory = 'C:\' #'
# Ask that output be captured in the
# .StandardOutput / .StandardError properties of
# the Process object created later.
UseShellExecute = $false # must be $false
RedirectStandardOutput = $true
RedirectStandardError = $true
# Uncomment this line if you want the process to run effectively hidden.
# CreateNoNewWindow = $true
# Specify the user identity.
# Note: If you specify a UPN in .UserName
# (user@doamin.com), set .Domain to $null
Domain = $env:USERDOMAIN
UserName = $cred.UserName
Password = $cred.Password
}
# Create (launch) the process...
$ps = [System.Diagnostics.Process]::Start($psi)
# Read the captured standard output, in CLIXML format,
# stripping the `#` comment line at the top (`#< CLIXML`)
# which the deserializer doesn't know how to handle.
$stdoutCliXml = $ps.StandardOutput.ReadToEnd() -replace '^#.*\r?\n'
# Uncomment the following lines to report the process' exit code.
# $ps.WaitForExit()
# "Process exit code: $($ps.ExitCode)"
# Use PowerShell's deserialization API to
# "rehydrate" the objects.
$stdoutObjects = [Management.Automation.PSSerializer]::Deserialize($stdoutCliXml)
"Running ``Get-Date`` as user $($cred.UserName) yielded:"
$stdoutObjects
"`nas data type:"
$stdoutObjects.GetType().FullName
위의 결과는 다음과 같이 출력되며 [datetime]
인스턴스 ( System.DateTime
) 출력 Get-Date
이 직렬화 해제 되었음을 나타냅니다 .
Running `Get-Date` as user jdoe yielded:
Friday, March 27, 2020 6:26:49 PM
as data type:
System.DateTime