Powershell:如何将变量导出到现有的运行空间(不同的Powershell ISE选项卡)和该运行空间中的现有远程PSSession

时间:2017-11-11 16:14:55

标签: powershell powershell-ise

我尝试设置Powershell ISE来管理在Hyper-V下托管的几个虚拟机并使用Powershell Direct。

我想做的是:

  1. 在一个脚本中收集所有相关的"设置"在名称以适当前缀开头的变量下,例如" vms";

  2. 在此脚本的末尾为每个要管理的VM打开PowerShellTab(如果尚未打开);

  3. 在这个新Tab的运行空间中复制所有相关的设置变量(我认为这对下一步是必要的);

  4. 使用VM启动远程PSSession(如果尚未启动)并在此远程PSSession中复制或更新设置变量;

  5. 以交互方式输入此PSSession,以便在选择部分样本/模板脚本后启动我的命令(F8)。

  6. 我的剧本就是这个。

    $vms = 'VMName1','VMName2'
    $vmsCredentials = @{
        VMName1 = [pscredential]::new('User1', (ConvertTo-SecureString 'pw1' -AsPlainText -force))
        VMName2 = [pscredential]::new('User2', (ConvertTo-SecureString 'pw2' -AsPlainText -force))
    }
    
    $vmsInfo1 = 'blah,blah,blah'
    $vmsInfo2 = @{}
    $vmsInfo3 = @(1,2,3)
    
    $tabPrevious = $psISE.CurrentPowerShellTab
    
    $vms |% {
    
            Write-Information $_
            $tab = $psISE.PowerShellTabs |? DisplayName -eq $_
    
            if ($tab -eq $null)
            {
                # opens new PS ISE Tab
                $tab = $psISE.PowerShellTabs.Add()
                $psISE.PowerShellTabs.SetSelectedPowerShellTab($tabPrevious)
                $tab.DisplayName = $_
                $tab.ExpandedScript = $true
                $tab.Files.Clear()
    
                # open all files in new tab 
                $tabPrevious.Files |% FullPath |? { Test-Path $_ } |% {
                    [void]$tab.Files.Add($_)
                }
            }
            else
            {
                # exit remote interactive session, if any 
                if ($tab.Prompt -match "^\[$_\]: ") {
                    while (!$tab.CanInvoke) { sleep -Milliseconds 100 }
                    $tab.Invoke('exit')
                }
            }
    
            # export/update variables to tab
            while (!$tab.CanInvoke) { sleep -Milliseconds 100 }
            $rs = ($tab.InvokeSynchronous({ $ExecutionContext.Host.Runspace }, $false))[0]
            if ($null -ne $rs) {
                Get-Variable "vms*" |% { $rs.SessionStateProxy.SetVariable($_.Name, $_.Value) }            
            }
    
            # start a new remote PSSession for the tab, if not already done
            while (!$tab.CanInvoke) { sleep -Milliseconds 100 }
            $tab.Invoke("if (`$null -eq `$pchPSSession) { `$pchPSSession = New-PSSession -VMName '$_' -Credential `$vmsCredentials['$_'] }")
    
            # export/update variables to the remote PSSession and enter interactively
            while (!$tab.CanInvoke) { sleep -Milliseconds 100 }
            $tab.Invoke("Invoke-Command `$pchPSSession { `$args |% { Set-Variable `$_.Name `$_.Value } } -ArgumentList (Get-Variable 'vms*'); Enter-PSSession -Session `$pchPSSession")
    
            # uncomment this line and no error occurs
            #[void]$psISE.PowerShellTabs.Remove($tab)
        }
    

    不幸的是这个脚本效果很好:

    • 我第一次在一个新的ISE中运行脚本,
    • 或只需要打开一个新标签
    • 或者如果我立即关闭刚添加的Tab(取消注释最后一行),
    • 或在Debugger下

    否则最后两个PowerShellTab.Invoke失败(空引用)。

    有什么想法解决这个错误吗? 有什么方法可以做得更好吗?

0 个答案:

没有答案