Last active
September 13, 2023 00:47
-
-
Save santisq/93fd0f5a4ff9be5c542d1cbceb50aed0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using namespace System.Diagnostics | |
using namespace System.Management.Automation.Runspaces | |
using namespace System.System.Diagnostics | |
using namespace System.Management.Automation | |
using namespace System.Management.Automation.Host | |
class PwshPipe : IDisposable { | |
[Process] $pwshProcess | |
[NamedPipeConnectionInfo] $pipeinfo | |
[powershell] $pwsh | |
[runspace] $runspace | |
[bool] $disposed | |
PwshPipe([PSHost] $pshost) { | |
# ideally, this should be a Job object instead so if the parent process is terminated, | |
# this process also dies with it. | |
# https://learn.microsoft.com/en-us/windows/win32/procthread/job-objects | |
$this.pwshProcess = [Process]::Start( | |
[ProcessStartInfo]@{ | |
CreateNoWindow = $true | |
FileName = 'pwsh.exe' | |
WindowStyle = [ProcessWindowStyle]::Hidden | |
UseShellExecute = $true | |
LoadUserProfile = $false | |
Arguments = '-NoProfile' | |
}) | |
$this.pipeinfo = [NamedPipeConnectionInfo]::new($this.pwshProcess.Id) | |
$this.runspace = [runspacefactory]::CreateRunspace($pshost, $this.pipeinfo) | |
$this.runspace.Open() | |
$this.PSObject.Members.Add([psscriptproperty]::new( | |
'IsAlive', | |
{ -not $this.disposed -and -not $this.pwshProcess.HasExited })) | |
} | |
[void] Invoke( | |
[scriptblock] $scriptblock, | |
[object[]] $arguments, | |
[PSCmdlet] $cmdlet | |
) { | |
# ideally this should be handled with extension methods but pwsh class support sucks.. | |
$cmdlet.WriteObject( | |
$this.AddScript($scriptblock). | |
AddArguments($arguments). | |
pwsh.Invoke(), | |
$true) | |
if ($this.pwsh.HadErrors) { | |
foreach ($record in $this.pwsh.Streams.Error) { | |
$cmdlet.WriteError($record) | |
} | |
} | |
} | |
[PwshPipe] AddScript([scriptblock] $scriptblock) { | |
if ($this.pwsh) { | |
$this.pwsh.Dispose() | |
} | |
$this.pwsh = [powershell]::Create().AddScript($scriptblock, $false) | |
$this.pwsh.Runspace = $this.runspace | |
return $this | |
} | |
[PwshPipe] AddArguments([object[]] $arguments) { | |
foreach ($argument in $arguments) { | |
$this.pwsh = $this.pwsh.AddArgument($argument) | |
} | |
return $this | |
} | |
hidden [void] Dispose([bool] $disposing) { | |
if (-not $this.disposed -and $disposing) { | |
if ($this.pwsh) { | |
$this.pwsh.Dispose() | |
} | |
if ($this.runspace) { | |
$this.runspace.Dispose() | |
} | |
if ($this.pwshProcess) { | |
$this.pwshProcess.Kill() | |
} | |
$this.disposed = $true | |
} | |
} | |
[void] Dispose() { | |
$this.Dispose($true) | |
[GC]::SuppressFinalize($this) | |
} | |
} | |
function Invoke-Pwsh7 { | |
[CmdletBinding()] | |
param( | |
[Parameter(Mandatory)] | |
[scriptblock] $ScriptBlock, | |
[Parameter()] | |
[object[]] $ArgumentList | |
) | |
end { | |
if (-not $script:pipe.IsAlive) { | |
$script:pipe = [PwshPipe]::new($Host) | |
} | |
$script:pipe.Invoke($ScriptBlock, $ArgumentList, $PSCmdlet) | |
} | |
} | |
function Clear-Pipe { | |
$script:pipe.Dispose() | |
} | |
$ExecutionContext.SessionState.Module.OnRemove = { | |
if ($script:pipe.IsAlive) { | |
$script:pipe.Dispose() | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Import-Module (Join-Path $PSScriptRoot invokepwsh7pseudomodule.psm1) -Force | |
Invoke-Pwsh7 { $PSVersionTable } | |
Invoke-Pwsh7 { | |
0..10 | ForEach-Object -Parallel { | |
Start-Sleep -Milliseconds 200 | |
$_ | |
} | |
} | |
Invoke-Pwsh7 { | |
Write-Host 'testing streams' | |
Write-Verbose 'testing streams' -Verbose | |
Write-Error 'testing streams' | |
Write-Warning 'testing streams' | |
} | |
Invoke-Pwsh7 { | |
param($foo, $bar, $baz) | |
$PSBoundParameters | |
} -ArgumentList hello, world, 123 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment