Search code examples
powershellpowercli

powershell Set-variable not passing properly


I added a menu portion of my script which is using a function to set-variables for connections to vcenter servers. The problem is it isn't passing the variable. When I quit the script the variable is correct when I do a get-variable.

#Main menu
function MainMenu {
    Clear-Host
    [int]$xMenuChoiceA = 0

    while ($xMenuChoiceA -lt 01 -or $xMenuChoiceA -gt 04) {
        Write-Host "============================================" -ForegroundColor Green
        Write-Host "|   Main Menu                              |" -ForegroundColor Green
        Write-Host "============================================" -ForegroundColor Green
        Write-Host "|  Migration Script                        |" -ForegroundColor Green
        Write-Host "============================================" -ForegroundColor Green
        Write-Host "|                                          |" -ForegroundColor Green
        Write-Host "| 1. Development                           |" -ForegroundColor Green
        Write-Host "| 2. Model                                 |" -ForegroundColor Green
        Write-Host "| 3. Production                            |" -ForegroundColor Green
        Write-Host "| 4. Quit                                  |" -ForegroundColor Green
        Write-Host "|                                          |" -ForegroundColor Green
        Write-Host "============================================" -ForegroundColor Green
        Write-Host ""
        Write-Host "Please enter an option 1 to 4..." -ForegroundColor Green -NoNewline

        [Int]$xMenuChoiceA = Read-Host
    }

    Switch($xMenuChoiceA) {
        1 { SetDev }
        2 { SetModel }
        3 { SetProd }
        4 { Are-YouSure }
        default { MainMenu }
    }
}

#Verifiyng exit of menu
function Are-YouSure {
    Write-Host "Are you sure you want to exit? (y/n)" -ForegroundColor Cyan -NoNewline
    $areyousure = Read-Host

    if ($areyousure -eq "y") { exit }
    if ($areyousure -eq "n") { MainMenu }
    else {
        Write-Host -ForegroundColor Red "Invalid Selection"
        Are-YouSure
    }
}

#clear vCenter variables
$SourceVC = $null
$DestVC = $null

#menu set vCenter function
function SetDev {
    Set-Variable -Name SourceVC -Value devvc.effingps.corp -Scope global
    Set-Variable -Name DestVC -Value ucsvcd.effingps.corp -Scope global
    break
}

function SetModel {
    Set-Variable -Name SourceVC -Value modelvc.effingps.corp -Scope global
    Set-Variable -Name DestVC -Value ucsvcm.effingps.corp -Scope global
    break
}

function SetProd {
    Set-Variable -Name SourceVC -Value prodvc.effingps.corp -Scope global
    Set-Variable -Name DestVC -Value ucsvcp.effingps.corp -Scope global
    break
}

MainMenu

#connects to the source vCenter for right-sizing
Connect-VIServer $SourceVC

When it fails it looks like the variable is not passed and it's using the literal $variable instead of the variable that was set in the function. Get-variable returns the correct variable (as does write-host $sourceVC, etc). Here's the error:

Connect-VIServer : Cannot validate argument on parameter 'Server'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.

At D:\scripts\vm-uscmigration.ps1:84 char:18

+ connect-viserver $SourceVC + ~~~~~~~~~ CategoryInfo : InvalidData: (:) [Connect-VIServer], ParameterBindingValidationException + FullyQualifiedErrorId : ParameterArgumentValidationError,VMware.VimAutomation.ViCore.Cmdlets.Commands.ConnectVIServer

The script did work fine with manual input for the servers, but as Operations will be running the script, I wanted to take manual error out of the equation since the source and destination vCenters are known.

Thanks!


Solution

  • I suggest to use ([ref]$Variable).Value='NewValue' to update variable in the scope where it defined.

    function SetDev {
        ([ref]$SourceVC).Value='devvc.effingps.corp'
        ([ref]$DestVC).Value='ucsvcd.effingps.corp'
        break
    }
    function SetModel {
        ([ref]$SourceVC).Value='modelvc.effingps.corp'
        ([ref]$DestVC).Value='ucsvcm.effingps.corp'
        break
    }
    function SetProd {
        ([ref]$SourceVC).Value='prodvc.effingps.corp'
        ([ref]$DestVC).Value='ucsvcp.effingps.corp'
        break
    }