Posh-SSH.psm1

##############################################################################################
# SSH Function

<#
.Synopsis
   Get current SSH Session that are available for interaction.
.DESCRIPTION
   Get current SSH Session that are available for interaction.
 
.EXAMPLE
    Get list of current sessions available.
 
    PS C:\> Get-SSHSession
 
    Index Host Connected
    ----- ---- ---------
      0 192.168.1.163 True
      1 192.168.1.154 False
      2 192.168.1.155 True
      3 192.168.1.234 True
 
.PARAMETER Index
    Index number of Session to retrive.
 
.NOTES
    AUTHOR: Carlos Perez carlos_perez@darkoprator.com
.LINK
    http://sshnet.codeplex.com/
    http://www.darkoperator.com/
#>

function Get-SSHSession 
{
    [CmdletBinding()]
    param( 
        [Parameter(Mandatory=$false)]
        [Int32]$Index
    )

    Begin{}
    Process
    {
        if ($Index)
        {
            foreach($i in $Index)
            {
                foreach($session in $SshSessions)
                {
                    if ($session.Index -eq $i)
                    {
                        $session
                    }
                }
            }
        }
        else
        {
            # Can not reference SShSessions directly so as to be able
            # to remove the sessions when Remove-SSHSession is used
            $return_sessions = @()
            foreach($s in $SshSessions){$return_sessions += $s}
            $return_sessions
        }
    }
    End{}
}


<#
.Synopsis
   Removes and Closes an existing SSH Session.
.DESCRIPTION
    Removes and Closes an existing SSH Session. The session can be a SSH Session object
    or they can be specified by Index.
 
.EXAMPLE
    Remove a SSH Session specified by Index
 
    PS C:\> Remove-SSHSession -Index 0
    True
 
.PARAMETER Index
    Index number of Session to close and remove.
 
.PARAMETER Session
    SSH Session to close and remove.
 
.NOTES
    AUTHOR: Carlos Perez carlos_perez@darkoprator.com
.LINK
    http://sshnet.codeplex.com/
    http://www.darkoperator.com/
#>

function Remove-SSHSession
{
    [CmdletBinding(DefaultParameterSetName='Index')]
    param(
        [Parameter(Mandatory=$true,
        ParameterSetName = 'byname',
        ValueFromPipelineByPropertyName=$true)]
        [Int32[]]$Index,

        [Parameter(Mandatory=$false,
        ParameterSetName = 'Session',
        ValueFromPipeline=$true)]
        [Alias('Name')]
        [SSH.SSHSession[]]$SSHSession
        )

        Begin{}
        Process
        {
            if ($Index.Count -gt 0)
            {
                $sessions2remove = @()
                 foreach($i in $Index)
                {
                    Write-Verbose $i
                    foreach($session in $Global:SshSessions)
                    {
                        if ($session.Index -eq $i)
                        {
                            $sessions2remove += $session
                        }
                    }
                }

                foreach($badsession in $sessions2remove)
                {
                     Write-Verbose "Removing session $($badsession.index)"
                     if ($badsession.session.IsConnected) 
                     { 
                        $badsession.session.Disconnect() 
                     }
                     $badsession.session.Dispose()
                     $global:SshSessions.Remove($badsession)
                     Write-Verbose "Session $($badsession.index) Removed"
                }
            }

            if ($SSHSession.Count -gt 0)
            {
                $sessions2remove = @()
                 foreach($i in $SSHSession)
                {
                    foreach($ssh in $Global:SshSessions)
                    {
                        if ($ssh -eq $i)
                        {
                            $sessions2remove += $ssh
                        }
                    }
                }

                foreach($badsession in $sessions2remove)
                {
                     Write-Verbose "Removing session $($badsession.index)"
                     if ($badsession.session.IsConnected) 
                     { 
                        $badsession.session.Disconnect() 
                     }
                     $badsession.session.Dispose()
                     $Global:SshSessions.Remove($badsession)
                     Write-Verbose "Session $($badsession.index) Removed"
                }
            }

        }
        End{}
    
}


<#
.Synopsis
   Executes a given command on a remote SSH host.
.DESCRIPTION
   Executes a given command on a remote SSH hosst given credentials to the host or using an existing
   SSH Session.
 
.EXAMPLE
    Executes the "uname -a" command against several sessions
 
    PS C:\> Invoke-SSHCommand -Command "uname -a" -Index 0,2,3
 
 
    Host : 192.168.1.163
    Output : Linux debian6 2.6.32-5-amd64 #1 SMP Sun Sep 23 10:07:46 UTC 2012 x86_64 GNU/Linux
              
    ExitStatus : 0
 
    Host : 192.168.1.155
    Output : Linux ole6 2.6.39-300.17.1.el6uek.x86_64 #1 SMP Fri Oct 19 11:29:17 PDT 2012 x86_64 x86_64 x86_64 GNU/Linux
              
    ExitStatus : 0
 
    Host : 192.168.1.234
    Output : Linux ubuntusrv 3.2.0-29-generic #46-Ubuntu SMP Fri Jul 27 17:03:23 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux
              
    ExitStatus : 0
 
.PARAMETER Command
    Command to execute in remote host.
 
.PARAMETER Index
    Index number of Session to execute command against.
 
.PARAMETER Session
    SSH Session to execute command against.
 
.NOTES
    AUTHOR: Carlos Perez carlos_perez@darkoprator.com
.LINK
    http://sshnet.codeplex.com/
    http://www.darkoperator.com/
#>

function Invoke-SSHCommand
{
    [CmdletBinding(DefaultParameterSetName='Index')]
    param(

        [Parameter(Mandatory=$true)]
        [string]$Command,
        
        [Parameter(Mandatory=$true,
        ParameterSetName = 'Session',
        ValueFromPipeline=$true)]
        [Alias('Name')]
        [SSH.SSHSession[]]$SSHSession,

        [Parameter(Mandatory=$true,
        ParameterSetName = 'Index')]
        [int32[]]$Index = $null,

        # Ensures a connection is made by reconnecting before command.
        [Parameter(Mandatory=$false)]
        [switch]$EnsureConnection

    )

    Begin{}
    Process
    {
        
        if ($SSHSession)
        {
            foreach($s in $SshSession)
            {
                if ($s.session.isconnected)
                {
                    if ($EnsureConnection)
                    {
                        $s.session.connect()
                    }
                    $result = $S.session.RunCommand($Command)
                }
                else
                {
                    $s.session.connect()
                    $result = $s.session.RunCommand($Command)
                }
                if ($result)
                    {
                        $ResultObj = New-Object psobject -Property @{Output = $result.Result
                                                                     ExitStatus = $result.ExitStatus 
                                                                     Host = $s.Host
                                                                     Error=$result.Error}

                        $ResultObj.pstypenames.insert(0,'Renci.SshNet.SshCommand')
                        $ResultObj
                    }
            }
        }
        elseif ($Index.Length -gt 0)
        {
            foreach($s in $SshSessions)
            {
                if($Index -contains $s.Index)
                {
                    Write-Verbose "Running command against $($s.Index)"
                    if ($s.session.isconnected)
                    {
                        if ($EnsureConnection)
                        {
                            $s.session.connect()
                        }
                        $result = $S.session.RunCommand($Command)
                    }
                    else
                    {
                        $s.session.connect()
                        $result = $s.session.RunCommand($Command)
                    }
                    if ($result)
                    {
                        $ResultObj = New-Object psobject -Property @{Output = $result.Result; ExitStatus = $result.ExitStatus; Host = $s.Host}
                        $ResultObj.pstypenames.insert(0,'Renci.SshNet.SshCommand')
                        $ResultObj
                    }
                }
            }
        }

    }
    End{}
}

