Search code examples
.netpowershellsftpwinscpwinscp-net

Download files from an array from SFTP server using WinSCP in PowerShell only when the files exist


I have this PowerShell code.

I have a little problem:

  • I download two remote files Device.log and Saveinfo.dat; Not all machines have both device.log and saveinfo.dat. Some machines have only device.log and when I try on machine what have only device.log the script fails. What can I do?

  • If machine have both file archive together and if machine have only device.log archive only that file (device.log).

Thank you

Add-Type -Path "C:\Program Files (x86)\WinSCP\WinSCPnet.dll"
 
$db = import-csv -Path "C:\Program Files (x86)\WinSCP\db.csv"
 
$inputID = Read-Host -Prompt "ID"
 
$entry = $db -match $inputID

Write-Host "IP:" $entry.IP

    $User = "user"
    $Password = "password"
    $Command = "C:\SaveBVInfo.exe"

    $secpasswd = ConvertTo-SecureString $Password -AsPlainText -Force
    $Credentials = New-Object System.Management.Automation.PSCredential($User, $secpasswd)

Get-SSHTrustedHost | Remove-SSHTrustedHost

$SessionID = New-SSHSession -ComputerName $entry.IP -Credential $Credentials -AcceptKey:$true

Invoke-SSHCommand -Index $sessionid.sessionid -Command $Command

# Set up session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{
    Protocol = [WinSCP.Protocol]::Sftp
    HostName = $entry.IP
    UserName = "$User"
    Password = "$Password"
    GiveUpSecurityAndAcceptAnySshHostKey = "true"
}
 
$session = New-Object WinSCP.Session

$file = "Device.log", "SaveBVInfo.dat"
$localPath = "E:\loguri\Log\Arhive\*"
$remotePath = "/C:/Program Files/Common Files/logs/Device.log", "/C:/Program Files/Pc/SaveBVInfo.dat"
 
try {

    # Connect
    $session.Open($sessionOptions)

    # Check files exists
 
        if ($session.FileExists($remotePath))
        {
            Write-Host "File $remotePath exists"
            # Transfer files

            $session.GetFiles($remotePath, $localPath).Check()
 
            exit 0
        }
        else
        {
            Write-Host "File $remotePath does not exist"
            exit 1
        }
}
finally {
    $session.Dispose()
}
foreach ($file in "E:\loguri\Log\Arhive\Device.log", "E:\loguri\Log\Arhive\SaveBVInfo.dat") {
    Compress-Archive $file -DestinationPath "E:\Arhive\$inputID.zip" -Update
    Remove-Item $file -Force
}

Solution

  • You cannot pass PowerShell arrays to .NET methods that do not take arrays.

    You have to process your files in a loop:

    $remotePaths = "/C:/Program Files/Common Files/logs/Device.log", "/C:/Program Files/Pc/SaveBVInfo.dat"
    
    foreach ($remotePath in $remotePaths)
    {
        if ($session.FileExists($remotePath))
        {
            Write-Host "File $remotePath exists"
            # Transfer files
    
            $session.GetFiles($remotePath, $localPath).Check()
        }
        else
        {
            Write-Host "File $remotePath does not exist"
        }
    }