Posts Tagged ‘C#’

The Chilkat Mono Library for Linux, Windows, and MAC OS X Beta is ready for testing:

http://www.chilkatsoft.com/mono.asp

The Chilkat C/C++ libs for Visual Studio 2013 (VC12) downloads are ready:

32-bit: http://www.chilkatsoft.com/preRelease/chilkat-9.5.0-x86-vc12.zip
64-bit: http://www.chilkatsoft.com/preRelease/chilkat-9.5.0-x86_64-vc12.zip

Question:

In C++, is it somehow possible to specify a desired charset (like ISO-8859-15) when getting mail headers with POP3?

Answer:

Instead of calling the method that returns a “const char *” — which can return either utf-8 or ANSI (see this Chilkat blog post about the Utf8 property common to all Chilkat C++ classes), call the alternate method that returns the string in a CkString object.  You can then get the iso-8859-15 string from the CkString object.

Each Chilkat C++ method that returns a string has two versions — an upper-case version that returns the string in a CkString (always the last argument), and a lower-case version that returns a “const char *”.

For example, in the CkEmail class:

bool GetHeaderField(const char *fieldName, CkString &outFieldValue);
const char *getHeaderField(const char *fieldName);

The lower-case method returning a “const char *” returns a pointer to memory that may be overwritten in subsequent calls.  Therefore, make sure to copy the string to a safe place immediately before making additional calls on the same Chilkat object instance.  (Only methods that also return “const char *” would overwrite the memory from a previous call.)

The upper-case version of the method returns the string in a CkString object.  It is an output-only argument, meaning that the CkString contents are replaced, not appended.  To get the iso-8859-15 string from the CkString, call the getEnc method.  For example:

const char  *str_iso_8859_15 = outFieldValue.getEnc("iso-8859-15");

This returns a NULL-terminated string where each character is represented as a single byte using the iso-8859-15 encoding.

The Chilkat C/C++ libraries are now available for MAC OS X. For the download link and more information, see http://www.chilkatsoft.com/installMacOSX.asp

Chilkat will soon release MAC OS X compatible builds for Java, Perl, Python, and Ruby. Following that, builds for the IOS (IPhone) will be released, along with Objective-C/C++ native libraries for both MAC OS X and IPhone.

Here’s an example that demonstrates a rough start to creating a C# console SSH shell terminal (where the user can type commands and output from the remote command echos to the console:

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace SshTerminalConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            Chilkat.Ssh ssh = new Chilkat.Ssh();
            ssh.UnlockComponent("Test");

            //  Hostname may be an IP address or hostname:
            string hostname = "192.168.1.117";
            int port = 22;

            Console.WriteLine("Connecting...");

            //ssh.KeepSessionLog = true;
            bool success = ssh.Connect(hostname, port);
            if (success != true)
            {
                Console.WriteLine(ssh.LastErrorText + "\r\n");
                // Read so we can see the error before the console closes.
                string x = Console.ReadLine();      
                return;
            }

            //  When reading, if no additional data arrives for more than
            //  5 seconds, then abort:
            ssh.IdleTimeoutMs = 5000;

            Console.WriteLine("Authenticating...");

            //  SSH Server Authentication
            //  If there is no login/password required, you must still call
            //  AuthenticatePw and use any values for login/password.
            success = ssh.AuthenticatePw("chilkat", "***");
            if (success != true)
            {
                Console.WriteLine(ssh.LastErrorText + "\r\n");
                // Read so we can see the error before the console closes.
                string x = Console.ReadLine();
                return;
            }

            Console.WriteLine("Opening Channel...");

            //  Open a session channel.
            int channelNum = ssh.OpenSessionChannel();
            if (channelNum < 0)
            {
                Console.WriteLine(ssh.LastErrorText + "\r\n");
                // Read so we can see the error before the console closes.
                string x = Console.ReadLine();
                return;
            }

            //  Request a pseudo-terminal
            string termType;
            termType = "dumb";
            int widthInChars;
            widthInChars = 120;
            int heightInChars;
            heightInChars = 40;
            int pixWidth;
            pixWidth = 0;
            int pixHeight;
            pixHeight = 0;
            success = ssh.SendReqPty(channelNum, termType, widthInChars, heightInChars, pixWidth, pixHeight);
            if (success != true)
            {
                Console.WriteLine(ssh.LastErrorText + "\r\n");
                // Read so we can see the error before the console closes.
                string x = Console.ReadLine();
                return;
            }

            Console.WriteLine("Starting a shell...");

            //  Start a shell on the channel:
            success = ssh.SendReqShell(channelNum);
            if (success != true)
            {
                Console.WriteLine(ssh.LastErrorText + "\r\n");
                // Read so we can see the error before the console closes.
                string x = Console.ReadLine();
                return;
            }

            // Loop to read from the SSH channel, output to the console, and read keyboard input from the console.
            StringBuilder sb = new StringBuilder();
            while (true)
            {
                if (Console.KeyAvailable)
                {
                    ConsoleKeyInfo key = Console.ReadKey(true);
                    Console.Write(key.KeyChar);

                    switch (key.Key)
                    {
                        case ConsoleKey.Enter:
                            Console.WriteLine("");

                            sb.Append("\n");
                            success = ssh.ChannelSendString(channelNum, sb.ToString(), "ansi");
                            if (success != true)
                            {
                                Console.WriteLine(ssh.LastErrorText + "\r\n");
                                // Read so we can see the error before the console closes.
                                string x = Console.ReadLine();
                                return;
                            }

                            sb.Length = 0;
                            break;
                        default:
                            //Console.Write(key.KeyChar);
                            sb.Append(key.KeyChar);
                            break;
                    }

                }

                // Now check for incoming data from the SSH channel.
                int retval = ssh.ChannelPoll(channelNum, 10);
                if (retval == -1)
                {
                    Console.Write(ssh.LastErrorText);
                    Console.WriteLine("");
                    // Read so we can see the error before the console closes.
                    string x = Console.ReadLine();
                    return;
                }
                if (retval > 0)
                {
                    Console.Write(ssh.GetReceivedText(channelNum, "ansi"));
                }
                else
                {
                    // If data arrived, loop around and get more immediately.
                    // Otherwise wait 20ms.
                    System.Threading.Thread.Sleep(20);
                }

            }  

        }
    }
}

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 CkMailProgress (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 <CkMailProgress.h>

class MyMailProgress : public CkMailProgress
    {
    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;
	}

    }