##############################################################################################
# SSH Port Forwarding


<#
.Synopsis
   Redirects traffic from a local port to a remote host and port via a SSH Session.
.DESCRIPTION
   Redirects TCP traffic from a local port to a remote host and port via a SSH Session.
.EXAMPLE
   Forward traffic from 0.0.0.0:8081 to 10.10.10.1:80 thru a SSH Session
 
    PS C:\> New-SSHLocalPortForward -Index 0 -LocalAdress 0.0.0.0 -LocalPort 8081 -RemoteAddress 10.10.10.1 -RemotePort 80 -Verbose
    VERBOSE: Finding session with Index 0
    VERBOSE: 0
    VERBOSE: Adding Forward Port Configuration to session 0
    VERBOSE: Starting the Port Forward.
    VERBOSE: Forwarding has been started.
 
    PS C:\> Invoke-WebRequest -Uri http://localhost:8081
 
 
    StatusCode : 200
    StatusDescription : OK
    Content :
                        <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                                "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                        <html>
                            <head>
                                <script type="text/javascript" src="/javascript/scri...
    RawContent : HTTP/1.1 200 OK
                        Expires: Tue, 16 Apr 2013 03:43:18 GMT,Thu, 19 Nov 1981 08:52:00 GMT
                        Cache-Control: max-age=180000,no-store, no-cache, must-revalidate, post-check=0, pre-check=0
                        Set-Cookie: PHPSESS...
    Forms : {iform}
    Headers : {[Expires, Tue, 16 Apr 2013 03:43:18 GMT,Thu, 19 Nov 1981 08:52:00 GMT], [Cache-Control, max-age=180000,no-store, no-cache,
                        must-revalidate, post-check=0, pre-check=0], [Set-Cookie, PHPSESSID=d53d3dc62ffac241112bcfd16af36bb8; path=/], [Pragma, no-cache]...}
    Images : {}
    InputFields : {@{innerHTML=; innerText=; outerHTML=<INPUT onchange=clearError(); onclick=clearError(); tabIndex=1 id=usernamefld class="formfld user"
                        name=usernamefld>; outerText=; tagName=INPUT; onchange=clearError();; onclick=clearError();; tabIndex=1; id=usernamefld; class=formfld
                        user; name=usernamefld}, @{innerHTML=; innerText=; outerHTML=<INPUT onchange=clearError(); onclick=clearError(); tabIndex=2
                        id=passwordfld class="formfld pwd" type=password value="" name=passwordfld>; outerText=; tagName=INPUT; onchange=clearError();;
                        onclick=clearError();; tabIndex=2; id=passwordfld; class=formfld pwd; type=password; value=; name=passwordfld}, @{innerHTML=;
                        innerText=; outerHTML=<INPUT tabIndex=3 class=formbtn type=submit value=Login name=login>; outerText=; tagName=INPUT; tabIndex=3;
                        class=formbtn; type=submit; value=Login; name=login}}
    Links : {}
    ParsedHtml : mshtml.HTMLDocumentClass
    RawContentLength : 5932
#>


<#function New-SSHLocalPortForward
{
    [CmdletBinding(DefaultParameterSetName="Index")]
    param(
    [Parameter(Mandatory=$true)]
    [String]$LocalAdress = '127.0.0.1',
 
    [Parameter(Mandatory=$true)]
    [Int32]$LocalPort,
 
    [Parameter(Mandatory=$true)]
    [String]$RemoteAddress,
 
    [Parameter(Mandatory=$true)]
    [Int32]$RemotePort,
 
    [Parameter(Mandatory=$true,
        ParameterSetName = "Session",
        ValueFromPipeline=$true)]
    [Alias("Session")]
    [SSH.SSHSession]$SSHSession,
 
    [Parameter(Mandatory=$true,
        ParameterSetName = "Index",
        ValueFromPipeline=$true)]
    [Int32]$Index = $null
    )
 
    Begin
    {
        # Initialize the ForwardPort Object
        $SSHFWP = New-Object Renci.SshNet.ForwardedPortLocal($LocalAdress, $LocalPort, $RemoteAddress, $RemotePort)
    }
    Process
    {
        if ($Index -ne $null)
        {
            Write-Verbose "Finding session with Index $Index"
            foreach($session in $Global:SshSessions)
            {
                Write-Verbose $session.index
                if ($session.index -eq $Index)
                {
                    # Add the forward port object to the session
                    Write-Verbose "Adding Forward Port Configuration to session $Index"
                    $session.session.AddForwardedPort($SSHFWP)
                    Write-Verbose "Starting the Port Forward."
                    $SSHFWP.start()
                    Write-Verbose "Forwarding has been started."
                }
            }
        }
        elseif ($SSHSession)
        {
            if ($SSHSession -in $Global:SshSessions)
            {
                # Add the forward port object to the session
                Write-Verbose "Adding Forward Port Configuration to session $($SSHSession.index)"
                $SSHSession.session.AddForwardedPort($SSHFWP)
                Write-Verbose "Starting the Port Forward."
                $SSHFWP.start()
                Write-Verbose "Forwarding has been started."
            }
            else
            {
                Write-Error "The Session does not appear in the list of created sessions."
            }
        }
     
    }
    End{}
 
 
}#>



