1
Help New-item -parameter "Value"

show us -Value <System.Object> could be bind ByPropertyName or ByValue. The question is:

** Is it possible pipe ByPropertyName? **

As ByValue takes precedence over ByPropertyName, I can't find any example to be able to do that pipe. Anything I write to the left is an object, and is bound by ByValue, even if that object has the -Value attribute.

Thank you

Example:

$customObject = [PSCustomObject]@{
    Value = "Lorem ipsum"
}

$customObject | New-Item -Name BPN_value.txt

The content of BPN_value.txt is @{Value = "Lorem ipsum"} because $customObject is an object (obviously) and it's binding byValue to the paramete Value of New_Item

mklement0
  • 382,024
  • 64
  • 607
  • 775

2 Answers2

4

Is it possible to bind New-Item -Value parameter ByPropertyName?

No, because as you have already noticed, the parameter type is System.Object and since all objects inherit from this class every input from pipeline is bound with ValueFromPipeline instead of ValueFromPipelineByPropertyName.

Should the type for this parameter be other than System.Object?

No, because it would conflict with other providers. In example, defining a new function would no longer be possible:

$null = New-Item -Path function:Say-Hello -Value {
    'hey there'
}

Say-Hello

Should the -Value parameter be enabled to bind by Property Name?

Probably not, because it can never be bound by it.

Is there a workaround?

You could have a ProxyCommand or wrapper function around New-Item that changes the parameter type from System.Object to System.String, this way the function would be able to work properly taking ValueFromPipeline and ValueFromPipelineByPropertyName. You could then store this wrapper in your $PROFILE and have it available for you each time a new session is started.

For the reasons stated before, this wrapper would only work targetting the FileSystem provider and has been hardcoded for ItemType = File.

function New-File {
    [CmdletBinding(DefaultParameterSetName='pathSet', SupportsShouldProcess=$true, ConfirmImpact='Medium', HelpUri='https://go.microsoft.com/fwlink/?LinkID=2096592')]
    param(
        [Parameter(ParameterSetName='pathSet', Mandatory=$true, Position=0, ValueFromPipelineByPropertyName=$true)]
        [Parameter(ParameterSetName='nameSet', Position=0, ValueFromPipelineByPropertyName=$true)]
        [string[]]
        ${Path},

        [Parameter(ParameterSetName='nameSet', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
        [AllowNull()]
        [AllowEmptyString()]
        [string]
        ${Name},

        [Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [Alias('Target')]
        [string]
        ${Value},

        [switch]
        ${Force}
    )

    begin {
        try {
            $outBuffer = $null
            if ($PSBoundParameters.TryGetValue('OutBuffer', [ref] $outBuffer)) {
                $PSBoundParameters['OutBuffer'] = 1
            }

            $PSBoundParameters['ItemType'] = 'File'

            $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Management\New-Item', [System.Management.Automation.CommandTypes]::Cmdlet)
            $scriptCmd = { & $wrappedCmd @PSBoundParameters }

            $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
            $steppablePipeline.Begin($PSCmdlet)
        }
        catch {
            $PSCmdlet.ThrowTerminatingError($_)
        }
    }

    process {
        try {
            $steppablePipeline.Process($Value)
        }
        catch {
            $PSCmdlet.ThrowTerminatingError($_)
        }
    }

    end {
        try {
            $steppablePipeline.End()
        } catch {
            $PSCmdlet.ThrowTerminatingError($_)
        }
    }
    <#
    .ForwardHelpTargetName Microsoft.PowerShell.Management\New-Item
    .ForwardHelpCategory Cmdlet
    #>
}

[PSCustomObject]@{ Value = "Lorem ipsum" } | New-File .\BPN_value.txt -Force
"Lorem ipsum" | New-File .\BPN_value2.txt -Force

For reference, the definition of the code used above was autogenerated using:

[System.Management.Automation.ProxyCommand]::Create((Get-Command New-Item))

Then it has been slightly modified and simplified for this specific answer.

Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
  • 1
    Thank you very much for the reply! I have only recently started learning powershell and I find your New-File example incredible. I don't quite understand the definition of the function, but it understands the goal of wrapping New-Item. Thanks again!! :-) – Eduardo Fernández Nov 23 '22 at 19:55
  • @EduardoFernández I'm glad the answer was helpful and I'm happy to help. See my update to show you how that code used in the function can be autogenerated – Santiago Squarzon Nov 23 '22 at 19:56
  • I see. Really useful! I have a lot to learn :-) – Eduardo Fernández Nov 23 '22 at 20:27
0

It is possible if the values of the -Path or -Name parameter is also a property of the object in the pipeline:

[PSCustomObject]@{
    name = 'TestFile'
    value = 'Hello World'
} | New-Item

Console capture:

PS ScratchPad> [PSCustomObject]@{
>>     Name = 'TestFile'
>>     value = 'Hello World'
>> } | New-Item


    Directory: C:\ScratchPad


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        11/23/2022  12:07 AM             35 TestFile

Or:

PS ScratchPad> [PSCustomObject]@{
>>     Path = "$Home\Documents\TestFile.txt"
>>     value = 'Hello World'
>> } | New-Item


    Directory: C:\Users\keith\Documents


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a----        11/23/2022  12:27 AM             64 TestFile.txt

But for some reason, it doesn't like -Path + -Name:

PS ScratchPad> [PSCustomObject]@{
>>     Path = "$Home\Documents"
>>     Name = 'TestFile'
>>     value = 'Hello World'
>> } | New-Item
New-Item : Access to the path 'C:\Users\keith\Documents' is denied.
At line:5 char:5
+ } | New-Item
+     ~~~~~~~~
    + CategoryInfo          : PermissionDenied: (C:\Users\keith\Documents:String) [New
   -Item], UnauthorizedAccessException
    + FullyQualifiedErrorId : NewItemUnauthorizedAccessError,Microsoft.PowerShell.Comm
   ands.NewItemCommand
Keith Miller
  • 702
  • 5
  • 13