I today needed to create an autoupdate solution for an application on a device (Win CE, Windows Mobile 6.5 Professionel). The application is to support auto update, to allow the device to always be running the latest bits. Now, this can seem a pretty trivial task, but again – you are quite limited when it comes to support on the CE-device.
The issue is not so much how to download the new files from a remote server. The issue is more how do I shutdown an application in a nice way to be allowed to update parts of this application and next restart the application (in the illustration: how does ProcessB kill ProcessA?). Of course you could enumerate the processlist and invoke KILL on a process, but that would be like “pulling away the carpet” under the feet of the application. Not the best solution. I want to be allowed to inform the application that it should shutdown in it’s own pace.
The options I could come up with were these:
1) WCF
2) Interprocess Communication (named pipe)
3) Interprocess (tcp-sockets)
4) ClickOnce

1) WCF
Well – this was quite a short adventure. It is not supported on CE-devices to host a WCF-service that one could call to shut down the Process (A). So, so much for that.
2) Interprocess Comm. (named pipe)
Again a pretty short adventure. Named pipes are not supported in any CE-framework.
3) Interprocess Comm. (tcp-sockets)
Now we are getting somewhere. This is supported by CE and is a viable route for this purpose.
4) ClickOnce
Again – this would have been the best solution of them all. But, ClickOnce is not supported on a CE-device.
Solution:
So we are left with option (3): Socket communication. As a POC, I made a system with 2 applications (Client to shutdown a Server). The 2 applications are seen here.
Server (to be shutdown, called “Process A” in above illustration):
This application does nothing (in this POC), but listening for an incoming message from the Client. Once this message is received and it contains the word “KILL”; it will gracefully shutdown after having freed resources.
Note: In a real life scenario – you would most likely want the listening part to run on a background thread. In the POC, this is run on the UI-thread hence it is pretty non-responsive when it comes to the UI of the application (as this thread is now blocked by the TcpListener!)
Code:
private void btnStart_Click(object sender, EventArgs e)
{
var ip = IPAddress.Loopback;
var listener = new TcpListener(ip, 9090);
lblStatus.Text = listener.LocalEndpoint.ToString();
listener.Start();
var client = listener.AcceptTcpClient(); //block and wait...
//if here - received data
byte[] buffer = new byte[1024]; //should be enough for now.
try
{
var ns = client.GetStream();
int index = 0;
while (true)
{
int readData = ns.Read(buffer, index, 1); //read one at the time (CHANGE)
index += readData;
if (readData == 0)
break;
}
}
finally
{
client.Close();
}
//write out buffer
string rcv = Encoding.ASCII.GetString(buffer, 0, buffer.Length);
tbxData.Text = rcv;
bool doKill = (rcv == "KILL");
lblStatus.Text = "Stopped";
buffer = null;
if (doKill)
{
CleanUpResources(); //clean up stuff before shutting down
Application.Exit();
}
}
Client (to shutdown server, called “ProcessB” in the above illustration):
This application can ask the Server to shut down. It basically just establishes a socket connection to the Server, and tells this to shutdown. The “Command” sent is only a simple string at this time; but it could be an object that was serialized by the Client and then de-serialized on the Server side. This could carry more meaningful information.
Code:
private void btnKill_Click(object sender, EventArgs e)
{
var ip = IPAddress.Loopback;
var ipEp = new IPEndPoint(ip,9090);
var cl = new TcpClient();
cl.Connect(ipEp);
byte[] data = Encoding.ASCII.GetBytes("KILL");
cl.GetStream().Write(data, 0, data.Length);
cl.GetStream().Flush();
cl.GetStream().Close();
//done
}