<#function New-SSHRemotePortForward
{
    [CmdletBinding(DefaultParameterSetName="Index")]
    param(
    [Parameter(Mandatory=$true)]
    [String]$LocalAdress = '127.0.0.1',
 
    [Parameter(Mandatory=$true)]
    [Int32]$LocalPort,
 
    [Parameter(Mandatory=$true)]
    [String]$RemoteAddress,
 
    [Parameter(Mandatory=$true)]
    [Int32]$RemotePort,
 
    [Parameter(Mandatory=$true,
        ParameterSetName = "Session",
        ValueFromPipeline=$true)]
    [Alias("Session")]
    [SSH.SSHSession]$SSHSession,
 
    [Parameter(Mandatory=$true,
        ParameterSetName = "Index",
        ValueFromPipeline=$true)]
    [Int32]$Index = $null
    )
 
    Begin
    {
        # Initialize the ForwardPort Object
        $SSHFWP = New-Object Renci.SshNet.ForwardedPortRemote($LocalAdress, $LocalPort, $RemoteAddress, $RemotePort)
    }
    Process
    {
        if ($Index -ne $null)
        {
            Write-Verbose "Finding session with Index $Index"
            foreach($session in $Global:SshSessions)
            {
                Write-Verbose $session.index
                if ($session.index -eq $Index)
                {
                    # Add the forward port object to the session
                    Write-Verbose "Adding Forward Port Configuration to session $Index"
                    $session.session.AddForwardedPort($SSHFWP)
                    Write-Verbose "Starting the Port Forward."
                    $SSHFWP.start()
                    Write-Verbose "Forwarding has been started."
                }
            }
        }
        elseif ($SSHSession)
        {
            if ($SSHSession -in $Global:SshSessions)
            {
                # Add the forward port object to the session
                Write-Verbose "Adding Forward Port Configuration to session $($SSHSession.index)"
                $SSHSession.session.AddForwardedPort($SSHFWP)
                Write-Verbose "Starting the Port Forward."
                $SSHFWP.start()
                Write-Verbose "Forwarding has been started."
            }
            else
            {
                Write-Error "The Session does not appear in the list of created sessions."
            }
        }
     
    }
    End{}
 
 
}
#>

<#
.Synopsis
   Establishes a Dynamic Port Forward thru a stablished SSH Session.
.DESCRIPTION
   Dynamic port forwarding is a transparent mechanism available for applications, which
   support the SOCKS4 or SOCKS5 client protoco. In windows for best results the local address
   to bind to should be the IP of the network interface.
.EXAMPLE
    New-SSHDynamicPortForward -LocalAdress 192.168.28.131 -LocalPort 8081 -Index 0 -Verbose
VERBOSE: Finding session with Index 0
VERBOSE: 0
VERBOSE: Adding Forward Port Configuration to session 0
VERBOSE: Starting the Port Forward.
VERBOSE: Forwarding has been started.
#>


<#function New-SSHDynamicPortForward
{
    [CmdletBinding(DefaultParameterSetName="Index")]
    param(
    [Parameter(Mandatory=$true)]
    [String]$LocalAdress = 'localhost',
 
    [Parameter(Mandatory=$true)]
    [Int32]$LocalPort,
 
    [Parameter(Mandatory=$true,
        ParameterSetName = "Session",
        ValueFromPipeline=$true)]
    [Alias("Session")]
    [SSH.SSHSession]$SSHSession,
 
    [Parameter(Mandatory=$true,
        ParameterSetName = "Index",
        ValueFromPipeline=$true)]
    [Int32]$Index
    )
 
     Begin
    {
        # Initialize the ForwardPort Object
        $SSHFWP = New-Object Renci.SshNet.ForwardedPortDynamic($LocalAdress, $LocalPort)
    }
    Process
    {
        if ($Index -ne $null)
        {
            Write-Verbose "Finding session with Index $Index"
            foreach($session in $Global:SshSessions)
            {
                Write-Verbose $session.index
                if ($session.index -eq $Index)
                {
                    # Add the forward port object to the session
                    Write-Verbose "Adding Forward Port Configuration to session $Index"
                    $session.session.AddForwardedPort($SSHFWP)
                    $session.session.SendKeepAlive()
                    [System.Threading.Thread]::Sleep(500)
                    Write-Verbose "Starting the Port Forward."
                    $SSHFWP.start()
                    Write-Verbose "Forwarding has been started."
                }
            }
        }
        elseif ($SSHSession)
        {
            if ($SSHSession -in $Global:SshSessions)
            {
                # Add the forward port object to the session
                Write-Verbose "Adding Forward Port Configuration to session $($SSHSession.index)"
                $SSHSession.session.AddForwardedPort($SSHFWP)
                Write-Verbose "Starting the Port Forward."
                $SSHFWP.start()
                Write-Verbose "Forwarding has been started."
            }
            else
            {
                Write-Error "The Session does not appear in the list of created sessions."
            }
        }
    }
    End{}
}#>



<#
.Synopsis
   Get a list of forwarded TCP Ports for a SSH Session
.DESCRIPTION
   Get a list of forwarded TCP Ports for a SSH Session
.EXAMPLE
   Get list of configured forwarded ports
 
    PS C:\> Get-SSHPortForward -Index 0
 
 
    BoundHost : 0.0.0.0
    BoundPort : 8081
    Host : 10.10.10.1
    Port : 80
    IsStarted : True
#>


<#function Get-SSHPortForward
{
    [CmdletBinding(DefaultParameterSetName="Index")]
    param(
 
    [Parameter(Mandatory=$true,
        ParameterSetName = "Session",
        ValueFromPipeline=$true)]
    [Alias("Session")]
    [SSH.SSHSession]$SSHSession,
 
    [Parameter(Mandatory=$true,
        ParameterSetName = "Index",
        ValueFromPipeline=$true)]
    [Int32]$Index
    )
 
     Begin
    {
    }
    Process
    {
        if ($Index -ne $null)
        {
            Write-Verbose "Finding session with Index $Index"
            foreach($session in $Global:SshSessions)
            {
                if ($session.index -eq $Index)
                {
                    Write-Verbose "Session with index $Index found."
                    $session.Session.ForwardedPorts
                }
            }
        }
        elseif ($SSHSession)
        {
            if ($SSHSession -in $Global:SshSessions)
            {
                $SSHSession.Session.ForwardedPorts
            }
            else
            {
                Write-Error "The Session does not appear in the list of created sessions."
            }
        }
    }
    End{}
}#>



<#
.Synopsis
   Stops a configured port forward configured for a SSH Session
.DESCRIPTION
   Stops a configured port forward configured for a SSH Session given the session and port number
.EXAMPLE
   Stop a currently working port forward thru a SSH Session
 
   C:\Users\Carlos> Get-SSHPortForward -Index 0
 
 
    BoundHost : 192.168.1.158
    BoundPort : 8081
    Host : 10.10.10.1
    Port : 80
    IsStarted : True
 
 
 
    C:\Users\Carlos> Stop-SSHPortForward -Index 0 -BoundPort 8081
 
 
    BoundHost : 192.168.1.158
    BoundPort : 8081
    Host : 10.10.10.1
    Port : 80
    IsStarted : False
#>


