public/Get-VSAAPList.ps1
|
function Get-VSAAPList { <# .SYNOPSIS Lists Agent Procedures (the procedure tree) from a VSA 9 environment. .DESCRIPTION Returns one object per Agent Procedure. VSA 9 Agent Procedures are stored as XML, so the underlying endpoint (api/v1.0/automation/agentprocs/proclist) returns a Kaseya ScExport XML document rather than JSON -- by design, not error. This cmdlet therefore has its own implementation instead of routing through the generic JSON read path: it fetches the raw body and parses it with ConvertFrom-VSAScExport, keeping XML handling local to the one endpoint that needs it. Paging matches every other collection: the ScExport `<Records totalRecords=...>` element carries the same total the JSON envelope exposes, so pages are fetched via $skip/$top until the whole tree is retrieved. Paging is sequential (there is no -Parallel here): the shared parallel engine deserializes JSON, so reusing it would mean teaching the generic transport to parse XML, which this design deliberately avoids. The full procedure `<Body>` (the step definition) is not returned -- this is a list, not an export; fetch a single procedure's detail with Get-VSAAP. .PARAMETER VSAConnection Specifies an existing non-persistent VSAConnection. When omitted, the persistent connection is used. .PARAMETER URISuffix Specifies the URI suffix if it differs from the default. .PARAMETER RecordsPerPage Number of records requested per page via $top (1-100; the server caps at 100). .EXAMPLE Get-VSAAPList Lists every Agent Procedure via the persistent connection. .EXAMPLE Get-VSAAPList -VSAConnection $connection | Where-Object { $_.Shared } Lists the shared Agent Procedures on a non-persistent connection. .INPUTS Accepts a piped non-persistent VSAConnection. .OUTPUTS One PSCustomObject per Agent Procedure: Id, Name, Path, FolderId, Shared (bool), TreePres. Ids are strings (they overflow Int32). #> [CmdletBinding()] [OutputType([pscustomobject])] param ( [parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [VSAConnection] $VSAConnection, [parameter(DontShow, Mandatory = $false)] [ValidateNotNullOrEmpty()] [string] $URISuffix = 'api/v1.0/automation/agentprocs/proclist', [parameter(Mandatory = $false)] [ValidateRange(1, 100)] [int] $RecordsPerPage = 100 ) process { # Resolve base URI + cert flag from the connection; the token is fetched per page in the loop # below (so it stays fresh over a long tree), which is why it is not read here. if ($null -eq $VSAConnection) { $VSAServerURI = Get-VSAPersistentURI [bool]$IgnoreCertificateErrors = Get-VSAPersistentIgnoreCertErrors } else { $VSAServerURI = $VSAConnection.URI [bool]$IgnoreCertificateErrors = $VSAConnection.IgnoreCertificateErrors } $baseUri = New-Object System.Uri -ArgumentList $VSAServerURI [string]$endpoint = [System.Uri]::new($baseUri, $URISuffix) | Select-Object -ExpandProperty AbsoluteUri $UriSeparator = if ($endpoint -match '\?') { '&' } else { '?' } [hashtable]$HttpArgs = @{ Method = 'GET' } if ($IgnoreCertificateErrors) { $HttpArgs['IgnoreCertificateErrors'] = $true } $all = New-Object System.Collections.ArrayList [int]$skip = 0 [int]$total = -1 do { # Renew the session token between pages if it is near expiry (a no-op otherwise), so a # long procedure tree does not outlive the token mid-fetch. if ($null -eq $VSAConnection) { Update-VSAConnection; $HttpArgs['AuthString'] = "Bearer $( Get-VSAPersistentToken )" } else { Update-VSAConnection -VSAConnection $VSAConnection; $HttpArgs['AuthString'] = "Bearer $($VSAConnection.Token)" } $query = ConvertTo-VSAQueryString -Parameters @{ '$skip' = "$skip"; '$top' = $RecordsPerPage } $pageUri = '{0}{1}{2}' -f $endpoint, $UriSeparator, $query # Invoke-VSAHttp gives the raw body and still throws a typed VSAApiException on a # transport/HTTP failure; only the JSON envelope step is bypassed. $resp = Invoke-VSAHttp -Uri $pageUri @HttpArgs $parsed = ConvertFrom-VSAScExport -Body $resp.Body if ($total -lt 0) { $total = $parsed.TotalRecords } foreach ($proc in $parsed.Procedures) { [void]$all.Add($proc) } $skip += $RecordsPerPage # Stop when the whole tree is in hand; the Procedures-count guard prevents an infinite # loop if the server ever reports a total it does not deliver. } while ($all.Count -lt $total -and $parsed.Procedures.Count -gt 0) return $all.ToArray() } } Export-ModuleMember -Function Get-VSAAPList |