Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save FriedrichWeinmann/6b44166a31795b13c4ef5ac7fcb45283 to your computer and use it in GitHub Desktop.
Save FriedrichWeinmann/6b44166a31795b13c4ef5ac7fcb45283 to your computer and use it in GitHub Desktop.
$Name = 'cmd'
$ArgumentList = @(
)
#region Functions
function Start-RedirectedProcess {
[OutputType([System.Diagnostics.Process])]
[CmdletBinding()]
param (
[string]
$Name,
$ArgumentList = @(),
[switch]
$PassThru
)
$info = [System.Diagnostics.ProcessStartInfo]::new()
$info.FileName = $Name
if ($WorkingDirectory) { $info.WorkingDirectory = $WorkingDirectory }
foreach ($entry in $ArgumentList) { $info.ArgumentList.Add($entry) }
$info.RedirectStandardInput = $true
$info.RedirectStandardError = $true
$info.RedirectStandardOutput = $true
$proc = [System.Diagnostics.Process]::new()
$proc.StartInfo = $info
# Start
$null = $proc.Start()
$script:process = $proc
if ($PassThru) { $proc }
}
function Stop-RedirectedProcess {
[CmdletBinding()]
param ()
if (-not $script:process) { return }
$script:process.Kill()
$script:process = $null
if (-not $script:runspace) { return }
$script:runspace.Reader.Active = $false
$script:runspace.Pipe.EndInvoke($script:runspace.Status)
$script:runspace.Pipe.Dispose()
$script:runspace.Pipe.RunspacePool.Close()
$script:runspace = $null
}
function Start-OutputReader {
[CmdletBinding()]
param (
[System.Diagnostics.Process]
$Process = $script:Process
)
$reader = [PSCustomObject]@{
Process = $Process
Active = $true
Data = [System.Collections.Concurrent.ConcurrentQueue[object]]::new()
}
$sessionState = [initialsessionstate]::CreateDefault()
$sessionState.Variables.Add(
[System.Management.Automation.Runspaces.SessionStateVariableEntry]::new('reader', $reader, '')
)
$pool = [RunspaceFactory]::CreateRunspacePool($sessionState)
$pool.Open()
$runspace = [PowerShell]::Create()
$runspace.RunspacePool = $pool
$null = $runspace.AddScript({
while ($reader.Active) {
$line = $reader.Process.StandardOutput.ReadLine()
$reader.Data.Enqueue($line)
}
})
$script:runspace = [PSCustomObject]@{
Pipe = $runspace
Status = $runspace.BeginInvoke()
Reader = $reader
}
$reader
}
function Read-Output {
[OutputType([string])]
[CmdletBinding()]
param (
$Reader = $script:runspace.Reader
)
while (-not $Reader.Data.IsEmpty) {
$result = $null
$worked = $Reader.Data.TryDequeue([ref]$result)
if ($worked) { $result }
}
}
function Write-Input {
[CmdletBinding()]
param (
[string[]]
$Line,
[System.Diagnostics.Process]
$Process = $script:process
)
foreach ($entry in $Line) {
$Process.StandardInput.WriteLine($entry)
}
}
#endregion Functions
# Get Started
$proc = Start-RedirectedProcess -Name $Name -ArgumentList $ArgumentList -PassThru
$reader = Start-OutputReader -Process $proc
# Read
Read-Output -Reader $reader
# Write / Send input / Send Command
Write-Input -Line "dir C:\" -Process $proc
# Close & Stop
Stop-RedirectedProcess
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment