mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Implement Get-Error cmdlet as Experimental Feature (#10727)
This commit is contained in:
committed by
Aditya Patwardhan
parent
8b68a4cd99
commit
d8d32d79c2
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Management.Automation;
|
||||
|
||||
namespace Microsoft.PowerShell.Commands
|
||||
{
|
||||
/// <summary>
|
||||
/// Class for Get-Error implementation.
|
||||
/// </summary>
|
||||
[Experimental("Microsoft.PowerShell.Utility.PSGetError", ExperimentAction.Show)]
|
||||
[Cmdlet(VerbsCommon.Get, "Error",
|
||||
HelpUri = "https://docs.microsoft.com/powershell/module/microsoft.powershell.utility/get-error?view=powershell-7&WT.mc_id=ps-gethelp",
|
||||
DefaultParameterSetName = NewestParameterSetName)]
|
||||
public sealed class GetErrorCommand : PSCmdlet
|
||||
{
|
||||
internal const string ErrorParameterSetName = "Error";
|
||||
internal const string NewestParameterSetName = "Newest";
|
||||
internal const string AliasNewest = "Last";
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the error object to resolve.
|
||||
/// </summary>
|
||||
[Parameter(Position = 0, ValueFromPipeline = true, ParameterSetName = ErrorParameterSetName)]
|
||||
[ValidateNotNullOrEmpty]
|
||||
public PSObject InputObject { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of error objects to resolve starting with newest first.
|
||||
/// </summary>
|
||||
[Parameter(ParameterSetName = NewestParameterSetName)]
|
||||
[Alias(AliasNewest)]
|
||||
[ValidateRange(1, int.MaxValue)]
|
||||
public int Newest { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Process the error object.
|
||||
/// </summary>
|
||||
protected override void ProcessRecord()
|
||||
{
|
||||
var errorRecords = new List<object>();
|
||||
var index = 0;
|
||||
|
||||
if (InputObject != null)
|
||||
{
|
||||
if (InputObject.BaseObject is Exception || InputObject.BaseObject is ErrorRecord)
|
||||
{
|
||||
errorRecords.Add(InputObject);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var errorVariable = SessionState.PSVariable.Get("error");
|
||||
var count = Newest;
|
||||
ArrayList errors = (ArrayList)errorVariable.Value;
|
||||
if (count > errors.Count)
|
||||
{
|
||||
count = errors.Count;
|
||||
}
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
errorRecords.Add(errors[index]);
|
||||
index++;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
index = 0;
|
||||
bool addErrorIdentifier = errorRecords.Count > 1 ? true : false;
|
||||
|
||||
foreach (object errorRecord in errorRecords)
|
||||
{
|
||||
PSObject obj = PSObject.AsPSObject(errorRecord);
|
||||
obj.TypeNames.Insert(0, "PSExtendedError");
|
||||
|
||||
// Remove some types so they don't get rendered by those formats
|
||||
obj.TypeNames.Remove("System.Management.Automation.ErrorRecord");
|
||||
obj.TypeNames.Remove("System.Exception");
|
||||
|
||||
if (addErrorIdentifier)
|
||||
{
|
||||
obj.Properties.Add(new PSNoteProperty("PSErrorIndex", index++));
|
||||
}
|
||||
|
||||
WriteObject(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -735,125 +735,184 @@ namespace Microsoft.PowerShell
|
||||
_ui = ui;
|
||||
}
|
||||
|
||||
public ConsoleColor FormatAccentColor
|
||||
{
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
get
|
||||
{
|
||||
return _ui.FormatAccentColor;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
set
|
||||
{
|
||||
_ui.FormatAccentColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ConsoleColor ErrorAccentColor
|
||||
{
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
get
|
||||
{ return _ui.ErrorAccentColor; }
|
||||
{
|
||||
return _ui.ErrorAccentColor;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
set
|
||||
{ _ui.ErrorAccentColor = value; }
|
||||
{
|
||||
_ui.ErrorAccentColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ConsoleColor ErrorForegroundColor
|
||||
{
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
get
|
||||
{ return _ui.ErrorForegroundColor; }
|
||||
{
|
||||
return _ui.ErrorForegroundColor;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
set
|
||||
{ _ui.ErrorForegroundColor = value; }
|
||||
{
|
||||
_ui.ErrorForegroundColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ConsoleColor ErrorBackgroundColor
|
||||
{
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
get
|
||||
{ return _ui.ErrorBackgroundColor; }
|
||||
{
|
||||
return _ui.ErrorBackgroundColor;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
set
|
||||
{ _ui.ErrorBackgroundColor = value; }
|
||||
{
|
||||
_ui.ErrorBackgroundColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ConsoleColor WarningForegroundColor
|
||||
{
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
get
|
||||
{ return _ui.WarningForegroundColor; }
|
||||
{
|
||||
return _ui.WarningForegroundColor;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
set
|
||||
{ _ui.WarningForegroundColor = value; }
|
||||
{
|
||||
_ui.WarningForegroundColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ConsoleColor WarningBackgroundColor
|
||||
{
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
get
|
||||
{ return _ui.WarningBackgroundColor; }
|
||||
{
|
||||
return _ui.WarningBackgroundColor;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
set
|
||||
{ _ui.WarningBackgroundColor = value; }
|
||||
{
|
||||
_ui.WarningBackgroundColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ConsoleColor DebugForegroundColor
|
||||
{
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
get
|
||||
{ return _ui.DebugForegroundColor; }
|
||||
{
|
||||
return _ui.DebugForegroundColor;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
set
|
||||
{ _ui.DebugForegroundColor = value; }
|
||||
{
|
||||
_ui.DebugForegroundColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ConsoleColor DebugBackgroundColor
|
||||
{
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
get
|
||||
{ return _ui.DebugBackgroundColor; }
|
||||
{
|
||||
return _ui.DebugBackgroundColor;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
set
|
||||
{ _ui.DebugBackgroundColor = value; }
|
||||
{
|
||||
_ui.DebugBackgroundColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ConsoleColor VerboseForegroundColor
|
||||
{
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
get
|
||||
{ return _ui.VerboseForegroundColor; }
|
||||
{
|
||||
return _ui.VerboseForegroundColor;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
set
|
||||
{ _ui.VerboseForegroundColor = value; }
|
||||
{
|
||||
_ui.VerboseForegroundColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ConsoleColor VerboseBackgroundColor
|
||||
{
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
get
|
||||
{ return _ui.VerboseBackgroundColor; }
|
||||
{
|
||||
return _ui.VerboseBackgroundColor;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
set
|
||||
{ _ui.VerboseBackgroundColor = value; }
|
||||
{
|
||||
_ui.VerboseBackgroundColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ConsoleColor ProgressForegroundColor
|
||||
{
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
get
|
||||
{ return _ui.ProgressForegroundColor; }
|
||||
{
|
||||
return _ui.ProgressForegroundColor;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
set
|
||||
{ _ui.ProgressForegroundColor = value; }
|
||||
{
|
||||
_ui.ProgressForegroundColor = value;
|
||||
}
|
||||
}
|
||||
|
||||
public ConsoleColor ProgressBackgroundColor
|
||||
{
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
get
|
||||
{ return _ui.ProgressBackgroundColor; }
|
||||
{
|
||||
return _ui.ProgressBackgroundColor;
|
||||
}
|
||||
|
||||
[SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
set
|
||||
{ _ui.ProgressBackgroundColor = value; }
|
||||
{
|
||||
_ui.ProgressBackgroundColor = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1355,6 +1355,9 @@ namespace Microsoft.PowerShell
|
||||
}
|
||||
}
|
||||
|
||||
// Format colors
|
||||
public ConsoleColor FormatAccentColor { get; set; } = ConsoleColor.Green;
|
||||
|
||||
// Error colors
|
||||
public ConsoleColor ErrorAccentColor { get; set; } = ConsoleColor.Cyan;
|
||||
public ConsoleColor ErrorForegroundColor { get; set; } = ConsoleColor.Red;
|
||||
|
||||
@@ -25,7 +25,7 @@ CmdletsToExport = @(
|
||||
'Get-TraceSource', 'Set-TraceSource', 'Add-Type', 'Get-TypeData', 'Remove-TypeData', 'Update-TypeData',
|
||||
'Get-UICulture', 'Get-Unique', 'Get-Uptime', 'Clear-Variable', 'Get-Variable', 'New-Variable',
|
||||
'Remove-Variable', 'Set-Variable', 'Get-Verb', 'Write-Verbose', 'Write-Warning', 'Invoke-WebRequest',
|
||||
'Format-Wide', 'ConvertTo-Xml', 'Select-Xml'
|
||||
'Format-Wide', 'ConvertTo-Xml', 'Select-Xml', 'Get-Error'
|
||||
)
|
||||
FunctionsToExport = @()
|
||||
AliasesToExport = @('fhx')
|
||||
@@ -38,6 +38,10 @@ PrivateData = @{
|
||||
Name = 'Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace'
|
||||
Description = 'Enables -BreakAll parameter on Debug-Runspace and Debug-Job cmdlets to allow users to decide if they want PowerShell to break immediately in the current location when they attach a debugger.'
|
||||
}
|
||||
@{
|
||||
Name = 'Microsoft.PowerShell.Utility.PSGetError'
|
||||
Description = 'Enable Get-Error cmdlet that displays detailed information about ErrorRecords included nested objects'
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ CmdletsToExport = @(
|
||||
'ConvertFrom-StringData', 'Format-Table', 'New-TemporaryFile', 'New-TimeSpan', 'Get-TraceSource', 'Set-TraceSource',
|
||||
'Add-Type', 'Get-TypeData', 'Remove-TypeData', 'Update-TypeData', 'Get-UICulture', 'Get-Unique', 'Get-Uptime',
|
||||
'Clear-Variable', 'Get-Variable', 'New-Variable', 'Remove-Variable', 'Set-Variable', 'Get-Verb', 'Write-Verbose',
|
||||
'Write-Warning', 'Invoke-WebRequest', 'Format-Wide', 'ConvertTo-Xml', 'Select-Xml'
|
||||
'Write-Warning', 'Invoke-WebRequest', 'Format-Wide', 'ConvertTo-Xml', 'Select-Xml', 'Get-Error'
|
||||
)
|
||||
FunctionsToExport = @()
|
||||
AliasesToExport = @('fhx')
|
||||
@@ -36,6 +36,10 @@ PrivateData = @{
|
||||
Name = 'Microsoft.PowerShell.Utility.PSManageBreakpointsInRunspace'
|
||||
Description = 'Enables -BreakAll parameter on Debug-Runspace and Debug-Job cmdlets to allow users to decide if they want PowerShell to break immediately in the current location when they attach a debugger.'
|
||||
}
|
||||
@{
|
||||
Name = 'Microsoft.PowerShell.Utility.PSGetError'
|
||||
Description = 'Enable Get-Error cmdlet that displays detailed information about ErrorRecords included nested objects'
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+195
-12
@@ -137,6 +137,10 @@ namespace System.Management.Automation.Runspaces
|
||||
"System.Management.Automation.ScriptBlock",
|
||||
ViewsOf_System_Management_Automation_ScriptBlock());
|
||||
|
||||
yield return new ExtendedTypeDefinition(
|
||||
"PSExtendedError",
|
||||
ViewsOf_System_Management_Automation_GetError());
|
||||
|
||||
yield return new ExtendedTypeDefinition(
|
||||
"System.Management.Automation.ErrorRecord",
|
||||
ViewsOf_System_Management_Automation_ErrorRecord());
|
||||
@@ -722,6 +726,197 @@ namespace System.Management.Automation.Runspaces
|
||||
.EndControl());
|
||||
}
|
||||
|
||||
// This generates a custom view for ErrorRecords and Exceptions making
|
||||
// specific nested types defined in $expandTypes visible. It also handles
|
||||
// IEnumerable types. Nested types are indented by 4 spaces.
|
||||
private static IEnumerable<FormatViewDefinition> ViewsOf_System_Management_Automation_GetError()
|
||||
{
|
||||
yield return new FormatViewDefinition("GetErrorInstance",
|
||||
CustomControl.Create()
|
||||
.GroupByProperty("PSErrorIndex", label: "ErrorIdentifier")
|
||||
.StartEntry()
|
||||
.AddScriptBlockExpressionBinding(@"
|
||||
$maxDepth = 10
|
||||
$ellipsis = ""`u{2026}""
|
||||
$resetColor = ''
|
||||
if ($Host.UI.SupportsVirtualTerminal) {
|
||||
$resetColor = ""`e[0m""
|
||||
}
|
||||
|
||||
function Get-VT100Color([string] $color) {
|
||||
if (! $Host.UI.SupportsVirtualTerminal) {
|
||||
return ''
|
||||
}
|
||||
|
||||
$colors = @{
|
||||
'Black' = ""`e[2;30m""
|
||||
'DarkRed' = ""`e[2;31m""
|
||||
'DarkGreen' = ""`e[2;32m""
|
||||
'DarkYellow' = ""`e[2;33m""
|
||||
'DarkBlue' = ""`e[2;34m""
|
||||
'DarkMagenta' = ""`e[2;35m""
|
||||
'DarkCyan' = ""`e[2;36m""
|
||||
'Gray' = ""`e[2;37m""
|
||||
'DarkGray' = ""`e[1;30m""
|
||||
'Red' = ""`e[1;31m""
|
||||
'Green' = ""`e[1;32m""
|
||||
'Yellow' = ""`e[1;33m""
|
||||
'Blue' = ""`e[1;34m""
|
||||
'Magenta' = ""`e[1;35m""
|
||||
'Cyan' = ""`e[1;36m""
|
||||
'White' = ""`e[1;37m""
|
||||
}
|
||||
|
||||
return $colors[$color]
|
||||
}
|
||||
|
||||
function Show-ErrorRecord($obj, [int]$indent = 0, [int]$depth = 1) {
|
||||
$newline = [Environment]::Newline
|
||||
$output = [System.Text.StringBuilder]::new()
|
||||
$prefix = ' ' * $indent
|
||||
$accentColor = Get-VT100Color $Host.PrivateData.FormatAccentColor
|
||||
$expandTypes = @(
|
||||
'Microsoft.Rest.HttpRequestMessageWrapper'
|
||||
'Microsoft.Rest.HttpResponseMessageWrapper'
|
||||
'System.Management.Automation.InvocationInfo'
|
||||
)
|
||||
|
||||
# first find the longest property so we can indent properly
|
||||
$propLength = 0
|
||||
foreach ($prop in $obj.PSObject.Properties) {
|
||||
if ($prop.Value -ne $null -and $prop.Value -ne [string]::Empty -and $prop.Name.Length -gt $propLength) {
|
||||
$propLength = $prop.Name.Length
|
||||
}
|
||||
}
|
||||
|
||||
$addedProperty = $false
|
||||
foreach ($prop in $obj.PSObject.Properties) {
|
||||
|
||||
# don't show empty properties or our added property for $error[index]
|
||||
if ($prop.Value -ne $null -and $prop.Value -ne [string]::Empty -and $prop.Value.count -gt 0 -and $prop.Name -ne 'PSErrorIndex') {
|
||||
$addedProperty = $true
|
||||
$null = $output.Append($prefix)
|
||||
$null = $output.Append($accentColor)
|
||||
$null = $output.Append($prop.Name)
|
||||
$propNameIndent = ' ' * ($propLength - $prop.Name.Length)
|
||||
$null = $output.Append($propNameIndent)
|
||||
$null = $output.Append(' : ')
|
||||
$null = $output.Append($resetColor)
|
||||
|
||||
$newIndent = $indent + 4
|
||||
|
||||
# only show nested objects that are Exceptions, ErrorRecords, or types defined in $expandTypes and types not in $ignoreTypes
|
||||
if ($prop.Value -is [Exception] -or $prop.Value -is [System.Management.Automation.ErrorRecord] -or
|
||||
$expandTypes -contains $prop.TypeNameOfValue -or ($prop.TypeNames -ne $null -and $expandTypes -contains $prop.TypeNames[0])) {
|
||||
|
||||
if ($depth -ge $maxDepth) {
|
||||
$null = $output.Append($ellipsis)
|
||||
}
|
||||
else {
|
||||
$null = $output.Append($newline)
|
||||
$null = $output.Append((Show-ErrorRecord $prop.Value $newIndent ($depth + 1)))
|
||||
}
|
||||
}
|
||||
# `TargetSite` has many members that are not useful visually, so we have a reduced view of the relevant members
|
||||
elseif ($prop.Name -eq 'TargetSite' -and $prop.Value.GetType().Name -eq 'RuntimeMethodInfo') {
|
||||
if ($depth -ge $maxDepth) {
|
||||
$null = $output.Append($ellipsis)
|
||||
}
|
||||
else {
|
||||
$targetSite = [PSCustomObject]@{
|
||||
Name = $prop.Value.Name
|
||||
DeclaringType = $prop.Value.DeclaringType
|
||||
MemberType = $prop.Value.MemberType
|
||||
Module = $prop.Value.Module
|
||||
}
|
||||
|
||||
$null = $output.Append($newline)
|
||||
$null = $output.Append((Show-ErrorRecord $targetSite $newIndent ($depth + 1)))
|
||||
}
|
||||
}
|
||||
# `StackTrace` is handled specifically because the lines are typically long but necessary so they are left justified without additional indentation
|
||||
elseif ($prop.Name -eq 'StackTrace') {
|
||||
# for a stacktrace which is usually quite wide with info, we left justify it
|
||||
$null = $output.Append($newline)
|
||||
$null = $output.Append($prop.Value)
|
||||
}
|
||||
# Dictionary and Hashtable we want to show as Key/Value pairs, we don't do the extra whitespace alignment here
|
||||
elseif ($prop.Value.GetType().Name.StartsWith('Dictionary') -or $prop.Value.GetType().Name -eq 'Hashtable') {
|
||||
$isFirstElement = $true
|
||||
foreach ($key in $prop.Value.Keys) {
|
||||
if ($isFirstElement) {
|
||||
$null = $output.Append($newline)
|
||||
}
|
||||
|
||||
if ($key -eq 'Authorization') {
|
||||
$null = $output.Append(""${prefix} ${accentColor}${key} : ${resetColor}${ellipsis}${newline}"")
|
||||
}
|
||||
else {
|
||||
$null = $output.Append(""${prefix} ${accentColor}${key} : ${resetColor}$($prop.Value[$key])${newline}"")
|
||||
}
|
||||
|
||||
$isFirstElement = $false
|
||||
}
|
||||
}
|
||||
# if the object implements IEnumerable and not a string, we try to show each object
|
||||
# We ignore the `Data` property as it can contain lots of type information by the interpreter that isn't useful here
|
||||
elseif (!($prop.Value -is [System.String]) -and $prop.Value.GetType().GetInterface('IEnumerable') -ne $null -and $prop.Name -ne 'Data') {
|
||||
|
||||
if ($depth -ge $maxDepth) {
|
||||
$null = $output.Append($ellipsis)
|
||||
}
|
||||
else {
|
||||
$isFirstElement = $true
|
||||
foreach ($value in $prop.Value) {
|
||||
$null = $output.Append($newline)
|
||||
if (!$isFirstElement) {
|
||||
$null = $output.Append($newline)
|
||||
}
|
||||
$null = $output.Append((Show-ErrorRecord $value $newIndent ($depth + 1)))
|
||||
$isFirstElement = $false
|
||||
}
|
||||
}
|
||||
}
|
||||
# anything else, we use ToString()
|
||||
else {
|
||||
$value = $prop.Value.ToString().Trim()
|
||||
|
||||
$isFirstLine = $true
|
||||
if ($value.Contains($newline)) {
|
||||
# the 3 is to account for ' : '
|
||||
$valueIndent = ' ' * ($propLength + 3)
|
||||
# need to trim any extra whitespace already in the text
|
||||
foreach ($line in $value.Split($newline)) {
|
||||
if (!$isFirstLine) {
|
||||
$null = $output.Append(""${newline}${prefix}${valueIndent}"")
|
||||
}
|
||||
$null = $output.Append($line.Trim())
|
||||
$isFirstLine = $false
|
||||
}
|
||||
}
|
||||
else {
|
||||
$null = $output.Append($value)
|
||||
}
|
||||
}
|
||||
|
||||
$null = $output.Append($newline)
|
||||
}
|
||||
}
|
||||
|
||||
# if we had added nested properties, we need to remove the last newline
|
||||
if ($addedProperty) {
|
||||
$null = $output.Remove($output.Length - $newline.Length, $newline.Length)
|
||||
}
|
||||
|
||||
$output.ToString()
|
||||
}
|
||||
|
||||
Show-ErrorRecord $_
|
||||
")
|
||||
.EndEntry()
|
||||
.EndControl());
|
||||
}
|
||||
|
||||
private static IEnumerable<FormatViewDefinition> ViewsOf_System_Management_Automation_ErrorRecord()
|
||||
{
|
||||
yield return new FormatViewDefinition("ErrorInstance",
|
||||
@@ -837,18 +1032,6 @@ namespace System.Management.Automation.Runspaces
|
||||
}
|
||||
|
||||
return ($string.Substring(0,$length) -split '\s',-2)[0]
|
||||
|
||||
#if (-not $string.Contains(' ')) {
|
||||
# return $string.Substring(0, $length)
|
||||
#}
|
||||
|
||||
#$split = $string.Substring(0, $length).Split(' ')
|
||||
#if ($split.Count -gt 1) {
|
||||
# return [string]::Join(' ', $split, 0, $split.Count - 1)
|
||||
#}
|
||||
#else {
|
||||
# return $split[0]
|
||||
#}
|
||||
}
|
||||
|
||||
$errorColor = ''
|
||||
|
||||
@@ -4557,6 +4557,7 @@ end {
|
||||
new SessionStateAliasEntry("rp", "Remove-ItemProperty", string.Empty, ReadOnly),
|
||||
new SessionStateAliasEntry("rmo", "Remove-Module", string.Empty, ReadOnly),
|
||||
new SessionStateAliasEntry("rv", "Remove-Variable", string.Empty, ReadOnly),
|
||||
new SessionStateAliasEntry("gerr", "Get-Error", string.Empty, ReadOnly),
|
||||
new SessionStateAliasEntry("rvpa", "Resolve-Path", string.Empty, ReadOnly),
|
||||
new SessionStateAliasEntry("sal", "Set-Alias", string.Empty, ReadOnly),
|
||||
new SessionStateAliasEntry("sbp", "Set-PSBreakpoint", string.Empty, ReadOnly),
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
Describe 'Get-Error tests' -Tag CI {
|
||||
BeforeAll {
|
||||
$skipTest = -not $EnabledExperimentalFeatures.Contains('Microsoft.PowerShell.Utility.PSGetError')
|
||||
if ($skipTest) {
|
||||
Write-Verbose "Test Suite Skipped. The test suite requires the experimental feature 'Microsoft.PowerShell.Utility.PSGetError' to be enabled." -Verbose
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
}
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
if ($skipTest) {
|
||||
$global:PSDefaultParameterValues = $originalDefaultParameterValues
|
||||
}
|
||||
}
|
||||
|
||||
It 'Get-Error resolves $Error[0] and includes InnerException' {
|
||||
try {
|
||||
1/0
|
||||
}
|
||||
catch {
|
||||
}
|
||||
|
||||
$out = Get-Error | Out-String
|
||||
$out | Should -BeLikeExactly '*InnerException*'
|
||||
}
|
||||
|
||||
It 'Get-Error -Newest `<count>` works: <scenario>' -TestCases @(
|
||||
@{ scenario = 'less than total'; count = 1; paramname = 'Newest' }
|
||||
@{ scenario = 'equal to total'; count = 2; paramname = 'Last' }
|
||||
@{ scenario = 'greater than total'; count = 9999; paramname = 'Newest' }
|
||||
){
|
||||
param ($count, $paramname)
|
||||
|
||||
try {
|
||||
1/0
|
||||
}
|
||||
catch {
|
||||
}
|
||||
|
||||
try {
|
||||
get-item (new-guid) -ErrorAction SilentlyContinue
|
||||
}
|
||||
catch {
|
||||
}
|
||||
|
||||
$params = @{ $paramname = $count }
|
||||
|
||||
$out = Get-Error @params
|
||||
|
||||
$expected = $count
|
||||
if ($count -eq 9999) {
|
||||
$expected = $error.Count
|
||||
}
|
||||
|
||||
$out.Count | Should -Be $expected
|
||||
}
|
||||
|
||||
It 'Get-Error -Newest with invalid value `<value>` should fail' -TestCases @(
|
||||
@{ value = 0 }
|
||||
@{ value = -2 }
|
||||
){
|
||||
param($value)
|
||||
|
||||
{ Get-Error -Newest $value } | Should -Throw -ErrorId 'ParameterArgumentValidationError,Microsoft.PowerShell.Commands.GetErrorCommand'
|
||||
}
|
||||
|
||||
It 'Get-Error will accept pipeline input' {
|
||||
try {
|
||||
1/0
|
||||
}
|
||||
catch {
|
||||
}
|
||||
|
||||
$out = $error[0] | Get-Error | Out-String
|
||||
$out | Should -BeLikeExactly '*-2146233087*'
|
||||
}
|
||||
|
||||
It 'Get-Error will handle Exceptions' {
|
||||
try {
|
||||
Invoke-Expression '1/d'
|
||||
}
|
||||
catch {
|
||||
}
|
||||
|
||||
$out = Get-Error | Out-String
|
||||
$out | Should -BeLikeExactly '*ExpectedValueExpression*'
|
||||
$out | Should -BeLikeExactly '*UnexpectedToken*'
|
||||
}
|
||||
}
|
||||
@@ -73,6 +73,7 @@ Describe "Verify approved aliases list" -Tags "CI" {
|
||||
"Alias", "gcm", "Get-Command", $($FullCLR -or $CoreWindows -or $CoreUnix), "ReadOnly", "", ""
|
||||
"Alias", "gcs", "Get-PSCallStack", $($FullCLR -or $CoreWindows -or $CoreUnix), "ReadOnly", "", ""
|
||||
"Alias", "gdr", "Get-PSDrive", $($FullCLR -or $CoreWindows -or $CoreUnix), "ReadOnly", "", ""
|
||||
"Alias", "gerr", "Get-Error", $( $CoreWindows -or $CoreUnix), "ReadOnly", "", ""
|
||||
"Alias", "ghy", "Get-History", $($FullCLR -or $CoreWindows -or $CoreUnix), "ReadOnly", "", ""
|
||||
"Alias", "gi", "Get-Item", $($FullCLR -or $CoreWindows -or $CoreUnix), "ReadOnly", "", ""
|
||||
"Alias", "gin", "Get-ComputerInfo", $($FullCLR -or $CoreWindows ), "", "", ""
|
||||
@@ -269,6 +270,7 @@ Describe "Verify approved aliases list" -Tags "CI" {
|
||||
"Cmdlet", "Get-Credential", "", $($FullCLR -or $CoreWindows -or $CoreUnix), "", "", "None"
|
||||
"Cmdlet", "Get-Culture", "", $($FullCLR -or $CoreWindows -or $CoreUnix), "", "", "None"
|
||||
"Cmdlet", "Get-Date", "", $($FullCLR -or $CoreWindows -or $CoreUnix), "", "", "None"
|
||||
"Cmdlet", "Get-Error", "", $( $CoreWindows -or $CoreUnix), "", "", "None"
|
||||
"Cmdlet", "Get-Event", "", $($FullCLR -or $CoreWindows -or $CoreUnix), "", "", "None"
|
||||
"Cmdlet", "Get-EventLog", "", $($FullCLR ), "", "", ""
|
||||
"Cmdlet", "Get-EventSubscriber", "", $($FullCLR -or $CoreWindows -or $CoreUnix), "", "", "None"
|
||||
|
||||
Reference in New Issue
Block a user