A question about writing a background/automatic/silent downloader/installer for an app in C#
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 usedSystem.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.
The usual way to do this goes like this:
- Your application detects that an update is needed.
- 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.
Check out the BITS service:
http://msdn.microsoft.com/en-us/magazine/cc188766.aspx
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.
How about trying http://netsparkle.codeplex.com/. A port of the very successful Mac Sparkle framework http://sparkle.andymatuschak.org/.
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;
}
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.
精彩评论