1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
param(
[Parameter(Mandatory = $true)]
[string] $ExePath,
[string] $Session = "ci-windows-$([guid]::NewGuid().ToString('N'))"
)
$ErrorActionPreference = "Stop"
function Invoke-Checked {
param([string] $Command, [string[]] $Arguments)
& $Command @Arguments
if ($LASTEXITCODE -ne 0) {
throw "command failed with exit code $LASTEXITCODE`: $Command $($Arguments -join ' ')"
}
}
$exe = (Resolve-Path $ExePath).Path
$fakeDir = Join-Path ([System.IO.Path]::GetTempPath()) "herdr-fake-conpty-$([guid]::NewGuid().ToString('N'))"
New-Item -ItemType Directory -Force $fakeDir | Out-Null
$fakeSource = Join-Path $fakeDir "fake_conpty.rs"
$fakeDll = Join-Path $fakeDir "conpty.dll"
@'
#![allow(non_snake_case)]
use std::ffi::c_void;
#[repr(C)]
pub struct COORD {
pub X: i16,
pub Y: i16,
}
type HANDLE = *mut c_void;
type HRESULT = i32;
#[no_mangle]
pub extern "system" fn CreatePseudoConsole(
_size: COORD,
_h_input: HANDLE,
_h_output: HANDLE,
_flags: u32,
_hpc: *mut HANDLE,
) -> HRESULT {
-2147467259
}
#[no_mangle]
pub extern "system" fn ResizePseudoConsole(_hpc: HANDLE, _size: COORD) -> HRESULT {
-2147467259
}
#[no_mangle]
pub extern "system" fn ClosePseudoConsole(_hpc: HANDLE) {}
'@ | Set-Content -NoNewline -Encoding utf8 $fakeSource
Invoke-Checked rustc @("--crate-type", "cdylib", "--edition", "2021", $fakeSource, "-o", $fakeDll)
$oldPath = $env:PATH
$oldSession = $env:HERDR_SESSION
$env:PATH = "$fakeDir;$oldPath"
$env:HERDR_SESSION = $Session
$server = $null
try {
Invoke-Checked $exe @("--version")
& $exe --default-config | Out-Null
if ($LASTEXITCODE -ne 0) {
throw "command failed with exit code $LASTEXITCODE`: $exe --default-config"
}
$server = Start-Process -FilePath $exe -ArgumentList "server" -PassThru -WindowStyle Hidden
$deadline = (Get-Date).AddSeconds(10)
do {
Start-Sleep -Milliseconds 250
$status = & $exe status server 2>&1
if ($LASTEXITCODE -eq 0 -and (($status -join "`n") -match "status: running")) {
break
}
} while ((Get-Date) -lt $deadline)
if ((Get-Date) -ge $deadline) {
throw "server did not become ready"
}
Invoke-Checked $exe @("agent", "start", "smoke", "--", $env:ComSpec, "/K", "dir")
Start-Sleep -Seconds 2
$read = & $exe agent read smoke --source recent --lines 40 --format text
if ($LASTEXITCODE -ne 0) {
throw "command failed with exit code $LASTEXITCODE`: $exe agent read smoke"
}
$text = $read -join "`n"
if ($text -notmatch "File\(s\)" -or $text -notmatch "Dir\(s\)") {
throw "pane read did not include cmd.exe directory output: $text"
}
} finally {
if ($null -ne $server) {
& $exe server stop 2>$null
Wait-Process -Id $server.Id -Timeout 10 -ErrorAction SilentlyContinue
}
$env:PATH = $oldPath
$env:HERDR_SESSION = $oldSession
Remove-Item -Recurse -Force $fakeDir -ErrorAction SilentlyContinue
}
|