Differences

This shows you the differences between the selected revisions of the page.

library_powershell 2014-12-23 library_powershell 2023-10-30 (current)
Line 1: Line 1:
====== Using WinSCP .NET Assembly from PowerShell ====== ====== Using WinSCP .NET Assembly from PowerShell ======
-===== About PowerShell ===== +===== [[powershell]] About PowerShell ===== 
-[[wp>Windows_PowerShell|Windows PowerShell]] is Microsoft's task automation framework, consisting of a command-line shell and associated scripting language built on .NET Framework.+[[wp>PowerShell|PowerShell]] is Microsoft's task automation framework, consisting of a command-line shell and associated scripting language built on .NET.
-PowerShell is built into Windows 7 and newer; and is optionally available for Windows 98 SP2 and newer.((&wikipedia_ref(Windows_PowerShell|Windows PowerShell))) &win9x+Windows PowerShell (''powershell.exe'') is built into Windows 7 and newer; and is optionally available for Windows 98 SP2 and newer.((&wikipedia_ref(PowerShell|PowerShell))) &win9x It uses .NET Framework. Its successor, PowerShell (''pwsh.exe''), previously known as PowerShell Core, aka PowerShell 6/7, is cross-platform and can be optionally installed in Windows. It uses .NET (previously known as .NET Core).
PowerShell scripts can be directly executed, they do not need to be compiled first. PowerShell scripts can be directly executed, they do not need to be compiled first.
-===== PowerShell Scripting =====+===== [[scripting]] PowerShell Scripting =====
-From WinSCP scripting perspective, important aspect of PowerShell (''powershell.exe'') is its ability to run simple, yet powerful, scripts that can make use functionality exposed by WinSCP .NET assembly.+From WinSCP scripting perspective, an important aspect of PowerShell is its ability to run simple, yet powerful, scripts that can make use of functionality exposed by WinSCP .NET assembly.
-The ''powershell.exe'' is located in ''%WINDIR%\System32\WindowsPowershell\v1.0''.((It's ''v1.0'', disregarding what version you actually use.)) Typically you run ''powershell.exe'' with ''-File'' argument followed by path to your PowerShell script. The script file needs to have ''.ps1'' extension:+Windows PowerShell's ''powershell.exe'' is located in ''%WINDIR%\System32\WindowsPowershell\v1.0''.((It's ''v1.0'', disregarding what version you actually use.)) Typically you run ''powershell.exe'' with ''-File'' argument followed by path to your PowerShell script. The script file needs to have ''.ps1'' extension:
<code> <code>
Line 18: Line 18:
</code> </code>
-Note that by default, executing PowerShell scripts is disabled. To override that, you can either lift the restriction by typing using ''[[http://technet.microsoft.com/en-us/library/hh849812.aspx|Set-ExecutionPolicy]]'' cmdlet on PowerShell administrator console((Run ''powershell.exe'' as Administrator to get PowerShell console.)):+PowerShell (Core)'s ''pwsh.exe'' installs into ''C:\Program Files\PowerShell\<version>''. 
 + 
 +Note that by default, executing PowerShell scripts is disabled. To override that, you can either lift the restriction by typing using ''[[ps&gt;microsoft.powershell.security/set-executionpolicy|Set-ExecutionPolicy]]'' cmdlet on PowerShell administrator console:((Run ''powershell.exe'' as Administrator to get PowerShell console.))
<code powershell> <code powershell>
Line 30: Line 32:
</code> </code>
-===== Installing the Assembly ===== +===== [[install]] Installing the Assembly ===== 
-First, you need to [[library_install|install the WinSCP·.NET assembly]].((You do not need to register the assembly for COM, as PowerShell can use .NET assemblies directly.))+First, you need to install the WinSCP .NET assembly. In most cases, all you need to do is [[library_install#downloading|download]] the ''WinSCP-X.X.X-Automation.zip'' package((In some cases, the downloaded [[message_net_operation_not_supported|executables need to be unblocked]].)) and extract it along with your PowerShell script.((Generally you only need ''WinSCPnet.dll'' and ''WinSCP.exe''.)) 
 + 
 +The version of ''WinSCPnet.dll'' in the root of the package is the .NET Framework build of the assembly. It can be used with Windows PowerShell only. With PowerShell (Core) 6/7, you have to use the .NET Standard build of the assembly, which is located in the ''netstandard2.0'' subfolder.  
 + 
 +For specific cases, read full instructions to [[library_install|installing the WinSCP .NET assembly]].
===== Using from PowerShell ===== ===== Using from PowerShell =====
Line 38: Line 44:
Though there are some less known techniques and peculiarities that you may need to use, which are described in following sections. Though there are some less known techniques and peculiarities that you may need to use, which are described in following sections.
-==== Loading Assembly ==== +==== [[loading]] Loading Assembly ==== 
-PowerShell script needs to load the assembly before it can use classes the assembly exposes. To load assembly use ''[[http://technet.microsoft.com/en-us/library/hh849914.aspx|Add-Type]]'' cmdlet.((In PowerShell 1.0, use ''[[msdn>System.Reflection.Assembly.LoadFrom]]'' method.))+PowerShell script needs to load the assembly before it can use classes the assembly exposes. To load assembly use ''[[ps&gt;microsoft.powershell.utility/add-type|Add-Type]]'' cmdlet.((In PowerShell 1.0, use ''[[dotnet>System.Reflection.Assembly.LoadFrom]]'' method.))
<code powershell> <code powershell>
Line 45: Line 51:
</code> </code>
-Had you need to run the script from other directory, you need to specify a full path to the assembly. You can derive the path from the script file path using ''[[http://technet.microsoft.com/en-us/library/hh847768.aspx|$PSScriptRoot]]'' automatic variable:((In PowerShell 1.0 and 2.0, use ''%%Add-Type -Path (Join-Path (Split-Path $script:MyInvocation.MyCommand.Path) "WinSCPnet.dll")%%''))+Had you need to run the script from other directory, you need to specify a full path to the assembly. You can derive the path from the script file path using [[ps&gt;microsoft.powershell.core/about/about_automatic_variables#psscriptroot|''$PSScriptRoot'' automatic variable]]:((In PowerShell 2.0, use ''%%Add-Type -Path (Join-Path (Split-Path $script:MyInvocation.MyCommand.Path) "WinSCPnet.dll")%%''))
<code powershell> <code powershell>
Add-Type -Path (Join-Path $PSScriptRoot "WinSCPnet.dll") Add-Type -Path (Join-Path $PSScriptRoot "WinSCPnet.dll")
 +</code>
 +
 +If you are writing a script that you plan to use as a [[extension|WinSCP extension]] (a [[custom_command|custom command]]), you can use the copy of the assembly installed with WinSCP. In that case you can use the ''WINSCP_PATH'' environment variable to resolve the path to the assembly. To allow the script run even outside of WinSCP, you should fall back to the ''$PSScriptRoot'' approach (as above), if the variable is not defined:
 +
 +<code powershell>
 +$assemblyPath = if ($env:WINSCP_PATH) { $env:WINSCP_PATH } else { $PSScriptRoot }
 +Add-Type -Path (Join-Path $assemblyPath "WinSCPnet.dll")
</code> </code>
Line 56: Line 69:
Enumeration values are accessed using static field syntax ''%%[Namespace.Type]::Member%%'', for example ''[WinSCP.Protocol]::Sftp''. Enumeration values are accessed using static field syntax ''%%[Namespace.Type]::Member%%'', for example ''[WinSCP.Protocol]::Sftp''.
-==== Event Handlers ====+==== [[event_handlers]] Event Handlers ====
The ''[[library_session|Session]]'' class exposes several [[library_session#events|events]]. The ''[[library_session|Session]]'' class exposes several [[library_session#events|events]].
If you need to make use of these events: If you need to make use of these events:
  * Define event handling function;   * Define event handling function;
-  * Associate the event handling function with an instance of ''Session'' class using ''.add_Event'' method, where ''Event'' is a name of the event.((Avoid using ''[[http://technet.microsoft.com/en-us/library/hh849929.aspx|Register-ObjectEvent]]'' cmdlet, as it introduces threading problems and possible crashes.))+  * Associate the event handling function with an instance of ''Session'' class using ''.add_Event'' method, where ''Event'' is a name of the event.((Avoid using ''[[ps&gt;microsoft.powershell.utility/register-objectevent|Register-ObjectEvent]]'' cmdlet, as it introduces threading problems and possible crashes.)) 
 +  * If you need to disassociate the event handling function later, use ''.remove_Event'' method.
See following code snippet: See following code snippet:
Line 72: Line 86:
    if ($e.Error -eq $Null)     if ($e.Error -eq $Null)
    {     {
-        Write-Host ("Transfer of {0} succeeded" -f $e.FileName)+        Write-Host "Transfer of $($e.FileName) succeeded"
    }     }
    else     else
    {     {
-        Write-Host ("Transfer of {0} failed: {1}" -f $e.FileName, $e.Error)+        Write-Host "Transfer of $($e.FileName) failed: $($e.Error)"
    }     }
} }
Line 87: Line 101:
==== [[module]] PowerShell Module ==== ==== [[module]] PowerShell Module ====
-There is a third-party PowerShell module, [[http://dotps1.github.io/WinSCP/|WinSCP PowerShell Wrapper]], that provides a cmdlet interface on top of the .NET assembly.+There is a third-party PowerShell module, [[https://github.com/tomohulk/WinSCP|WinSCP PowerShell Wrapper]], that provides a cmdlet interface on top of the .NET assembly.
Example: Example:
<code powershell> <code powershell>
-# Define the options for the WinSCP Session. +# Set credentials to a PSCredential Object. 
-$options = New-WinSCPSessionOptions -Hostname "example.com" -Username &quot;user" -Password "mypassword" -SshHostKeyFingerprint "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx" +$credential = Get-Credential 
-# Open the WinSCP Session with the defined options. +# Create a WinSCP Session. 
-$session = Open-WinSCPSession -SessionOptions $options +$session = New-WinSCPSession -Hostname "example.com" -Credential $credential -SshHostKeyFingerprint "ssh-rsa 2048 xxxxxxxxxxx...
-# Using the open WinSCPSession, download the file from the remote host to the local host. +# Using the WinSCPSession, download the file from the remote host to the local host. 
-Receive-WinSCPItem -WinSCPSession $session -RemoteItem "/home/user/file.txt" -LocalItem "C:\download\" +Receive-WinSCPItem -WinSCPSession $session -Path "/home/user/file.txt" -Destination "C:\download\" 
-# Close the WinSCPSession after completion. +# Remove the WinSCPSession after completion. 
-Close-WinSCPSession -WinSCPSession $session+Remove-WinSCPSession -WinSCPSession $session
</code> </code>
Line 105: Line 119:
<code powershell> <code powershell>
-# Piping the WinSCPSession into the Receive-WinSCPItem auto disposes the object after completion. +# Piping the WinSCPSession into the Receive-WinSCPItem auto disposes the WinSCP.Session object after completion. 
-Open-WinSCPSession -SessionOptions (New-WinSCPSessionOptions -Hostname "example.com" -Username &quot;user" -Password &quot;mypassword" -SshHostKeyFingerprint "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx") |  +New-WinSCPSession -Hostname "example.com" -Credential (Get-Credential) -SshHostKeyFingerprint "ssh-rsa 2048 xxxxxxxxxxx...") |  
-    Receive-WinSCPItem -RemoteItem "/home/user/file.txt" -LocalItem "C:\download\"+    Receive-WinSCPItem -Path "/home/user/file.txt" -Destination "C:\download\"
</code> </code>
-===== Example =====+===== [[example]] Example =====
This example is functionally equivalent to [[library#example|overall C# example for WinSCP .NET assembly]]. This example is functionally equivalent to [[library#example|overall C# example for WinSCP .NET assembly]].
Line 122: Line 136:
    # Setup session options     # Setup session options
-    $sessionOptions = New-Object WinSCP.SessionOptions +    $sessionOptions = New-Object WinSCP.SessionOptions -Property @{ 
- ···$sessionOptions.Protocol = [WinSCP.Protocol]::Sftp +········Protocol = [WinSCP.Protocol]::Sftp 
-   $sessionOptions.HostName = "example.com" + ·······HostName = "example.com" 
-   $sessionOptions.UserName = "user" + ·······UserName = "user" 
-   $sessionOptions.Password = "mypassword" + ·······Password = "mypassword" 
-   $sessionOptions.SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"+ ·······SshHostKeyFingerprint = "ssh-rsa 2048 xxxxxxxxxxx..." 
 +    }
    $session = New-Object WinSCP.Session     $session = New-Object WinSCP.Session
Line 140: Line 155:
        $transferOptions.TransferMode = [WinSCP.TransferMode]::Binary         $transferOptions.TransferMode = [WinSCP.TransferMode]::Binary
-        $transferResult = $session.PutFiles("b:\toupload\*", "/home/user/", $False, $transferOptions)+        $transferResult = 
 + ···········$session.PutFiles("d:\toupload\*", "/home/user/", $False, $transferOptions)
        # Throw on any error         # Throw on any error
Line 148: Line 164:
        foreach ($transfer in $transferResult.Transfers)         foreach ($transfer in $transferResult.Transfers)
        {         {
-            Write-Host ("Upload of {0} succeeded" -f $transfer.FileName)+            Write-Host "Upload of $($transfer.FileName) succeeded"
        }         }
    }     }
Line 159: Line 175:
    exit 0     exit 0
} }
-catch [Exception]+catch
{ {
-    Write-Host $_.Exception.Message+    Write-Host "Error: $($_.Exception.Message)"
    exit 1     exit 1
} }

Last modified: by martin