ParameterBindingValidationException on Powershell v3

by cmcknz77 at 2012-10-29 04:18:45

Hi.
I have written a module to assist some of my colleauges with Performing a specific action in SCCM. It comprises 3 functions:-
Convert-MACAddress (to standardise the formatting of a user supplied MAC Address)
Get-SCCMUnknownEntry (to retrieve the list of resources in a certain collection in SCCM)
Remove-SCCMUnknownEntry (to remove one or more entries from that same collection in SCCM)

It works fine with Powershellv2 and is in active use by a number of my colleagues.

They are able to retrieve specific entries and clear them without error.

As was I - right until I upgraded to Powershell v3. Now, although the process of removing a specified resource entry ‘functions’ correctly, I receive a series of errors when piping the output of the Get-SCCMUnknownEntry function through to Remove-SCCMUnknownEntry and I’m at a complete loss as to why.

If I manually specify a MACAddress or ResourceID to Remove-SCCMUnknownEntry it works and produces no errors in both cases.
If I run Remove-SCCMUnknownEntry without specifying any parameters, it prompts me for a ResourceID as intended.

When I try to enable function tracing using Set-PSDebug -trace 2, neither function completes properly (possibly due to some odd interaction with WMI?) so I can’t troubleshoot this in the way I normally would.

Get-SCCMUnknownEntry produces objects like this]

TypeName: MY.SCCM.UnknownResource

Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
MACAddress NoteProperty System.Net.NetworkInformation.PhysicalAddress MACAddress=001234FADE7D
MACAddressCount NoteProperty System.Int32 MACAddressCount=1
MACAddressList NoteProperty System.String MACAddressList=System.String
ResourceID NoteProperty System.UInt32 ResourceID=1234


My Parameter block for Remove-SCCMUnknownEntry looks like this]

[cmdletBinding(SupportsShouldProcess=$True,ConfirmImpact='High',DefaultParameterSetName="ByResourceID")]
Param(
[Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ByResourceID")]
[System.UInt32]$ResourceID,
[Parameter(Position=0,Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ByMACAddress")]
[String]$MACAddress,
[Parameter()]
[Alias('SCCMServer')]
[System.String]$ComputerName='SCCMServer',
[Parameter()]
[System.String]$Site='ABC'
)


An example result from running this on computer with Powershell v3 installed is as follows]


PS C:> Get-SCCMUnknownEntry -mac 001234FADE7D

ResourceID MACAddressList MACAddressCount MACAddress
---------- -------------- --------------- ----------
1234 {00:1F:16:27:3D:53} 1 001234FADE7D


PS C:> Get-SCCMUnknownEntry -mac 001234FADE7D | Remove-SCCMUnknownEntry
Remove-SCCMUnknownEntry : Cannot bind argument to parameter 'ResourceID' because it is null.
At line:1 char:45
+ Get-SCCMUnknownEntry -mac 001234FADE7D | Remove-SCCMUnknownEntry
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:slight_smile: [Remove-SCCMUnknownEntry], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Remove-SCCMUnknownEntry

Remove-SCCMUnknownEntry : Cannot bind argument to parameter 'ResourceID' because it is null.
At line:1 char:45
+ Get-SCCMUnknownEntry -mac 001234FADE7D | Remove-SCCMUnknownEntry
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:slight_smile: [Remove-SCCMUnknownEntry], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Remove-SCCMUnknownEntry

Remove-SCCMUnknownEntry : Cannot bind argument to parameter 'ResourceID' because it is null.
At line:1 char:45
+ Get-SCCMUnknownEntry -mac 001234FADE7D | Remove-SCCMUnknownEntry
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:slight_smile: [Remove-SCCMUnknownEntry], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Remove-SCCMUnknownEntry

Remove-SCCMUnknownEntry : Cannot bind argument to parameter 'ResourceID' because it is null.
At line:1 char:45
+ Get-SCCMUnknownEntry -mac 001234FADE7D | Remove-SCCMUnknownEntry
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:slight_smile: [Remove-SCCMUnknownEntry], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Remove-SCCMUnknownEntry

Remove-SCCMUnknownEntry : Cannot bind argument to parameter 'ResourceID' because it is null.
At line:1 char:45
+ Get-SCCMUnknownEntry -mac 001234FADE7D | Remove-SCCMUnknownEntry
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:slight_smile: [Remove-SCCMUnknownEntry], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Remove-SCCMUnknownEntry

Remove-SCCMUnknownEntry : Cannot bind argument to parameter 'ResourceID' because it is null.
At line:1 char:45
+ Get-SCCMUnknownEntry -mac 001234FADE7D | Remove-SCCMUnknownEntry
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:slight_smile: [Remove-SCCMUnknownEntry], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Remove-SCCMUnknownEntry

Remove-SCCMUnknownEntry : Cannot bind argument to parameter 'ResourceID' because it is null.
At line:1 char:45
+ Get-SCCMUnknownEntry -mac 001234FADE7D | Remove-SCCMUnknownEntry
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:slight_smile: [Remove-SCCMUnknownEntry], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Remove-SCCMUnknownEntry

Remove-SCCMUnknownEntry : Cannot bind argument to parameter 'ResourceID' because it is null.
At line:1 char:45
+ Get-SCCMUnknownEntry -mac 001234FADE7D | Remove-SCCMUnknownEntry
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:slight_smile: [Remove-SCCMUnknownEntry], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Remove-SCCMUnknownEntry

Remove-SCCMUnknownEntry : Cannot bind argument to parameter 'ResourceID' because it is null.
At line:1 char:45
+ Get-SCCMUnknownEntry -mac 001234FADE7D | Remove-SCCMUnknownEntry
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:slight_smile: [Remove-SCCMUnknownEntry], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Remove-SCCMUnknownEntry


Confirm
Are you sure you want to perform this action?
Performing operation "Deleting Entry from SCCM Server CHIDS099.bl.bacardi.net" on Target "1234".
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "Y"): y

Remove-SCCMUnknownEntry : Cannot bind argument to parameter 'ResourceID' because it is null.
At line:1 char:45
+ Get-SCCMUnknownEntry -mac 001234FADE7D | Remove-SCCMUnknownEntry
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:slight_smile: [Remove-SCCMUnknownEntry], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Remove-SCCMUnknownEntry

Remove-SCCMUnknownEntry : Cannot bind argument to parameter 'ResourceID' because it is null.
At line:1 char:45
+ Get-SCCMUnknownEntry -mac 001234FADE7D | Remove-SCCMUnknownEntry
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:slight_smile: [Remove-SCCMUnknownEntry], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Remove-SCCMUnknownEntry

PS C]



