This project is read-only.

Problem with putfiles

Sep 12, 2011 at 1:12 AM

Hi Alex,

nice library, thanks a lot!

I try to upload multiple files with subdirs with the command myftp.PutFiles(source, "/myFTP/" & dest , "*", EPatternStyle.Wildcard, True, New FileTransferCallback(AddressOf progress))

Example:

  • all files from source = c:\temp\
  • to ftp-server dest = /myFTP/temp (the temp dir does not exist !)

The first time I run this command an exception is raised:  The object with a null-value must have a value (Das Objekt mit Nullwert muss einen Wert haben.) but the strange thing is, that the subdir is createt: /myFTP/temp (but it is empty)

If I run it for the second tíme everything is fine, all files are transfered... BUT if there are dirs in subdirs, I have to run it as many times as subdirs are present. After that alle files are transfered.

What do I miss, thanks in advance.

 

Best regards

  -Stefan

Sep 12, 2011 at 11:10 AM

Hi Stefan,

can you pelase post the full Exception stack trace?

 

Thanks,

Alessandro

 

Sep 12, 2011 at 9:57 PM

Hi Alessandro,

here comes the stack trace: german VS 2008:

{"Das Objekt mit Nullwert muss einen Wert haben."}
    System.InvalidOperationException: {"Das Objekt mit Nullwert muss einen Wert haben."}
    Data: {System.Collections.ListDictionaryInternal}
    HelpLink: Nothing
    InnerException: Nothing
    Message: "Das Objekt mit Nullwert muss einen Wert haben."
    Source: "mscorlib"
    StackTrace: "   bei System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)    bei System.Nullable`1.op_Explicit(Nullable`1 value)    bei ftp.Form1._Lambda$__5(FTPSClient a0, ETransferActions a1, String a2, String a3, UInt64 a4, Nullable`1 a5, Boolean& a6) in C:\Users\ich\Documents\Visual Studio 2008\Projects\ftp_VB\ftp_VB\Form1.vb:Zeile 124.    bei AlexPilotti.FTPS.Client.FTPSClient.CallTransferCallback(FileTransferCallback transferCallback, ETransferActions transferAction, String localObjectName, String remoteObjectName, UInt64 fileTransmittedBytes, Nullable`1 fileTransferSize)    bei AlexPilotti.FTPS.Client.FTPSClient.EnsureDir(String remoteDirectoryName, FileTransferCallback transferCallback)    bei AlexPilotti.FTPS.Client.FTPSClient.PutFiles(String localDirectoryName, String remoteDirectoryName, String filePattern, EPatternStyle patternStyle, Boolean recursive, FileTransferCallback transferCallback)    bei ftp.Form1.up_Click(Object sender, EventArgs e) in C:\Users\ich\Documents\V
isual Studio 2008\Projects\ftp_VB\ftp_VB\Form1.vb:Zeile 124."
    TargetSite: {System.Reflection.RuntimeMethodInfo}

The code looks like this:

...
Try
   Dim myftp = New FTPSClient
   Dim erg as string
   ...<some code>
   erg=myftp.Connect(Me.server.Text, New NetworkCredential(Me.benutzer.Text, Me.passwort.Text), ESSLSupportMode.All, New RemoteCertificateValidationCallback(AddressOf ValidateServerCertificate))
   ...<some code>...
   myftp.PutFiles(woher, "/myFTP/" & wohin & "/", "*", EPatternStyle.Wildcard, True, New FileTransferCallback(AddressOf fortschritt))
   log_write("uploaded " & wohin)
Catch ex As Exception
   If ex.Message = "Operation cancelled by the user" Then
      log_write("ACHTUNG: Upload wurde abgebrochen!")
   Else
      Console.WriteLine(ex.StackTrace)
      log_write(ex.Message)
   End If
End Try
...

I also tried to compile the project with 2.0, 3.0 and 3.5 .net framework. Always the same error.

Current config: VS 2008 german, Windows 7 Professional 64 bit and up to date patch-level (as far as I know :-)

Best regards

  -Stefan

Sep 13, 2011 at 11:00 AM

Stefan, 

Just to sort this out, can you please set null/nothing instead of new FileTransferCallback(...)?

 

Cheers,

Alessandro

Sep 13, 2011 at 8:06 PM
Edited Sep 13, 2011 at 8:07 PM

Hi Alessandro,

If I modify the command as requested, everything works fine regarding the correct file transfer :-)

 

myftp.PutFiles(woher, "/myFTP/" & wohin & "/", "*", EPatternStyle.Wildcard, True, Nothing)

 

BUT!

The good thing with your progress-callback-function is that implicitly a context switch is made and also I do 

My.Application.DoEvents()

 

to refresh my other controls and the form itself! If there is no possibility in "getting in between" while files are uploaded, I get a message saying: ContextSwitchDeadlock was detected after 60 sec.

I turned it off in the IDE and everything works fine but due to the fact that with your library a smal number of files but big in size are transfered, the progress-feedback is pretty much appreciated ;-)

Best wishes

  -Stefan

Sep 13, 2011 at 8:47 PM

