Adding a Callback Event Handler in VB.NET

  1. Dim “WithEvents”
    Dim WithEvents ftp As Chilkat.Ftp2
  2. Add some code to create a new instance of the object.
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
            ftp = New Chilkat.Ftp2()
    
            ftp.EnableEvents = True
            ftp.HeartbeatMs = 100
    
    	...
  3. Select the “ftp” object.

  4. Select the event. This causes Visual Studio to generate the event handler function.

  5. Add your application code to the event handler function.
    Private Sub ftp_OnAbortCheck(ByVal sender As Object, ByVal args As Chilkat.AbortCheckEventArgs) Handles ftp.OnAbortCheck
        ' Add your application code here...
        End Sub
    

PercentDone callback counts as an AbortCheck

Question:

“I’ve got the Chilkat C++ libs linked with my project, and am using the HTTP classes successfully.
One thing is confusing me, though. I’ve derived a class from CkHttpProgress.h and overridden AbortCheck(…) to provide cancellation support. However, AbortCheck(…) never gets called. At first, I thought perhaps the HTTP retrieval was occurring too quickly, so I set the “HeartbeatMs” property to “1”, and it still never gets called.
I know the assignment of the callback class is working, because if I override PercentDone(…), it does indeed get called.
Is it possible that my use of the HTTP QuickGetStr(…) method does not support the AbortCheck(…) callback? I’m (successfully) reading a small XML file from a web server in close proximity to the client.”

Answer:
The PercentDone callback method also has an “abort” argument, so it may also be used to abort a method while in progress.  In cases where the PercentDone callback provides abort capability, it counts as an AbortCheck callback — to prevent too many callbacks from bombarding your application.
Therefore, if HeartbeatMs is set to 100ms, and a PercentDone callback is fired, then the timer for the next AbortCheck callback is reset.  The entire operation could be short enough such that all of the callbacks are PercentDone callbacks, and AbortCheck never gets called.  The AbortCheck callback would only be called when the elapsed time between 1% completion intervals exceeds the HeartbeatMs.

Encryption Progress Monitoring

Question:

Is there a way to encrypt a file with progress monitoring?  Huge files can take a while and it seems like the app is hanging.

Answer:

Yes, here is the sample VB6 code:

Public WithEvents myCrypt As ChilkatCrypt2

' ....

Private Sub myCrypt_PercentDone(ByVal pctDone As Long)

    ProgressBar1.Value = pctDone
    
End Sub

Private Sub Command2_Click()

    Set myCrypt = New ChilkatCrypt2
    
    success = myCrypt.UnlockComponent("test")
    
    ' ...

    success = myCrypt.CkEncryptFile("c:/temp/big.txt", "c:/temp/bigEncrypted.dat")
        
End Sub

Aborting in C++

The technique for aborting any time-consuming Chilkat C++ method call follows this recipe:

  1. Declare your own class that derives from the appropriate Chilkat progress monitoring class.  For CkMailMan it is CkMailManProgress (as shown below).  For other Chilkat classes it is CkHttpProgress, CkFtpProgress, CkImapProgress, CkZipProgress, etc.
  2. Create an implementation for the AbortCheck method.  This will override the default implementation from the base class.  (The default implementation simply does nothing.)
  3. The AbortCheck method is called periodically according to the value of the HeartbeatMs property.  The default value of HeartbeatMs is 0, which indicate that no AbortCheck events should be called.  Set HeartbeatMs to a non-zero value (in milliseconds) to enable the AbortCheck callbacks.  Do this by calling put_HeartbeatMs(someValue)  as shown below.
  4. Whenever your application wishes to abort an operation in progress (SMTP, POP3, IMAP, Zip, FTP, etc.), set the abort boolean argument of AbortCheck to true.
  5. Don’t forget to hookup your event monitoring class by calling the SetProgressCallback method.  (See the code example below.)  In some classes, such as for CkImap, the way to hookup the event class is via the put_EventCallbackObject function.  Please review the .h file for details.