<#function Stop-SSHPortForward
{
    [CmdletBinding(DefaultParameterSetName="Index")]
    param(
 
    [Parameter(Mandatory=$true,
        ParameterSetName = "Session",
        ValueFromPipeline=$true)]
    [Alias("Session")]
    [SSH.SSHSession]$SSHSession,
 
    [Parameter(Mandatory=$true,
        ParameterSetName = "Index",
        ValueFromPipeline=$true)]
    [Int32]$Index,
 
    [Parameter(Mandatory=$true)]
    [Int32]$BoundPort
    )
 
     Begin
    {
    }
    Process
    {
        if ($Index -ne $null)
        {
            Write-Verbose "Finding session with Index $Index"
            foreach($session in $Global:SshSessions)
            {
                Write-Verbose $session.index
                if ($session.index -eq $Index)
                {
                    $ports = $session.Session.ForwardedPorts
                    foreach($p in $ports)
                    {
                        if ($p.BoundPort -eq $BoundPort)
                        {
                            $p.Stop()
                            $p
                        }
                    }
                }
            }
        }
        elseif ($SSHSession)
        {
            if ($SSHSession -in $Global:SshSessions)
            {
                $ports = $SSHSession.Session.ForwardedPorts
                foreach($p in $ports)
                {
                    if ($p.BoundPort -eq $BoundPort)
                    {
                        $p.Stop()
                        $p
                    }
                }
            }
            else
            {
                Write-Error "The Session does not appear in the list of created sessions."
            }
        }
    }
    End{}
}#>



<#
.Synopsis
   Start a configured port forward configured for a SSH Session
.DESCRIPTION
   Stops a configured port forward configured for a SSH Session given the session and port number
.EXAMPLE
   Stop a currently working port forward thru a SSH Session
 
   C:\Users\Carlos> Get-SSHPortForward -Index 0
 
 
    BoundHost : 192.168.1.158
    BoundPort : 8081
    Host : 10.10.10.1
    Port : 80
    IsStarted : False
 
 
 
    C:\Users\Carlos> Start-SSHPortForward -Index 0 -BoundPort 8081
 
 
    BoundHost : 192.168.1.158
    BoundPort : 8081
    Host : 10.10.10.1
    Port : 80
    IsStarted : True
#>

<#function Start-SSHPortForward
{
    [CmdletBinding(DefaultParameterSetName="Index")]
    param(
 
    [Parameter(Mandatory=$true,
        ParameterSetName = "Session",
        ValueFromPipeline=$true)]
    [Alias("Session")]
    [SSH.SSHSession]$SSHSession,
 
    [Parameter(Mandatory=$true,
        ParameterSetName = "Index",
        ValueFromPipeline=$true)]
    [Int32]$Index,
 
    [Parameter(Mandatory=$true)]
    [Int32]$BoundPort
    )
 
     Begin
    {
    }
    Process
    {
        if ($Index -ne $null)
        {
            Write-Verbose "Finding session with Index $Index"
            foreach($session in $Global:SshSessions)
            {
                Write-Verbose $session.index
                if ($session.index -eq $Index)
                {
                    $ports = $session.Session.ForwardedPorts
                    foreach($p in $ports)
                    {
                        if ($p.BoundPort -eq $BoundPort)
                        {
                            $p.Start()
                            $p
                        }
                    }
                }
            }
        }
        elseif ($SSHSession)
        {
            if ($SSHSession -in $Global:SshSessions)
            {
                $ports = $SSHSession.Session.ForwardedPorts
                foreach($p in $ports)
                {
                    if ($p.BoundPort -eq $BoundPort)
                    {
                        $p.Start()
                        $p
                    }
                }
            }
            else
            {
                Write-Error "The Session does not appear in the list of created sessions."
            }
        }
    }
    End{}
}#>


########################################################################################
# SFTP Functions


<#
.Synopsis
   Get current SFTP Sessions that are available for interaction.
.DESCRIPTION
   Get current SFTP Sessions that are available for interaction.
 
.EXAMPLE
    Get list of current sessions available.
 
    PS C:\> Get-SFTPSession
 
    Index Host Connected
    ----- ---- ---------
      0 192.168.1.155 True
 
.PARAMETER Index
    Index number of Session to retrive.
 
.NOTES
    AUTHOR: Carlos Perez carlos_perez@darkoprator.com
.LINK
    http://sshnet.codeplex.com/
    http://www.darkoperator.com/
#>


function Get-SFTPSession 
{
    [CmdletBinding(DefaultParameterSetName='Index')]
    param( 
        [Parameter(Mandatory=$false)]
        [Int32[]] $Index
    )

    Begin{}
    Process
    {
        if ($Index.Length -gt 0)
        {
            foreach($i in $Index)
            {
                foreach($session in $global:SFTPSessions)
                {
                    if ($session.Index -eq $i)
                    {
                        $session
                    }
                }
            }
        }
        else
        {
            # Can not reference SFTPSessions directly so as to be able
            # to remove the sessions when Remove-Sftpession is used
            $return_sessions = @()
            foreach($s in $Global:SFTPSessions){$return_sessions += $s}
            $return_sessions
        }
    }
    End{}
}


<#
.Synopsis
   Close and Remove a SFTP Session
.DESCRIPTION
   Close and Remove a SFTP Session specified by Index or SFTP Session Object.
.EXAMPLE
   Close a SFTP Session
 
    PS C:\> Remove-SFTPSession -Index 0 -Verbose
    VERBOSE: 0
    VERBOSE: Removing session 0
    True
    VERBOSE: Session 0 Removed
#>


function Remove-SFTPSession
{
    [CmdletBinding(DefaultParameterSetName='Index')]
    param(
        [Parameter(Mandatory=$true,
        ParameterSetName = 'byname',
        ValueFromPipelineByPropertyName=$true)]
        [Int32[]] $Index,

        [Parameter(Mandatory=$false,
        ParameterSetName = 'Session',
        ValueFromPipeline=$true)]
        [Alias('Session')]
        [SSH.SFTPSession[]]$SFTPSession
        )

        Begin{}
        Process
        {
            if ($Index.Count -gt 0)
            {
                $sessions2remove = @()
                 foreach($i in $Index)
                {
                    Write-Verbose $i
                    foreach($session in $Global:SFTPSessions)
                    {
                        if ($session.Index -eq $i)
                        {
                            $sessions2remove += $session
                        }
                    }
                }

                foreach($badsession in $sessions2remove)
                {
                     Write-Verbose "Removing session $($badsession.index)"
                     if ($badsession.session.IsConnected) 
                     { 
                        $badsession.session.Disconnect() 
                     }
                     $badsession.session.Dispose()
                     $Global:SFTPSessions.Remove($badsession)
                     Write-Verbose "Session $($badsession.index) Removed"
                }
            }

            if ($SFTPSession.Count -gt 0)
            {
                $sessions2remove = @()
                 foreach($i in $SFTPSession)
                {
                    foreach($ssh in $global:SFTPSessions)
                    {
                        if ($ssh -eq $i)
                        {
                            $sessions2remove += $ssh
                        }
                    }
                }

                foreach($badsession in $sessions2remove)
                {
                     Write-Verbose "Removing session $($badsession.index)"
                     if ($badsession.session.IsConnected) 
                     { 
                        $badsession.session.Disconnect() 
                     }
                     $badsession.session.Dispose()
                     $Global:SFTPSessions.Remove($badsession)
                     Write-Verbose "Session $($badsession.index) Removed"
                }
            }

        }
        End{}
    
}


