functions/New-ISERemoteTab.ps1
Function New-ISERemoteTab { [cmdletbinding(DefaultParameterSetName = "ComputerCredential")] [alias("nrt")] [OutputType("None")] Param( [Parameter( Position = 0, Mandatory, HelpMessage = "Enter the name of a remote computer", ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = "ComputerCredential" )] [Parameter(ParameterSetName = "ComputerPrompt")] [ValidateNotNullorEmpty()] [Alias("cn")] [string[]]$Computername, [Parameter( ParameterSetName = "VMCredential", HelpMessage = "Specifies the name of a virtual machine. The connection will be made using PowerShell Direct." )] [Parameter(ParameterSetName = "VMPrompt")] [string]$VMName, [Parameter(ParameterSetName = "ComputerCredential")] [Parameter(ParameterSetName = "VMCredential")] [Alias("RunAs")] [ValidateNotNullorEmpty()] [PSCredential]$Credential, [Parameter(ParameterSetName = "ComputerPrompt")] [Parameter(ParameterSetName = "VMPrompt")] [switch]$PromptForCredential, [Parameter(ParameterSetName = "ComputerPrompt")] [Parameter(ParameterSetName = "ComputerCredential")] [ValidateSet("Basic", "CredSSP", "Default", "Digest", "Kerberos", "Negotiate", "NegotiateWithImplicitCredential", "None")] [Alias('auth', 'am')] [string]$Authentication, [Parameter(ParameterSetName = "ComputerPrompt")] [Parameter(ParameterSetName = "ComputerCredential")] [ValidateNotNullOrEmpty()] [Alias("thumb")] [string]$CertificateThumbprint, [ValidateNotNullOrEmpty()] [string]$ConfigurationName, [Parameter(ParameterSetName = "ComputerPrompt")] [Parameter(ParameterSetName = "ComputerCredential")] [ValidateNotNullOrEmpty()] [ValidateRange(1, 2147483647)] [int32]$Port, [Parameter(ParameterSetName = "ComputerPrompt")] [Parameter(ParameterSetName = "ComputerCredential")] [System.Management.Automation.Remoting.PSSessionOption]$SessionOption, [Parameter(ParameterSetName = "ComputerPrompt")] [Parameter(ParameterSetName = "ComputerCredential")] [Switch]$UseSSL, [ValidateScript( { if (Test-Path $_) { $True } else { Throw "Cannot validate path $_" } })] [string]$ProfileScript = $ISERemoteProfile ) Begin { Write-Verbose "Starting: $($MyInvocation.Mycommand)" Write-Verbose "Using parameter Set: $($pscmdlet.ParameterSetName)" Write-Verbose "PSBoundParameters" Write-Verbose ($PSBoundParameters | Out-String) #disable PowerShell profiles in new ISE tabs which speeds up the process #thanks for Tobias Weltner for the guidance on this. Write-Verbose "Temporarily disabling PowerShell profiles in new ISE tabs" $type = ([Microsoft.Windows.PowerShell.Gui.Internal.MainWindow].Assembly.GetTypes()).Where( { $_.Name -eq 'PSGInternalHost' }) $currentField = $type.GetField('current', 'NonPublic,Static') $noprofileField = $type.GetField('noProfile', 'NonPublic,Instance') $pshost = $currentField.GetValue($type) $noprofileField.SetValue($pshost, $True) #dynamically build the Enter-PSSession Commmand as a string so that it can #be invoked if ($pscmdlet.ParameterSetName -like "VM*") { $cmdstring = "Enter-PSSession -VMName {0}" } else { $cmdstring = "Enter-PSSession -computername {0}" } if ($credential.username -AND $pscmdlet.ParameterSetName -like "*credential") { #export credential to a temporary local file because each new tab is a new session $credPath = [System.IO.Path]::GetTempFileName() Write-Verbose "Exporting credential for $($credential.username) to $credpath" $credential | Export-Clixml -Path $credpath $cmdstring += " -credential (Import-Clixml -path $credpath)" } #export session option to cliXML so that it can be read into the scriptblock if ($SessionOption) { $optPath = [System.IO.Path]::GetTempFileName() Write-Verbose "Exporting session options to $optPath" $sessionOption | Export-Clixml -Path $optPath $cmdstring += " -SessionOption (Import-cliXML -path $optPath)" } if ($Authentication) { $cmdstring += " -authentication $Authentication" } if ($CertificateThumbprint) { $cmdstring += " -CertificateThumbprint $CertificateThumbprint" } if ($ConfigurationName) { $cmdstring += " -configurationname $ConfigurationName" } if ($Port) { $cmdstring += " -Port $Port" } if ($UseSSL) { $cmdstring += " -UseSSL" } } #begin Process { Write-Verbose "PSBoundParameters in Process" Write-Verbose ($PSBoundParameters | Out-String) #copy bound parameters to a new hashtable $testParams = $PSBoundParameters #remove invalid parameters if ($ProfileScript) { #remove profile parameter since Test-WSMan won't recognize it [void]$testParams.remove("profilescript") } if ($SessionOption) { [void]$testParams.remove("sessionoption") } if ($PromptForCredential) { [void]$testParams.remove("promptforCredential") } #Using the ForEach() method to eke out a little bit better performance #when processing multiple computer names if ($pscmdlet.ParameterSetName -like "VM*") { if ($Credential -OR $PromptForCredential) { $Remote = $VMName } else { Write-Warning "You must specify a credential when connecting to a VM." #bail out Return } } else { $remote = $Computername } ($Remote).Foreach( { $computer = $_.ToUpper() Write-Verbose "Processing: $computer" #insert each computername $cmd = $cmdstring -f $computer Try { if ($psise.powershelltabs.displayname -contains $computer) { Throw "A tab with computername [$($computer.toUpper())] is already open." } $newtab = $psise.powershelltabs.Add() #change the tab name $newTab.DisplayName = $Computer.ToUpper() if ($ConfigurationName) { $newtab.DisplayName += " $ConfigurationName" } #wait for new tab to be created Do { Start-Sleep -Milliseconds 10 } until ($newTab.CanInvoke) if ($PromptForCredential) { Write-Verbose "Prompting for credential" $NewTab.invoke("`$cred = Get-Credential -message 'Enter a credential for $($newtab.DisplayName)'") Do { Start-Sleep -Milliseconds 10 } until ($newTab.CanInvoke) $cmd += ' -credential $cred' } #if prompt for credential Write-Verbose "Executing: $cmd" #need to verify the Enter-PSSession command was successful $newtab.Invoke($cmd) do { Start-Sleep -Milliseconds 50 } Until ($newtab.CanInvoke) Write-Verbose $newtab.ConsolePane.Text if ($newtab.ConsolePane.Text -notmatch 'error') { Do { #wait until ready Start-Sleep -Milliseconds 10 } until ($newTab.CanInvoke) #run some initial commands in each remote session if ($ProfileScript) { Write-Verbose "Launching commands from $profile" $profilecontent = Get-Content -Path $ProfileScript -Raw $sb = [scriptblock]::Create($profilecontent) [void]$newtab.Invoke($sb) } #if profile script else { $newtab.Invoke("clear-host") } } else { Write-Warning $newtab.ConsolePane.text } } #Try Catch { Write-Warning "Can't create remote tab to $computer. $($_.exception.Message)" } }) #foreach computer } #process End { #re-enable PowerShell profiles Write-Verbose "Re-enabling PowerShell ISE profiles" $noprofileField.SetValue($pshost, $False) #delete credential file if it exists if ($credpath -AND (Test-Path -Path $credPath)) { Write-Verbose "Deleting $credpath" Remove-Item $credPath -Force } #delete session option file if it exists if ($optpath -AND (Test-Path -Path $optPath)) { Write-Verbose "Deleting $optpath" Remove-Item $optPath -Force } Write-Verbose "Ending: $($MyInvocation.Mycommand)" } #end } #end function |