Link to home
Start Free TrialLog in
Avatar of bfuchs
bfuchsFlag for United States of America

asked on

Permission denied error while synchronizing folders.

Hi Experts,
I have the following function trying to synchronize my local folder with a FTP folder.
Sub Example()
 
    Dim mySession As New Session
    
    ' Enable custom error handling
    On Error Resume Next
    
    Download mySession
    
    ' Query for errors
    If Err.Number <> 0 Then
        MsgBox "Error: " & Err.Description
 
        ' Clear the error
        
        Err.Clear
    End If
     
    ' Disconnect, clean up
    mySession.Dispose
     
    ' Restore default error handling
    On Error GoTo 0
    
End Sub
Public Sub Download(ByRef mySession As Session)
'Public Sub Download()
    ' Setup session options
    Dim mySessionOptions As New SessionOptions
    With mySessionOptions
        .Protocol = Protocol_Sftp
        .hostname = "sftp.MySite.com"
        .username = "MyUser"
        .password = "MyPWD"
        .SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"
        
        
    End With
    
    ' Connect
    mySession.Open mySessionOptions
    
    ' Upload files
    Dim myTransferOptions As New TransferOptions
    myTransferOptions.TransferMode = TransferMode_Binary
    'myTransferOptions.ResumeSupport = TransferResumeSupportState.TransferResumeSupportState_Off
    myTransferOptions.ResumeSupport.State = TransferResumeSupportState_Off
     
    Dim transferResult As SynchronizationResult
    'Set transferResult = _
        mySession.GetFiles("/Outbox/*PatChanges*", "H:\FTP\", False, myTransferOptions)
' include *PatChanges* and *SchChanges* but exclude *Full*
myTransferOptions.FileMask = "*PatChanges*;*SchChanges*|*Full*"
'Set transferResult = mySession.GetFiles("/Outbox/*", "H:\FTP\", False, myTransferOptions)
Set transferResult = _
    mySession.SynchronizeDirectories(SynchronizationMode.SynchronizationMode_Local, "H:\FTP\", "/Outbox/*", 0, 0, SynchronizationCriteria.SynchronizationCriteria_Time, myTransferOptions)
     'Set mySynchronizationResult = mySession.SynchronizeDirectories(SynchronizationMode.SynchronizationMode_Remote, sLocalPath, sRemotePath, False)
    ' Throw on any error
    transferResult.check
    
     
    ' Display results
    Dim transfer As TransferEventArgs
    Dim i As Long
    For Each transfer In transferResult.transfers
        Debug.Print "Download of " & transfer.FileName & " succeeded"
        i = i + 1
    Next
    Debug.Print i
End Sub

Open in new window


However getting permission denied error.
See attached.
Untitled.png
Avatar of Gregory Miller
Gregory Miller
Flag of United States of America image

The one thing that jumps off the page at me is the use of the "*" character in the Path/Filename. On a windows host destination, you will need to substitute this for a valid character that is legal for Path/Filenames. If the destination is a Linux host, it should allow it but there could be other trickery in play which can force is as disallowed.
User generated image
A quick replace("*", "X", <STRING>) would tell you for certain.
Avatar of bfuchs

ASKER

Hi,
I had this working fine with the following
Set transferResult = mySession.GetFiles("/Outbox/*", "H:\FTP\", False, myTransferOptions)

Open in new window

The problem was that this was downloading all files, not just the new ones, so I switched to
Set transferResult = _
    mySession.SynchronizeDirectories(SynchronizationMode.SynchronizationMode_Local, "H:\FTP\", "/Outbox/*", 0, 0, SynchronizationCriteria.SynchronizationCriteria_Time, myTransferOptions)
   

Open in new window

Therefore I guess its not the asterisk character that's causing it.

However if you tell me explicitly what to change for, I can give it a try...

Thanks,
Ben
Avatar of bfuchs

ASKER

Think the reason is, in order to Synchronize Directories, it tries to open those files and read contents...

Wondering if we can modify the function to only look at the file names, if they're the same then skip it.

Thanks,
Ben
I certainly made the assumption that the Access Denied message was coming from failing to write the file but if the method you are using is trying to open files which are already open, this could be the source of the issue. I am not familiar with the method "SynchronizeDirectories". Is this a WinSCP library or another application?
Avatar of bfuchs

ASKER

Hi,

but if the method you are using is trying to open files which are already open, this could be the source of the issue.
No, they're are not open, I meant the following, perhaps we only have permission to download the files, not to read them on the server...
Is this a WinSCP library
Yes, it is.
https://winscp.net/forum/viewtopic.php?p=85890#85890

Thanks,
Ben
Avatar of bfuchs

ASKER

No, they're are not open, I meant the following, perhaps we only have permission to download the files, not to read them on the server...
I confirmed we do have read/write permission.

Now my question, why are we getting this permission error?

Thanks,
Ben
ASKER CERTIFIED SOLUTION
Avatar of Eddie Shipman
Eddie Shipman
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of bfuchs

ASKER

Hi Eddie,

Actually at the moment I cant even get to that point.

This is the full code

Public Sub Download(ByRef mySession As Session)
'Public Sub Download()
    ' Setup session options
    Dim mySessionOptions As New SessionOptions
    With mySessionOptions
        .Protocol = Protocol_Sftp
        .hostname = "sftp.MySite.com"
        .username = "MyUserName"
        .password = "MyPWD"
        .SshHostKeyFingerprint = "ssh-rsa 2048 xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"
        
        
    End With
    
    ' Connect
    mySession.Open mySessionOptions
    
    ' Upload files
    Dim myTransferOptions As New TransferOptions
    myTransferOptions.TransferMode = TransferMode_Binary
    'myTransferOptions.ResumeSupport = TransferResumeSupportState.TransferResumeSupportState_Off
    '''myTransferOptions.ResumeSupport.State = TransferResumeSupportState_Off
     
    Dim transferResult As SynchronizationResult
    'Set transferResult = _
        mySession.GetFiles("/Outbox/*PatChanges*", "H:\FTP\", False, myTransferOptions)
' include *PatChanges* and *SchChanges* but exclude *Full*
myTransferOptions.FileMask = "*PatChanges*;*SchChanges*|*Full*"
'Set transferResult = mySession.GetFiles("/Outbox/*", "H:\FTP\", False, myTransferOptions)
Set transferResult = _
    mySession.SynchronizeDirectories(SynchronizationMode.SynchronizationMode_Local, "H:\FTP\test2\", "/Outbox/", False, False, , myTransferOptions)
    'Set mySynchronizationResult = mySession.SynchronizeDirectories(SynchronizationMode.SynchronizationMode_Remote, sLocalPath, sRemotePath, False)
    ' Throw on any error
    transferResult.check
    
     
    ' Display results,
    Dim transfer As TransferEventArgs
    Dim i As Long
    For Each transfer In transferResult.downloads
        Debug.Print "Download of " & transfer.FileName & " succeeded"
        i = i + 1
    Next
    Debug.Print i
End Sub

Open in new window


I'm calling this in a loop and it exists on the following line

 mySession.Open mySessionOptions

Open in new window


Any idea?

Thanks,
Ben
Having no clue about WinSCP, I've found https://winscp.net/eng/docs/library as documentation about the .NET library.
Sadly, the Session.Open method does not return any result, but throws exceptions instead, according to https://winscp.net/eng/docs/library_session_open. VBA cannot handle that, so probably the error causing your new issue gets dismissed.
The documented reasons causing exceptions are
  • Session is already opened.
  • Invalid combination of values of SessionOptions properties.
  • Error communicating with winscp.com.
  • Connection or authentication has failed.
  • Timeout waiting for winscp.com to respond.
Assuming you did not change any of the session options, the first and second cause can be ignored. Maybe your SSH key is expired, your login locked or similar? Or there is an issue with the winscp executable.

If you would dare to use PowerShell for testing (shouldn't be difficult), you should get a reasonable exception response from Open. Or you try to log in using the WinSCP UI.
Avatar of bfuchs

ASKER

Hi Qlemo,

Actually I'm debating if to use the Powershell script you helped me finalize (below) or use this VBA function.
https://www.experts-exchange.com/questions/29112971/Script-causing-an-error-after-running-for-long-time.html?anchorAnswerId=42661446#a42661446
From one side I would prefer using the VBA as I'm familiar with the language, however from the other side, the VBA is so far causing me too much problems...

What would you suggest?

Thanks,
Ben
Ben, how about downloading Visual Studio Express for VB.net and testing it in there, then, at least, you'll know what is causing the exception.
You know both worlds now, and see it is easy to switch between PowerShell and VBA without much chamge of WinSCP related code. My approach would probably be to write the file transfer in PS, and call that from VBA. That of course only works well if there is little interaction required between both parts.

PowerShell is the "better" language because it allows much better testing, diagnostics, integration of DLLs, error checking, ... But that does not help much if you are uncomfortable with using it ;-). You should try as statedy with a call to a PS script, and then compare. Doesn't require much of effort, and you'll see whether you get along with that stategy.
Avatar of bfuchs

ASKER

Hi,

how about downloading Visual Studio Express for VB.net and testing it in there
didn't start with dotnet yet-:(, Is this a copy/paste matter or I need to modify the code?

My approach would probably be to write the file transfer in PS, and call that from VBA.
So whats wrong if I go with the PS script alone and leave it running forever, do you anticipate any problems with that approach?

Thanks,
Ben
No issues with that, I just expected this is part of a bigger (VBA) project.
Avatar of bfuchs

ASKER

expected this is part of a bigger (VBA) project.
Actually it is, and I will run some code in VBA for constantly checking if that folder does have new files and process them, however no direct interaction between those two...

Thanks,
Ben
Avatar of bfuchs

ASKER

Thank you my experts!