Windows Vista Forums
Vista Forums Home Join Vista Forums Donate Vista Tutorials Tags

Welcome to Vista Forums we are your forum to discuss Windows Vista x64 and x86 systems. Whether you need help or just want to post an idea you have on Vista, this is the forum for you.
Register at Vista forums...the world biggest Windows Vista resource Join Vista Forums Now

Go Back   Vista Forums > Microsoft Technical Newsgroups > PowerShell

Script Cmdlet Bug?

Closed Thread
 
Thread Tools Display Modes
Old 05-19-2008   #1 (permalink)
Joel (Jaykul) Bennett
Guest


 

Script Cmdlet Bug?

I'm posting this here before I put it on Connect because I'm hoping
someone can help me by confirming that this really is a bug, and not
just something I'm doing wrong. Basically, when I pass parameters to
a script cmdlet via the pipeline, their NoteProperty members vanish.

In actuality, it's a little worse than that -- ScriptProperties and
CodeProperties are still visible, but I can't bind WPF to them, even
though I can, if I pass them as an argument -- I haven't included WPF
code in this script, because I figure the fact that the NoteProperties
are missing completely is tied in somehow and is enough for the demo.

Please, if you're running CTP2, have a look at this and see if you see
the missing PS* and "Foo" properties in the first invocation.

Thanks,
Joel "Jaykul" Bennett



Cmdlet Test-Bug {
Param (
[Parameter(Position=0)]
[string[]]$Select
,
[Parameter(Position=1, Mandatory=$true, ValueFromPipeline=
$true)]
[object[]]$InputObjects
)
BEGIN {
$Script:Properties = @()
function Collect-Member ($object) {
foreach($member in ($object | Get-Member -type Properties))
{
if( $Properties -notcontains $member.Name ) {
if(!$Select -OR (@($Select | % { $member.Name -like
$_ }) -contains $True)) {
Write-Host $member.Name,"" -fore Green -NoNew
} else {
Write-Host $member.Name,"" -fore Yellow -NoNew
}
$Script:Properties += $member.Name
}
}
}

if ($CommandLineParameters.ContainsKey("InputObjects")) {
Collect-Member $InputObjects
}
}
PROCESS {
Collect-Member $InputObjects
$InputObjects | ft Name, BaseName, Mode
}
}

Write-Host
## Execute my test. I store the input in a variable, but the results
## are the same, regardless of putting the ls | add-member "into" the
## commands, but this makes it clearer that the input is the same...
$files = ls | Add-Member NoteProperty Foo "Broken" -PassThru

