Post a reply

Options
Add an Attachment

If you do not want to add an Attachment to your Post, please leave the Fields blank.

(maximum 10 MB; please compress large files; only common media, archive, text and programming file formats are allowed)

Options

Topic review

martin

Re: Getting disconnected when attempting to upload a file that already exists.

Sorry, but I'm really lost. This looks like XY problem to me.

Can you post a log file showing how you get disconnected after the server rejects to overwrite an existing file? Can you explain what you want WinSCP to do instead, when the server rejects to overwrite an existing file?
Guest

Re: Getting disconnected when attempting to upload a file that already exists.

martin wrote:

You didn't really explain what you want WinSCP to do, when the upload fails.
Sorry, I thought that I asked a different question.

TXShooter wrote:

What's the best or recommended set of actions to take to ensure that my script won't get disconnected when attempting to upload a file that already exists?
How about establishing a log file so that I can see on the client side what's going on. I'm a novice at enumerating, so I'm not sure how to implement a log file for a new session from an AutoHotKey script. I guess that's the best way to get an idea of what's really going on with WinSCP, right? (I've read through a lot of posts on this forum where you ask for a log file.)

So, Step 1: How would you suggest I proceed in order to enumerate for a log file?
martin

Re: Getting disconnected when attempting to upload a file that already exists.

You didn't really explain what you want WinSCP to do, when the upload fails.
TXShooter

WinSCP.ahk

;~ -----------------------------------------------------------------------------

;~ Name:               WinSCP Class
;~ http://lipkau.net/WinSCP.ahk/
;~ -----------------------------------------------------------------------------
;~ Version:            1.1.0
;~ Date:               2015-06-20
;~ Author:             Lipkau, Oliver <oliver@lipkau.net>
;~                     https://github.com/lipkau
;~ -----------------------------------------------------------------------------
;~ TODO:
;~       - Try/Catch if dll is not registered?
;~       - Allow dll to be outside A_ScriptDir?
;~       - better documentation
;~       - more methods
;~       - more events
;~       - cleanup
;Register the DLL by using the following Command Line:
; %WINDIR%\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe "C:\Program Files (x86)\WinSCP\WinSCPnet.dll" /codebase /tlb

;   %WINDIR%\Microsoft.NET\Framework\v4.0.30319\RegAsm.exe "C:\Program Files (x86)\WinSCP\WinSCPnet.dll" /codebase /tlb:WinSCPnet32.tlb
;   %WINDIR%\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe "C:\Program Files (x86)\WinSCP\WinSCPnet.dll" /codebase /tlb:WinSCPnet64.tlb
;~ -----------------------------------------------------
;~  Enumerations
;~ -----------------------------------------------------
/*
Description
   Reproduce WinSCP Enumerations.

Scope
   Global
*/
class WinSCPEnum
{
   static FtpMode                 := {Passive:0, Active:1}
   static FtpSecure               := {None:0, Implicit:1, ExplicitTls:2, ExplicitSsl:3}
   static FtpProtocol             := {Sftp:0, Scp:1, Ftp:2}
   static TransferMode            := {Binary:0, Ascii:1, Automatic:2}
   static SynchronizationMode     := {Local:0, Remote:1, Both:2}
   static SynchronizationCriteria := {None:0, Time:1, Size:2, Either:3}
}

;~ -----------------------------------------------------
;~  Event Handlers
;~ -----------------------------------------------------
/*
Description
   Example on how to use the FileTransferred Event
*/
;~ session_FileTransferred(sender, e)
;~ {
   ;~ MsgBox % e.FileName " => "  e.Destination
;~ }

/*
Description
   Example on how to use the Failed Event
*/
;~ session_Failed(sender, e)
;~ {
   ;~ MsgBox % e.FileName " => "  e.Destination
;~ }

/*
Description
   Example on how to use the RemovalEventArgs Event
   https://winscp.net/eng/docs/library_removaleventargs
*/
;~ session_RemovalEventArgs(sender, e)
;~ {
   ;~ if (e.Error)
      ;~ MsgBox % "Failed to remove " e.FileName " => "  e.Error
   ;~ else
      ;~ MsgBox % "Removed " e.FileName
;~ }

/*
Description
   Example on how to use the FileTransferProgress Event to display the Progress using AHK GUI
*/
;~ session_FileTransferProgress(sender, e)
;~ {
   ;~ RegExMatch(e.FileName, ".*\\(.+?)$", match)
   ;~ FileName        := match1
   ;~ CPS             := Round(e.CPS / 1024)
   ;~ FileProgress    := Round(e.FileProgress * 100)
   ;~ OverallProgress := Round(e.OverallProgress * 100)
   ;~ action          := (e.Side==0) ? "Uploading" : "Downloading"
;~ }

