SessionHelper.ps1
function Get-WinRmConnectionToTargetMachine { [CmdletBinding()] Param ( [string] $computerName, [string] $port, [pscredential] $credential, [string] $authentication, [string] $sessionName, [string] $sessionConfigurationName, [switch] $useSsl, [ValidateRange(1,10)] [int] $maxRetryLimit = 3, [ValidateRange(5, 60)] [int] $timeoutPeriod = 30 ) Trace-VstsEnteringInvocation $MyInvocation try { $retryCount = 0; $isConnectionComplete = $false $newPsSessionCommand = Get-NewPSSessionCommand -computerName $computerName ` -port $port ` -authentication $authentication ` -sessionName $sessionName ` -useSsl:$useSsl ` -sessionConfigurationName $sessionConfigurationName ` -NoCredential:($credential -eq $null) while ($retryCount -lt $maxRetryLimit) { Write-Verbose "Trying to establish connection: Attempt #$($retryCount + 1)" $session = (Invoke-Expression $newPsSessionCommand) foreach ($sessionError in $sessionErrors) { Write-Verbose $("New-PSSession Error: " + $sessionError.Exception.Message) } if($session -ne $null) { $isConnectionComplete = $true break; } $retryCount++ Start-Sleep -Seconds $timeoutPeriod } if ($isConnectionComplete) { Write-Verbose "Connection established to computer:'$computerName' port:'$port'" Write-Host $(Get-VstsLocString -Key "RemoteDeployer_ConnectedMachines" -ArgumentList $computerName) return $session } else { foreach ($sessionError in $sessionErrors) { Write-Error (Get-VstsLocString -Key "PS_TM_UnableToCreatePSSession" -ArgumentList ($sessionError.Exception.Message)) } throw (Get-VstsLocString -Key "RemoteDeployer_NotConnectedMachines" -ArgumentList $computerName, $port) } } finally { Trace-VstsLeavingInvocation $MyInvocation } } function Get-NewPSSessionCommand { [CmdletBinding()] Param ( [string] $computerName, [string] $port, [string] $authentication, [string] $sessionName, [string] $sessionConfigurationName, [switch] $useSsl, [switch] $NoCredential ) Trace-VstsEnteringInvocation $MyInvocation try { $newPsSessionCommandArgs = "-ComputerName '$computerName' -Port $port -Authentication $authentication -Name '$sessionName'" if(!$NoCredential) { $newPsSessionCommandArgs += " -Credential `$credential" } if($useSsl) { $newPsSessionCommandArgs += " -UseSSL" } $newPsSessionCommandArgs += " -ErrorAction 'SilentlyContinue' -ErrorVariable sessionErrors" $newPsSessionCommandArgs += " -ConfigurationName '$sessionConfigurationName'" $newPsSessionCommand = "New-PSSession $newPsSessionCommandArgs" Write-Verbose "New-PSSessionCommand: $newPsSessionCommand" return $newPsSessionCommand } finally { Trace-VstsLeavingInvocation $MyInvocation } } function Retry-Connection { [CmdletBinding()] Param ( [psobject[]] $targetMachines, [string] $computerName, [string] $sessionName, [psobject] $sessionOption ) Trace-VstsEnteringInvocation -InvocationInfo $MyInvocation -Parameter '' try { $targetMachine = $targetMachines | Where-Object { $_.ComputerName.ToLowerInvariant() -eq $computerName.ToLowerInvariant() } if($targetMachine -eq $null) { $allComputerNames = $($targetMachines | ForEach-Object { $_.ComputerName }) -join ',' Write-Verbose "Unable to find target machine: '$computerName' in the list of target machines: '$allComputerNames'" } else { $remoteSession = Get-RemoteConnection -targetMachine $targetMachine -sessionName $sessionName -sessionOption $sessionOption if($remoteSession -eq $null) { Write-Verbose "Unable to get remote pssession with name: '$sessionName' on remote computer: '$($targetMachine.ComputerName)'" } else { if(($remoteSession.State.ToString().ToLowerInvariant() -eq "disconnected") -and ($remoteSession.Availability.ToString().ToLowerInvariant() -eq "none")) { Write-Verbose "Session: '$sessionName' is available for reconnection on remote computer: '$($targetMachine.ComputerName)'" $job = Receive-PSSession -Session $remoteSession -OutTarget Job -ErrorAction 'Stop' return ($job.ChildJobs[0].Id) } else { Write-Verbose "Remote PSSession unavailable for connection. PSSessionState: '$($remoteSession.State)'. PSSessionAvailability: '$($remoteSession.Availability)'" } } } } catch { Write-Verbose "Error during reconnection attempt: $($_.Exception.ToString())" } finally { Trace-VstsLeavingInvocation $MyInvocation } return $null } function Disconnect-WinRmConnectionToTargetMachines { [CmdletBinding()] Param ( [psobject[]] $targetMachines, [string] $sessionName, [psobject] $sessionOption ) Trace-VstsEnteringInvocation -InvocationInfo $MyInvocation -Parameter '' try { foreach($targetMachine in $targetMachines) { $remoteSession = Get-RemoteConnection -targetMachine $targetMachine -sessionName $sessionName -sessionOption $sessionOption if($remoteSession -ne $null) { try { Write-Verbose "Trying to disconnect pssession with name: $sessionName, computerName: $($targetMachine.ComputerName)" $null = Disconnect-PSSession -Session $remoteSession -IdleTimeoutSec 60 -ErrorAction 'Stop' Write-Verbose "Successfully disconnected session: $sessionName on computer: $($targetMachine.ComputerName)" } catch { Write-Verbose "Unable to disconnect pssession with name: $sessionName, computerName: $($targetMachine.ComputerName). Error: $($_.Exception.Message)" } } } } finally { Trace-VstsLeavingInvocation $MyInvocation } } function Get-RemoteConnection { [CmdletBinding()] Param ( [Parameter(Mandatory = $true)] [psobject] $targetMachine, [Parameter(Mandatory = $true)] [string] $sessionName, [Parameter(Mandatory = $true)] [psobject] $sessionOption ) Trace-VstsEnteringInvocation -InvocationInfo $MyInvocation -Parameter '' try { if($targetMachine.Credential -eq $null) { $remoteSession = Get-PSSession -ComputerName $($targetMachine.ComputerName) ` -Name $sessionName ` -ConfigurationName ($targetMachine.SessionConfigurationName) ` -Port ($targetMachine.WSManPort) ` -Authentication ($targetMachine.Authentication) ` -SessionOption $sessionOption ` -UseSSL:$($targetMachine.UseSsl) } else { $remoteSession = Get-PSSession -ComputerName ($targetMachine.ComputerName) ` -Name $sessionName ` -ConfigurationName ($targetMachine.SessionConfigurationName) ` -Credential ($targetMachine.Credential) ` -Port ($targetMachine.WSManPort) ` -Authentication ($targetMachine.Authentication) ` -SessionOption $sessionOption ` -UseSSL:$($targetMachine.UseSsl) } return $remoteSession } finally { Trace-VstsLeavingInvocation $MyInvocation } } |