I get a much ‘cleaner’ result in Powershell v2 (same output with none of the errors)

If anyone can give me any hints as to why (and how to resolve) I’d appreciate it

Thanks,
by poshoholic at 2012-10-29 08:12:36
A few quick questions:

1. Are you running in strict mode using "Latest" for the version?
2. Can you invoke the following command by itself and share what do you get back?
@(Get-SCCMUnknownEntry -mac 001234FADE7D).Count

I’m very curious about the second question, and how it compares between PowerShell 2.0 and PowerShell 3.0 (you know you can launch PowerShell 2.0 on a system with PowerShell 3.0 using powershell -version 2, right?). Based on the errors you are seeing, it seems that there are a bunch of nulls being piped in to Remove-SCCMUnknownEntry. You could add [ValidateNotNull()] to the ResourceId parameter and [ValidateNotNullOrEmpty()] to the MacAddress parameter to see if PowerShell catches null values coming in to those parameters from the pipeline (it will raise a more explicit error). Regardless of that last part, you probably need to inspect the results of your Get-SCCMUnknownEntry call to see exactly what you get back in both PowerShell 2.0 and PowerShell 3.0. Assign it to a variable, check the type, validate the contents, and do it side by side with 2.0 and 3.0 sessions so that you can identify if something has changed between those two. That would be a good first step in diagnosing what the problem is here.
by cmcknz77 at 2012-10-29 09:37:14
Wow… Er… You’re quite correct:
In Powershell 2:

PS C:> @(GET-SCCMUnknownEntry -mac 001234FADE7D).count
1
PS C:>

Whereas in Powershell v3

PS C:> @(GET-SCCMUnknownEntry -mac 001234FADE7D).count
15
PS C:>

That ‘count’ keeps track with the number of entries currently sitting in the collection
So basically it looks like my filter in Get-SCCMUnknownEntry is the thing that is not working properly…

if($MACAddress){
foreach($MAC in $MACAddress){
Write-Output ($Object | ?{$_.MACAddress -match $($MAC -replace '\W')})
}
}


I’m not working in strict-mode at all (I suppose I should be ?)

I reckon I’ve been trying to use comparison operators on un-alike types (regex [System.String] matching on a [System.Net.NetworkInformation.PhysicalAddress]) and Powershell 3’s been struggling

Thanks - I think I’ve got it from here.
by poshoholic at 2012-10-29 10:07:19
Excellent. If you have additional questions, don’t hesitate to ask.

Also one thing to keep in mind: PowerShell 3 does have some regressions in it, which show up as new, unexpected bugs sometimes, and it also has some improvements that expose bugs in script that were not exposed before. Whenever a script’s behaviour changes between v2 and v3, it’s a good idea to peel back the onion and identify specifically what changed to cause the behavioural change. That helps identify regressions so that the PowerShell team can fix them in future releases. It also helps as a script author because it may highlight incorrect assumptions or frailties in scripts that you have written.