Click here to Skip to main content
15,880,796 members
Articles / Programming Languages / C#

FTP from Windows CE 5.0 Devices

Rate me:
Please Sign up or sign in to vote.
4.75/5 (8 votes)
16 Apr 2014CPOL5 min read 53.9K   2.7K   14   20
Windows CE devices are not setup properly for the use of FTP despite the HttpWebRequest and HttpWebResponse classes.

Windows CE still alive!

Introduction

In the industry, many hand-held devices with bar code scanners are still in use. With Windows CE 5.0, it is possible to program applications for these devices, who's technology was 10 years ago mainstream. One of my clients is using these devices to scan bar codes outside his buildings. While registering his data in SQL Compact, he does not want to use the sync framework to get his data in the central system. He uses FTP. And FTP is not so well supported in the Compact .NET Framework. Microsoft offers a solution to use HttpWebRequest to send the file to the central system. But that NAS replies me with '405 Method not Allowed'. After that, I used the OpenNet CF DLLs to use FtpRequest. It looked like the file was sent, but no data was received on the NAS. Despite the log files, no errors were found. After these pitfalls, I decided to use a TcpClient to send the files. And that works like a charm. In this article, only BASIC sending with FTP is described. Please read the comments in the source code.

One other thing. Visual Studio 2008 was the latest version to be able to create such mobile applications. There are possibilities in VS 2013 but I do not have a license for that (yet).

Background

The TcpClient allows you to create connections to other client over the TCP/IP protocol. In that case, you can make your own FTP client to send files. A low level solution that works, but FTP must be known by the programmer. In fact, it is a question/answer system. Furthermore the Compact Framework supports:

C#
event Action<someObject> SomeEventAFormCanSubScribeToEvent;

So an interface can describe the event and can be shot via the class and the form only needs the received object to update its form objects.

Due to limitations of the Compact Framework 2.0, FTP is not so well incorporated in the Framework as is in the newer Frameworks. By writing FTP possibilities in your code, you can achieve sending of files.

Using the Code

When you use this code, you are able to connect to an FTP Server and send a file to it. You can set up connection with 'User name' and 'Password', but you can also comment out these lines. In the program, a check is done if your device can connect to the PPP_Peer protocol, otherwise you cannot reach an FTP server.

Getting Started

In this example, a simple form holds:

  • Label with text "File Progress"
  • ProgressBar which shows how many files have been sent
  • Label with response from the FTP Server
  • Label with text "Files"
  • ListBox which will show the file names ready to be sent. The ListBox is ReadOnly. While transferring files, the transferred file is selected in the list.
  • Button with text "Start". If the ListBox contains more than 0 lines and PPP_Peer can be found, the button is Enabled.
  • Instantiates the interface IFtpClient and uses the available commands to transfer files and get event updates from the files.

The form listens to the next events.

  • FtpProgressEvent: holds an FtpProgress business object with data of the current transferring file.
  • RetrieveFileListEvent: Gets a FileInfo[] object with files that can be sent.
  • SendFinishedEvent: Receives a String message to show in a message-box after all files have been transferred.

The class FtpClient uses class FTPHelper and interface IFtpClient. In class FtpClient, you will find 3 methods:

  • public GetLocalFiles: This sets a FileInfo[] object with the available files and shoots the RetrieveFileListEventevent.
  • public SendFiles(): Methods to send the files in the FileInfo[] object.
  • private FtpClient_FtpCurrentProgressEvent(<code>FtpProgress ftpProgress). This method listens to the FtpCurrentProgressEvent in FTPHelper class; The event is set in the constructor of the FtpClient class. This methods sets the FtpProgressEvent so the form updates its controls.

There is 1 read only property in the class called ActiveSyncConnectionEnabled. This property can tell if the device can connect to the FTP server via FTPHelper class Boolean ActiveSyncConnected.

In class FTPHelper, you will find 5 methods:

  • SendFTPCommand(<code>String Command, String Verb, String Verb2): writes the command with needed verb(s) to the StreamWriter
  • CreatePassiveFtpSocketInformation(): when sending a file, the PASV command is used. The response gives a string that must be converted to an IPEndPoint with a port number.
  • ReadLineFromStream(): After writing a command to the StreamWriter, read the response stream. This response is send to the FtpCurrentProgressEvent event.
  • ReadAllBytesFromTheFile(<code>FileInfo file): Read the bytes from the file that will be sent to the FTP server.
  • StartCurrentProgressEvent(): Method to send the current FtpProgress business object to the form via FtpClient class.

Sample code

Business Objects

There are 2 business objects in the source files:

  • FtpPassiveConnection: which holds the passive IP address and the passive port number:
    C#
    public IPAddress PassiveIP;
    public Int32 PasssivePortNr;
  • FtpProgress: which holds information about the current file in transfer and information for the ProgressBar:
    C#
    public Int32 CurrentFileNr; // after sending each file Iterate +1. The selectedIndex of the ListBox will reflect the current file in sending
    public Int32 LastFileNr;   // needed for the Maximum property for the ProgressBar
    public String FileName;    // name of the current file name
    public Int64 FileBytes;    // the number of bytes to be send. When streaming in parts a file progress can be shown (2nd progress bar needed)
    public Int64 SendFileBytes; // number of bytes send
    public String FtpResponse;  // current FtpReponse

There is 1 helper class called IOHelpers and fills the FileInfo[] object in the application.
There is 1 class for basic exception handling ExceptionHandling.ShowMessage. It shows a MessageBox with the occurred exception.

Basic Information on TcpClient

