New-ISERemoteTab.ps1
#requires -version 4.0 #requires -module ISE Function New-ISERemoteTab { [cmdletbinding(DefaultParameterSetName="Credential")] Param( [Parameter( Position = 0, Mandatory, HelpMessage = "Enter the name of a remote computer", ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateNotNullorEmpty()] [Alias("cn")] [string[]]$Computername, [Parameter(ParameterSetName="Credential")] [Alias("RunAs","cred","c")] [ValidateNotNullorEmpty()] [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty, [Parameter(ParameterSetName="Prompt")] [switch]$PromptForCredential, [ValidateSet("Basic","CredSSP", "Default", "Digest", "Kerberos", "Negotiate", "NegotiateWithImplicitCredential","None")] [Alias('auth','am')] [string]$Authentication, [ValidateNotNullOrEmpty()] [Alias("thumb")] [string]$CertificateThumbprint, [ValidateNotNullOrEmpty()] [string]$ConfigurationName, [ValidateNotNullOrEmpty()] [ValidateRange(1, 2147483647)] [int32]$Port, [System.Management.Automation.Remoting.PSSessionOption]$SessionOption, [Switch]$UseSSL, [ValidateScript({ if (Test-Path $_) { $True } else { Throw "Cannot validate path $_" } })] [string]$Profile ) 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 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 $cmdstring = "Enter-PSSession -computername {0}" if ($credential.username -AND $pscmdlet.ParameterSetName -eq "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 ($profile) { #remove profile parameter since Test-WSMan won't recognize it $testParams.remove("profile") | Out-Null } if ($SessionOption) { $testParams.remove("sessionoption") | Out-Null } if ($PromptForCredential) { $testParams.remove("promptforCredential") | Out-Null } #Using the ForEach() method to eke out a little bit better performance #when processing multiple computer names ($Computername).Foreach({ $computer = $_ Write-Verbose "Processing: $computer" #insert each computername $cmd = $cmdstring -f $computer #insert the current computer nto the parameters for Test-WSMan $testParams.Computername = $computer #remove configurationname from Test-WSMan $testparams.Remove("ConfigurationName") | Out-Null #Verify Computer is accessible with Test-WSMan Try { Test-WSMan @testParams -ErrorAction Stop | Out-Null $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)' -username $env:userdomain\$env:username") Do { Start-Sleep -Milliseconds 10 } until ($newTab.CanInvoke) $cmd+= ' -credential $cred' } #if prompt for credential Write-Verbose "Executing: $cmd" $newtab.Invoke($cmd) Do { #wait until ready start-Sleep -Milliseconds 10 } until ($newTab.CanInvoke) #run some initial commands in each remote session if ($profile) { Write-Verbose "Launching commands from $profile" #get contents of profile script where there are words but no comments Get-Content $profile | where {$_ -match "\w+" -AND $_ -notmatch "#"} | foreach { Write-Verbose "[$($newTab.Displayname)] Invoking $_" $newTab.Invoke($_) #wait for command to complete Do { Start-Sleep -Milliseconds 10 } until ($newTab.CanInvoke) } #foreach command } #if profile script else { $newtab.Invoke("clear-host") } } #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" del $credPath -Force } #delete session option file if it exists if ($optpath -AND (Test-Path -path $optPath)) { Write-Verbose "Deleting $optpath" del $optPath -Force } Write-Verbose "Ending: $($MyInvocation.Mycommand)" } #end } #end function #define an alias Set-Alias -Name nrt -Value New-ISERemoteTab |