Created
January 21, 2017 08:00
-
-
Save Jaykul/a1cfb8405334b47ab0de484d21f5f0d3 to your computer and use it in GitHub Desktop.
A wrapper to improve Write-Information
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using namespace System.Management.Automation | |
function Write-Information { | |
<# | |
.Synopsis | |
An enhancement to the built-in Write-Information to make it show the calling script line | |
.Description | |
Creates a stopwatch that tracks the time elapsed while a script runs, and adds caller position and time to the output | |
.Example | |
.Example | |
#> | |
[CmdletBinding(DefaultParameterSetName="InformationOutput")] | |
param( | |
# Specifies an informational message that you want to display to users as they run a script or command. | |
# Note that this is a rich object, and the -InformationVariable can collect those objects, but the stream will just get the ToString() | |
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName="InformationOutput", Position=0)] | |
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName="VerboseOutput", Position=0)] | |
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName="WarningOutput", Position=0)] | |
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, ParameterSetName="DebugOutput", Position=0)] | |
[PSObject]$MessageData, | |
# Specifies a simple string that you can use to sort and filter messages that you have added to the information stream with Write-Information | |
[String[]]$Tags, | |
# When set, output to the verbose stream in addition to the information stream | |
[Parameter(Mandatory=$true, ParameterSetName="VerboseOutput")] | |
[Alias("AsVerbose")] | |
[switch]$VerboseOutput, | |
# When set, output to the warning stream in addition to the information stream | |
[Parameter(Mandatory=$true, ParameterSetName="WarningOutput")] | |
[Alias("AsWarning")] | |
[switch]$WarningOutput, | |
# When set, output to the debug stream in addition to the information stream | |
[Parameter(Mandatory=$true, ParameterSetName="DebugOutput")] | |
[Alias("AsDebug")] | |
[switch]$DebugOutput | |
) | |
begin { | |
if(-not ${Trace Message Timer}) { | |
${global:Trace Message Timer} = New-Object System.Diagnostics.Stopwatch | |
${global:Trace Message Timer}.Start() | |
# Clean up automatically when we hit the prompt | |
$PreTraceTimerPrompt = $function:prompt | |
$function:prompt = { | |
if(${global:Trace Message Timer}) { | |
${global:Trace Message Timer}.Stop() | |
Remove-Variable "Trace Message Timer" -Scope global -ErrorAction SilentlyContinue | |
} | |
& $PreTraceTimerPrompt | |
${function:global:prompt} = $PreTraceTimerPrompt | |
}.GetNewClosure() | |
} | |
$Script:LastElapsed = $Script:Elapsed | |
$Script:Elapsed = ${Trace Message Timer}.Elapsed.Duration() | |
# Note this requires a host with RawUi | |
$w = $Host.UI.RawUi.BufferSize.Width | |
} | |
process { | |
$Message = [PSCustomObject]@{Data=$MessageData} | Format-Table -HideTableHeaders -AutoSize -Wrap | Out-String -Stream | |
$Location = if($MyInvocation.CommandOrigin -eq "Runspace") { | |
"line:{0}" -f "$($MyInvocation.ScriptLineNumber)".PadRight(4) | |
} | |
else { | |
"{0}, line:{1}" -f ($MyInvocation.ScriptName | Split-Path -Leaf), "$($MyInvocation.ScriptLineNumber)".PadRight(4) | |
} | |
$Information = [InformationRecord]::new($MessageData, $Location) | |
foreach($Tag in $Tags) { $Information.Tags.Add($Tag) } | |
$PSCmdlet.WriteInformation($Information) | |
$Tail = $(if($Elapsed.TotalHours -ge 1.0) { | |
"{0:h\:mm\:ss\.ffff}" -f $Elapsed | |
} | |
elseif($Elapsed.TotaMinutes -ge 1.0) { | |
"{0:mm\m\ ss\.ffff\s}" -f $Elapsed | |
} | |
else { | |
"{0:ss\.ffff\s}" -f $Elapsed | |
}).PadLeft(12) | |
$Tail = $Location + $Tail | |
# "WARNING: ".Length = 10 | |
$Length = ($Message.Length + 10 + $Tail.Length) | |
# Twenty-five is a minimum 15 character message... | |
$PaddedLength = if($Length -gt $w -and $w -gt (25 + $Tail.Length)) { | |
[string[]]$words = -split $message | |
$short = 10 # "VERBOSE: ".Length | |
$count = 0 # Word count so far | |
$lines = 0 | |
do { | |
do { | |
$short += 1 + $words[$count++].Length | |
} while (($words.Count -gt $count) -and ($short + $words[$count].Length) -lt $w) | |
$Lines++ | |
if(($Message.Length + $Tail.Length) -gt ($w * $lines)) { | |
$short = 0 | |
} | |
} while($short -eq 0) | |
$Message.Length + ($w - $short) - $Tail.Length | |
} else { | |
$w - 10 - $Tail.Length | |
} | |
$Message = "$Message ".PadRight($PaddedLength, "$([char]8331)") + $Tail | |
if($VerboseOutput) { | |
Write-Verbose $Message | |
} | |
elseif($WarningOutput) { | |
Write-Warning $Message | |
} | |
elseif($DebugOutput) { | |
Write-Debug $Message | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment