0

So I writing some code to run some patching on AWS, I have the following script snippet taken out of the whole thing for now.. I seem to be running into an issue with $PSBoundParameters.. (It's Friday & I've had a long week so I may just need to sleep on it) - but I can't seem to pass anything out of read-host...

param (
[Parameter(Mandatory = $true)][ValidateNotNullorEmpty()][string]$Prof,
[Parameter(Mandatory = $false)][ValidateNotNullorEmpty()][string]$Reminder,
[Parameter(Mandatory = $false)][ValidateNotNullorEmpty()][string]$AddToTGs,
[Parameter(Mandatory = $false)][ValidateNotNullorEmpty()][string]$PatchType,
[Parameter(Mandatory = $false)][ValidateNotNullorEmpty()][string]$Instance,
[Parameter(Mandatory = $false)][ValidateNotNullorEmpty()][string]$Environment
)

function PromptInstance {
    $Instance = Read-Host -Prompt "Please Specify the Instance"
    Write-Host "Using: $Instance" -ForegroundColor Cyan
}

function PromptEnvtoPatch {
    $Environment = Read-Host -Prompt "Please Specify the Environment (e.g. dev)"
    Write-Host "Using: $Environment" -ForegroundColor Cyan
}

function PromptReminder {
$title = "Calendar"
$message = "Do you want to Add an Outlook Reminder in 24 Hrs?"
$pA = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Adds an Outlook Reminder"
$pB = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Won''t add a reminder"
$options = [System.Management.Automation.Host.ChoiceDescription[]]($pA, $pB)
$CalResult = $host.ui.PromptForChoice($title, $message, $options, 0)

    switch ($CalResult)
    {
        0 {
            $global:CalRes = 1
            Write-Host "Reminder will be added.." -ForegroundColor Cyan
        }
        1 {
            $global:CalRes = 0
            Write-Host "No Reminder will be added.." -ForegroundColor Cyan
        } 
    }
}

function PromptAddToTGs {
    $title = "Re-Add to Target Groups"
    $message = "Do you want to have this script Automatically add the instances back into the Target Groups after Patching?"
    $pA = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Will ADD the instance back into Target Groups"
    $pB = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Will NOT add the instance back into Target Groups"
    $options = [System.Management.Automation.Host.ChoiceDescription[]]($pA, $pB)
    $result = $host.ui.PromptForChoice($title, $message, $options, 1)
    
    switch ($result)
    {
        0 {
            $global:AddTGRes = 1
            Write-Host "Instances WILL be added back into Target Groups" -ForegroundColor Cyan
        }
        1 {
            $global:AddTGRes = 0
            Write-Host "Instances will NOT be added back into Target Groups" -ForegroundColor Cyan
        }
    }
}

function PromptPatchType {
    $title = "Patching Type"
    $message = "Do you want to Patch a Single Instance, or ALL Instances for a specific Team Env?"
    $pA = New-Object System.Management.Automation.Host.ChoiceDescription "&Instance", "Patches an Instance"
    $pB = New-Object System.Management.Automation.Host.ChoiceDescription "&ALL Instances for an Env", "Patches ALL Instances in a Team Env"
    $pQ = New-Object System.Management.Automation.Host.ChoiceDescription "&Quit", "Cancel/Exit"
    $options = [System.Management.Automation.Host.ChoiceDescription[]]($pA, $pB, $pQ)
    $PatchResult = $host.ui.PromptForChoice($title, $message, $options, 0)
    
    switch ($PatchResult)
    {
        0 {
            $Instance = Read-Host "Please Specify the Instance Id"
        }
        1 {
            $Environment = Read-Host "Please Specify the Team (i.e. dev)"
        }
        2 {
            Write-Host "You Quitter!... :-)"
            Exit
        }
    }
}

function KickOffPatchingEnv {
    param ($Prof, $Reg, $Reminder, $AddToTGs, $PatchType, $Environment)
    Write-Host "Using the Following Options: (Profile:$Prof) (Region:$Reg) (Reminder:$Reminder) (AddToTGs:$AddToTGs) (PatchType:$PatchType) (Environment:$Environment)"
}

function KickOffPatchingInst {
    param ($Prof, $Reg, $Reminder, $AddToTGs, $PatchType, $Instance)
    Write-Host "Using the Following Options: (Profile:$Prof) (Region:$Reg) (Reminder:$Reminder) (AddToTGs:$AddToTGs) (PatchType:$PatchType) (Instance:$Instance)"
}

