Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
dd2133b
test(agent): cover policy management end to end
CBenoit Sep 8, 2026
2bec3e6
ci(agent): run policy E2E as both identities
CBenoit Sep 8, 2026
38cc31c
test(agent): separate policy client identity
CBenoit Sep 9, 2026
84d75bd
ci(agent): handle detached policy tester launch
CBenoit Sep 9, 2026
5806e56
test(agent): use medium-integrity policy client
CBenoit Sep 9, 2026
116df84
ci(agent): stop policy server after launch failures
CBenoit Sep 9, 2026
dafdb88
test(agent): exercise revised policy lifecycle
CBenoit Sep 15, 2026
59f3cce
fix(agent): restore NuGet test imports for SYSTEM
CBenoit Sep 15, 2026
f331bae
fix(agent): run installer tests as LocalSystem
CBenoit Sep 15, 2026
5f8d6d8
fix(agent): authenticate installer E2E client
CBenoit Sep 15, 2026
632427c
test(agent): retain canonical policy E2E
CBenoit Sep 17, 2026
04ba6d9
test(agent): cover final policy contract
CBenoit Sep 17, 2026
26152e3
test(agent): cover policy review gaps
CBenoit Sep 17, 2026
a9395f5
fix(agent): accept advisory policy findings
CBenoit Sep 20, 2026
aaf0bcf
feat(agent,agent-installer): add policy consent helper
CBenoit Sep 9, 2026
c1b5c48
fix(agent): enforce signer revocation checks
CBenoit Sep 9, 2026
df31e2b
fix(agent): bind broker trust to running image
CBenoit Sep 10, 2026
ff025b1
fix(agent,agent-installer): correct helper packaging
CBenoit Sep 10, 2026
357d19d
fix(agent): validate policy credentials
CBenoit Sep 10, 2026
acc3950
fix(agent,agent-installer): require current UI signer
CBenoit Sep 17, 2026
f1b2e20
fix(agent,agent-installer): discover broker pipe
CBenoit Sep 17, 2026
d6270cd
docs(agent-installer): add helper package step
CBenoit Sep 17, 2026
36f9213
fix(agent): require local consent parent
CBenoit Sep 17, 2026
4361e0d
fix(agent): resolve retained consent paths
CBenoit Sep 17, 2026
6c06b9e
fix(agent): align policy pipe deadline
CBenoit Sep 17, 2026
7cbaae0
fix(agent): limit consent pipe timeout
CBenoit Sep 17, 2026
86aa026
fix(agent): extend authorized policy writes
CBenoit Sep 17, 2026
7b1446a
fix(agent): recover interrupted policy probes
CBenoit Sep 17, 2026
07858fc
fix(agent): match Unicode policy sources
CBenoit Sep 17, 2026
725e368
fix(agent): normalize policy source names
CBenoit Sep 17, 2026
0da6ed3
fix(agent): reject ambiguous policy sources
CBenoit Sep 17, 2026
b9c33dd
fix(agent): validate package source identity
CBenoit Sep 17, 2026
7abc416
fix(agent): bound pipe connections from accept
CBenoit Sep 17, 2026
59289e7
fix(agent): reject padded policy sources
CBenoit Sep 17, 2026
5715f19
fix(agent): preserve manager source identity
CBenoit Sep 17, 2026
f8cea81
fix(agent): validate policy source spelling
CBenoit Sep 17, 2026
cc30252
test(agent): cover policy source spelling guard
CBenoit Sep 17, 2026
3239f2e
fix(agent,agent-installer): publish helper discovery in both views
CBenoit Sep 18, 2026
1145f0c
fix(agent): align helper policy contract
CBenoit Sep 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -926,6 +926,9 @@ jobs:
$DAgentSessionExecutable = Join-Path $TargetOutputPath "DevolutionsSession.exe"
echo "dagent-session-executable=$DAgentSessionExecutable" >> $Env:GITHUB_OUTPUT

$DAgentPolicyConsentHelper = Join-Path $TargetOutputPath "DevolutionsAgentPolicyConsent.exe"
echo "dagent-policy-consent-helper=$DAgentPolicyConsentHelper" >> $Env:GITHUB_OUTPUT

$DAgentUpdaterExecutable = Join-Path $TargetOutputPath "DevolutionsAgentUpdater.exe"
echo "dagent-updater-executable=$DAgentUpdaterExecutable" >> $Env:GITHUB_OUTPUT
}
Expand Down Expand Up @@ -1091,6 +1094,28 @@ jobs:
DAGENT_EXECUTABLE: ${{ steps.load-variables.outputs.dagent-executable }}
TARGET_OUTPUT_PATH: ${{ steps.load-variables.outputs.target-output-path }}

- name: Build NativeAOT policy consent helper
if: ${{ matrix.os == 'windows' }}
run: |
$Rid = "win-${{ matrix.arch }}"
$Output = Split-Path -Parent '${{ steps.load-variables.outputs.dagent-policy-consent-helper }}'
dotnet publish package/AgentPolicyConsent/DevolutionsAgentPolicyConsent.csproj `
--configuration Release `
--runtime $Rid `
--output $Output `
-p:Version=${{ needs.preflight.outputs.version }}
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
}
$Helper = '${{ steps.load-variables.outputs.dagent-policy-consent-helper }}'
if (-Not (Test-Path -LiteralPath $Helper -PathType Leaf)) {
throw "NativeAOT policy consent helper was not produced"
}
if ((Get-Item -LiteralPath $Helper).Length -gt 8MB) {
throw "NativeAOT policy consent helper exceeds 8 MiB"
}
shell: pwsh

- name: Package
if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }}
run: |
Expand All @@ -1104,6 +1129,7 @@ jobs:
$Env:DAGENT_PEDM_SHELL_EXT_DLL = "${{ steps.load-variables.outputs.dagent-pedm-shell-ext-dll }}"
$Env:DAGENT_PEDM_SHELL_EXT_MSIX = "${{ steps.load-variables.outputs.dagent-pedm-shell-ext-msix }}"
$Env:DAGENT_SESSION_EXECUTABLE = "${{ steps.load-variables.outputs.dagent-session-executable }}"
$Env:DAGENT_POLICY_CONSENT_HELPER = "${{ steps.load-variables.outputs.dagent-policy-consent-helper }}"
$Env:DAGENT_TUN2SOCKS_EXE = "${{ steps.tun2socks.outputs.tun2socks-executable-path }}"
$Env:DAGENT_WINTUN_DLL = "${{ steps.tun2socks.outputs.wintun-library-path }}"
$Env:DAGENT_MULTI_PWSH_EXECUTABLE = "${{ steps.multi-pwsh.outputs.executable-path }}"
Expand Down Expand Up @@ -1225,6 +1251,11 @@ jobs:
run: dotnet test package/AgentWindowsManaged.Tests/DevolutionsAgent.Installer.Tests.csproj
shell: pwsh

- name: Policy consent helper tests
run: dotnet test package/AgentPolicyConsent.Tests/DevolutionsAgentPolicyConsent.Tests.csproj -c Release
Comment thread
CBenoit marked this conversation as resolved.
shell: pwsh


winapi-sanitizer-tests:
name: Windows API sanitizer tests
runs-on: windows-2022
Expand Down Expand Up @@ -1385,12 +1416,14 @@ jobs:
name: Agent policy end-to-end test
runs-on: windows-2022
needs: [preflight]
env:
AGENT_POLICY_TEST_SHA: ${{ inputs.ref || github.event.pull_request.head.sha || needs.preflight.outputs.ref }}

steps:
- name: Checkout ${{ github.repository }}
uses: actions/checkout@v6
with:
ref: ${{ needs.preflight.outputs.ref }}
ref: ${{ env.AGENT_POLICY_TEST_SHA }}

- name: Setup Rust cache
uses: ./.github/actions/setup-rust-cache
Expand All @@ -1413,8 +1446,13 @@ jobs:
Add-Content -Path $env:GITHUB_PATH -Value $toolsDir

- name: Build Agent policy test executables
id: build-policy-executables
shell: pwsh
run: |
$actualCommit = git rev-parse HEAD
if ($LASTEXITCODE -ne 0 -or $actualCommit -ne $env:AGENT_POLICY_TEST_SHA) {
throw "Agent policy tests must build the requested commit $env:AGENT_POLICY_TEST_SHA, got $actualCommit"
}
cargo build --locked -p devolutions-agent --features dev-skip-broker-signature
if ($LASTEXITCODE -ne 0) {
exit $LASTEXITCODE
Expand All @@ -1424,7 +1462,18 @@ jobs:
exit $LASTEXITCODE
}

- name: Run Agent policy tester as standard user
shell: pwsh
run: |
./crates/agent-policy-tester/run-unelevated.ps1
$exitCode = $LASTEXITCODE
Get-Content -Path ./crates/agent-policy-tester/agent-policy-tester-unelevated.out
if ($exitCode -ne 0) {
exit $exitCode
}

- name: Run Agent policy tester as LocalSystem
if: ${{ !cancelled() && steps.build-policy-executables.outcome == 'success' }}
shell: pwsh
run: |
$scriptPath = Resolve-Path -Path "./crates/agent-policy-tester/run-as-system.ps1"
Expand All @@ -1435,6 +1484,10 @@ jobs:
exit $exitCode
}

- name: Run policy route authorization tests
shell: pwsh
run: cargo test --locked -p now-package-broker --features dev-skip-broker-signature