<#
.Synopsis
   Get a List of Files for SFTP Session.
.DESCRIPTION
   Get a collection of objection representing files on a given path on a SFTP Session.
.EXAMPLE
   List files in the /tmp path on a remote SFTP Session
 
   C:\Users\Carlos> Get-SFTPDirectoryList -Index 0 -Path "/tmp"
 
 
    FullName : /tmp/vmware-root
    LastAccessTime : 4/13/2013 5:44:56 PM
    LastWriteTime : 4/13/2013 5:44:56 PM
    Length : 4096
    UserId : 0
 
    FullName : /tmp/..
    LastAccessTime : 4/13/2013 5:31:46 PM
    LastWriteTime : 4/13/2013 7:11:05 PM
    Length : 4096
    UserId : 0
 
    FullName : /tmp/vmware-config1
    LastAccessTime : 4/13/2013 5:44:23 PM
    LastWriteTime : 4/13/2013 5:44:23 PM
    Length : 4096
    UserId : 0
 
    FullName : /tmp/.
    LastAccessTime : 4/13/2013 8:11:43 PM
    LastWriteTime : 4/13/2013 8:11:41 PM
    Length : 4096
    UserId : 0
 
    FullName : /tmp/yum.conf.security
    LastAccessTime : 4/13/2013 6:19:22 PM
    LastWriteTime : 4/13/2013 6:19:21 PM
    Length : 865
    UserId : 0
 
    FullName : /tmp/.ICE-unix
    LastAccessTime : 4/13/2013 5:27:15 PM
    LastWriteTime : 4/13/2013 5:27:15 PM
    Length : 4096
    UserId : 0
 
.PARAMETER Index
    Index number of Session to interact with.
 
.PARAMETER Path
    Remote path to list.
 
.NOTES
    AUTHOR: Carlos Perez carlos_perez@darkoprator.com
.LINK
    http://sshnet.codeplex.com/
    http://www.darkoperator.com/
#>


function Get-SFTPDirectoryList
{
    [CmdletBinding(DefaultParameterSetName='Index')]
    param(
        [Parameter(Mandatory=$true,
        ParameterSetName = 'byname',
        ValueFromPipelineByPropertyName=$true)]
        [Int32[]] $Index,

        [Parameter(Mandatory=$true,
        ParameterSetName = 'Session',
        ValueFromPipeline=$true)]
        [Alias('Session')]
        [SSH.SFTPSession[]]$SFTPSession,

        [Parameter(Mandatory=$false)]
        [string]$Path

     )

     Begin
     {
       
     }

     Process
     {
        if ($Index.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $Index)
            {
                foreach($session in $global:SFTPSessions)
                {
                    if ($session.Index -eq $i)
                    {
                        if ($Path -eq $null)
                        {
                            $Path = $session.Session.WorkingDirectory
                        }
                        $session.Session.ListDirectory($Path)
                    }
                 }
            }
        }

        if ($SFTPSession.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $SFTPSession)
            {
                foreach($ssh in $Global:SFTPSessions)
                {
                    if ($ssh -eq $i)
                    {
                        if ($Path -eq $null)
                        {
                            $Path = $ssh.Session.WorkingDirectory
                        }
                        $ssh.Session.ListDirectory($Path)
                    }
                }
             }       
         }
     }
     End{}
}


<#
.Synopsis
   Create Directory on Remote Server via SFTP
.DESCRIPTION
   Create Directory on Remote Server via SFTP specified by Index or SFTP Session Object.
.EXAMPLE
   Create a folder in the /tmp directory on servia via a SFTP Session
 
   PS C:\> New-SFTPDirectory -Index 0 -Path "/tmp/temporaryfolder"
#>


function New-SFTPDirectory
{
    [CmdletBinding(DefaultParameterSetName='Index')]
    param(
        [Parameter(Mandatory=$true,
        ParameterSetName = 'byname',
        ValueFromPipelineByPropertyName=$true)]
        [Int32[]] $Index,

        [Parameter(Mandatory=$true,
        ParameterSetName = 'Session',
        ValueFromPipeline=$true)]
        [Alias('Session')]
        [SSH.SFTPSession[]]$SFTPSession,

        [Parameter(Mandatory=$true)]
        [string]$Path

     )

     Begin{}
     Process
     {
        if ($Index.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $Index)
            {
                foreach($session in $Global:SFTPSessions)
                {
                    if ($session.Index -eq $i)
                    {
                        $session.Session.CreateDirectory($Path)
                    }
                 }
            }
        }

        if ($SFTPSession.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $SFTPSession)
            {
                foreach($ssh in $Global:SFTPSessions)
                {
                    if ($ssh -eq $i)
                    {
                        $ssh.Session.CreateDirectory($Path)
                    }
                }
             }       
         }
     }
     End{}
}


<#
.Synopsis
   Remove Directory on Remote Server via SFTP
.DESCRIPTION
   Remove Directory on Remote Server via SFTP specified by Index or SFTP Session Object.
.EXAMPLE
   Remove a folder in the /tmp directory on servia via a SFTP Session
 
   PS C:\> Remove-SFTPDirectory -Index 0 -Path "/tmp/temporaryfolder"
#>


function Remove-SFTPDirectory
{
    [CmdletBinding(DefaultParameterSetName='Index')]
    param(
        [Parameter(Mandatory=$true,
        ParameterSetName = 'byname',
        ValueFromPipelineByPropertyName=$true)]
        [Int32[]] $Index,

        [Parameter(Mandatory=$true,
        ParameterSetName = 'Session',
        ValueFromPipeline=$true)]
        [Alias('Session')]
        [SSH.SFTPSession[]]$SFTPSession,

        [Parameter(Mandatory=$true)]
        [string]$Path

     )

     Begin{}
     Process
     {
        if ($Index.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $Index)
            {
                foreach($session in $global:SFTPSessions)
                {
                    if ($session.Index -eq $i)
                    {
                        $session.Session.DeleteDirectory($Path)
                    }
                 }
            }
        }

        if ($SFTPSession.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $SFTPSession)
            {
                foreach($ssh in $global:SFTPSessions)
                {
                    if ($ssh -eq $i)
                    {
                        $ssh.Session.DeleteDirectory($Path)
                    }
                }
             }       
         }
     }
     End{}
}


