Perl WinSCP .Net Assembly Script via Win32::OLE , Sort the Output by File Name or Mod Date?

Advertisement

jpantera
Joined:
Posts:
29
Location:
Los Angeles, CA

Perl WinSCP .Net Assembly Script via Win32::OLE , Sort the Output by File Name or Mod Date?

Hello Martin & WinSCP Support,

I have a Perl script that is succesfuly pulling in all of the WinSCP data for an SFTP site I'm downloading files from.

Open a session via a Perl script that uses Win32::OLE:
Win32::OLE->Initialize(Win32::OLE::COINIT_OLEINITIALIZE);
my $session = Win32::OLE->new('WinSCP.Session') || warn "Can't create winscp session: ", Win32::OLE->LastError;
my $consts = Win32::OLE::Const->Load($session);
my $sessionOptions = Win32::OLE->new('WinSCP.SessionOptions')|| die "Can't open winscp session Options: ", Win32::OLE->LastError;
$sessionOptions->{'Protocol'} = $consts->{'Protocol_Sftp'};
$sessionOptions->{'HostName'} = $ProgramRemoteSFTPSettings::RemoteSFTPServer;
$sessionOptions->{'UserName'} = $ProgramRemoteSFTPSettings::DOWNLOAD_USER;
$sessionOptions->{'Password'} = $ProgramRemoteSFTPSettings::DOWNLOAD_USERPASSWD;
$sessionOptions->{'SshHostKeyFingerprint'} = $ProgramRemoteSFTPSettings::DestServerFingerPrintKey;
 
$session->Open($sessionOptions);
my $directory = $session->ListDirectory("${FileContent::FileSFTPLoc[$i]}");
my $items = Win32::OLE::Enum->new($directory->{'Files'});
my $item;
while (defined($item = $items->Next))
{
  my $FilePermissionsHash = $item->{'FilePermissions'};
  my $FilePermissions = $FilePermissionsHash->{'Text'};
}
Is there an easy way to sort the list of files that come from this, via Perl Win32::OLE, without extrapolating all of the data into date or file name logic?

I see your examples with PowerShell:

For sort the file for example by time, use:
$directory = $session.ListDirectory($remotePath)
$files = $directory.Files | Sort-Object LastWriteTime -Descending
foreach ($fileInfo in $files)
{
    ...
}
How can I replicate the $files = $directory.Files | Sort-Object LastWriteTime -Descending?

thanks,
Joe P.

Reply with quote

Advertisement

martin
Site Admin
martin avatar
Joined:
Posts:
42,011
Location:
Prague, Czechia

Re: Perl WinSCP .Net Assembly Script via Win32::OLE , Sort the Output by File Name or Mod Date?

This seems to be rather Perl question, so you will not have much luck asking here.
I also do not understand what you mean by "without extrapolating all of the data into date or file name logic".

Anyway, ChatGPT says that this should do:
In Perl with Win32::OLE, because $items is an enumerator and you can't directly sort it, you need to first collect all the items into an array, sort that array, and then iterate.

Here’s how you can modify your code:
# Collect all items into an array first
my @all_items;
while (defined(my $item = $items->Next)) {
    push @all_items, $item;
}
 
# Now sort the array by LastWriteTime
# 'LastWriteTime' is a .NET DateTime object with a 'ToFileTimeUtc'
# method, which we can use to get a comparable number
@all_items = sort {
    $a->{'LastWriteTime'}->ToFileTimeUtc <=> $b->{'LastWriteTime'}->ToFileTimeUtc
} @all_items;
 
# Now iterate sorted items
foreach my $item (@all_items) {
...
}

Reply with quote

jpantera

Re: Perl WinSCP .Net Assembly Script via Win32::OLE , Sort the Output by File Name or Mod Date?

Thank you sir! This sounds like what I anticipated, but thanks for the example, will check that out.
Enumerating all of the file names... I tend to be TMI. Probably meant I left file name data where I did some manipulation out of my example.

Reply with quote

jpantera
Joined:
Posts:
29
Location:
Los Angeles, CA

ToFileTimeUtc referenced inside my Perl script can't be found.

Any idea how to reference ToFileTimeUtc in my Perl script?
Can't locate object method "ToFileTimeUtc" via package "Win32::OLE::Variant" at .\WinSCP_Perl_Script.pl line 373.
Line with issue:
@all_items = sort {$a->{'LastWriteTime'}->ToFileTimeUtc <=> $b->{'LastWriteTime'}->ToFileTimeUtc} @all_items;
I got around this issue, as the file name is standard, except for the date and time stamp that is in the name, so this works:
@all_items = sort {$a->{'Name'} cmp $b->{'Name'}} @all_items;
But can't seem to get my script to find $item->{'LastWriteTime'}->ToFileTimeUtc

Thanks,
Joe P.

Reply with quote

martin
Site Admin
martin avatar
Joined:
Posts:
42,011
Location:
Prague, Czechia

Re: ToFileTimeUtc referenced inside my Perl script can't be found.

Ok, so it seems that the DateTime is marshalled to Variant. That probably means that you can simply drop the ->ToFileTimeUtc:
@all_items = sort {
    $a->{'LastWriteTime'} <=> $b->{'LastWriteTime'}
} @all_items;

Reply with quote

Advertisement

You can post new topics in this forum