;~ -----------------------------------------------------
;~  Class
;~ -----------------------------------------------------
class WinSCP
{
   ;~ -----------------------------------------------------
   ;~  Properties
   ;~ -----------------------------------------------------
   Hostname                := ""
   Port                    := ""
   Secure                  := ""
   Protocol                := ""
   User                    := ""
   Password                := ""
   Mode                    := ""
   TransferMode            := ""
   SynchronizationMode     := ""
   SynchronizationCriteria := ""
   Fingerprint             := ""
   SessionLogPath         := ""

   ;https://winscp.net/eng/docs/library_session
   Session                 := ComObjCreate("WinSCP.Session")
   SessionOptions          := ComObjCreate("WinSCP.SessionOptions")
   TransferOptions         := ComObjCreate("WinSCP.TransferOptions")
   ;https://winscp.net/eng/docs/library_filepermissions
   FilePermissions         := ComObjCreate("WinSCP.FilePermissions")

   /*
   Description
      Create a Property for Log Path. Class Session should be transparent in Class FTP.
   */
   LogPath[]
   {
      Get
      {
         return this.Session.SessionLogPath
      }
      Set
      {
         return this.Session.SessionLogPath := value
      }
   }

   /*
   Description
      Create a Property for the HomePath. Class Session should be transparent in Class FTP.
   */
   HomePath[]
   {
      Get
      {
         return this.Session.HomePath
      }
      Set
      {
         return this.Session.HomePath := value
      }
   }

   /*
   Description
      Create a Property for the Opened. Class Session should be transparent in Class FTP.
   */
   Connected[]
   {
      Get
      {
         return this.Session.Opened
      }
   }

   ;~ -----------------------------------------------------
   ;~  Methods
   ;~ -----------------------------------------------------
   /*
   Description
      Constructor - sets default values
   */
   __New()
   {
      global WinSCPEnum ; WinSCP Enums

      ;~ Set defaults
      this.Port                    := 21
      this.Secure                  := WinSCPEnum.FtpSecure.None
      this.Protocol                := WinSCPEnum.FtpProtocol.Ftp
      this.Mode                    := WinSCPEnum.FtpMode.Passive
      this.TransferMode            := WinSCPEnum.TransferMode.Binary
      this.SynchronizationMode     := WinSCPEnum.SynchronizationMode.Local
       this.SynchronizationCriteria := WinSCPEnum.SynchronizationCriteria.Time
      this.Fingerprint             := false
      ComObjConnect(this.Session, "session_")
   }

   /*
   Description
      Destructor
   */
   ; __Delete()
   ; {
   ;    this.Dispose()
   ;    this.CloseConnection()
   ; }

   /*
   Description
      Open connection to server

   Input
      srv        : [string] Server DNS or IP
      uName      : [string] User Name
      pWord      : [string] Password
   */
   OpenConnection(srv="", uName="", pWord="")
   {
      global WinSCPEnum ; WinSCP Enums

      this.SessionOptions.HostName := (srv)   ? srv   : this.Hostname
      this.SessionOptions.UserName := (uName) ? uName : this.User
      this.SessionOptions.Password := (pWord) ? pWord : this.Password

      ;~ FTP Mode
      this.SessionOptions.FtpMode := this.Mode

      ;~ FTP Protocol
      this.SessionOptions.Protocol := this.Protocol

      ;~ FTP Security
      this.SessionOptions.FtpSecure := this.Secure

      ;~ Fingerprint
      ;MsgBox, % Fingerprint is this.Fingerprint
      IsEncrypted := this.Secure
      Encryptions := WinSCPEnum.FtpSecure.Implicit "," WinSCPEnum.FtpSecure.ExplicitTls "," WinSCPEnum.FtpSecure.ExplicitSsl
      if IsEncrypted in %Encryptions%
      {
         if (StrLen(this.Fingerprint) > 1)
         {
            if (this.Protocol==WinSCPEnum.FtpProtocol.Scp)
               this.SessionOptions.SshHostKeyFingerprint := this.Fingerprint
            else
               this.SessionOptions.TlsHostCertificateFingerprint := this.Fingerprint
         } else {
            if (this.Protocol==WinSCPEnum.FtpProtocol.Scp)
               this.SessionOptions.GiveUpSecurityAndAcceptAnySshHostKey := true
            else
               this.SessionOptions.GiveUpSecurityAndAcceptAnyTlsHostCertificate := true
         }
      }

      this.Session.Open(this.SessionOptions)
   }