<#
.Synopsis
   Change the current folder location of a SFTP Session
.DESCRIPTION
   Change the current folder location of a SFTP Session specified by Index or SFTP Session Object.
.EXAMPLE
   Change a SFTP Session current folder
 
   PS C:\> Get-SFTPCurrentDirectory -Index 0
    /root
 
    PS C:\> Set-SFTPDirectoryPath -Index 0 -Path "/tmp"
 
    PS C:\> Get-SFTPCurrentDirectory -Index 0
    /tmp
#>


function Set-SFTPDirectoryPath
{
    [CmdletBinding(DefaultParameterSetName='Index')]
    param(
        [Parameter(Mandatory=$true,
        ParameterSetName = 'byname',
        ValueFromPipelineByPropertyName=$true)]
        [Int32[]] $Index,

        [Parameter(Mandatory=$true,
        ParameterSetName = 'Session',
        ValueFromPipeline=$true)]
        [Alias('Session')]
        [SSH.SFTPSession[]]$SFTPSession,

        [Parameter(Mandatory=$true)]
        [string]$Path

     )

     Begin{}
     Process
     {
        if ($Index.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $Index)
            {
                foreach($session in $global:SFTPSessions)
                {
                    if ($session.Index -eq $i)
                    {
                        $session.Session.ChangeDirectory($Path)
                    }
                 }
            }
        }

        if ($SFTPSession.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $SFTPSession)
            {
                foreach($ssh in $global:SFTPSessions)
                {
                    if ($ssh -eq $i)
                    {
                        $ssh.Session.ChangeDirectory($Path)
                    }
                }
             }       
         }
     }
     End{}
}


<#
.Synopsis
   Get the current location of a SFTP Session
.DESCRIPTION
   Get the current location of a SFTP Session specified by Index or SFTP Session Object.
.EXAMPLE
   Get current folder location of a SFTP Session
 
   PS C:\> Get-SFTPCurrentDirectory -Index 0
    /root
#>


function Get-SFTPCurrentDirectory
{
    [CmdletBinding(DefaultParameterSetName='Index')]
    param(
        [Parameter(Mandatory=$true,
        ParameterSetName = 'byname',
        ValueFromPipelineByPropertyName=$true)]
        [Int32[]] $Index,

        [Parameter(Mandatory=$true,
        ParameterSetName = 'Session',
        ValueFromPipeline=$true)]
        [Alias('Session')]
        [SSH.SFTPSession[]]$SFTPSession
     )

     Begin{}
     Process
     {
        if ($Index.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $Index)
            {
                foreach($session in $global:SFTPSessions)
                {
                    if ($session.Index -eq $i)
                    {
                        $session.Session.WorkingDirectory
                    }
                 }
            }
        }

        if ($SFTPSession.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $SFTPSession)
            {
                foreach($ssh in $global:SFTPSessions)
                {
                    if ($ssh -eq $i)
                    {
                        $ssh.Session.WorkingDirectory
                    }
                }
             }       
         }
     }
    End{}
}


<#
.Synopsis
   Download remote file from a SFTP Session
.DESCRIPTION
   Download remote file from a SFTP Session specified by Index or SFTP Session Object
.EXAMPLE
   Download the anaconda configuration file of a remote Red Hat Session via a SFTP Session
 
   PS C:\> Get-SFTPFile -Index 0 -RemoteFile "/root/anaconda-ks.cfg" -LocalPath $env:homepath\Desktop
 
    PS C:\> ls $env:homepath\Desktop -Filter *.cfg
 
 
        Directory: C:\Users\Carlos\Desktop
 
 
    Mode LastWriteTime Length Name
    ---- ------------- ------ ----
    -a--- 4/13/2013 8:40 PM 1337 anaconda-ks.cfg
#>


function Get-SFTPFile
{
    [CmdletBinding(DefaultParameterSetName='Index')]
    param(
        [Parameter(Mandatory=$true,
        ParameterSetName = 'byname',
        ValueFromPipelineByPropertyName=$true)]
        [Int32[]] $Index,

        [Parameter(Mandatory=$true,
        ParameterSetName = 'Session',
        ValueFromPipeline=$true)]
        [Alias('Session')]
        [SSH.SFTPSession[]]$SFTPSession,

        # Full path of file on remote system.
        [Parameter(Mandatory=$true)]
        [string]$RemoteFile,

        # Directory Path to save the file.
        [Parameter(Mandatory=$true)]
        [ValidateScript({Test-Path $_})]
        [string]$LocalPath,

        # Append to start of filename
        [Parameter(Mandatory=$false)]
        [string]$FileNameAppend
     )

     Begin
     {
        
     }
     Process
     {
        if ($Index.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $Index)
            {
                foreach($session in $global:SFTPSessions)
                {
                    if ($session.Index -eq $i)
                    {
                        $FileName = Split-Path $RemoteFile -Leaf
                        $LocalFile = "$((Resolve-Path $LocalPath).Path)\$filename"
                        if ($FileNameAppend)
                        {
                            $FileName = "$($FileNameAppend.Trim())$FileName"
                        }
                        $LocalFileStream = [System.IO.File]::Create($LocalFile)
                        $session.Session.DownloadFile($RemoteFile, $LocalFileStream)
                        $LocalFileStream.Flush()
                        $LocalFileStream.Close()
                    }
                 }
            }
        }

        if ($SFTPSession.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $SFTPSession)
            {
                foreach($ssh in $global:SFTPSessions)
                {
                    if ($ssh -eq $i)
                    {
                        $FileName = Split-Path $RemoteFile -Leaf
                        $LocalFile = "$((Resolve-Path $LocalPath).Path)\$filename"
                        if ($FileNameAppend)
                        {
                            $FileName = "$($FileNameAppend.Trim())$FileName"
                        }
                        $LocalFileStream = [System.IO.File]::Create($LocalFile)
                        $ssh.Session.DownloadFile($RemoteFile, $LocalFileStream)
                        $LocalFileStream.Flush()
                        $LocalFileStream.Close()
                    }
                }
             }       
         }
     }
    End{}
}


<#
.Synopsis
   Upload local file using a SFTP Session to remote system
.DESCRIPTION
   Upload local file using a SFTP Session to remote system given the local file
   and remote path to place the file. The session can be specified by session index or
   a SFTP Session object.