## Pass the input via the pipeline
$files | Test-Bug Name, Foo, PS.*
## Write a little separator
Write-Host "`n`n===== Notice that when we pass the input as a
parameter =====" -Fore Cyan
Write-Host "===== The PS* properties and my 'Foo' property show up
=====`n" -Fore Cyan

## Pass the input as a parameter
Test-Bug Name, Foo, PS* -Input $files
## Write some empty space
Write-Host; Write-Host;
Old 05-20-2008   #2 (permalink)
Kiron
Guest


 

Re: Script Cmdlet Bug?

Hi Jaykul,
Pipe the value wrapped in an array:

,$files | Test-Bug Name, Foo, PS*

--
Kiron
Old 05-20-2008   #3 (permalink)
Joel (Jaykul) Bennett
Guest


 

Re: Script Cmdlet Bug?

Kiron wrote:
Quote:

> Pipe the value wrapped in an array:
Nice catch -- that's odd. If I take the array out of the parameter
definition it works too.

[Parameter(Position=1, Mandatory=$true, ValueFromPipeline=
$true)]
[Object]$InputObjects

Well, that solves my immediate problem, but it's kind of odd behavior,
can anyone explain why the custom attributes go missing from pipeline
parameters when it's defined the other way?

[Parameter(Position=1, Mandatory=$true, ValueFromPipeline=
$true)]
[Object[]]$InputObjects



Old 05-20-2008   #4 (permalink)
Kiron
Guest


 

Re: Script Cmdlet Bug?

Here are my two cents...
This is based on observation and Debug info. I don't claim to be 100% right but it makes sense, at least to me

$files=ls *.ps1|add-member 8 Foo 'MIA' -p

# $files is a collection of [io.fileInfo] whose item's 'Original Type'
# are [psObjects]. After the cast as [object[]] each item's new
# 'Original Type' is [io.fileInfo] w/o NoteProperties.
$files|%{$col=@()}{$col+=[object[]]$_}{gm -i $col[-1] -t 31}

# the cast as Object doesn't alter the item's 'Original Type'
$files|%{$col=@()}{$col+=[object]$_}{gm -i $col[-1] -t 31}

trace-command TypeConversion {$files|%{[object[]]$_}} -psh

--
Kiron
Old 05-21-2008   #5 (permalink)
Joel (Jaykul) Bennett
Guest


 

Re: Script Cmdlet Bug -- ETS attributes stripped

After further investigation ...

* Using [PsObject] or [Object] leaves the attributes intact.
* Using [PsObject[]] or [Object[]] strips the attributes ... but only
when they're from the pipeline.
* Using [IO.FileSystemInfo[]] strips the attributes no matter what.

I've filed this as a bug, since stripping the ETS info seems to be
_bad_ behavior. There is a possible work around: use a
ValidateScript ... but the error messages from these are confusing,
and they don't help with parameter set binding!!!

https://connect.microsoft.com/feedba...5387&SiteID=99

[ValidateScript({if($_ -is [IO.FileSystemInfo] -or $_ -is
[IO.FileSystemInfo[]]) { return $true } else { throw "They are not
[System.IO.FileSystemInfo] objects!" } })]
[PsObject]

DEMONSTRATION:

# Change the type of $InputObjects as indicated
Cmdlet Test-Bug {
Param (
[Parameter(Position=0)][string[]]$Select,
[Parameter(Position=1, Mandatory=$true, ValueFromPipeline=$true)]
# BugBug: types other than [Object] or [PSObject] loose ETS
properties.
# Using [PSObject] OR [Object] is ok
# Using [PsObject[]] or [Object[]] looses *ONLY* from pipeline
# But if you try [IO.FileSystemInfo[]] -- then they will always be
lost
# This works:
[ValidateScript({if($_ -is [IO.FileSystemInfo] -or $_ -is
[IO.FileSystemInfo[]])
{ return $true } else { throw "They are not [System.IO.FileSystemInfo]
objects!" }
})][PsObject]$InputObjects
)
BEGIN {
$Script:Properties = @()
function Collect-Member ($object) {
foreach($member in ($object | Get-Member -type Properties))
{
if( $Properties -notcontains $member.Name ) {
if(!$Select -OR (@($Select | % { $member.Name -like $_ }) -
contains $True)) {
Write-Host $member.Name,"" -fore Green -NoNew
} else {
Write-Host $member.Name,"" -fore Yellow -NoNew
}
$Script:Properties += $member.Name
}
}
}
if ($CommandLineParameters.ContainsKey("InputObjects")) {
Collect-Member $InputObjects
}
}
PROCESS { Collect-Member $InputObjects }
}
Write-Host
# Execute my test. I store the input in a variable, but the results
# are the same, regardless of putting the ls | add-member "into" the
# commands, but this makes it clearer that the input is the same...
$files = ls | Add-Member NoteProperty Foo "Broken" -PassThru

# Pass the input via the pipeline
$files | Test-Bug Name, Foo, PS*
# Write a little separator
Write-Host "`n`n =====`n" -Fore Cyan

# Pass the input as a parameter
Test-Bug Name, Foo, PS* -Input $files
# Write some empty space
Write-Host; Write-Host;

# if using the [ValidateScript], this will fail:
Test-Bug Name, PS* -input (ps)
Old 05-21-2008   #6 (permalink)
Joel (Jaykul) Bennett
Guest


 

Re: Script Cmdlet Bug -- ETS attributes stripped

After further investigation ...

* Using [PsObject] or [Object] leaves the attributes intact.
* Using [PsObject[]] or [Object[]] strips the attributes ... but only
when they're from the pipeline.
* Using [IO.FileSystemInfo[]] strips the attributes no matter what.

I've filed this as a bug, since stripping the ETS info seems to be
_bad_ behavior. There is a possible work around: use a
ValidateScript ... but the error messages from these are confusing,
and they don't help with parameter set binding!!!

https://connect.microsoft.com/feedba...5387&SiteID=99

