Skip to content

Commit

Permalink
Fix accidental wrapping of scalar Write-Output input
Browse files Browse the repository at this point in the history
when -NoEnumerate is used.

Fix PowerShell#5122
  • Loading branch information
mklement0 committed Nov 26, 2017
1 parent 32286ed commit 673117c
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 2 deletions.
Expand Up @@ -3,6 +3,7 @@
--********************************************************************/

using System.Management.Automation;
using System.Collections.Generic;

namespace Microsoft.PowerShell.Commands
{
Expand All @@ -14,15 +15,15 @@ namespace Microsoft.PowerShell.Commands
[Cmdlet(VerbsCommunications.Write, "Output", HelpUri = "https://go.microsoft.com/fwlink/?LinkID=113427", RemotingCapability = RemotingCapability.None)]
public sealed class WriteOutputCommand : PSCmdlet
{
private PSObject[] _inputObjects = null;
private object _inputObjects = null;

/// <summary>
/// Holds the list of objects to be Written
/// </summary>
[Parameter(Position = 0, Mandatory = true, ValueFromPipeline = true, ValueFromRemainingArguments = true)]
[AllowNull]
[AllowEmptyCollection]
public PSObject[] InputObject
public object InputObject
{
get { return _inputObjects; }
set { _inputObjects = value; }
Expand All @@ -39,6 +40,25 @@ public SwitchParameter NoEnumerate
set;
}

/// <summary>
/// This method implements the BeginProcessing method for Write-output command
/// </summary>
protected override void BeginProcessing() {
// If the input is a List<object> instance with a single element,
// assume that it is a single argument bound via ValueFromRemainingArguments and unwrap it.

This comment has been minimized.

Copy link
@BrucePay

BrucePay Mar 15, 2018

This is not correct. The value might be an enumerable wrapped inside a PSObject in which case you have to extract the PSObject base object, then check for an enumeration.

This comment has been minimized.

Copy link
@mklement0

mklement0 Mar 22, 2018

Author Owner

@BrucePay: Given how many things the ill-fated PowerShell#2038 PR that arose out of issue PowerShell#2035 broke (PowerShell#5122, PowerShell#5955, PowerShell#6451, PowerShell#6451) and that @SteveL-MSFT just added the "6.1.0-Consider" milestone flag to PowerShell#6451, perhaps fixing the curtains on the Titanic is not necessary, so I'll hold off on pursuing this PR further.

// Note:
// * This case is indistinguishable from something like the following:
// Write-Output -NoEnumerate -InputObject ([System.Collections.Generic.List[object]]::new((, 1)))
// However, this seems like an acceptable price to pay in order to prevent unexpected wrapping of
// a scalar in a collection when using -NoEnumerate.
// * Is the case of *multiple* ValueFromRemainingArguments values, the List<object> instance
// is passed through when -NoEnumerate is specified.
List<object> lst;
if (_inputObjects is List<object> && (lst = (List<object>)_inputObjects).Count == 1) {
_inputObjects = lst[0];
}
}

/// <summary>
/// This method implements the ProcessRecord method for Write-output command
/// </summary>
Expand Down
Expand Up @@ -71,4 +71,12 @@ Describe "Write-Output" -Tags "CI" {
$singleCollection | Should Be 1
}
}

Context "Scalar input" {
It "Write-Object -NoEnumerate should not wrap a scalar" {
Write-Output -NoEnumerate 1 | Should BeOfType [int]
Write-Output -NoEnumerate -InputObject 1 | Should BeOfType [int]
1 | Write-Output -NoEnumerate | Should BeOfType [int]
}
}
}

0 comments on commit 673117c

Please sign in to comment.