- name: Show sccache stats
if: ${{ needs.preflight.outputs.sccache == 'true' && !cancelled() }}
shell: pwsh
Expand Down
7 changes: 5 additions & 2 deletions .github/workflows/package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ jobs:
run: |
$IncludePattern = @(switch ('${{ matrix.project }}') {
'devolutions-gateway' { @('DevolutionsGateway.exe') }
'devolutions-agent' { @('DevolutionsAgent.exe', 'DevolutionsAgentUpdater.exe', 'DevolutionsPedmShellExt.dll', 'DevolutionsPedmShellExt.msix', 'DevolutionsDesktopAgent.exe') }
'devolutions-agent' { @('DevolutionsAgent.exe', 'DevolutionsAgentUpdater.exe', 'DevolutionsAgentPolicyConsent.exe', 'DevolutionsPedmShellExt.dll', 'DevolutionsPedmShellExt.msix', 'DevolutionsDesktopAgent.exe') }
'jetsocat' { @('jetsocat.exe', 'jetsocat') }
})
$ExcludePattern = "*.pdb"
Expand Down Expand Up @@ -495,6 +495,7 @@ jobs:
$Env:DAGENT_PEDM_SHELL_EXT_DLL = Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsPedmShellExt.dll' -File | Select-Object -First 1
$Env:DAGENT_PEDM_SHELL_EXT_MSIX = Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsPedmShellExt.msix' -File | Select-Object -First 1
$Env:DAGENT_SESSION_EXECUTABLE = Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsSession.exe' -File | Select-Object -First 1
$Env:DAGENT_POLICY_CONSENT_HELPER = Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsAgentPolicyConsent.exe' -File | Select-Object -First 1
$Env:DAGENT_TUN2SOCKS_EXE = Join-Path $ArchRoot 'tun2socks.exe'
$Env:DAGENT_WINTUN_DLL = Join-Path $ArchRoot 'wintun.dll'
$MultiPwshDirectory = Join-Path $Env:RUNNER_TEMP 'multi-pwsh' 'windows' $Arch
Expand All @@ -508,6 +509,7 @@ jobs:
Write-Host "DAGENT_PEDM_SHELL_EXT_DLL = ${Env:DAGENT_PEDM_SHELL_EXT_DLL}"
Write-Host "DAGENT_PEDM_SHELL_EXT_MSIX = ${Env:DAGENT_PEDM_SHELL_EXT_MSIX}"
Write-Host "DAGENT_SESSION_EXECUTABLE = ${Env:DAGENT_SESSION_EXECUTABLE}"
Write-Host "DAGENT_POLICY_CONSENT_HELPER = ${Env:DAGENT_POLICY_CONSENT_HELPER}"
Write-Host "DAGENT_TUN2SOCKS_EXE = ${Env:DAGENT_TUN2SOCKS_EXE}"
Write-Host "DAGENT_WINTUN_DLL = ${Env:DAGENT_WINTUN_DLL}"
Write-Host "DAGENT_MULTI_PWSH_EXECUTABLE = ${Env:DAGENT_MULTI_PWSH_EXECUTABLE}"
Expand All @@ -534,7 +536,8 @@ jobs:
@((Join-Path $ArchRoot DesktopAgent),
(Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsPedmShellExt.dll' | Select-Object -First 1),
(Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsPedmShellExt.msix' | Select-Object -First 1),
(Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsSession.exe' | Select-Object -First 1)) | ForEach-Object {
(Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsSession.exe' | Select-Object -First 1),
(Get-ChildItem -Path $ArchRoot -Filter 'DevolutionsAgentPolicyConsent.exe' | Select-Object -First 1)) | ForEach-Object {
Remove-Item $_ -Recurse -ErrorAction SilentlyContinue | Out-Null
}
}
Expand Down
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 20 additions & 2 deletions ci/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,32 @@ This folder contains PowerShell scripts for CI, building, and packaging.
| Gateway | Windows (regular) | `build.ps1 gateway`<br />`copy-ps-module.ps1`<br />`package-gateway-windows.ps1` |
| Gateway | Windows (assembled) | `build.ps1 gateway`<br />`copy-ps-module.ps1`<br />`package-gateway-windows.ps1 -Generate`<br />`package-assembled.ps1 gateway` |
| Gateway | Linux | `build.ps1 gateway`<br />`package-gateway-linux.ps1` (not available yet) |
| Agent | Windows (regular) | `build.ps1 agent` <br />`build.ps1 pedm`<br />`build.ps1 session`<br />`..\dotnet\DesktopAgent\build.ps1`<br />`package-agent-windows.ps1` |
| Agent | Windows (assembled) | `build.ps1 agent` <br />`build.ps1 pedm`<br />`build.ps1 session`<br />`..\dotnet\DesktopAgent\build.ps1`<br />`package-agent-windows.ps1 -Generate`<br />`package-assembled.ps1 agent` |
| Agent | Windows (regular) | `build.ps1 agent`<br />`build.ps1 pedm`<br />`build.ps1 session`<br />`..\dotnet\DesktopAgent\build.ps1`<br />`dotnet publish ..\package\AgentPolicyConsent\DevolutionsAgentPolicyConsent.csproj -c Release -r win-x64 --self-contained`<br />`package-agent-windows.ps1` with the arguments below |
| Agent | Windows (assembled) | `build.ps1 agent`<br />`build.ps1 pedm`<br />`build.ps1 session`<br />`..\dotnet\DesktopAgent\build.ps1`<br />`dotnet publish ..\package\AgentPolicyConsent\DevolutionsAgentPolicyConsent.csproj -c Release -r win-x64 --self-contained`<br />`package-agent-windows.ps1 -Generate` with the arguments below<br />`package-assembled.ps1 agent` |
| Jetsocat | Windows/macOS/Linux | `build.ps1 jetsocat`<br />Jetsocat is not packaged. |
| Session | Windows/macOS/Linux | `build.ps1 session` <br />Session is not packaged. |
| PEDM module | Windows | `build.ps1 pedm` |
| PowerShell module | Windows | `copy-ps-module.ps1` |
| Desktop Agent | Windows | `..\dotnet\DesktopAgent\build.ps1` |

## Agent Windows package arguments

Pass every staged artifact to `package-agent-windows.ps1`.

```powershell
.\package-agent-windows.ps1 `
-Exe <DevolutionsAgent.exe> `
-UpdaterExe <DevolutionsAgentUpdater.exe> `
-PedmDll <DevolutionsPedmShellExt.dll> `
-PedmMsix <DevolutionsPedmShellExt.msix> `
-SessionExe <DevolutionsSession.exe> `
-PolicyConsentHelper ..\package\AgentPolicyConsent\bin\Release\net10.0-windows\win-x64\publish\DevolutionsAgentPolicyConsent.exe `
-Architecture x64 `
-Outfile <DevolutionsAgent.msi>
```

For an assembled package, replace `-Outfile <DevolutionsAgent.msi>` with `-Generate`.

## What is the difference between _Windows (regular)_ and _Windows (assembled)_?

_Windows (regular)_ is the "normal" build process where the MSI is built by WiX but not signed. This is used in _ci.yaml_. _Windows (assembled)_ is a two-step process where the `-Generate` flag is used to build supporting files for the MSI, including DLLs, language transforms, and _cmd_ scripts. The MSI is assembled in second step using _package-assembled.ps1_. The two-step approach is described [here](https://github.com/oleg-shilo/wixsharp/wiki/Developer's-Guide#compiling-wix-project).
Expand Down
15 changes: 12 additions & 3 deletions ci/package-agent-windows.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ param(
[parameter(Mandatory = $true)]
[string] $SessionExe,
[parameter(Mandatory = $true)]
[string] $PolicyConsentHelper,
[parameter(Mandatory = $true)]
[ValidateSet('x64', 'arm64')]
[string] $Architecture,
[string] $Outfile
Expand Down Expand Up @@ -43,8 +45,9 @@ function Set-FileNameAndCopy {

# If the name is already correct, return the original path without copying
if ($currName -ieq $NewName) {
Write-Host "Using $Path without copying"
return $Path
$resolvedPath = (Resolve-Path -LiteralPath $Path).Path
Write-Host "Using $resolvedPath without copying"
return $resolvedPath
}

# Copy to a temporary directory.
Expand Down Expand Up @@ -98,6 +101,9 @@ function New-AgentMsi() {
# The path to the devolutions-session.exe file.
[string] $SessionExe,
[parameter(Mandatory = $true)]
# The path to the signed DevolutionsAgentPolicyConsent.exe file.
[string] $PolicyConsentHelper,
[parameter(Mandatory = $true)]
[ValidateSet('x64', 'arm64')]
# Architecture: x64 or arm64
[string] $Architecture,
Expand All @@ -120,6 +126,7 @@ function New-AgentMsi() {
$PedmDll = Convert-Path -Path $PedmDll
$PedmMsix = Convert-Path -Path $PedmMsix
$SessionExe = Convert-Path -Path $SessionExe
$PolicyConsentHelper = Convert-Path -Path $PolicyConsentHelper
if ($Outfile) {
$Outfile = Convert-Path -Path $Outfile
}
Expand All @@ -137,6 +144,7 @@ function New-AgentMsi() {
$myUpdaterExe = Set-FileNameAndCopy -Path $UpdaterExe -NewName 'DevolutionsAgentUpdater.exe'
# The session is a service that gets launched on demand.
$mySessionExe = Set-FileNameAndCopy -Path $SessionExe -NewName 'DevolutionsSession.exe'
$myPolicyConsentHelper = Set-FileNameAndCopy -Path $PolicyConsentHelper -NewName 'DevolutionsAgentPolicyConsent.exe'
Comment thread
CBenoit marked this conversation as resolved.

Write-Output "$repoDir\dotnet\DesktopAgent\bin\Release\net48\DevolutionsDesktopAgent.exe"

Expand All @@ -145,6 +153,7 @@ function New-AgentMsi() {
Set-EnvVarPath 'DAGENT_PEDM_SHELL_EXT_DLL' $myPedmDll
Set-EnvVarPath 'DAGENT_PEDM_SHELL_EXT_MSIX' $myPedmMsix
Set-EnvVarPath 'DAGENT_SESSION_EXECUTABLE' $mySessionExe
Set-EnvVarPath 'DAGENT_POLICY_CONSENT_HELPER' $myPolicyConsentHelper

# The actual DevolutionsDesktopAgent.exe will be `\dotnet\DesktopAgent\bin\Release\net48\DevolutionsDesktopAgent.exe`.
# After install, the contents of `net48` will be copied to `C:\Program Files\Devolutions\Agent\desktop\`.
Expand Down Expand Up @@ -184,4 +193,4 @@ function New-AgentMsi() {
Pop-Location
}

New-AgentMsi -Generate:($Generate.IsPresent) -Exe $Exe -UpdaterExe $UpdaterExe -PedmDll $PedmDll -PedmMsix $PedmMsix -SessionExe $SessionExe -Architecture $Architecture -Outfile $Outfile
New-AgentMsi -Generate:($Generate.IsPresent) -Exe $Exe -UpdaterExe $UpdaterExe -PedmDll $PedmDll -PedmMsix $PedmMsix -SessionExe $SessionExe -PolicyConsentHelper $PolicyConsentHelper -Architecture $Architecture -Outfile $Outfile
2 changes: 2 additions & 0 deletions crates/agent-policy-tester/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ fastrand = "2"
serde_json = "1"
tempfile = "3"
tokio = { version = "1", features = ["io-util", "macros", "net", "process", "rt-multi-thread", "time"] }
win-api-wrappers = { path = "../win-api-wrappers" }
windows = { version = "0.61", features = ["Win32_Security", "Win32_System_Threading"] }

[lints]
workspace = true
13 changes: 10 additions & 3 deletions crates/agent-policy-tester/run-as-system.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@ $workspacePath = (Resolve-Path (Join-Path $PSScriptRoot "../..")).Path
$testerPath = Join-Path $workspacePath "target/debug/agent-policy-tester.exe"
$agentPath = Join-Path $workspacePath "target/debug/devolutions-agent.exe"
$outputPath = Join-Path $PSScriptRoot "agent-policy-tester.out"
$stagingPath = Join-Path $env:ProgramData "dgw-agent-policy-tester-$([guid]::NewGuid().ToString('N'))"
$stagingPath = Join-Path ([Environment]::GetFolderPath('CommonApplicationData')) "dgw-agent-policy-tester-$([guid]::NewGuid().ToString('N'))"
$stagedTesterPath = Join-Path $stagingPath "agent-policy-tester.exe"
$exitCode = 1

try {
Set-Content -LiteralPath $outputPath -Value ""
if (-not [System.Security.Principal.WindowsIdentity]::GetCurrent().IsSystem) {
throw "This runner requires LocalSystem"
}
if ([System.IO.DriveInfo]::new([System.IO.Path]::GetPathRoot($workspacePath)).DriveType -ne 'Fixed') {
throw "Use a local fixed-volume workspace path visible to LocalSystem, not a mapped drive"
}
Add-Type -TypeDefinition @'
using System;
using System.ComponentModel;
Expand Down Expand Up @@ -61,7 +68,6 @@ public static class AgentPolicyTesterNativeDirectory
if (Get-ChildItem -LiteralPath $stagingPath -Force) {
throw "The atomically protected staged tester directory was not empty"
}

Copy-Item -LiteralPath $testerPath -Destination $stagedTesterPath
& icacls.exe $stagedTesterPath /setowner '*S-1-5-18' 2>&1 | Out-File $outputPath -Append
if ($LASTEXITCODE -ne 0) {
Expand All @@ -76,7 +82,7 @@ public static class AgentPolicyTesterNativeDirectory
"Staged policy tester at $stagedTesterPath" | Out-File $outputPath -Append
Get-Acl -LiteralPath $stagingPath | Format-List Owner, Sddl | Out-File $outputPath -Append
Get-Acl -LiteralPath $stagedTesterPath | Format-List Owner, Sddl | Out-File $outputPath -Append
& $stagedTesterPath $agentPath 2>&1 | Out-File $outputPath -Append
& $stagedTesterPath $agentPath elevated 2>&1 | Out-File $outputPath -Append
$exitCode = $LASTEXITCODE
} catch {
$_ | Out-File $outputPath -Append
Expand All @@ -88,6 +94,7 @@ public static class AgentPolicyTesterNativeDirectory
} catch {
if ($attempt -eq 19) {
"Failed to remove $stagingPath after 20 attempts: $_" | Out-File $outputPath -Append
$exitCode = 1
} else {
Start-Sleep -Milliseconds 250
}
Expand Down
Loading
Loading