When using the TcpClient for the Compact Framework, you'll notice no difference with that of the 2.0 framework. See here. You can easily use the TcpClient class by stating:

C#
TcpClient client = new TcpClient();
// in this case the next line will be
client.Connect(servername, port); // servername = String, port is Int32

or:

C#
TcpClient client = new TcpClient(servername, port); // servername = String, port is Int32

Note that you can also connect by using an IPEndPoint. See here.

TcpClient uses IDisposable so it is advised to use:

C#
using (TcpClient client = new TcpClient(servername, port))
{
// code here
}

Basic FTP Knowledge

Some FTPServers have welcoming messages of more than 1 line. So when only reading 1 line, the client starts running behind the truth. FileZille server has 3 lines in the welcoming message. But how to detect in FTP answers if you are dealing with multiple lines or not. The answer of an FTP server always start with 3 digits. After these 3 digits, you see a - or a <space>. When you see the space, you know you are on the last line of the server's answer. In code:

C#
protected void ReadLineFromStream()
{
    bool MultipleLines = false;
    while (true)
    {
        string line = rdStrm.ReadLine();
        MultipleLines = line.Substring(3, 1).Equals("-");

        ftpProg.FtpResponse = line;
        StartCurrentProgressEvent();
        if (!MultipleLines) break;
    }
}

Points of Interest

The TcpClient is useful with older communication technologies that are still used today.

History

  • 15th April, 2014
    • Initial article
  • 25th April, 2014
    • Fixed NULL reference exception
    • Reading all lines from the stream instead of one
  • 30th April, 2015
    • Solved the Control.Invoke exception caused by using a thread to start the FTP sending of files. It is now non-threaded created.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Netherlands Netherlands
I started in the eightees with Basic and QuickBasic. When the ninetees started dBase was my thing. Close to the millenium years I swapped to C++ and since 2003 it is only programming in c#.

There is one thing about me.
Not that kind of OO guy and definately not an ORM-fan. I know a database to well to give the importance of data out in the hands of a tool.

Comments and Discussions

 
GeneralMy vote of 5 Pin
Member 1398856418-Sep-18 0:49
Member 1398856418-Sep-18 0:49 
QuestionExcellent Post Pin
Member 1039052021-Oct-17 13:25
Member 1039052021-Oct-17 13:25 
AnswerRe: Excellent Post Pin
Herman<T>.Instance24-Oct-17 0:21
Herman<T>.Instance24-Oct-17 0:21 
QuestionThanks and help Pin
neso_best200219-Oct-17 9:44
neso_best200219-Oct-17 9:44 
Dear Friend I aprecciate a lot for your program

I use it for send files form hand held to ftp server

Do you have the code for download from server to hand held using ftp too

Please let me know if you can send me the rest of the code please

GOD Bless you

Best regards from Mexico City

David Aguilera
AnswerRe: Thanks and help Pin
Herman<T>.Instance24-Oct-17 0:21
Herman<T>.Instance24-Oct-17 0:21 
Questionthanks Pin
hankjiang30-Jun-15 20:16
hankjiang30-Jun-15 20:16 
QuestionControl.Invoke must be used to interact with controls created on a separate thread Pin
AbdellahDidi21-Apr-15 12:30
AbdellahDidi21-Apr-15 12:30 
AnswerRe: Control.Invoke must be used to interact with controls created on a separate thread Pin
Herman<T>.Instance21-Apr-15 20:01
Herman<T>.Instance21-Apr-15 20:01 
GeneralRe: Control.Invoke must be used to interact with controls created on a separate thread Pin
AbdellahDidi26-Apr-15 1:21
AbdellahDidi26-Apr-15 1:21 
GeneralRe: Control.Invoke must be used to interact with controls created on a separate thread Pin
Herman<T>.Instance26-Apr-15 7:34
Herman<T>.Instance26-Apr-15 7:34 
GeneralRe: Control.Invoke must be used to interact with controls created on a separate thread Pin
Herman<T>.Instance30-Apr-15 11:38
Herman<T>.Instance30-Apr-15 11:38 
GeneralRe: Control.Invoke must be used to interact with controls created on a separate thread Pin
AbdellahDidi1-May-15 1:41
AbdellahDidi1-May-15 1:41 
AnswerRe: Control.Invoke must be used to interact with controls created on a separate thread Pin
Herman<T>.Instance30-Apr-15 11:50
Herman<T>.Instance30-Apr-15 11:50 
QuestionFTP from Windows CE 5.0 Devices Pin
assa626-Jan-15 7:46
assa626-Jan-15 7:46 
AnswerRe: FTP from Windows CE 5.0 Devices Pin
Herman<T>.Instance6-Jan-15 12:32
Herman<T>.Instance6-Jan-15 12:32 
AnswerRe: FTP from Windows CE 5.0 Devices Pin
assa626-Jan-15 21:46
assa626-Jan-15 21:46 
GeneralRe: FTP from Windows CE 5.0 Devices Pin
Herman<T>.Instance7-Jan-15 2:02
Herman<T>.Instance7-Jan-15 2:02 
AnswerRe: FTP from Windows CE 5.0 Devices Pin
Herman<T>.Instance30-Apr-15 11:51
Herman<T>.Instance30-Apr-15 11:51 
QuestionNull reference Pin
Herman<T>.Instance16-Apr-14 10:46
Herman<T>.Instance16-Apr-14 10:46 
AnswerRe: Null reference Pin
Herman<T>.Instance29-Apr-14 8:44
Herman<T>.Instance29-Apr-14 8:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.