Differences
This shows you the differences between the selected revisions of the page.
| library_powershell 2014-10-01 | 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>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>microsoft.powershell.utility/add-type|Add-Type]]'' cmdlet.((In PowerShell 1.0, use ''[[dotnet>System.Reflection.Assembly.LoadFrom]]'' method.)) |
| <code powershell> | <code powershell> | ||
| Add-Type -Path "WinSCPnet.dll" | Add-Type -Path "WinSCPnet.dll" | ||
| </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 [[ps>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> | ||
| + | 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> | ||
| + | |||
| + | |||
| ==== [[enums]] Accessing Enumeration Values ==== | ==== [[enums]] Accessing Enumeration Values ==== | ||
| 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>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 60: | Line 82: | ||
| function FileTransferred | function FileTransferred | ||
| { | { | ||
| - | Param($e) | + | param($e) |
| 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 79: | 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 "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 97: | 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 "user" -Password "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 114: | 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 132: | 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 140: | 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 151: | Line 175: | ||
| exit 0 | exit 0 | ||
| } | } | ||
| - | catch [Exception] | + | catch |
| { | { | ||
| - | Write-Host $_.Exception.Message | + | Write-Host "Error: $($_.Exception.Message)" |
| exit 1 | exit 1 | ||
| } | } | ||