Search code examples
powershellcsvsftpwinscp

Select SFTP connection data for WinSCP .NET assembly from CSV file based on user input


I have this PowerShell code. Works good. But when I add more lines to db.csv, it doesn't work and return error code:

Exception calling "Open" with "1" argument(s): "Connection has been unexpectedly closed. Server sent command exit status 0.
Authentication log (see session log for details):
Using username "username".
Authentication failed."
At C:\Users\me\Desktop\testeScript\CollectLog.ps1:41 char:5
+ $session.Open($sessionOptions)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : SessionRemoteException

When I have for example only two lines in db.csv the script works very well

HostName,IP
name1,10.10.1.1
name2,10.10.1.2

I try with 19 hostname and Ip addr line in CSV doc and works, but when I add only 1 more stopping works.

19 works 20+ doesn't work..

Any idea? (Thank you and sorry for my english)

Add-Type -Path "WinSCPnet.dll"
 
$Name = @()
$ip = @()
 
Import-Csv db.csv |`
    ForEach-Object {
        $Name += $_.HostName
        $ip += $_.IP
    }
 
$inputID = Read-Host -Prompt "Type ID"
 
if ($Name -contains $inputID)
    {
    $Where = [array]::IndexOf($Name, $inputID)
    Write-Host "IP: " $ip[$Where]
    }
 
# Set up session options
$sessionOptions = New-Object WinSCP.SessionOptions -Property @{
    Protocol = [WinSCP.Protocol]::Sftp
    HostName = "$ip"
    UserName = "username"
    Password = "password"
    GiveUpSecurityAndAcceptAnySshHostKey = "true"
}
 
$session = New-Object WinSCP.Session
 
try
{
    # Connect
    $session.Open($sessionOptions)
 
    # Transfer files
    $session.GetFiles("/C:/Program Files/Common Files/logs/Device.log", "E:\loguri\Log\Arhive\*").Check()
}
finally
{
    $session.Dispose()
}
 
Compress-Archive -Path "E:\loguri\Log\Arhive\Device.log" -DestinationPath "E:\loguri\Log\Arhive\$inputID.zip" -Update
Remove-Item -Path "E:\loguri\Log\Arhive\Device.log" -Force

Solution

  • as Theo says you have no need to separate out your CSV into two arrays as you have. Import it like this

    $db = import-csv 'db.csv'
    

    You can access each row as $db[0], $db[1] and each column from your CSV will be a property, e.g. $db[0].Hostname and $db[0].IP

    After you have read in your input you just need to select the entry from the array $db. Perhaps like this. However neither your code nor mine covers the case where is no match!

    $entry = $db -match $inputID
    

    Then your session will be defined like this

    $sessionOptions = New-Object WinSCP.SessionOptions -Property @{
        Protocol = [WinSCP.Protocol]::Scp
        HostName = $entry.ip
        UserName = "username"
        Password = "password"
        GiveUpSecurityAndAcceptAnySshHostKey = "true"
    }
    

    With all that said, given the error message that you have it would appear that the combination of username/password and ip are not valid.

    Add-Type -Path "WinSCPnet.dll"
     
    $db = import-csv 'db.csv'
     
    $inputID = Read-Host -Prompt "Type ID"
     
    $entry = $db -match $inputID
     
    # Set up session options
    $sessionOptions = New-Object WinSCP.SessionOptions -Property @{
        Protocol = [WinSCP.Protocol]::Sftp
        HostName = $entry.IP
        UserName = "username"
        Password = "password"
        GiveUpSecurityAndAcceptAnySshHostKey = "true"
    }
     
    $session = New-Object WinSCP.Session
     
    try {
        # Connect
        $session.Open($sessionOptions)
     
        # Transfer files
        $session.GetFiles("/C:/Program Files/Common Files/logs/Device.log", "E:\loguri\Log\Arhive\*").Check()
    }
    finally {
        $session.Dispose()
    }
    
    if (Test-Path "E:\loguri\Log\Arhive\Device.log") {
      Compress-Archive -Path "E:\loguri\Log\Arhive\Device.log" -DestinationPath "E:\loguri\Log\Arhive\$inputID.zip" -Update
      Remove-Item -Path "E:\loguri\Log\Arhive\Device.log" -Force
    }