我尝试设置Powershell ISE来管理在Hyper-V下托管的几个虚拟机并使用Powershell Direct。
我想做的是:
在一个脚本中收集所有相关的"设置"在名称以适当前缀开头的变量下,例如" vms";
在此脚本的末尾为每个要管理的VM打开PowerShellTab
(如果尚未打开);
在这个新Tab的运行空间中复制所有相关的设置变量(我认为这对下一步是必要的);
使用VM启动远程PSSession
(如果尚未启动)并在此远程PSSession
中复制或更新设置变量;
以交互方式输入此PSSession
,以便在选择部分样本/模板脚本后启动我的命令(F8)。
我的剧本就是这个。
$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)
}
不幸的是这个脚本效果很好:
否则最后两个PowerShellTab.Invoke
失败(空引用)。
有什么想法解决这个错误吗? 有什么方法可以做得更好吗?