Using WinSCP .NET Assembly from Perl (ActivePerl)

This article is based on ActivePerl Perl distribution.

Advertisement

Installing and Registering for COM

First, you need to install the WinSCP .NET assembly and register it for COM.

Using from Perl (ActivePerl)

You use WinSCP .NET assembly from Perl as any other COM library (In this example we are using Win32::OLE package).

Though there are some less known techniques and peculiarities that you may need to use, which are described in following sections.

Accessing Enumeration Values

As Perl accesses COM classes via IDispatch, it does not make use of type library, hence it does not have direct access to constants defined there, like Protocol.Sftp for instance.

One of several ways to use these constants is to use Win32::OLE::Const->Load method. It returns hash array of all enum members from type library, with keys like <type>_<member>, e.g. Protocol.Sftp becomes Protocol_Sftp.

Following example shows how to access Protocol_Sftp constant:

use Win32::OLE;
use Win32::OLE::Const;
use Win32::OLE::Variant;
 
Win32::OLE->Initialize(Win32::OLE::COINIT_OLEINITIALIZE);
my $session = Win32::OLE->new('WinSCP.Session');
 
my $consts = Win32::OLE::Const->Load($session);
 
my $sessionOptions = Win32::OLE->new('WinSCP.SessionOptions');
 
$sessionOptions->{'Protocol'} = $consts->{'Protocol_Sftp'};
$sessionOptions->{'HostName'} = 'example.com';
$sessionOptions->{'UserName'} = 'user';
$sessionOptions->{'Password'} = 'mypassword';
$sessionOptions->{'SshHostKeyFingerprint'} = 'ssh-rsa 2048 xxxxxxxxxxx...';

Advertisement

Event Handlers

The Session class exposes several events.

If you need to make use of these events:

  • Define event handling function that takes arguments object, event and array of event arguments;
  • Make it handle the event you need by comparing value of event argument against names of the Session events (e.g. FileTransferred);
  • Associate the event handling function with an instance of Session class using Win32::OLE->WithEvents mehod.

See following code snippet:

use feature qw(switch); # in order to use given
 
sub session_Events()
{
    my ($obj, $event, @args) = @_;
 
    given ($event)
    {
        when ('FileTransferred')
        {
            my ($sender, $e) = @args;
            printf "%s => %s\n", ( $e->{'FileName'}, $e->{'Destination'} );
        }
    }
}
 
my $session = Win32::OLE->new('WinSCP.Session');
Win32::OLE->WithEvents($session, \&session_Events);

Boolean Arguments

Some arguments of the assembly methods are of Boolean type. They do not accept integer values 0 or 1. Use Win32::OLE::Variant instead, e.g. Variant(VT_BOOL, 1).

You can define constants TRUE and FALSE for use with the assembly:

use Win32::OLE::Variant;
 
use constant
{
    TRUE  => Variant(VT_BOOL, 1),
    FALSE => Variant(VT_BOOL, 0)
};

Example

This example is functionally equivalent to overall C# example for WinSCP .NET assembly.

Advertisement

use strict;
use warnings;
 
use Win32::OLE;
use Win32::OLE::Const;
use Win32::OLE::Variant;
 
use constant
{
    TRUE  => Variant(VT_BOOL, 1),
    FALSE => Variant(VT_BOOL, 0)
};
 
my $session = Win32::OLE->new('WinSCP.Session');
 
# Load constants
my $consts = Win32::OLE::Const->Load($session);
 
# Setup session options
my $sessionOptions = Win32::OLE->new('WinSCP.SessionOptions');
 
$sessionOptions->{'Protocol'} = $consts->{'Protocol_Sftp'};
$sessionOptions->{'HostName'} = 'example.com';
$sessionOptions->{'UserName'} = 'user';
$sessionOptions->{'Password'} = 'mypassword';
$sessionOptions->{'SshHostKeyFingerprint'} = 'ssh-rsa 2048 xxxxxxxxxxx...';
 
# Connect
$session->Open($sessionOptions);
 
# Upload files
my $transferOptions = Win32::OLE->new('WinSCP.TransferOptions');
$transferOptions->{'TransferMode'} = $consts->{'TransferMode_Binary'};
 
my $transferResult =
    $session->PutFiles('d:\\toupload\\*', '/home/user/', FALSE, $transferOptions);
 
# Throw on any error
$transferResult->Check();
 
# Print results
my $items = Win32::OLE::Enum->new($transferResult->{'Transfers'});
my $item;
while (defined($item = $items->Next))
{
    print $item->{'FileName'} . "\n";
}

Last modified: by martin