[ValidateScript({if($_ -is [IO.FileSystemInfo] -or $_ -is
[IO.FileSystemInfo[]]) { return $true } else { throw "They are not
[System.IO.FileSystemInfo] objects!" } })]
[PsObject]

DEMONSTRATION:

# Change the type of $InputObjects as indicated
Cmdlet Test-Bug {
Param (
[Parameter(Position=0)][string[]]$Select,
[Parameter(Position=1, Mandatory=$true, ValueFromPipeline=$true)]
# BugBug: types other than [Object] or [PSObject] loose ETS
properties.
# Using [PSObject] OR [Object] is ok
# Using [PsObject[]] or [Object[]] looses *ONLY* from pipeline
# But if you try [IO.FileSystemInfo[]] -- then they will always be
lost
# This works:
[ValidateScript({if($_ -is [IO.FileSystemInfo] -or $_ -is
[IO.FileSystemInfo[]])
{ return $true } else { throw "They are not [System.IO.FileSystemInfo]
objects!" }
})][PsObject]$InputObjects
)
BEGIN {
$Script:Properties = @()
function Collect-Member ($object) {
foreach($member in ($object | Get-Member -type Properties))
{
if( $Properties -notcontains $member.Name ) {
if(!$Select -OR (@($Select | % { $member.Name -like $_ }) -
contains $True)) {
Write-Host $member.Name,"" -fore Green -NoNew
} else {
Write-Host $member.Name,"" -fore Yellow -NoNew
}
$Script:Properties += $member.Name
}
}
}
if ($CommandLineParameters.ContainsKey("InputObjects")) {
Collect-Member $InputObjects
}
}
PROCESS { Collect-Member $InputObjects }
}
Write-Host
# Execute my test. I store the input in a variable, but the results
# are the same, regardless of putting the ls | add-member "into" the
# commands, but this makes it clearer that the input is the same...
$files = ls | Add-Member NoteProperty Foo "Broken" -PassThru

# Pass the input via the pipeline
$files | Test-Bug Name, Foo, PS*
# Write a little separator
Write-Host "`n`n =====`n" -Fore Cyan

# Pass the input as a parameter
Test-Bug Name, Foo, PS* -Input $files
# Write some empty space
Write-Host; Write-Host;

# if using the [ValidateScript], this will fail:
Test-Bug Name, PS* -input (ps)
Old 07-13-2008   #7 (permalink)
Xml Green
Guest


 

RE: Script Cmdlet Bug?

When I typed my first ps words
(yes it was a typo at ibackground, intent was -background)...

Write-Host "These few words" ibackground yellow -foreground black

These few words ibackground yellow

....was the output where it should be

These few words

Is this overflow ?

Old 07-14-2008   #8 (permalink)
Jon
Guest


 

Re: Script Cmdlet Bug?

"Xml Green" <XmlGreen@xxxxxx> wrote in message
news:3139E4C5-EDE8-4ADF-AD1C-2949EEECBD3A@xxxxxx
Quote:

> When I typed my first ps words
> (yes it was a typo at ibackground, intent was -background)...
>
> Write-Host "These few words" ibackground yellow -foreground black
>
> These few words ibackground yellow
>
> ...was the output where it should be
>
> These few words
>
> Is this overflow ?
>


Nope, just a case of whatever can't be mapped to another parameter being
added to what is written to the console. This would be an overflow ....

$b=""; foreach ($a in 1..10000){$b += "xxxxxxxxxx"}
Write-Host $b


Write-Host : The Win32 internal error "Not enough storage is available to
process this co
mmand" 0x8 occurred when writing console output buffer at current cursor
position. Please
contact Microsoft Support Services.
At line:1 char:11
+ Write-Host <<<< $b

--
Jon



Closed Thread

Thread Tools
Display Modes


Similar Threads
Thread Thread Starter Forum Replies Last Post
Registering a Script CmdLet? moskie827 PowerShell 3 07-19-2008 09:43 AM
Re: Using a colon in a script to call another cmdlet Keith Hill [MVP] PowerShell 0 04-29-2008 10:58 PM
CTP: Script cmdlet parameter attributes error Shay Levi PowerShell 6 12-12-2007 01:52 AM
'Write-object' is not recognized as a cmdlet, function, operable program, or script file PowershellBoy PowerShell 4 10-20-2006 10:17 PM
Script for automatically generating a .NET object-centered cmdlet skeleton Alex K. Angelopoulos [MVP] PowerShell 4 08-07-2006 08:16 PM








Vistax64.com is an independent web site and has not been authorized,
sponsored, or otherwise approved by Microsoft Corporation.
"Windows Vista", the Start Orb, and related materials are trademarks of Microsoft Corp.
© Designer Media 2005-2008

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50