.EXAMPLE
    Upload local file in to remote system /tmp directory
 
    PS C:\> Set-SFTPFile -Index 0 -RemotePath "/tmp" -LocalFile $env:homepath\Desktop\anaconda-ks.cfg -Verbose
    VERBOSE: Uploading \Users\Carlos\Desktop\anaconda-ks.cfg as /tmp/anaconda-ks.cfg
    VERBOSE: Successfully Uploaded file to /tmp/anaconda-ks.cfg
#>


function Set-SFTPFile
{
    [CmdletBinding(DefaultParameterSetName='Index')]
    param(
        [Parameter(Mandatory=$true,
        ParameterSetName = 'byname',
        ValueFromPipelineByPropertyName=$true)]
        [Int32[]] $Index,

        [Parameter(Mandatory=$true,
        ParameterSetName = 'Session',
        ValueFromPipeline=$true)]
        [Alias('Session')]
        [SSH.SFTPSession[]]$SFTPSession,

        # Full path of where to upload file on remote system.
        [Parameter(Mandatory=$true)]
        [string]$RemotePath,

        # Local File to upload to remote host.
        [Parameter(Mandatory=$true)]
        [ValidateScript({Test-Path $_})]
        [string]$LocalFile
     )

     Begin
     {
        
     }
     Process
     {
        if ($Index.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $Index)
            {
                foreach($session in $global:SFTPSessions)
                {
                    if ($session.Index -eq $i)
                    {
                        $LocalFileName = Split-Path $LocalFile -Leaf
                        $RemoteFile = "$RemotePath/$LocalFileName"
                        Write-Verbose "Uploading $LocalFile as $RemoteFile"
                        $LocalFileStream = [System.IO.File]::OpenRead((resolve-path $LocalFile).path)
                        $session.Session.UploadFile($LocalFileStream, $RemoteFile)
                        $LocalFileStream.Close()
                        Write-Verbose "Successfully Uploaded file to $RemoteFile"
                    }
                 }
            }
        }

        if ($SFTPSession.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $SFTPSession)
            {
                foreach($ssh in $global:SFTPSessions)
                {
                    if ($ssh -eq $i)
                    {
                        $LocalFileName = Split-Path $LocalFile -Leaf
                        $RemoteFile = "$RemotePath/$LocalFileName"
                        Write-Verbose "Uploading $LocalFile as $RemoteFile"
                        $LocalFileStream = [System.IO.File]::OpenRead($LocalFile)
                        $ssh.Session.UploadFile( $LocalFileStream, $RemoteFile)
                        $LocalFileStream.Close()
                        Write-Verbose "Successfully Uploaded file to $RemoteFile"
                    }
                }
             }       
         }
     }
    End{}
}


<#
.Synopsis
   Deletes a file on a remote system via a SFTP Session
.DESCRIPTION
   Deletes a file on a remote system via a SFTP Session specified by index or SFTP Session object.
.EXAMPLE
   Deleting file on /tmp directory.
     
    PS C:\> Remove-SFTPFile -Index 0 -RemoteFile "/tmp/anaconda-ks.cfg" -Verbose
    VERBOSE: Deleting /tmp/anaconda-ks.cfg
    VERBOSE: Deleted /tmp/anaconda-ks.cfg
#>


function Remove-SFTPFile
{
    [CmdletBinding(DefaultParameterSetName='Index')]
    param(
        [Parameter(Mandatory=$true,
        ParameterSetName = 'byname',
        ValueFromPipelineByPropertyName=$true)]
        [Int32[]] $Index,

        [Parameter(Mandatory=$true,
        ParameterSetName = 'Session',
        ValueFromPipeline=$true)]
        [Alias('Session')]
        [SSH.SFTPSession[]]$SFTPSession,

        # Full path of where to upload file on remote system.
        [Parameter(Mandatory=$true)]
        [string]$RemoteFile
     )

     Begin
     {
        
     }
     Process
     {
        if ($Index.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $Index)
            {
                foreach($session in $global:SFTPSessions)
                {
                    if ($session.Index -eq $i)
                    {
                        Write-Verbose "Deleting $RemoteFile"
                        $session.Session.DeleteFile($RemoteFile)
                        Write-Verbose "Deleted $RemoteFile"
                    }
                 }
            }
        }

        if ($SFTPSession.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $SFTPSession)
            {
                foreach($ssh in $global:SFTPSessions)
                {
                    if ($ssh -eq $i)
                    {
                        Write-Verbose "Deleting $RemoteFile"
                        $ssh.Session.DeleteFile($RemoteFile)
                        Write-Verbose "Deleted $RemoteFile"
                    }
                }
             }       
         }
     }
    End{}
}


<#
.Synopsis
   Move or Rename remote file via a SFTP Session
.DESCRIPTION
   Move or Rename remote file via a SFTP Session specified by index or SFTP Session object.
.EXAMPLE
   Rename file by moving it
 
    PS C:\> Move-SFTPFile -Index 0 -OriginalPath /tmp/anaconda-ks.cfg -NewPath /tmp/anaconda-ks.cfg.old -Verbose
    VERBOSE: Renaming /tmp/anaconda-ks.cfg to /tmp/anaconda-ks.cfg.old
    VERBOSE: File renamed
#>


function Move-SFTPFile
{
    [CmdletBinding(DefaultParameterSetName='Index')]
    param(
        [Parameter(Mandatory=$true,
        ParameterSetName = 'byname',
        ValueFromPipelineByPropertyName=$true)]
        [Int32[]] $Index,

        [Parameter(Mandatory=$true,
        ParameterSetName = 'Session',
        ValueFromPipeline=$true)]
        [Alias('Session')]
        [SSH.SFTPSession[]]$SFTPSession,

        [Parameter(Mandatory=$true)]
        [string]$OriginalPath,

        [Parameter(Mandatory=$true)]
        [string]$NewPath
     )

     Begin
     {
        
     }
     Process
     {
        if ($Index.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $Index)
            {
                foreach($session in $global:SFTPSessions)
                {
                    if ($session.Index -eq $i)
                    {
                        Write-Verbose "Renaming $OriginalPath to $NewPath"
                        $session.Session.RenameFile($OriginalPath, $NewPath)
                        Write-Verbose 'File renamed'
                    }
                 }
            }
        }

        if ($SFTPSession.Count -gt 0)
        {
            $sessions2remove = @()
            foreach($i in $SFTPSession)
            {
                foreach($ssh in $global:SFTPSessions)
                {
                    if ($ssh -eq $i)
                    {
                        Write-Verbose "Renaming $OriginalPath to $NewPath"
                        $ssh.Session.RenameFile($OriginalPath, $NewPath)
                        Write-Verbose 'File renamed'
                    }
                }
             }       
         }
     }
    End{}
}


 <#
 .Synopsis
    Gets the current installed version and the latest version of Posh-SSH.
 .DESCRIPTION
    Gets the current installed version and the latest version of Posh-SSH.
 .EXAMPLE
     Get-PoshSecModVersion
 
