Can't seem to get my $ComputerName parameter to be utilized by my function

I have an advanced function that I created and it works great, but the only problem I seem to be having is that when I call on the function without explicitly using any parameters, the $ComputerName parameter that is set to a default of $env:COMPUTERNAME, is not even being processed by the function whatsoever.

Take the following ‘Do-SomeThing’ function example for instance:

[CmdletBinding(DefaultParameterSetName = 'Set4')] 
    
    Param
	(
	    [Parameter(Position = 0)]
            [ValidateNotNullOrEmpty()]
            [Alias('CN')]
	        $ComputerName = $env:COMPUTERNAME,

        [Parameter(Position = 1)]
            [ValidateNotNullOrEmpty()]
            [Alias('Cred')]
	        [System.Management.Automation.PSCredential]$Credential,
	    
        [Parameter(ParameterSetName = 'Set1', Position = 2)]
            [ValidateNotNullOrEmpty()]
	        $Param1,
        
        [Parameter(ParameterSetName = 'Set2', Position = 2)]
            [ValidateNotNullOrEmpty()]
	        [String[]]$Param2,
        
        [Parameter(ParameterSetName = 'Set3', Position = 2)]
            [ValidateNotNullOrEmpty()]
	        $Param3,

        [Parameter(ParameterSetName = 'Set4', Position = 2)]
            [ValidateNotNullOrEmpty()]
	        $Param4 
	)

Now, if I use Do-Something -ComputerName ‘MyComputer’, it works GREAT and uses the default $Param4 parameter.

However, if I just use Do-Something without any parameters at all, it does NOTHING, like the function didn’t even run at all. What I want it to do is to use the local computer name that I defined in the $ComputerName parameter as the default, but it is not doing that.

So the intention is for the function to use the local computer name and then also process $Param4 as the default parameter set along with it to get the data that I am looking for.

If I use the following test function, I see that there is no key listed for the ComputerName property and the value is listed instead.

Here is an example of what I am referring to.

Take this TestIt function for example:

function testit{
	[CmdletBinding(DefaultParameterSetName = 'Set4')]
	Param(
		[Parameter(Position = 0)]
		[ValidateNotNullOrEmpty()]
		[Alias('CN')]
		$ComputerName = $env:COMPUTERNAME,
		[Parameter(Position = 1)]
		[ValidateNotNullOrEmpty()]
		[Alias('Cred')]
		[System.Management.Automation.PSCredential]$Credential,
		[Parameter(ParameterSetName = 'Set1', Position = 2)]
		[ValidateNotNullOrEmpty()]
		$Param1,
		[Parameter(ParameterSetName = 'Set2', Position = 2)]
		[ValidateNotNullOrEmpty()]
		[String[]]$Param2,
		[Parameter(ParameterSetName = 'Set3', Position = 2)]
		[ValidateNotNullOrEmpty()]
		$Param3,
		[Parameter(ParameterSetName = 'Set4', Position = 2)]
		[ValidateNotNullOrEmpty()]
		$Param4
	)
	Process{
		$PSBoundParameters
	}
}

TestIt -Param1 'Testing'

If I run TestIt -Param1 ‘Testing’, I get the following output:

Key Value


Param1 Testing

Shouldn’t the ‘ComputerName’ parameter show up under the Key property and ‘MyComputer’ show up under the Value property?

When I use the following command:

TestIt -ComputerName $env:COMPUTERNAME -Param1 ‘Testing’

I get the following output:

Key Value


ComputerName MyComputer
Param1 Testing

I simply want the function to be able to use the default $env:COMPUTERNAME variable that is assigned to my ‘ComputerName’ parameter without me having to explicitly use the ‘ComputerName’ parameter in my command.

How can I go about doing this?

Should I not use Parameter Sets since it appears to be the reason behind this issue?

Thanks

Function do-something
{
Param([string]$computerName = $env:computerName)

$computername

}

Your $ComputerName variable should have the correct value. The $PSBoundParameters collection only contains parameters that the user actually passed in; not the ones that were allowed to just have their default values assigned.

I know it has the correct value, BUT, the issue is that it is NOT being used when it is set to the default of $env:COMPUTERNAME. What I am trying to get at is, if I do not want to actually use my -ComputerName parameter, because I want it to run the function on the local computer, it simply will NOT run.

Does this mean that I will just simply have to use the -ComputerName parameter and use the $env:COMPUTERNAME value instead, since it is not being used anyway as the default?

Thanks

third times a charm.