switch -wildcard ($Prof) {
    "*dev*"        { $Reg = "eu-west-1"; $Bucket = "s3-dev-bucket" }
    "*admin*"      { $Reg = "eu-west-1"; $Bucket = "s3-admin-bucket" }
    "*prod*"       { $Reg = "eu-west-1"; $Bucket = "s3-prod-bucket" }
    "*staging*"    { $Reg = "eu-west-1"; $Bucket = "s3-staging-bucket" }
}

if (!$PSBoundParameters['Reminder']) { PromptReminder }

if (!$PSBoundParameters['AddToTGs']) { PromptAddToTGs }

if ($PSBoundParameters['PatchType']) {
    if (($PatchType -eq "i") -or ($PatchType -eq "instance") -or ($PatchType -eq "I") -or ($PatchType -eq "Instance")) {
        if (!$PSBoundParameters['Instance']) { PromptInstance }
        KickOffPatchingInst $Prof $Reg $Reminder $AddToTGs $PatchType $Instance
    }
    if (($PatchType -eq "a") -or ($PatchType -eq "all") -or ($PatchType -eq "A") -or ($PatchType -eq "All")) {
        if (!$PSBoundParameters['Environment']) { PromptEnvtoPatch }
        KickOffPatchingEnv $Prof $Reg $Reminder $AddToTGs $PatchType $Environment
    }
} else { PromptPatchType }

If I use the parameters on the command line, it works fine..

PS C:\Users\myself\Desktop> .\test.ps1 -Prof dev -Reminder y -AddToTGs y -PatchType a -Environment dev
Using the Following Options: (Profile:dev) (Region:eu-west-1) (Reminder:y) (AddToTGs:y) (PatchType:a) (Environment:dev)

But if I omit an option, say for instance the Environment, I'm prompted for it, but the value is not displayed..

PS C:\Users\myself\Desktop> .\test.ps1 -Prof dev -Reminder y -AddToTGs y -PatchType a 
Please Specify the Environment (e.g. dev): dev
Using: dev
Using the Following Options: (Profile:dev) (Region:eu-west-1) (Reminder:y) (AddToTGs:y) (PatchType:a) (Environment:)

Environment is empty.... I've tried loads of different things such as setting global:Environment etc, but I always seem to be missing out whichever variable isn't specified in the command?

Maybe this isn't the best way to write this, but i've never used $PSBoundParameters before so this is my first time trying it out..

Can anyone see my glaring error here at all? TIA :)

Alex
  • 29
  • 5
  • 1
    You need to read [`about_Scopes`](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_scopes?view=powershell-7.2) - `$Instance` is a _local_ variable, it stops existing as soon as `PromptInstance` returns :) – Mathias R. Jessen Sep 16 '22 at 16:11
  • Ditto to what 'Mathias ' said, but I am just curious as to why you choose to script this vs using AWS Systems Manager for patching. ['site:aws.amazon.com aws systems manager'](https://duckduckgo.com/?q=site%3A+aws.amazon.com+aws+systems+manager%27&t=h_&ia=web) --- [site:aws.amazon.com aws systems manager' 'patch manager'](https://duckduckgo.com/?q=site%3Aaws.amazon.com+aws+systems+manager%27+%27patch+manager%27&t=h_&ia=webhttps://duckduckgo.com/?q=site%3Aaws.amazon.com+aws+systems+manager%27+%27patch+manager%27&t=h_&ia=web) – postanote Sep 16 '22 at 17:30
  • thanks @MathiasR.Jessen - I thought as much - adding in a $global: underneath this seems to be working.. I put ```$global:UserProf = $Prof``` in & changed the other variables & it's now showing that value... Thanks. – Alex Sep 20 '22 at 07:15
  • @postanote - I am using AWS Patch Manager, but this script pulls the server out of the Load Balancer Target Groups first, so that it is not going to be an unhealthy target, then stops relevant services on the server (also via SSM commands) then patches it, then starts the relevant services back up, then puts it back into the Load Balancer Target Groups.... Saves anyone patching having to worry about doing all that.... - but yes, the patching is a send-ssm command. – Alex Sep 20 '22 at 07:16

1 Answers1

0

@Mathias R. Jessen answered this for me.

I put this in the function

function PromptProfile {
    $Prof = Read-Host -Prompt "Please Specify the Profile"
    $global:UserProf = $Prof
}

then changed code later on with the global variable, so I can use them

Alex
  • 29
  • 5