   /*
   Description
      Closes session.
      New session can be opened using Session.Open using the same instance of Session.
   */
   CloseConnection()
   {
      try
         this.Session.Close()
   }

   /*
   Description
      If session was opened, closes it, terminates underlying WinSCP process, deletes XML log file and disposes object.
   */
   Dispose()
   {
      try
         this.Session.Dispose()
   }

   /*
   Description:
      Lists the contents of specified remote directory.
      https://winscp.net/eng/docs/library_session_listdirectory

   Input:
      remotePath : [string] Full path to remote directory to be read.

   Output:
      [RemoteDirectoryInfo]
   */
   ListDirectory(remotePath)
   {
      return this.Session.ListDirectory(remotePath)
   }

   /*
   Description:
      Creates remote directory.
      https://winscp.net/eng/docs/library_session_createdirectory

   Input:
      remotePath : [string] Full path to remote directory to create.

   Output:
      [void]
   */
   CreateDirectory(remotePath)
   {
      return this.Session.CreateDirectory(remotePath)
   }

   /*
   Description:
      Checks for existence of remote file.
      https://winscp.net/eng/docs/library_session_fileexists

   Input:
      remotePath : [string] Full path to remote file. Note that you cannot use wild-cards here.

   Output:
      [bool] true if file exists, false otherwise.
   */
   FileExists(remotePath)
   {
      return this.Session.FileExists(remotePath)
   }

   /*
   Description:
      Retrieves information about remote file.
      https://winscp.net/eng/docs/library_session_getfileinfo

   Input:
      remotePath : [string] Full path to remote file.

   Output:
      [RemoteFileInfo]
      https://winscp.net/eng/docs/library_remotefileinfo
   */
   GetFileInfo(remotePath)
   {
      return this.Session.GetFileInfo(remotePath)
   }

   /*
   Description:
      Downloads one or more files from remote directory to local directory.
      https://winscp.net/eng/docs/library_session_getfiles

      This Method supports Wild-cards
      https://winscp.net/eng/docs/library_wildcard

   Input:
      remotePath : [string]          Full path to remote directory followed by slash and wild-card to
                                     select files or subdirectories to download. When wild-card is
                                omitted (path ends with slash), all files and subdirectories in
                                the remote directory are downloaded.
      localPath  : [string]          Full path to download the file to. When downloading multiple
                                     files, the filename in the path should be replaced with operation
                                mask or omitted (path ends with backslash).
      remove     : [bool]            When set to true, deletes source remote file(s) after transfer.
                                     Defaults to false.
      options    : [TransferOptions] Transfer options. Defaults to null, what is equivalent to new
                                     TransferOptions().

   Output:
      [TransferOperationResult]
      See also Capturing results of operations.
   */
   GetFiles(remotePath, localPath, remove=false)
   {
      ;~ Check
      ;remove
      if remove not in 0,1
         throw "Invalid value for remove"

      return this.Session.GetFiles(remotePath, localPath, remove, this.TransferOptions)
   }

   /*
   Description:
      Uploads one or more files from local directory to remote directory.
      https://winscp.net/eng/docs/library_session_putfiles

      This Method supports Wild-cards
      https://winscp.net/eng/docs/library_wildcard

   Input:
      localPath  : [string]          Full path to local file or directory to upload. Filename in the
                                     path can be replaced with Windows wildcard1) to select multiple
                                 files. When file name is omitted (path ends with backslash), all
                                files and subdirectories in the local directory are uploaded.
      remotePath : [string]          Full path to upload the file to. When uploading multiple files,
                                     the filename in the path should be replaced with operation mask
                                or omitted (path ends with slash).
      remove     : [bool]            When set to true, deletes source local file(s) after transfer.
                                     Defaults to false.
      options    : [TransferOptions] Transfer options. Defaults to null, what is equivalent to new
                                     TransferOptions().

   Output:
      [TransferOperationResult]
      See also Capturing results of operations.
   */
   PutFiles(localPath, remotePath, remove:=false)
   {
      ;~ Checks
      ;localPath
      if (!FileExist(localPath))
         throw "Could not find " localPath

      ;remove
      if remove not in 0,1
         throw "Invalid value for remove"

      return this.Session.PutFiles(localPath, remotePath, remove, this.TransferOptions)
   }

