A question about writing a background/automatic/silent downloader/installer for an app in C#

937 views Asked by At

Background:
I have a main application that needs to be able to go to the web and download DLL files associated with it (ones that we write, located on our server). It really needs to be able to download these DLL files to the application folder in "C:\Program Files\". In the past I have used System.Net.WebClient to download whatever files I wanted from the web.

The Issue
I have had a lot of trouble downloading data in the past and saving to files on a user's hard drive. I get many reports of users saying that this does not work and it is generally because of user rights issues in the program.

In the cases where it was an issue with program user rights every user could go to the exact file location on the web, download it, and then save it to the right place manually.

I want this to work like all the other programs I have seen download/install in this fassion (i.e. Firefox Pluign Updates, Flash Player, JAVA, Adobe Reader, etc). All of these work without a hitch.

The Question
Is there some code I need to use to give my downloader program special rights to the Program Files folder? Can I even do this? Is there a better class or library that I should use? Is there a different approach to downloading files I should take, such as using threads or something else to download data?

Any help here is appreciated. I want to try to stay away from third-party apps/libraries if at all possible, other than Microsoft of course, due to licensing issues, but still send any suggestions my way.

Again, other programs seem to have the rights issues and download capability figured out. I want this same capability.

6

There are 6 answers

2
Heinzi On BEST ANSWER

The usual way to do this goes like this:

  1. Your application detects that an update is needed.
  2. Your application starts another (updater) application, that will download the required files and install them into Program Files. This updater application must run with administrative rights (i.e., prompt for UAC elevation in Vista/Win7). The easiest way to ensure this is to add an application manifest to that updater application.

If the user is an administrator with UAC enabled, point 2 will cause a UAC prompt to appear which must be accepted (note that the same is true for Firefox/Acrobat/etc. updaters). If the user is not an administrator, he will be asked for administrator credentials. (Note that this is a good thing: Only an administrator should be allowed to upgrade applications installed for all users.)

Your updater application does not need to be written in a special way: It can use System.Net.WebClient just like before. The application manifest will ensure that it requests the required premissions for writing to Program Files.

Note that this issue (Program Files not being writable by administrators without UAC elevation) is an operating system feature and not a programing language limitation, so you won't solve this issue just by "using a different library". If you want your application to run on Vista/Win7 and write to Program Files, you will need UAC elevation.

4
Robert Levy On

Writing to the Program Files directory requires UAC elevation (if the user has that enabled) on Vista/Win7. See this code sample on how to prompt users for permission: http://msdn.microsoft.com/en-us/library/aa970890.aspx

Really though, please think about designing your app so that it writes to a more appropriate place where this is no risk of accidentally overwritting a critical program file.

0
phillip On

How about trying http://netsparkle.codeplex.com/. A port of the very successful Mac Sparkle framework http://sparkle.andymatuschak.org/.

0
Jerod Venema On
0
AK_ On

Don't do it.

Theoretically it can be done easily. you just lunch another app, that runs with administrative privileges - you can request these in configuration. In the updater app, you just connect to a secure(ssl) web site, download everything you need, the files you download must be cryptographically signed.

This can also be easily solved using ClickOnce or some other web installer, capable of updates.

What you shouldn't do is just download insecure DLL's from an unverified source and execute them.

0
tallseth On

Does it really need to be in Program Files? I had a similar problem in an application, and we've written a class to resolve non-installed assemblies by first trying to load them from a subfolder of the %usersprofile%, then by going trying to download. This can be seamless if you add you resolve method to the current app domain's AssemblyResolve event.

    AppDomain.CurrentDomain.AssemblyResolve+= AssemblyResolve;
    public Assembly AssemblyResolve(object sender, ResolveEventArgs args)
    {
         //try to get locally

         //try to download
         return assembly;
    }