jms2k
jms2k

Reputation: 81

WinSCP XML log with PowerShell to confirm multiple file upload

With my script, I am attempting to scan a directory for a subdirectory that is automatically created each day that contains the date in the directory name. Once it finds yesterdays date (since I need to upload previous day), it looks for another subdirectory, then any files that contain "JONES". Once it finds those files, it does a foreach loop to upload them using winscp.com.

My issue is that I'm trying to use the .xml log created from winscp to send to a user to confirm uploads. The problem is that the .xml file contains only the last file uploaded.

Here's my script:

# Set yesterday's date (since uploads will happen at 2am)
$YDate = (Get-Date).AddDays(-1).ToString('MM-dd-yyyy')

# Find Directory w/ Yesterday's Date in name
$YesterdayFolder = Get-ChildItem -Path "\\Path\to\server" | Where-Object {$_.FullName.contains($YDate)}

If ($YesterdayFolder) {

    #we specify the directory where all files that we want to upload are contained 
    $Dir= $YesterdayFolder

    #list every sql server trace file
    $FilesToUpload = Get-ChildItem -Path (Join-Path $YesterdayFolder.FullName "Report") | Where-Object {$_.Name.StartsWith("JONES","CurrentCultureIgnoreCase")}

    foreach($item in ($FilesToUpload))
    { 
          $PutCommand = '& "C:\Program Files (x86)\WinSCP\winscp.com" /command "open ftp://USERNAME:[email protected]:21/dropoff/ -explicitssl" "put """"' + $Item.FullName + '""""" "exit"' 
          Invoke-Expression $PutCommand         
    } 
} Else {
    #Something Else will go here
}

I feel that it's my $PutCommand line all being contained within the ForEach loop, and it just overwrites the xml file each time it connects/exits, but I haven't had any luck breaking that script up.

Upvotes: 2

Views: 1183

Answers (1)

Martin Prikryl
Martin Prikryl

Reputation: 202721

You are running WinSCP again and again for each file. Each run overwrites a log of the previous run.

Call WinSCP once instead only. It's even better as you avoid re-connecting for each file.

$FilesToUpload = Get-ChildItem -Path (Join-Path $YesterdayFolder.FullName "Report") |
    Where-Object {$_.Name.StartsWith("JONES","CurrentCultureIgnoreCase")}

$PutCommand = '& "C:\Program Files (x86)\WinSCP\winscp.com" /command "open ftp://USERNAME:[email protected]:21/dropoff/ -explicitssl" '

foreach($item in ($FilesToUpload))
{ 
      $PutCommand += '"put """"' + $Item.FullName + '""""" '
} 
$PutCommand += '"exit"'

Invoke-Expression $PutCommand 

Though all you really need to do is checking WinSCP exit code. If it is 0, all went fine. No need to have the XML log as a proof.


And even better, use the WinSCP .NET assembly from PowerShell script, instead of driving WinSCP from command-line. It does all error checking for you (you get an exception if anything goes wrong). And you avoid all nasty stuff of command-line (like escaping special symbols in credentials and filenames).

try
{
    # Load WinSCP .NET assembly
    Add-Type -Path "WinSCPnet.dll"

    # Setup session options
    $sessionOptions = New-Object WinSCP.SessionOptions -Property @{
        Protocol = [WinSCP.Protocol]::Ftp
        FtpSecure = [WinSCP.FtpSecure]::Explicit
        TlsHostCertificateFingerprint = "xx:xx:xx:xx:xx:xx..."
        HostName = "ftps.hostname.com"
        UserName = "username"
        Password = "password"
    }

    $session = New-Object WinSCP.Session

    try
    {
        # Connect
        $session.Open($sessionOptions)

        # Upload files
        foreach ($item in ($FilesToUpload))
        {
            $session.PutFiles($Item.FullName, "/dropoff/").Check()
            Write-Host "Upload of $($Item.FullName) succeeded"
        }
    }
    finally
    {
        # Disconnect, clean up
        $session.Dispose()
    }

    exit 0
}
catch [Exception]
{
    Write-Host "Error: $($_.Exception.Message)"
    exit 1
}

Upvotes: 2

Related Questions