InstalledVersion CurrentVersion
---------------- --------------
1.1 1.1
 
 #>

 function Get-PoshSSHModVersion
 {
     [CmdletBinding(DefaultParameterSetName='Index')]
     [OutputType([pscustomobject])]
     Param
     ()
 
     Begin
     {
        $currentversion = ''
        $installed = Get-Module -Name 'posh-SSH' -ListAvailable
     }
     Process
     {
        $webClient = New-Object System.Net.WebClient
        Try
        {
            $current = Invoke-Expression  $webClient.DownloadString('https://raw.github.com/darkoperator/Posh-SSH/master/Posh-SSH.psd1')
            $currentversion = $current.moduleversion
        }
        Catch
        {
            Write-Warning 'Could not retrieve the current version.'
        }
        $majorver,$minorver = $currentversion.split('.')

        if ($majorver -gt $installed.Version.Major)
        {
            Write-Warning 'You are running an outdated version of the module.'
        }
        elseif ($minorver -gt $installed.Version.Minor)
        {
            Write-Warning 'You are running an outdated version of the module.'
        } 
        
        $props = @{
            InstalledVersion = $installed.Version.ToString()
            CurrentVersion   = $currentversion
        }
        New-Object -TypeName psobject -Property $props
     }
     End
     {
          
     }
 }

 <#
 .Synopsis
    List Host and Fingerprint pairs that Posh-SSH trusts.
 .DESCRIPTION
    List Host and Fingerprint pairs that Posh-SSH trusts.
 .EXAMPLE
Get-SSHTrustedHost
 
SSHHost Fingerprint
------- -----------
192.168.1.143 a4:6e:80:33:3f:32:4:cb:be:e9:a0:80:1b:38:fd:3b
192.168.10.3 27:ca:f8:39:7e:ba:a:ff:a3:2d:ff:75:16:a6:bc:18
192.168.1.225 ea:8c:ec:93:1e:9d:ad:2e:41:bc:d0:b3:d8:a9:98:80
 
 #>

 function Get-SSHTrustedHost
 {
     [CmdletBinding(DefaultParameterSetName='Index')]
     [OutputType([int])]
     Param
     ()
 
     Begin
     {
     }
     Process
     {
        $poshsshkey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Software\PoshSSH', $true)

        $hostnames = $poshsshkey.GetValueNames()
        $TrustedHosts = @()
        foreach($h in $hostnames)
        {
            $TrustedHost = @{
                SSHHost        = $h
                Fingerprint = $poshsshkey.GetValue($h)
            }
            $TrustedHosts += New-Object -TypeName psobject -Property $TrustedHost
        }
     }
     End
     {
        $TrustedHosts
     }
 }


 <#
 .Synopsis
    Adds a new SSH Host and Fingerprint pait to the list of trusted SSH Hosts.
 .DESCRIPTION
    Adds a new SSH Host and Fingerprint pait to the list of trusted SSH Hosts.
 .EXAMPLE
    New-SSHTrustedHost -SSHHost 192.168.10.20 -FingerPrint a4:6e:80:33:3f:31:4:cb:be:e9:a0:80:fb:38:fd:3b -Verbose
VERBOSE: Adding to trusted SSH Host list 192.168.10.20 with a fingerprint of a4:6e:80:33:3f:31:4:cb:be:e9:a0:80:fb:38:fd:3b
VERBOSE: SSH Host has been added.
 #>

 function New-SSHTrustedHost
 {
     [CmdletBinding(DefaultParameterSetName='Index')]
     Param
     (
         # IP Address of FQDN of host to add to trusted list.
         [Parameter(Mandatory=$true,
                    ValueFromPipelineByPropertyName=$true,
                    Position=0)]
         $SSHHost,
 
         # SSH Server Fingerprint.
         [Parameter(Mandatory=$true,
                    ValueFromPipelineByPropertyName=$true,
                    Position=1)]
         $FingerPrint
     )
 
     Begin
     {
     }
     Process
     {
        $softkey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Software')
        if ( $softkey.GetSubKeyNames() -contains 'PoshSSH')
        {
            $poshsshkey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Software\PoshSSH', $true)
        }
        else
        {
            Write-Verbose 'PoshSSH Registry key has not Present for this user.'
            $softkey.CreateSubKey('PoshSSH')
            Write-Verbose 'PoshSSH Key created.'
            $poshsshkey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Software\PoshSSH', $true)
        }
        Write-Verbose "Adding to trusted SSH Host list $($SSHHost) with a fingerprint of $($FingerPrint)"
        $poshsshkey.SetValue($SSHHost, $FingerPrint)
        Write-Verbose 'SSH Host has been added.'
     }
     End
     {
     }
 }

 <#
 .Synopsis
    Removes a given SSH Host from the list of trusted hosts.
 .DESCRIPTION
    Removes a given SSH Host from the list of trusted hosts.
 .EXAMPLE
    Remove-SSHTrustedHost -SSHHost 192.168.10.20 -Verbose
VERBOSE: Removing SSH Host 192.168.10.20 from the list of trusted hosts.
VERBOSE: SSH Host has been removed.
 #>

 function Remove-SSHTrustedHost
 {
     [CmdletBinding(DefaultParameterSetName='Index')]
     Param
     (
         # Param1 help description
         [Parameter(Mandatory=$true,
                    ValueFromPipelineByPropertyName=$true,
                    Position=0)]
         $SSHHost
     )
 
     Begin
     {
     }
     Process
     {
        $softkey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Software')
        if ($softkey.GetSubKeyNames() -contains 'PoshSSH' )
        {
            $poshsshkey = [Microsoft.Win32.Registry]::CurrentUser.OpenSubKey('Software\PoshSSH', $true)
        }
        else
        {
            Write-warning 'PoshSSH Registry key has not Present for this user.'
            return
        }
        Write-Verbose "Removing SSH Host $($SSHHost) from the list of trusted hosts."
        if ($poshsshkey.GetValueNames() -contains $SSHHost)
        {
            $poshsshkey.DeleteValue($SSHHost)
            Write-Verbose 'SSH Host has been removed.'
        }
        else
        {
            Write-Warning "SSH Hosts $($SSHHost) was not present in the list of trusted hosts." 
        }
     }
     End
     {
     }
 }

if (!(Test-Path variable:Global:SshSessions ))
{
    $global:SshSessions = New-Object System.Collections.ArrayList
}

if (!(Test-Path variable:Global:SFTPSessions ))
{
    $global:SFTPSessions = New-Object System.Collections.ArrayList
}