function testit{
[CmdletBinding(DefaultParameterSetName = ‘Set4’)]
Param(
[Parameter(Position = 0)]
[ValidateNotNullOrEmpty()]
[Alias(‘CN’)]
$ComputerName = $env:COMPUTERNAME,
[Parameter(Position = 1)]
[ValidateNotNullOrEmpty()]
[Alias(‘Cred’)]
[System.Management.Automation.PSCredential]$Credential,
[Parameter(ParameterSetName = ‘Set1’, Position = 2)]
[ValidateNotNullOrEmpty()]
$Param1,
[Parameter(ParameterSetName = ‘Set2’, Position = 2)]
[ValidateNotNullOrEmpty()]
[String]$Param2,
[Parameter(ParameterSetName = ‘Set3’, Position = 2)]
[ValidateNotNullOrEmpty()]
$Param3,
[Parameter(ParameterSetName = ‘Set4’, Position = 2)]
[ValidateNotNullOrEmpty()]
$Param4
)

get-process -computername $computername

}

TestIt -ComputerName othercomp

testit -Param1 ‘getprocess’

I don’t know why you say it doesn’t work.

take your process block out and put this in. get-process -computername $computername

Okay, let me toss in my real code, because apparently something is off here that I am just not getting.

Here you go:

#Requires -Version 3.0