#include <CkMailManProgress.h>

class MyMailProgress : public CkMailManProgress
    {
    public:
	MyMailProgress(void) { }
	virtual ~MyMailProgress(void) { }

	// Override the AbortCheck method (which is a virtual method in CkMailProgress)
	// Called periodically according to the value of the HeartbeatMs property.
	void AbortCheck(bool *abort)
	    {
	    printf("AbortCheck!\n");

	    // If your application wishes to abort the email sending/receiving operation,
	    // set the abort boolean like this:
	    *abort = true;
	    }

        // Percentage completion events may also be overridden to abort time-consuming operations.
	void SendPercentDone(long pctDone, bool *abort) 
	    { 
	    printf("SendPercentDone: %d percent\n",pctDone);
	    }
	void ReadPercentDone(long pctDone, bool *abort) 
	    { 
	    printf("ReadPercentDone: %d percent\n",pctDone);
	    }

    };

void AbortCheckDemo(void)
    {
    CkMailMan mailman;
    bool success;
    success = mailman.UnlockComponent("30-day trial");
    if (success != true)
	{
        printf("%s\n",mailman.lastErrorText());
        return;
	}

    // Set the HeartbeatMs property so that AbortCheck is called once every 80 milliseconds.
    mailman.put_HeartbeatMs(80);

    MyMailProgress myProgress;
    mailman.SetProgressCallback(&myProgress);

    CkEmail email;
    // ...
    // ...

    // The AbortCheck event is called periodically while SendEmail is in progress..
    // (Note: In some cases, including here, a percent-done event is also called, and it will have an "abort"
    // boolean argument that may be set to "true" to force an abort.
    // If the percent-done callbacks happen more frequently than the HeartbeatMs setting, then 
    // the AbortCheck events may not be fired at all.)
    success = mailman.SendEmail(email);
    if (success != true)
	{
        printf("%s\n",mailman.lastErrorText());
        return;
	}

    }

SendBufferSize/MaxPacketSize can make progress events more frequent in FTP and SSH/SFTP

Question:

I’ve downloaded the trial version of your FTP2 ActiveX control. I’m
using it in Visual FoxPro 9, but need to have a progress bar to track
an upload. When using your asynchronous example code, the progress
bar jumps from 0 to 524288 and so on. I need much more precision than
that so the progress bar will update smoothly. How do I accomplish
this with your tools?

Solution:

Set the SendBufferSize property to a smaller value, such as 8192. The FTP2 component has the SendBufferSize property. The equivalent property in SSH/SFTP is MaxPacketSize.

HTTP Progress Monitoring in C++

This blog post shows how to monitor the progress of HTTP uploads and downloads in C++.  The first step is to create a C++ callback class that derives from the CkHttpProgress base class.  You’ll be overriding one or more of the callback methods.  For example:

class MyHttpProgress : public CkHttpProgress
    {
    public:
	MyHttpProgress(void) { }
	virtual ~MyHttpProgress(void) { }

	void PercentDone(int pctDone, bool *abort) 
	    { 
	    printf("PercentDone: %d percent\n",pctDone);

	    // To abort the HTTP operation, set the abort flag equal to true.
	    //if (pctDone > 10)
		//{
		//*abort = true;
		//}
	    }
	void AbortCheck(bool *abort) 
	    { 
	    // To abort the HTTP operation, set the abort flag equal to true.
            // Like this:
            // *abort = true;

            // Note: The AbortCheck event callback is called periodically according to the HeartbeatMs 
            // property setting.

	    printf("AbortCheck!\n");
	    }
	void HttpBeginReceive(void) { printf("HttpBeginReceive!\n"); }
	void HttpEndReceive(bool success) { printf("HttpEndReceive!\n"); }
	void HttpBeginSend(void) { printf("HttpBeginSend!\n"); }
	void HttpEndSend(bool success) { printf("HttpEndSend!\n"); }

    };

In your C++ application, create an instance of your MyHttpProgress class and tell the CkHttp object to use it by calling put_EventCallbackObject. Here’s an example:

void TestDownloadWithEventCallbacks(void)
    {
    MyHttpProgress eventObj;

    CkHttp http;
    bool success = http.UnlockComponent("Anything for 30-day trial");
    
    http.put_EventCallbackObject(&eventObj);

    success = http.Download("http://www.chilkatsoft.com/something/something.zip","something.zip");
    if (!success) 
        {
        printf("%s\n",http.lastErrorText());
        }
    else
        {
        printf("Finished.\n");
        }

    }

SFTP Progress Monitoring and Abort (C#)

Here is an example for monitoring the progress of an SFTP file transfer:

        void sftp_OnPercentDone(object sender, Chilkat.PercentDoneEventArgs args)
        {
            progressBar1.Value = args.PercentDone;

            // To abort at any point, you may set args.Abort = true  
            // args.Abort = true;
        }

        void sftp_OnAbortCheck(object sender, Chilkat.AbortCheckEventArgs args)
        {
            // See http://cknotes.com/?p=149  for more information about 
            // using the AbortCheck event...
           
        }

private void button2_Click(object sender, EventArgs e)
{
	// SFTP upload with progress monitoring.
	Chilkat.SFtp sftp = new Chilkat.SFtp();

	// IMPORTANT: Enable event callbacks:
	sftp.EnableEvents = true;

	// Unlock the component.
	bool success = sftp.UnlockComponent("Anything for 30-day trial");
	if (!success)
	{
	textBox1.Text = sftp.LastErrorText;
	return;
	}

	// Connect to the SSH/SFTP server. (use a domain name or IP address)
	success = sftp.Connect("192.168.1.117", 22);
	if (!success)
	{
	textBox1.Text = sftp.LastErrorText;
	return;
	}

	// Authenticate..
	success = sftp.AuthenticatePw("chilkat", "myPassword");
	if (!success)
	{
	textBox1.Text = sftp.LastErrorText;
	return;
	}

	success = sftp.InitializeSftp();
	if (!success)
	{
	textBox1.Text = sftp.LastErrorText;
	return;
	}

	// Establish some event handlers:
	sftp.OnAbortCheck += new Chilkat.SFtp.AbortCheckEventHandler(sftp_OnAbortCheck);
	sftp.OnPercentDone += new Chilkat.SFtp.PercentDoneEventHandler(sftp_OnPercentDone);

	// See http://cknotes.com/?p=149  for more information about 
	// using the AbortCheck event...

	// Do an upload.
	// Note: If the file to be uploaded or downloaded is too small, 
	// the PercentDone callback will not be called for each 1%.
	// It's possible if the file is so small relative to the speed
	// of the connection that you may get a single 100% callback if
	// the data transfer happens almost instantaneously.
	string localFilepath = "c:/temp/hamlet.xml";
	string remoteFilepath = "hamlet.xml";
	progressBar1.Value = 0;
	success = sftp.UploadFileByName(remoteFilepath, localFilepath);
	if (!success)
	{
	textBox1.Text = sftp.LastErrorText;
	return;
	}
	MessageBox.Show("OK!");
}

SFTP Upload in VB6 with Progress Monitoring

The PercentDone event is called when the percentage completion increases by one or more points.  To use events in VB6, Dim the variable WithEvents.  Then name the event callback using the variable name.  (You should already understand how to use VB6 events in general prior to using the Chilkat objects.  A good VB6 book is “Programming Visual Basic 6.0” by Francesco Balena.

Here’s the example:

' Assumes a Form with a Button named "Command1" and a progress bar named "ProgressBar1".

Dim WithEvents sftp As ChilkatSFtp

Private Sub sftp_PercentDone(ByVal pctDone As Long)
    ProgressBar1.Value = pctDone
End Sub

Private Sub Command1_Click()

...


    ProgressBar1.Value = 0
    
    success = sftp.UploadFileByName(remoteFilePath, localFilePath)
    If (success <> 1) Then
        MsgBox sftp.LastErrorText
        Exit Sub
    End If
    
    MsgBox "Success."

End Sub

VB.NET HTTP Download with percent-done progress monitoring

Here is an example:

    Dim WithEvents http As Chilkat.Http

    Private Sub http_OnPercentDone(ByVal sender As Object, ByVal args As Chilkat.PercentDoneEventArgs) Handles http.OnPercentDone
        ProgressBar1.Value = args.PercentDone
    End Sub

    Private Sub HttpDownloadTest()

        http = New Chilkat.Http()

        Dim success As Boolean

        '  Any string unlocks the component for the 1st 30-days.
        success = http.UnlockComponent("Anything for 30-day trial")
        If (success <> True) Then
            MsgBox(http.LastErrorText)
            Exit Sub
        End If

        ' Enable event callbacks...
        http.EnableEvents = True

        '  Download the Python language install.
        '  Note: This URL may have changed since this example was created.
        success = http.Download("http://www.python.org/ftp/python/2.5/python-2.5.msi", "python-2.5.msi")
        If (success <> True) Then
            MsgBox(http.LastErrorText)
        Else
            MsgBox("Python Download Complete!")
        End If

        http = Nothing

    End Sub

SFTP Progress Monitoring in C++

This C++ example demonstrates how to derive a class from the CkSFtpProgress base class to implement progress monitoring and abort for SFTP:

// To monitor SFTP progress, derive a class from CkSFtpProgress and
// provide implementations for AbortCheck and PercentDone:
class MySFtpProgress : public CkSFtpProgress  
{
    public:
	MySFtpProgress() { }
	virtual ~MySFtpProgress() { }

	// Called periodically during any SFTP method that communicates with
	// the server.  The HeartbeatMs property controls the frequency
	// of callbacks.  The default HeartbeatMs value = 0, which disables
	// AbortCheck callbacks.
	void AbortCheck(bool *abort) 
	    { 
	    printf("SFTP abort check...\n");

	    // To abort any operation while in progress, set the "abort" argument
	    // equal to true, like this:    (uncomment the line below to abort)
	    //*abort = true;
	    }

	// The PercentDone callbacks is called for any method where it it is possible
	// to monitor a percentage completion, such as uploading and downloading files.
	void PercentDone(int pctDone, bool *abort)
	    {
	    printf("SFTP percent done: %d\n", pctDone);

	    // To abort an operation while in progress, set the "abort" argument
	    // equal to true, like this:    (uncomment the line below to abort)
	    //*abort = true;
	    }
    };


void TestSftp(void)
    {
    CkSFtp sftp;

    bool success = sftp.UnlockComponent("Anything for 30-day trial");
    if (success != true) {
        printf("%s\n",sftp.lastErrorText());
        return;
    }

    // Set the event callback object:
    MySFtpProgress myProgress;
    sftp.put_EventCallbackObject(&myProgress);

    // Set HeartbeatMs so that AbortCheck events are called once every 100 milliseconds.
    sftp.put_HeartbeatMs(100);

    const char *hostname = "192.168.1.107"; 
    long port = 22;

    sftp.put_ConnectTimeoutMs(8000);
    sftp.put_IdleTimeoutMs(8000);

    printf("calling Connect...\n");
    success = sftp.Connect(hostname,port);
    if (success != true) {
        printf("%s\n",sftp.lastErrorText());
        return;
    }

    //  Authenticate using login/password:
    printf("calling AuthenticatePw...\n");
    success = sftp.AuthenticatePw("myLogin","myPassword");
    if (success != true) {
        printf("%s\n",sftp.lastErrorText());
        return;
    }

    printf("calling InitializeSftp...\n");
    success = sftp.InitializeSftp();
    if (success != true) {
        printf("%s\n",sftp.lastErrorText());
        return;
    }

    printf("calling DownloadFileByName...\n");
    success = sftp.DownloadFileByName("hamlet.xml","out.txt");
    if (success != true) {
        printf("%s\n",sftp.lastErrorText());
        return;
    }
    printf("Download successful!\n");