powershell 设置变量未正确传递

powershell Set-variable not passing properly

我在我的脚本中添加了一个菜单部分,它使用一个函数来设置变量以连接到 vcenter 服务器。问题是它没有传递变量。当我退出脚本时,当我执行 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

当它失败时,看起来变量没有被传递,它使用的是文字 $variable 而不是函数中设置的变量。 Get-variable returns 正确的变量(write-host $sourceVC 等也是如此)。这是错误:

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

该脚本在服务器的手动输入下工作正常,但由于操作将是 运行 脚本,我想排除手动错误,因为源和目标 vCenter 是已知的。

谢谢!

我建议使用 ([ref]$Variable).Value='NewValue' 来更新定义范围内的变量。

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
}

当通过按 F5 从 ISE 中 运行 此脚本时,ISE 实际上会 运行 全局范围内的脚本内容,就好像您要将代码复制并粘贴到控制台。这将:

  • 清除全局范围内的 vCenter 变量。
  • 这些函数将在全局范围内更新 vCenter 变量
  • Connect-VIServer 将在全局范围内使用 $SourceVC 变量

另一方面,如果脚本是通过使用绝对或相对路径从控制台 运行 获得的,则代码将 运行 在它自己的范围内。此范围称为脚本范围,这将:

  • 清除脚本范围内的 vCenter 变量
  • 这些函数将更新全局范围内的 vCenter 变量
  • Connect-VIServer 将在脚本中使用 $SourceVC 变量,该变量仍设置为 $null。

有两种解决方法:

  1. 使用so-called "dot-sourcing" 运行 控制台全局范围内的脚本内容。这是通过在脚本路径前添加一个点(句点)来完成的。例如:

. .\myscript.ps1

  1. 通过将 Set-Variable 的范围参数从 -Scope Global 更改为 -Scope Script 来让函数修改脚本范围中的变量,或者通过添加范围访问全局范围中的 $SourceVC 变量像这样的修饰符:

Connect-VIServer $Global:SourceVC

您可以在帮助文档中阅读有关范围的更多信息 about_Scopes。