Function Get-InstalledSoftwareUpdates
{
    [CmdletBinding(DefaultParameterSetName = 'Set4')] 
    
    Param
	(
	    [Parameter(Position = 0)]
            [ValidateNotNullOrEmpty()]
            [Alias('CN')]
	        $ComputerName,

        [Parameter(Position = 1)]
            [ValidateNotNullOrEmpty()]
            [Alias('Cred')]
	        [System.Management.Automation.PSCredential]$Credential,
	    
        [Parameter(ParameterSetName = 'Set1', Position = 2)]
            [ValidateNotNullOrEmpty()]
            [ValidatePattern('KB(\d+)')]
            [Alias('KB')]
	        $KBID,
        
        [Parameter(ParameterSetName = 'Set2', Position = 2)]
            [ValidateNotNullOrEmpty()]
            [ValidateScript({ Test-Path -Path $_ })]
            [Alias('KBList')]
	        [String[]]$KBIDList,
        
        [Parameter(ParameterSetName = 'Set3', Position = 2)]
            [ValidateNotNullOrEmpty()]
            [ValidatePattern('\d{0,2}/\d{0,2}/\d{4}')]
            [Alias('IOD')]
	        $InstalledOnDate,

        [Parameter(ParameterSetName = 'Set4', Position = 2)]
            [ValidateNotNullOrEmpty()]
            [Alias('DEF')]
	        $Default 
	)

    Begin 
    {
        $scriptBlockSet1 = {

            $NewLine = "`r"
            
            $UpdateSession = [activator]::CreateInstance([type]::GetTypeFromProgID(“Microsoft.Update.Session”))
            $UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
            $UpdateCount = $UpdateSearcher.GetTotalHistoryCount()
            $InstalledUpdates = $UpdateSearcher.QueryHistory(0, $UpdateCount)
                        
            $OutputProperties = @(

                Foreach ($Update in $InstalledUpdates)
                {
                    [pscustomobject]@{
                        'ComputerName' = $env:COMPUTERNAME
                        'KBID'= ([regex]::match($Update.Title,'KB(\d+)')).Value;
                        'InstalledOnDate' = $Update.date | Get-Date -Format d;
                        'InstallTime' = $Update.date | Get-Date -Format t;
                        'RevisionNumber' = $Update.UpdateIdentity.RevisionNumber;
                        'SupportUrl' = $Update.SupportUrl;
                        'UpdateDescription' = $Update.Description;
                        'UpdateId' = $Update.UpdateIdentity.UpdateId;
                        'UpdateTitle'= $Update.title;
                    }
                }
            )

            Foreach ($ArgID in $Args[0])
            {
                $DisplayOutput = $OutputProperties | Where-Object -FilterScript { $_.KBID -eq $ArgID }
                
                If ($DisplayOutput)
                {
                    $DisplayOutput  
                }

                Else
                {
                    $NewLine

                    Write-Warning -Message "$ArgID is not installed on computer $env:COMPUTERNAME"

                    $NewLine
                }
            }
        }
        
        $scriptBlockSet2 = {

            $NewLine = "`r"

            $UpdateSession = [activator]::CreateInstance([type]::GetTypeFromProgID(“Microsoft.Update.Session”))
            $UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
            $UpdateCount = $UpdateSearcher.GetTotalHistoryCount()
            $InstalledUpdates = $UpdateSearcher.QueryHistory(0, $UpdateCount)
                        
            $OutputProperties = @(

                Foreach ($Update in $InstalledUpdates)
                {
                    [pscustomobject]@{
                        'ComputerName' = $env:COMPUTERNAME
                        'KBID'= ([regex]::match($Update.Title,'KB(\d+)')).Value;
                        'InstalledOnDate' = $Update.date | Get-Date -Format d;
                        'InstallTime' = $Update.date | Get-Date -Format t;
                        'RevisionNumber' = $Update.UpdateIdentity.RevisionNumber;
                        'SupportUrl' = $Update.SupportUrl;
                        'UpdateDescription' = $Update.Description;
                        'UpdateId' = $Update.UpdateIdentity.UpdateId;
                        'UpdateTitle'= $Update.title;
                    }
                }
            )
            
            Foreach ($ArgID in $Args[0])
            {
                $DisplayOutput = $OutputProperties | Where-Object -FilterScript { $_.KBID -eq $ArgID }
                
                If ($DisplayOutput)
                {
                    $DisplayOutput   
                }

                Else
                {
                    $NewLine

                    Write-Warning -Message "$ArgID is not installed on computer $env:COMPUTERNAME"

                    $NewLine
                }
            }
        }

        $scriptBlockSet3 = {

            $NewLine = "`r"

            $UpdateSession = [activator]::CreateInstance([type]::GetTypeFromProgID(“Microsoft.Update.Session”))
            $UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
            $UpdateCount = $UpdateSearcher.GetTotalHistoryCount()
            $InstalledUpdates = $UpdateSearcher.QueryHistory(0, $UpdateCount)
                        
            $OutputProperties = @(

                Foreach ($Update in $InstalledUpdates)
                {
                    [pscustomobject]@{
                        'ComputerName' = $env:COMPUTERNAME
                        'KBID'= ([regex]::match($Update.Title,'KB(\d+)')).Value;
                        'InstalledOnDate' = $Update.date | Get-Date -Format d;
                        'InstallTime' = $Update.date | Get-Date -Format t;
                        'RevisionNumber' = $Update.UpdateIdentity.RevisionNumber;
                        'SupportUrl' = $Update.SupportUrl;
                        'UpdateDescription' = $Update.Description;
                        'UpdateId' = $Update.UpdateIdentity.UpdateId;
                        'UpdateTitle'= $Update.title;
                    }
                }
            )
            
            Foreach ($ArgDate in $Args[0])
            {
                $DisplayOutput = $OutputProperties | Where-Object -FilterScript { $_.InstalledOnDate -eq $ArgDate }
                
                If ($DisplayOutput)
                {
                    $DisplayOutput    
                }

                Else
                {
                    $NewLine

                    Write-Warning -Message "No update was installed on computer $env:COMPUTERNAME on the date of $ArgDate"

                    $NewLine
                }
            }
        }

        $ScriptBlockSet4 = {

            $NewLine = "`r"

            $UpdateSession = [activator]::CreateInstance([type]::GetTypeFromProgID(“Microsoft.Update.Session”))
            $UpdateSearcher = $UpdateSession.CreateUpdateSearcher()
            $UpdateCount = $UpdateSearcher.GetTotalHistoryCount()
            $InstalledUpdates = $UpdateSearcher.QueryHistory(0, $UpdateCount)
                        
            $OutputProperties = @(

                Foreach ($Update in $InstalledUpdates)
                {
                    [pscustomobject]@{
                        'ComputerName' = $env:COMPUTERNAME
                        'KBID'= ([regex]::match($Update.Title,'KB(\d+)')).Value;
                        'InstalledOnDate' = $Update.date | Get-Date -Format d;
                        'InstallTime' = $Update.date | Get-Date -Format t;
                        'RevisionNumber' = $Update.UpdateIdentity.RevisionNumber;
                        'SupportUrl' = $Update.SupportUrl;
                        'UpdateDescription' = $Update.Description;
                        'UpdateId' = $Update.UpdateIdentity.UpdateId;
                        'UpdateTitle'= $Update.title;
                    }
                }
            )

            $OutputProperties 
        }
    }

    Process
    {
        Switch ($PSBoundParameters.Keys)
        {
            { $_ -contains 'ComputerName' -and $_ -contains 'Credential' }
        
            { 
                Switch ($PSCmdlet.ParameterSetName)
                {
                    'Set1' 
                    { 
                        Foreach ($Computer in $ComputerName)
                        {      
                            $Computer = $Computer.ToUpper()
                            
                            Foreach ($ID in $KBID)
                            {
                                Invoke-Command -ComputerName $Computer -Credential $Credential -ScriptBlock $scriptBlockSet1 -ArgumentList $ID 
                            }
                        }
                    }
                    
                    'Set2'
                    {
                        $ListContent = Get-Content -Path $KBIDList
                        
                        Foreach ($Computer in $ComputerName)
                        {
                            $Computer = $Computer.ToUpper()
                            
                            Foreach ($ID in $ListContent)
                            {
                                Invoke-Command -ComputerName $Computer -Credential $Credential -ScriptBlock $scriptBlockSet2 -ArgumentList $ID 
                            }
                        }
                    }

                    'Set3'
                    {
                        Foreach ($Computer in $ComputerName)
                        {
                            $Computer = $Computer.ToUpper()
                            
                            Foreach ($Date in $InstalledOnDate)
                            {
                                Invoke-Command -ComputerName $Computer -Credential $Credential -ScriptBlock $scriptBlockSet3 -ArgumentList $Date 
                            }
                        }
                    }

                    'Set4'
                    {
                       Foreach ($Computer in $ComputerName)
                       {
                            $Computer = $Computer.ToUpper()
                            
                            Invoke-Command -ComputerName $Computer -Credential $Credential -ScriptBlock $ScriptBlockSet4 
                       } 
                    }
                }
            }

            { $_ -contains 'ComputerName' -and $_ -notcontains 'Credential' }
            
            { 
                Switch ($PSCmdlet.ParameterSetName)
                {
                    'Set1' 
                    { 
                        Foreach ($Computer in $ComputerName)
                        {      
                            $Computer = $Computer.ToUpper()
                            
                            Foreach ($ID in $KBID)
                            {
                                Invoke-Command -ComputerName $Computer -ScriptBlock $scriptBlockSet1 -ArgumentList $ID 
                            }
                        }
                    }
                    
                    'Set2'
                    {
                        $ListContent = Get-Content -Path $KBIDList
                        
                        Foreach ($Computer in $ComputerName)
                        {
                            $Computer = $Computer.ToUpper()
                            
                            Foreach ($ID in $ListContent)
                            {
                                Invoke-Command -ComputerName $Computer -ScriptBlock $scriptBlockSet2 -ArgumentList $ID 
                            }
                        }
                    }

                    'Set3'
                    {
                        Foreach ($Computer in $ComputerName)
                        {
                            $Computer = $Computer.ToUpper()
                            
                            Foreach ($Date in $InstalledOnDate)
                            {
                                Invoke-Command -ComputerName $Computer -ScriptBlock $scriptBlockSet3 -ArgumentList $Date 
                            }
                        }
                    }

                    'Set4'
                    {
                       Foreach ($Computer in $ComputerName)
                       {
                            $Computer = $Computer.ToUpper()
                            
                            Invoke-Command -ComputerName $Computer -ScriptBlock $ScriptBlockSet4 | Select-Object -ExcludeProperty PSComputerName, RunSpaceID
                       } 
                    }
                } 
            }
        }
    }

    End {}
}

