Private/New-Win32ToolkitSandboxConfig.ps1
|
function New-Win32ToolkitSandboxConfig { <# .SYNOPSIS Builds a Windows Sandbox .wsb <Configuration> document — the first Sandbox test-backend primitive. .DESCRIPTION Emits the exact .wsb skeleton the three test/capture flows share: VGpu Disable, Networking Enable, one <MappedFolder> per mount (host path XML-encoded), and a single <LogonCommand>. It replaces the triplicated here-strings in New-TargetedDocumentation and Test-Win32ToolkitProject so every flow builds the sandbox config one way — Phase 0 of the pluggable test-backend seam (knowledge-base/designs/hyperv-backend-plan.md). Untrusted-value contract (unchanged from the callers): HOST PATHS are XML-encoded here via ConvertTo-XmlEncoded. The caller remains responsible for XML-encoding anything it splices into -LogonCommandXml — that string is emitted verbatim inside <Command>...</Command>, exactly as the callers do today (the guest install command is XML-encoded by the caller before being passed in). .PARAMETER Mount One or more mapped folders, each a hashtable/object with HostPath, GuestPath and ReadOnly (bool). Order is preserved — the project mount is listed first, the read-only baseline (if any) second. .PARAMETER LogonCommandXml The already-XML-encoded inner text of <Command> (e.g. the powershell.exe one-liner the guest runs at logon). .OUTPUTS [string] the full <Configuration>…</Configuration> document (no trailing newline). .EXAMPLE New-Win32ToolkitSandboxConfig ` -Mount @{ HostPath = $ProjectPath; GuestPath = 'C:\PSADT'; ReadOnly = $false } ` -LogonCommandXml 'powershell.exe -NoExit -ExecutionPolicy Bypass -File C:\PSADT\SupportFiles\TargetedDocumentationScript.ps1' #> [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [object[]]$Mount, [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$LogonCommandXml ) $sb = [System.Text.StringBuilder]::new() [void]$sb.AppendLine('<Configuration>') [void]$sb.AppendLine(' <VGpu>Disable</VGpu>') [void]$sb.AppendLine(' <Networking>Enable</Networking>') [void]$sb.AppendLine(' <MappedFolders>') foreach ($m in $Mount) { if (-not $m.HostPath) { throw 'Each -Mount needs a HostPath.' } if (-not $m.GuestPath) { throw 'Each -Mount needs a GuestPath.' } $readOnly = if ($m.ReadOnly) { 'true' } else { 'false' } [void]$sb.AppendLine(' <MappedFolder>') [void]$sb.AppendLine(" <HostFolder>$(ConvertTo-XmlEncoded $m.HostPath)</HostFolder>") [void]$sb.AppendLine(" <SandboxFolder>$($m.GuestPath)</SandboxFolder>") [void]$sb.AppendLine(" <ReadOnly>$readOnly</ReadOnly>") [void]$sb.AppendLine(' </MappedFolder>') } [void]$sb.AppendLine(' </MappedFolders>') [void]$sb.AppendLine(' <LogonCommand>') [void]$sb.AppendLine(" <Command>$LogonCommandXml</Command>") [void]$sb.AppendLine(' </LogonCommand>') [void]$sb.Append('</Configuration>') return $sb.ToString() } |