views:

237

answers:

1

I am designing an app using .NET 2.0 remoting. It has a single server and multiple clients which are workstations or laptops which may be on or off-line at any time.

Part of the design is that the server holds a copy of the client installer MSI. The plan is that for the first installation, the clients will be rolled-out using group policy, but that once installed the Client software will be automatically updated from the server every time the server copy is updated.

To do the transfer is technically easy in remoting, the server loads the update file using File.ReadAllBytes into a byte[] array, attaches it to a remoted object, then the client saves it using File.WriteAllBytes and uses Process.Start to commence the msi installation using /passive.

The design question is whether the update should be pushed from the server or pulled from the clients. Pushing from the server is faster, but leaves the disadvantage that the clients may be offline and may need to be updated at some random point in the future whenever they connect. Pulling from the client is preferable because it allows clients to update themselves automatically as and when they come online.

There are a great many ways to achieve this end, all of them give rise to versioning issues with the objects which are used in the remoting call and require subsequent versions to retain compatibility for the upgrading interfaces.

The main disadvantage of client pulling the file is that many clients may overload the server (the msi file to transfer is 5mb and there may be 200 clients) and although I could program the clients to retry until successful, on the server side there seems to be no simple way to schedule the number of remoting threads received because once I have loaded the packet and returned control to the remoting interface on the server side, there is no easy way apparent to determine how long the actual transfer of the data takes. I have considered a great many workarounds including limiting the actual connections by number over a period of time, but this will never reflect the actual working capacity of the LAN and would still not seem to be idea. I could probably use a custom channel sink to control the thread count (I already have a full set of custom sinks installed) but wish to avoid this if at all possible because that would have to be a last resort. I would prefer to keep the logic out of the channel sinks for simplicity.

Are there any well-known .NET apps that offer this type of automatic updates of data to clients which may be coming on or off-line at any time?

+2  A: 

For a pre-built solution in .NET for keeping client versions of software up-to-date, ClickOnce, included with Visual Studio does a fairly reliable job. On application startup, the application will check if an updated version has been uploaded to a server. If a new version is present, it will automatically download the latest version and install.

For a relatively simple project, ClickOnce generally works very well and is extremely simple to get up and running. You'll save yourself the effort of writing the update checking code and the transfer code, and since it will run on IIS, your concerns about multiple users downloading are somewhat alleviated (it's still possible to exhaust your bandwidth, but IIS will do fine with a large number of clients).

Ryan Brunner
Thanks Ryan. I need to control the distribution from my own custom .NET server running on the client's LAN and don't want to get involved with IIS. I've got all the transfer and checking code written already (its relatively simple to do the actual work in .NET). I had a look at ClickOnce but it didn't quite do what I need. There are many apps like network antivirus that push out updates to clients but they seem to be mostly legacy (i.e. Native C++) e.g. Symantec Antivirus. I've got the option to push or pull the updates either way
BrianJK
Can I ask why IIS / ClickOnce is inappropriate? Things like serving files tend to be problems that are easy to solve trivially but present problems when exposed to any kind of scale (for example, you almost certainly don't want to be transferring files using ReadAllBytes and WriteAllBytes)
Ryan Brunner
BrianJK
eg. I need to keep control of the distribution from the server of a single updated client package that remains compatible with the server version. My own server needs to control this.
BrianJK
ReadAllBytes isn't buggy, but it requires that you load the entire byte stream into memory, which can cause problems particularly if multiple people are downloading. Regarding installing IIS, the "user" as in the client doesn't need to have IIS installed, it would only need to be installed on the server. The client has no additional requirements by using ClickOnce.
Ryan Brunner
public static members of File class are thread-safe. I dont' plan to load more than about 100mb of data in memory at once (20 threads of 5mb each) and the server can handle that. So I think that will be OK. I dont' want to require the server to install IIS.
BrianJK
ClickOnce doesn't require deployment on an IIS instance, it can be any type of web server, see http://msdn.microsoft.com/en-us/library/ms228998.aspx 'Using Third-Party Web Servers'. In fact, you don't even need a webserver, you can deploy ClickOnce on an ordinary shared network location.
AdamRalph
+1 by the way - ClickOnce is a good solution
AdamRalph
Thanks. I'm already using Advanced Installer with an MSI. I'm installing services. ClickOnce looks good but it doesn't offer what I can do with an MSI. It doesn't seem to have the same power.
BrianJK