Now if I run “Get-InstalledSoftwareUpdates” with no -ComputerName parameter, it simply will not run, but if I use "Get-InstalledSoftwareUpdates -ComputerName ‘MyComputer’, it runs just fine.

This is what I am referring to.

There has to be something simple that I am just not seeing, what am I missing here?

Thanks

As I mentioned, $PSBoundParameters will not contain ‘ComputerName’ if the user didn’t actually pass in a value. (It won’t be in $PSBoundParameters.Keys.)

This bit of code is the problem:

        Switch ($PSBoundParameters.Keys)
        {
            { $_ -contains 'ComputerName' -and $_ -contains 'Credential' }
            { Do-Stuff }

            { $_ -contains 'ComputerName' -and $_ -notcontains 'Credential' }
            { Do-OtherStuff }
        }

Since you’re going to be assigning a default value to $ComputerName anyway, and you’ve got ValidateNotNullOrEmpty on it, testing for the presence of $ComputerName in any way doesn’t help anything. It will always have some non-empty value, or PowerShell will give the user an error before it ever executes the rest of your code. That code could become a simple check for the presence of $Credential:

if ($Credential)
{
    Do-Stuff
}
else
{
    Do-OtherStuff
}

Yes, posting the script you’re having issues with does indeed help :smiley:

Seems overly redundant. You could really simplify this by reading the windows update event log.

OMFG, I’m an IDIOT!

I CANNOT believe I missed that.

Dan, I am an SCCM Admin and utilize the WindowsUpdate.log file quite frequently when troubleshooting software update issues on SCCM clients, but that can get overwritten due to the set limit size configured by the WUA agent, plus it does not provide the best readable format, even when using the CMTrace log parser.

Also, I just like to write silly shit in PowerShell, because it’s fun and I have no life.

Thanks a ton, Dave.

Thank you too, Dan.

I appreciate your guys’ help on this.