Stefan,

can you post the content of your fortschritt method?

Please note that the callback comes from a different thread, so UI thread synchronization is typically needed to interact with the UI!

 

Cheers,

Alessandro

Sep 13, 2011 at 11:11 PM
Edited Sep 13, 2011 at 11:12 PM

Hi Alessandro,

here comes the code:

 

    Private Sub fortschritt(ByVal sender As FTPSClient, ByVal action As ETransferActions, ByVal localObjectName As String, ByVal remoteObjectName As String, ByVal fileTransmittedBytes As ULong, ByVal fileTransferSize As ULong, ByRef cancel As Boolean)

        If uebertragungAbbrechen Then
            cancel = True
        End If

        Select Case action
            Case ETransferActions.FileDownloaded, ETransferActions.FileUploaded
                'Wenn Datei fertig!
                Me.fort.Value = 0    
                Me.fortgesamt.PerformStep()
            Case ETransferActions.FileDownloadingStatus, ETransferActions.FileUploadingStatus

                If Now > aktuhr.AddSeconds(1) Then
                    aktuhr = Now
                    Me.fort.Minimum = 0
                    Me.fort.Maximum = fileTransferSize
                    Me.fort.Value = fileTransmittedBytes
                End If

        End Select

        My.Application.DoEvents()

    End Sub

 

Additional infos:

  • fort is the progress bar
  • fortgesamt is also a progress bar showing total files transfere

Best regards

  -Stefan

Sep 13, 2011 at 11:27 PM

Stefan,

Instead of using DoEvents, I'd put the PutFiles call in a separate thread using BackgroundWorker:

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

 

Beside that, as I wrote in the previous post, you need UI thread synchronization for calling UI controls from a separate thread. You should call .Invoke() on your progress bars.

Some examples:

http://www.dailycoding.com/Posts/using_invoke_to_access_object_in_a_windows_formscontrols_thread.aspx

 

Let me know how you progress with it!

 

Cheers,

Alessandro

 

 

 

 

 

 

Sep 14, 2011 at 9:19 AM

Hi Alessandro,

I will give it a try! Although the same code works fine for the putfile command. Progress is indicated correctly. I do not understand why it works (or should I say: it seems to work?) for putfile but not for putfiles. Is this only by chance?

I thought about using the BackgroundWorker, but probably missed a thing on the way, so I gave up because it did not work for me (I think it was somthing with thread synchronization or access to threads from another thread or so...) But anyway, I will give it a second try.

Thanks so far, I will post my efforts ;-)

Best regards,

  -Stefan

Sep 14, 2011 at 9:48 PM

Hi Alessandro,

I don't know if I figured out what you ment. First of all the BackgroundWorker worked fine. But I think that was not my problem: using the function putfiles in the BackgroudWorker_DoWork sub uploads my files to the FTP-server with the FileTransferCallback left unchanged to nothing. My previous code also did it, so this was a hint for not using DoEvents(), right? If so, everything is fine, I understood!

Your comment of the "progress thing" (UI synchronization) I don't know if I understand you:

In my fortschritt sub I want to update the progress indicator if the putfiles call-back is fired. The putfiles command creates a new thread (right?) so direct access to the progress indicator won't work. Now the delegate sub comes into play but I do not know how to integrate it into the call-back.

Here is what I did: Create a delegate sub fortschrittInvoker with the same signature of fortschritt (according you invoke / delagate hint):

Delegate Sub fortschrittInvoker(ByVal sender As FTPSClient, ByVal action As ETransferActions, ByVal localObjectName As String, ByVal remoteObjectName As String, ByVal fileTransmittedBytes As ULong, ByVal fileTransferSize As ULong, ByRef cancel As Boolean)
BUT how do I use the delegate in the putfiles function or if not there where else?

myFTP.PutFiles(woher, "/myFTP/" & wohin & "/", "*", EPatternStyle.Wildcard, True, ?????)
I am lost, sorry, any help is appreciated

Best regards,

  -Stefan

Sep 16, 2011 at 7:44 PM

Stefan,

I will write a sample for that, probably next week, sadly not earlier as I'm awfully busy this week! :-/

 

Cheers,

Alessandro

 

Sep 17, 2011 at 2:10 AM
Edited Sep 17, 2011 at 2:11 AM

Hi Alessandro,

don't worry, that are very good news, thanks for your time in andvance! Next week would be perfekt!

Next to this I was curious what happens inside your library ;-) So I found the method EnsureDir. Could you please be so kind to check this also next week, I changed the CallTransferCallback fileTransferSize from null to 0 in FTPSClient.cs

 

 

private void EnsureDir(string remoteDirectoryName, FileTransferCallback transferCallback)

CallTransferCallback(transferCallback, ETransferActions.RemoteDirectoryCreated, null,remoteDirectoryName, 0, null);

to

CallTransferCallback(transferCallback, ETransferActions.RemoteDirectoryCreated, null,remoteDirectoryName, 0, 0);

 

 

Now it seems to work, but I am not sure if this is correct or not.

Best regards

  -Stefan