   /*
   Description:
      Moves remote file to another remote directory and/or renames remote file.
      https://winscp.net/eng/docs/library_session_movefile

   Input:
      sourcePath : [string] Full path to remote file to move/rename.
      targetPath : [string] Full path to new location/name to move/rename the file to.

   Output:
      [void]
   */
   MoveFile(sourcePath, targetPath)
   {
      return this.Session.MoveFile(sourcePath, targetPath)
   }

   /*
   Description:
      Removes one or more remote files.
      https://winscp.net/eng/docs/library_session_removefiles

      This Method supports Wild-cards
      https://winscp.net/eng/docs/library_wildcard

   Input:
      remotePath : [string] Full path to remote directory followed by slash and
                            wild-card to select files or subdirectories to remove.

   Output:
      [RemovalOperationResult]
      See also Capturing results of operations.
   */
   RemoveFiles(remotePath)
   {
      return this.Session.RemoveFiles(remotePath)
   }

   /*
   Description:
      Synchronizes directories.
      https://winscp.net/eng/docs/library_session_synchronizedirectories

   Input:
      SynchronizationMode     : [enum]   Synchronization mode. Possible values are SynchronizationMode.Local,
                                         SynchronizationMode.Remote and SynchronizationMode.Both.
      localPath               : [string] Full path to local directory.
      remotePath              : [string] Full path to remote directory.
      removeFiles             : [bool]   When set to true, deletes obsolete files. Cannot be used for
                                         SynchronizationMode.Both.
      mirror                  : [bool]   When set to true, synchronizes in mirror mode (synchronizes also
                                         older files). Cannot be used for SynchronizationMode.Both. Defaults
                                 to false.
      SynchronizationCriteria : [enum]   Comparison criteria. Possible values are SynchronizationCriteria.None,
                                 SynchronizationCriteria.Time (default), SynchronizationCriteria.Size
                                 and SynchronizationCriteria.Either. For SynchronizationMode.Both
                                 SynchronizationCriteria.Time can be used only.

   Output:
      [SynchronizationResult]
      See also Capturing results of operations.
   */
   SynchronizeDirectories(SynchronizationMode, localPath, remotePath, removeFiles, mirror=false, SynchronizationCriteria=1)
   {
      global WinSCPEnum ; WinSCP Enums

      ;~ Checks
      ;Mode
      if SynchronizationMode not in % this.StringJoin(WinSCPEnum.SynchronizationMode,",")
         throw "Invalid SynchronizationMode"

      ;localPath
      if (!FileExist(localPath))
         throw "Could not find " localPath

      ;removeFiles
      if removeFiles not in 0,1
         throw "Invalid removeFiles"
      if (removeFiles && (removeFiles==WinSCPEnum.SynchronizationMode.Both))
         throw "Deletion of obsolete files cannot be used for SynchronizationMode.Both"

      ;mirror
      if mirror not in 0,1
         throw "Invalid mirror"
      if (mirror && (removeFiles==WinSCPEnum.SynchronizationMode.Both))
         throw "Synchronization in mirror mode (synchronizes also older files) cannot be used for SynchronizationMode.Both"

      ;SynchronizationCriteria
      if SynchronizationCriteria not in % this.StringJoin(WinSCPEnum.SynchronizationCriteria,",")
         throw "Invalid SynchronizationCriteria"

      ;TransferOptions
      if (options && (ComObjType(options,"Name")=="_TransferOptions"))
         throw "Invalid TransferOptions"

      if (!this.TransferOptions.TransferMode)
         this.SetTransferOptions(, ,, ,, WinSCPEnum.TransferMode.Binary)

      this.Session.SynchronizeDirectories(SynchronizationMode, localPath, remotePath, removeFiles, mirror, SynchronizationCriteria, this.TransferOptions)
   }

