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

This topic contains 9 replies, has 3 voices, and was last updated by Profile photo of I Am Sir Ask Alot I Am Sir Ask Alot 3 months ago.

  • Author
    Posts
  • #52137
    Profile photo of I Am Sir Ask Alot
    I Am Sir Ask Alot
    Participant

    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

  • #52152
    Profile photo of Dan Potter
    Dan Potter
    Participant

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

    $computername

    }

  • #52154
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    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.

  • #52240
    Profile photo of I Am Sir Ask Alot
    I Am Sir Ask Alot
    Participant

    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

  • #52264
    Profile photo of Dan Potter
    Dan Potter
    Participant

    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'

  • #52266
    Profile photo of Dan Potter
    Dan Potter
    Participant

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

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

  • #52303
    Profile photo of I Am Sir Ask Alot
    I Am Sir Ask Alot
    Participant

    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

  • #52307
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    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
    }
    
  • #52350
    Profile photo of Dan Potter
    Dan Potter
    Participant

    Yes, posting the script you're having issues with does indeed help 😀

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

  • #52367
    Profile photo of I Am Sir Ask Alot
    I Am Sir Ask Alot
    Participant

    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.

You must be logged in to reply to this topic.