Functions/Launcher/PSRemoting/Invoke-LauncherPSRemoting.ps1
<#
.SYNOPSIS Connect to a remote system by using a registered PowerShell Remoting connection. .DESCRIPTION Use the PowerShell Remoting connections registered in the profile launcher to connect to the remote host. This can be done by opening an interactive connection, invoke a script block or create a session. .EXAMPLE PS C:\> winrm List all available PowerShell Remoting connections. .EXAMPLE PS C:\> winrm srv01 Connect to the remote interactive prompt of PowerShell Remoting. .EXAMPLE PS C:\> $session = winrm srv01 Open a new PowerShell Remoting session to the remote system. .EXAMPLE PS C:\> winrm srv01 'gpupdate' Invoke the command on the remote system. #> function Invoke-LauncherPSRemoting { [CmdletBinding(DefaultParameterSetName = 'Show')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseUsingScopeModifierInNewRunspaces', '')] [Alias('winrm', 'win', 'w')] param ( # Name of the PowerShell Remoting connection to use. [Parameter(Mandatory = $true, ParameterSetName = 'Connect', Position = 0)] [System.String] $Name, # Optional a script block to invoke it on the remote system. If it's not # a script block, use the string representation to convert it to a # script block. [Parameter(Mandatory = $false, ParameterSetName = 'Connect', Position = 1)] [System.Object] $ScriptBlock ) $ErrorActionPreference = 'Stop' if ($PSCmdlet.ParameterSetName -eq 'Show') { # Show all registered PowerShell Remoting connections. This may help to # choose the correct connection. Get-LauncherPSRemoting } if ($PSCmdlet.ParameterSetName -eq 'Connect') { $launcherPSRemoting = @(Get-LauncherPSRemoting -Name $Name) if ($null -eq $launcherPSRemoting -or $launcherPSRemoting.Count -eq 0) { Write-Error "PowerShell Remoting connection named '$Name' not found." } elseif ($launcherPSRemoting.Count -gt 1) { $launcherPSRemoting | ForEach-Object { Write-Host "[Launcher] PS Remoting target found: $($_.Name)" -ForegroundColor 'DarkYellow' } Write-Error "Multiple PowerShell Remoting connections found. Be more specific." } else { # Define a splat to connect to the remoting system. $splat = @{ ComputerName = $launcherPSRemoting.ComputerName } $verbose = "'$($splat['ComputerName'])'" if (-not [System.String]::IsNullOrEmpty($launcherPSRemoting.Credential)) { $splat['Credential'] = Get-VaultCredential -TargetName $launcherPSRemoting.Credential $verbose += " as '$($splat['Credential'].Username)'" } if ($PSBoundParameters.ContainsKey('ScriptBlock')) { # Option 1: Invoke Command # If a script is appended to the command, execute that script on the # remote system. Write-Host "[Launcher] Invoke a remote command on $verbose ..." -ForegroundColor 'DarkYellow' if ($ScriptBlock -isnot [System.Management.Automation.ScriptBlock]) { $ScriptBlock = [System.Management.Automation.ScriptBlock]::Create([System.String] $ScriptBlock) } Invoke-Command @splat -ScriptBlock $ScriptBlock } else { $commandLine = (Get-PSCallStack)[1].Position.Text.Trim() if ($commandLine -like '$*') { # Option 2: Open Session # If a variable is specified as output of the command, a new # remoting session will be opened and returned. Write-Host "[Launcher] Create a new session on $verbose ..." -ForegroundColor 'DarkYellow' New-PSSession @splat } else { # Option 3: Enter Session # If no parameters were specified, just enter into a remote # session to the target system. Write-Host "[Launcher] Enter remote shell on $verbose ..." -ForegroundColor 'DarkYellow' $session = New-PSSession @splat $stubModule = '' $stubModule += Get-Content -Path "$PSScriptRoot\..\..\Performance\Measure-System.ps1" -Raw $stubModule += Get-Content -Path "$PSScriptRoot\..\..\Performance\Measure-Processor.ps1" -Raw $stubModule += Get-Content -Path "$PSScriptRoot\..\..\Performance\Measure-Memory.ps1" -Raw $stubModule += Get-Content -Path "$PSScriptRoot\..\..\Performance\Measure-Storage.ps1" -Raw $stubModule += Get-Content -Path "$PSScriptRoot\..\..\Performance\Measure-Session.ps1" -Raw $stubFormat = Get-Content -Path "$PSScriptRoot\..\..\..\ProfileFever.Xml.Format.ps1xml" -Raw Invoke-Command -Session $session -ScriptBlock { Set-Content -Path "$Env:Temp\ProfileFeverStub.Xml.Format.ps1xml" -Value $using:stubFormat -Force Set-Content -Path "$Env:Temp\ProfileFeverStub.psm1" -Value $using:stubModule -Force Update-FormatData -AppendPath "$Env:Temp\ProfileFeverStub.Xml.Format.ps1xml" Import-Module -Name "$Env:Temp\ProfileFeverStub.psm1" Set-Location -Path "$Env:SystemDrive\" } if ($Host.Name -eq 'ConsoleHost') { Invoke-Command -Session $session -ScriptBlock { $PromptLabel = $Env:ComputerName.ToUpper() $PromptIndent = $using:session.ComputerName.Length + 4 function Global:prompt { $Host.UI.RawUI.WindowTitle = "$Env:Username@$Env:ComputerName | $($executionContext.SessionState.Path.CurrentLocation)" Write-Host "[$PromptLabel]" -NoNewline -ForegroundColor Cyan; "$("`b `b" * $PromptIndent) $($executionContext.SessionState.Path.CurrentLocation)$('>' * ($nestedPromptLevel + 1)) " } } } Enter-PSSession -Session $session } } } } } # Register the argument completer for the Name parameter Register-ArgumentCompleter -CommandName 'Invoke-LauncherPSRemoting' -ParameterName 'Name' -ScriptBlock { param ($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) Get-LauncherPSRemoting -Name "$wordToComplete*" | ForEach-Object { [System.Management.Automation.CompletionResult]::new($_.Name, $_.Name, 'ParameterValue', $_.ComputerName) } } |