Write-ADOOutput.ps1
function Write-ADOOutput { <# .Synopsis Writes ADO Output .Description Writes formal Output to a ADO step. This output can be referenced in subsequent steps within a job. .Example Write-ADOOutput @{ key = 'value' } .Example Get-Random -Minimum 1 -Maximum 10 | Write-ADOOutput -Name RandomNumber .Link Write-ADOError .Link Write-ADODebug .Link Write-ADOWarning #> [OutputType([string])] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingWriteHost", "", Justification="Directly outputs in certain scenarios")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("Test-ForUnusableFunction", "", Justification="Directly outputs in certain scenarios")] param( # The InputObject. Values will be converted to a JSON array. [Parameter(Mandatory,ValueFromPipeline)] [PSObject] $InputObject, # The Name of the Output. By default, 'Output'. [string] $Name = 'Output', # The JSON serialization depth. By default, 10 levels. [int] $Depth = 10 ) begin { $inQ = [Collections.Queue]::new() } process { #region Output Dictionaries if ($InputObject -is [Collections.IDictionary]) { $adoOut = foreach ($kv in $InputObject.GetEnumerator()) { "##vso[task.setvariable variable=$($kv.Key);isOutput=true]$($kv.Value)" } if ($env:AGENT_ID -and $DebugPreference -eq 'SilentlyContinue') { Write-Host ($adoOut -join [Environment]::NewLine) } else { $adoOut } } #endregion Output Dictionaries #region Output Errors elseif ($InputObject -is [Management.Automation.ErrorRecord]) { $ADOErrorParams = @{ Message = $InputObject.Exception.Message } $stackTraceLine = @($InputObject.ScriptStackTrace -split 'at <ScriptBlock>,' -ne '' -match ':*line')[0] if ($stackTraceLine) { $stackTraceLineParts = @($stackTraceLine -split ':') $ADOErrorParams.Line = $stackTraceLineParts[-1] -replace 'line' -replace '\s' $file = $stackTraceLineParts[0..($stackTraceLineParts.Count - 2)] -join ':' if ($file -notlike '*<*>*') { $ADOErrorParams.File = $file } } Write-ADOError @ADOErrorParams } #endregion Output Errors #region Output Warnings elseif ($InputObject -is [Management.Automation.WarningRecord]) { Write-ADOWarning -Message $InputObject.Message } #endregion Output Warnings #region Output Debug and Verbose elseif ($InputObject -is [Management.Automation.VerboseRecord] -or $InputObject -is [Management.Automation.DebugRecord]) { Write-ADODebug -Message $InputObject.Message } #endregion Output Debug and Verbose #region Enqueue Remaining Input else { $inQ.Enqueue($InputObject) } #endregion Enqueue Remaining Input } end { $adoOut = if ($inQ.Count) { "##vso[task.setvariable variable=$name;isOutput=true]$($inQ.ToArray() | ConvertTo-Json -Compress -Depth $depth)" $inQ.Clear() } if ($adoOut) { if ($env:AGENT_ID -and $DebugPreference -eq 'SilentlyContinue') { Write-Host ($adoOut -join [Environment]::NewLine) } else { $adoOut } } } } |