Question:

I need to send a unicode string (e.g TCHAR *ptr) but the API only allows to send char.

Answer:

/*
The _TCHAR data type is defined conditionally in Tchar.h. 
If the symbol _UNICODE is defined for your build, _TCHAR is defined as wchar_t; 
otherwise, for single-byte and MBCS builds, it is defined as char.
*/
bool sendString(CkSocket &sock, TCHAR *str)
    {
    bool success = false;

#ifdef _UNICODE
    success = sock.SendBytes((const unsigned char *)str, _tcslen(str) * 2);
#else
    success = sock.SendString(str);
#endif

    return success;
    }

Question:

In your examples online, we have noticed that .Dispose() is never
called after using Chilkat classes (we are writing in C#).

Is calling .Dispose() recommended?  Does your code not need to destroy
any native resources or handles that would normally be cleaned up in
the Dispose method (the IDisposeable interface) ?

Answer:

For objects that manage a TCP/IP socket connection with a server (FTP2, SSH, SFTP, POP3, SMTP, IMAP, HTTP, etc.) then calling Dispose will close the connection.  Aside from memory-usage and socket connections, there are no other resources used by Chilkat classes.  Dispose may also deallocate some internal memory.

The important thing to realize is that once Dispose is called, your code should not use that particular instance of the object again.  I always prefer a more explicit approach.  For example, instead of calling Chilkat.MailMan.Dispose to ensure that a connection to the SMTP server is closed, call Chilkat.MailMan.CloseSmtpConnection.  (If the mailman is not actually connected, calling CloseSmtpConnection does NOT result in an error.  It is harmless.)

Also, when an Chilkat object’s finalizer is called (i.e. when it is garbage-collected), any existing socket connections are closed and internal memory is (of course) deallocated.   You may force garbage collection by doing this (in C#)

 GC.Collect();
 GC.WaitForPendingFinalizers();

Question:

I am developing a single EXE in C++ that doesn’t make use of any external libraries and including MFC. Can I add your zip libaries to my application and still maintain the application as a single EXE?

Answer:

Yes, the Chilkat C++ libs may be linked directly into your application.  This results in a single EXE containing the Chilkat library code required to satisfy all direct and indirect references.  (The linker includes only the code needed to resolve all references.)  You may run your EXE on any computer because the licensing is royalty-free.  Internally, Chilkat does not use or reference MFC.   (Note: MFC applications may still use the Chilkat libs.  The point is this: if your application does not use MFC, then linking with Chilkat will not cause MFC to be “pulled-into” your EXE.)

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");
        }

    }