   ;~ -----------------------------------------------------
   ;~  Helper Methods
   ;~ -----------------------------------------------------
   /*
   Description
      Set TransferOptions
      https://winscp.net/eng/docs/library_transferoptions

   Input
      FileMask          : [string]                FileMask
      FilePermissions   : [FilePermissions]       Permissions to applied to a remote file (used for
                                                  uploads only). Use default null to keep default permissions.
      PreserveTimestamp : [bool]                  Preserve timestamps (set last write time of destination file
                                       to that of source file). Defaults to true.
                                                    When used with Session.SynchronizeDirectories, timestamps is
                                        always preserved, disregarding property value, unless criteria
                                       parameter is SynchronizationCriteria.None or
                                       SynchronizationCriteria.Size.
      ResumeSupport     : [TransferResumeSupport] Configures automatic resume/transfer to temporary filename.
                                                  Read-only (set properties of returned TransferResumeSupport
                                       instance).
      SpeedLimit        : [int]                   Limit transfer speed (in KB/s).
      TransferMode      : [TransferMode]          Transfer mode. Possible values are TransferMode.Binary
                                                  (default), TransferMode. ASCII and TransferMode.Automatic
                                       (based on file extension).
   */
   SetTransferOptions(FileMask="", FilePermissions="", PreserveTimestamp=true, ResumeSupport="", SpeedLimit="", TransferMode=0)
   {
      global WinSCPEnum ; WinSCP Enums

      ;~ Check
      ;FilePermissions
      if (FilePermissions && (ComObjType(permissions,"Name")=="_FilePermissions"))
         throw "Invalid FilePermissions"

      ;PreserveTimestamp
      if PreserveTimestamp not in 0,1
         throw "Invalid value for PreserveTimestamp"

      ;permissions
      if (ResumeSupport && (ComObjType(ResumeSupport,"Name")=="_TransferResumeSupport"))
         throw "Invalid ResumeSupport"

      ;SpeedLimit
      if SpeedLimit is not Integer
         throw "Invalid SpeedLimit"

      ;TransferMode
      if TransferMode not in % this.StringJoin(WinSCPEnum.TransferMode,",")
         throw "Invalid TransferMode"

      this.TransferOptions.FileMask          := (FileMask) ? FileMask : ""
      this.TransferOptions.FilePermissions    := (FilePermissions) ? FilePermissions: ""
      this.TransferOptions.PreserveTimestamp    := (PreserveTimestamp) ? PreserveTimestamp : ""
      this.TransferOptions.ResumeSupport       := (ResumeSupport) ? ResumeSupport : ""
      this.TransferOptions.SpeedLimit          := (SpeedLimit) ? SpeedLimit : ""
      this.TransferOptions.TransferMode        := (TransferMode) ? TransferMode : ""
   }

   /*
   Description
      Converts special characters in file path to make it unambiguous file mask/wild-card.
      https://winscp.net/eng/docs/library_session_escapefilemask

   Input
      fileMask : [string] File path to convert.
   */
   EscapeFileMask(FileMask)
   {
      return this.Session.EscapeFileMask(FileMask)
   }

   /*
   Description
      Join Array to String

   Input
      array : [array]  Array that will be joined into string
      delim : [string] Character (set) that will be used between array elements in string

   Output
      [string]
   */
   StringJoin(array, delim=";")
   {
      t := ""
      for key, value in array
         t .= value "" delim
      return SubStr(t,1, -StrLen(delim))
   }
}
TXShooter

Getting disconnected when attempting to upload a file that already exists.

What's the best or recommended set of actions to take to ensure that my script won't get disconnected when attempting to upload a file that already exists?

(Unfortunately, I do not know how to set a log file from within my script in AutoHotKey, but I do welcome suggestions to create one from the script.)

However, looking at the log from the server side in FileZilla, I am getting error 550 when I attempt to upload a file that already exists, and then without any action I get disconnected (as though WinSCP said, "Whoops. There's an error. Time to disconnect without warning, throwing an error ("catch e"), or announcement back to the script."

If I delete the file(s) in question on the server, then it will upload every time, and even continue to upload the rest of the wildcard files.

#Include WinSCP.ahk

LocalDir := "X:\local\local_sub"
RemoteDir := "/remote/remote_sub1/remote_sub2/"
fName := "*.bat"
FTPSession := new WinSCP
try
{
   ;Define Connection Data
   FTPSession.Hostname := "xxx.xxx.xxx.xxx"
   FTPSession.Protocol := WinSCPEnum.FtpProtocol.Ftp
   FTPSession.Secure := WinSCPEnum.FtpSecure.Implicit
   FTPSession.User   := "User1"
   FTPSession.Password := "Password1"
   FTPSession.Fingerprint := "Xx:xx:xx:xx:xx:Xx:xx:xx:xx:xx:Xx:xx:xx:xx:xx:Xx:xx:xx:xx:xx" ;set to false to ignore server certificate
   FTPSession.OpenConnection()
   FTPSession.ListDirectory(RemoteDir)
   FTPSession.PutFiles(LocalDir "\" fname, RemoteDir)
} catch e
   ;Catch Exeptions
   msgbox % "Oops. . . Something went so very, horribly wrong. WE'RE ALL GONNA DIIIIIEE!!`nNo, but seriously, check your code, dude." e.Message