Chris Rasmussen · Photographer · Infrastructure Guy · Code Dabbler · Traveller

C# – Self updating application (without ClickOnce!)

This one might be interesting for people who have wondered about how to distribute the latest version of their application without having to tell people when an update is released.

There are built-in options that you can use with the Microsoft .NET platform such as ClickOnce. We use ClickOnce here at Trade Me to deploy some of our in-house applications and it works really well.

Recently, though, I thought “Why not see if I can write my own method of updating my application?” It turned out to be quite an interesting litte project! The application I was working on at the time is written in C# although the learning curve to go from VB.NET to C# or vice-versa isn’t too steep.

So, where do we start? To begin with I decided the update process should have the following steps.

- Check my website for a text file containing version information
- Read the version information text file and compare the version information in it to the version of the application currently running
- If the version in the text file is the same or less than the version currently being run, do nothing other than show a message to the user
- If the version in the text file is greater than the version currently being run ask the user if they want to update to the later version
- Do the actual update

There are 2 components to this particular solution. The first part is the actual application being updated and the updater application. If you are going to follow along with any of the stuff in this article you’ll need to start a new solution with 2 projects. My main project is called “CountDown” and the updater application is called “AppStart” (for reasons not related to the updating stuff here). For the purposes of this article I’m going to assume you have a single project that needs the update functionality.

The first thing your main application will need to do is make use of the System.Net namespace by adding the following line to the top of the main namespace file.

?View Code CSHARP
using System.Net;

When the user runs the application they can click a button that runs a method to do most of the steps above. The first thing the method does is try to resolve the IP address of my website (http://www.digitalformula.net resolves to 203.194.159.161).

?View Code CSHARP
try
{
   string RemoteDomain = "http://www.digitalformula.net";
   IPHostEntry inetServer = Dns.GetHostEntry(RemoteDomain.Replace("http://", String.Empty));
}
catch (Exception ex)
{
...
}

If the name resolution fails the following code is run in the catch block above (complete catch block shown below). It simply shows an error message with an OK button.

?View Code CSHARP
catch
{
   DialogResult result = MessageBox.Show(String.Format("Unable to connect to {0}.\nPlease check your internet connection and try again.", RemoteDomain), "Error during version check", MessageBoxButtons.OK, MessageBoxIcon.Error);
}

If the name was resolved correctly it then tries to download the version update file into the current user’s TEMP directory by running the following try block.

?View Code CSHARP
try
{
   string versionFileUrl = "http://www.digitalformula.net/countdown/countdown.version.txt";
   System.Net.WebClient client = new System.Net.WebClient();
   client.DownloadFile(versionFileUrl, System.Environment.ExpandEnvironmentVariables("%TEMP%"));
}
catch (Exception ex)
{
...
}

Note that the version information simply contains the text “2.0.0.1″ (without the quotes). When writing this article the application version was 2.0.0.0
To set the version of the application you need to open the AssemblyInfo.cs file – you can find this file under the project name and then by clicking Properties (assuming your project is C# like this example). Change [assembly: AssemblyVersion("2.0.0.0")] to the appropriate version.

If the download fails the following complete catch block is executed.

?View Code CSHARP
catch (Exception ex)
{
   string errorDetails = String.Empty;
   MessageBoxIcon iconsToShow = MessageBoxIcon.Information;
   if (ex.Message.Contains("could not be resolved"))
   {
      errorDetails = String.Format("Error looking up {0}.\nPlease check your internet connection and try again.", RemoteDomain);
      iconsToShow = MessageBoxIcon.Error;
   }
   else if (ex.Message.Contains("404"))
   {
      errorDetails = "Upgrades to Countdown are currently unavailable.\nPlease try again later.";
      iconsToShow = MessageBoxIcon.Information;
   }
   DialogResult result = MessageBox.Show(String.Format("{0}", errorDetails), "Error downloading file", MessageBoxButtons.OK, iconsToShow);
   return;
}

The then checks to see if the downloaded version file exists in the TEMP directory (defined by the environment variable %TEMP%) and then reads the version information from it. The first part of that code looks like this.

?View Code CSHARP
if (File.Exists(config.VersionFileLocal))
{
   string versionFileLocal = String.Format("{0}\\{1}", System.Environment.ExpandEnvironmentVariables("%TEMP%"), "countdown.version.txt");
   TextReader tr = new StreamReader(versionFileLocal);
   string tempStr = tr.ReadLine();
   tr.Close();
   File.Delete(versionFileLocal);
   string longVersionFromFile = tempStr;
   string shortVersionFromFile = tempStr.Replace(".", String.Empty);
   Version vrs = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
   string longVersionFromVrs = String.Format("{0}.{1}.{2}.{3}", vrs.Major, vrs.Minor, vrs.MajorRevision, vrs.MinorRevision);
   string shortVersionFromVrs = String.Format("{0}{1}{2}{3}", vrs.Major, vrs.Minor, vrs.MajorRevision,    vrs.MinorRevision);
...
}
else
{
   DialogResult result = MessageBox.Show(String.Format("Version file not found or not accessible.\nPlease check that you have permission to read the {0} folder", versionFolderLocal), "Version information missing", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}

That code opens the version text file, reads the first line from it, closes the file (important!) then gets a ‘fake’ number by removing all the version separator symbols from the version it has read.

Once the data reading process is complete the version read from the file and version of the currently running application are compared using the following code (I’ll get to the … bits in a minute). This code snippet also runs the actual upgrade process by calling AppStart.exe if the user says Yes when asked if they want to upgrade (assuming an updated version is available).

?View Code CSHARP
if (Convert.ToInt32(shortVersionFromVrs) < Convert.ToInt32(shortVersionFromFile))
{
   DialogResult result = MessageBox.Show(String.Format("Countdown upgrade from version {0} to {1} is now available!   Upgrade now?", longVersionFromVrs, longVersionFromFile), "Upgrade available", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
   switch (result)
   {
      case DialogResult.Yes:
      {
         string pathToExecutable = Application.StartupPath.ToString();
         string upgradeExecutable = "AppStart.exe";
         string fullUpgradeExecutable = String.Format("{0}\\{1}", pathToExecutable, upgradeExecutable);
         if (File.Exists(fullUpgradeExecutable))
         {
            ProcessStartInfo upgradeProcess = new ProcessStartInfo(fullUpgradeExecutable);
            upgradeProcess.WorkingDirectory = pathToExecutable;
            Process.Start(upgradeProcess);
            Environment.Exit(0);
         }
         else
         {
            DialogResult result2 = MessageBox.Show(String.Format("{0} not found in {1}.\nPlease check that this file exists then try the upgrade process again.", upgradeExecutable, pathToExecutable), "Upgrade Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
         }
         break;
      }
      default:
      {
         break;
      }
   }
}
else
{
   DialogResult result = MessageBox.Show(String.Format("There are no upgrades currently available.   You have the latest version of Countdown."), "No upgrade available", MessageBoxButtons.OK, MessageBoxIcon.Information);
}

The above does a couple of things. Here’s some more detail.

- Compares the currently running version to the version found in the downloaded file
- If an update is available the user is prompted to upgrade (Yes/No buttons) – see the screenshot below this list for what the prompt looks like.
- If they click No, nothing else happens
- If they click Yes the AppStart.exe process is started and the currently running executable is terminated gracefully with an exit code of 0 – Environment.Exit(0)

Self Updating Application - Upgrade Available

Now to the other part of the process – AppStart.exe. This small part of the project is important but relatively simple. The steps, from beginning to end, are as follows.

- Download the upgraded executable (in this case Countdown.exe) using a temporary file name
- Delete the old executable
- Rename the temporary downloaded executable to the same name as the old file
- Run the new executable
- Gracefully terminate AppStart.exe with an exit code of 0 – Environment.Exit(0)

In fact, the upgrade process is so simple, here is the entire code. :) Note that it ALL runs in the form’s Load event! The method below has some extra stuff to make the process pretty like showing the user where the process is up to but you could make the entire process invisible by leaving this code out and hiding the form when the app starts if you wanted.

Remember that you’ll need to add the following code to the top of the main code file if aren’t going to fully-qualify the WebClient object.

?View Code CSHARP
using System.Net;

So, onto the method source …

?View Code CSHARP
private void frmMain_Load(object sender, EventArgs e)
{
   string pathToExecutable = Application.StartupPath.ToString();
   string upgradeDomain = "http://www.digitalformula.net";
   string upgradeDirectory = "countdown";
   string downloadExecutable = "Countdown.exe";
   string upgradeExecutable = "Countdown.upgrade.exe";
   string upgradeUrl = String.Format("{0}/{1}/{2}", upgradeDomain, upgradeDirectory, downloadExecutable);
   string upgradeFolderLocal = pathToExecutable;
   string upgradeFileLocal = String.Format("{0}\\{1}", upgradeFolderLocal, upgradeExecutable);
   string oldExecutable = String.Format("{0}\\{1}", pathToExecutable, downloadExecutable);
   try
   {
      lblWaitingDone.Text = "done!";
      lblDownloadingDone.Text = "working";
      System.Net.WebClient client = new System.Net.WebClient();
      client.DownloadFile(upgradeUrl, upgradeFileLocal);
      lblDownloadingDone.Text = "done!";
      lblRenamingDone.Text = "working";
      File.Delete(oldExecutable);
      File.Move(upgradeFileLocal, oldExecutable);
      lblRenamingDone.Text = "done!";
      ProcessStartInfo upgradeProcess = new ProcessStartInfo(oldExecutable);
      upgradeProcess.WorkingDirectory = pathToExecutable;
      Process.Start(upgradeProcess);
      Environment.Exit(0);
      lblEnablingDone.Text = "done!";
   }
   catch (Exception ex)
   {
      DialogResult result = MessageBox.Show(String.Format("Error during upgrade.\n{0}", ex.Message.ToString()));
   }
}

Have a go – I’m very interested to hear if anyone tries this technique to update their own application. :)

52 Responses to “C# – Self updating application (without ClickOnce!)”

  1. Tiago Moises says:

    Hi,

    Congratulations for the article. You have the code source for download?

  2. Chris says:

    Hi Tiago,

    I think all the source code you’ll need to implement this yourself is in the article above.

    What specific code did you want?

    Thanks

  3. Stephan N says:

    It would be easier to understand with a Sample-Procjet! Please upload a working ProjectFile!

    Thanks! Your solution seems to be very good!

  4. Mayana says:

    Hi! I find your article useful, but for my task I need to do this: create manifest utility (xml based manifest file) intended for creating update content files (manifest files). Can you tell me how to do this?
    Thanks,
    Mayana

  5. Mayana says:

    sorry, I did not copy/paste well. It should be like this: “create manifest utility intended for creating update content files. This manifest utility should take a set of files as input parameter and generate XML based manifest file as output one”.

  6. Chris says:

    Hi Mayana,

    I don’t really understand your question, sorry. This particular article doesn’t use manifest files of any sort, and, to be honest, I’m not a developer so I’m not even sure what they are!

  7. Christo says:

    Hi,

    I have used this approach to great success! I changed it a bit to suite my needs but the foundation is awesome!

    I am using it in a production environment.

    Excellent! Thanks.

    Christo

  8. Steve says:

    I am trying to accomplish this using a single executable.
    It is possible? How can an application start a new instance of itself and start the new one?

    thanks

  9. Chris says:

    Hi Steve,

    I’m not sure that it is possible because of the file being locked while it’s running. You could possibly have an executable that starts when the app runs and then calls the main executable for the app … this obviously isn’t a single executable though.

    Sorry. :(

  10. Steve says:

    Hum. I know that .net reflector does it I am just not sure how. I will keep trying.

  11. Chris says:

    Steve,

    This is intended as a pretty simple solution really. If you want to advanced features of ClickOnce/.NET Reflector I’m afraid you may have to use one of them instead …

  12. Steve says:

    I did some spying on .net Reflector and his approach is very similar to yours. However, the difference is that he downloads a small program similar to your appstart and executes it instead of maintaining it locally.

    Thanks for your article.

  13. Chris says:

    Steve,

    Sure, that would work fine too. I guess the difference here is that if you wanted to do anything else at the same time as the update (alerts, database activity, whatever) you could do that if you were maintaining the appstart.exe executable yourself.

    Thanks

  14. Christo says:

    Hi Steve,

    I am replacing the exe file with the upgrade process.

    You can rename the current exe, copy the new file and
    restart.

    Regards,

    Christo

  15. Chris says:

    Christo & Steve,

    Yes that’s the point. Run the main executable that checks for updates and then, if they are found, run another executable that does the actual update work, including deleting the old executable and subsequent download then installation of the new main program executable.

    It works well but it is still simple. The only real downside in terms of bad programming practice is that users will need administrative rights to the program installation folder in order to run this process (usually C:\Program Files). This is considered bad practice.

    Interesting discussion though and I’m still interested to hear your ongoing thoughts or progress including any changes you make to get it working in your own environments.

  16. Steve says:

    I just lost a very lengthy discussion as I forgot to type in the security code before clicking submit and after hitting back in the browser my post was gone so here is the short version.

    Chris, I have always had admin rights when testing these approaches what action are you performing that needs Admin rights?

    I see two approaches

    1. Rename and replace method mentioned by Christo
    2. AppStart (secondary application)
    a. Stored locally
    b. Stored on the update server and downloaded by main
    exe when a new update exists.

    I see two paths you can take which apply respectly to the above mentioned approaches.

    1. Application is a single executable.
    2. Application has multiple parts.

  17. Chris says:

    Steve,

    That’s a shame about your lengthy reply. :(

    Re the admin rights thing I’m assuming that this approach will eventually be used in projects that implement the setup project methodology, i.e. a custom setup project for the application. If this is the case then the application will most likely be installed into C:\Program Files – this isn’t a location that is writable by non-privileged users (as you know). Because the executable for most applications will live there this method will fail without administrative rights.

    string pathToExecutable = Application.StartupPath.ToString();

    That line will return the directory the executable is running from, most likely C:\Program Files\.

    Of the 3 methods you mention above I can’t see how #1 would work as the executable will be locked while the application is running and therefore the upgrade process can’t be a single executable (unless I’m missing something pretty major you can’t rename a file while it’s in use).

    The other 2 methods would work fine but still force you to use 2 executables – I can’t see any other way around this.

    If there is a way of renaming then replacing the existing executable while the executable is running I’m keen to hear it though. :)

  18. Steve says:

    Chris,

    Actually, you can rename a running executable you just can’t delete it while in use.

    I have coding a working prototype.

    1. File.Move() i.e. MyApp.exe to MyApp.bak
    2. download new file to the working directory.
    3. Call Application.Restart() started the newly downloaded
    MyApp.exe
    4. Have main application always look for MyApp.bak and
    delete it.

    private void button2_Click(object sender, EventArgs e)
    {
    string source = Application.ExecutablePath;
    string destination = source.Replace(“.exe”, “.bak”));

    RenameExe(source,destination);
    DownloadUpdate(); // just downloads MyApp.exe

    Application.Restart();
    }

    private bool RenameExe(string sourcePath, string newPath)
    {
    // In case a previous attempt failed.

    try
    {
    if (File.Exists(newPath))
    {
    File.Delete(newPath);
    }

    File.Move(sourcePath, newPath);
    }
    catch (Exception)
    {
    return false;
    }
    return true;
    }

    This is just prototype code so don’t beat me up for ugly code or lack of error checking.

    There are so many veriations I have though of using the single rename and replace method.

    I don’t know how you are checking for a new version but if you have a file on your file server that contained something like the following:

    My Cool Applcation
    2.0.0.0

    Changes New in this Version
    - Added Favorite Contacts.
    - Improved tray icon logic.
    - Fixed rare problem.
    - Fixed some other (even rarer) problems.
    - 95% of the error reports have been fixed or worked around.
    - Sadly I lack time to add the features that have been requested.

    Here you have
    1. Application name
    2. Current version
    3. Upgrade note

    When you application detects that a new version exists you could prompt the user with a dlalog box with the text “A new version of My Cool Application is available would you like to upgrade?”. The options could be Yes, Whats New, or No. Yes and No are obvious but if the user selects whats new you could display the upgrade note mentioned above.

    Well just a couple of thoughts.

    It you have trouble with the rename and replace method let me know and I could email a sample project.

    Steve

  19. Steve says:

    Chris,

    I just tried to run my code under a non-admin account of as you mentioned it fails.

    I copied .net reflector to the program files directory and under an non-admin account is was able to access the its folder delete and update files without prompting for any credentials. So, some how there is a way programatically to get around this issue I just need to figure it out.

    Steve

  20. Chris says:

    Haha no worries, I won’t be ripping apart anyone’s code any time soon – I’m a hobbyist at most! :)

    Thanks for the comments about rename and replace – it makes sense although I’ve never tried that before (I’ve never had the need to).

    The sample code I posted does prompt the user for an answer if an upgrade is found so I guess it’s just a case of dealing with the answer appropriately.

    Can I ask what environment you’re using this stuff in? I’m really interested to hear how you’re using my stuff (if you’re using it at all) so any info would be very cool.

    Thanks for the discussion so far, it’s really interesting!

  21. Steve says:

    My interest in self updating applications is based on two things. First, after seeing .net reflector do it I wanted to figure it out and I have a friend with a single executable application and he wanted to add this capability.

    Actually, I am not using any parts of your code I was just googling and came across your post. I would consider your approach but this has been a labor of Love trying to figure out how to accomplish the update given a strict set of requirements.

    My interest is also that of a hobbyist on this topic as I don’t have a real need for it commerically or otherwise I just don’t like a problem getting the better of me.

    Currently, I have only been testing with Windows XP SP2.

  22. Håkan says:

    Hello, i want to try this script in my program but i don’t get it working. Can you post the C# Project File on a comment or to my mail: h.gerner@gmail.com

    Thanks.

  23. Håkan says:

    Oh, my email is h.gerner94@gmail.com. Forgot the 94 before..

    Sorry for that!

  24. Steve says:

    H.gerner94

    Who are you requesting code from Chris or Me?

    Steve

  25. Håkan says:

    Hi Steve

    I just wonder if someone can set this code together and send it to me. I don’t get how i should place these try and catch things. :/

    Thanks

  26. Chris says:

    Hi Håkan,

    Can you please explain which parts you are having trouble with? I’m more than happy to help out if it’s a specific part that you can’t get working.

    I don’t actually have a sample project here with me though, sorry (I’m at work).

    Post a comment here and I can probably help. :)

  27. Chris says:

    Steve,

    Are you able to explain the strict set of requirements? I’m interested to hear other about other peoples’ attempts at doing this sort of thing whether they use my code or not.

    Cheers!

  28. Steve says:

    Chris,

    In other words I was trying to mimick .Net Reflectors method of Autoupdate using a single exe. Not having to install any Microsoft products or anyone elses to enable this capiblity. And finally the kicker not needing administrative rights to do the update. All of these criteria are accomplished by .Net reflector.

    Last night I figured out the final piece of the puzzle, that is getting rid of the need for an Administrator account. I am not sure I will share that information as after much googling I found nothing and this info could be used in a negative way.

  29. Chris says:

    Steve,

    That’s your call about the administrative stuff I guess. I doubt any readers of this particular site would use it in a negative way but again, up to you. :)

  30. Steve says:

    Email mail me off line.

  31. alvan lee says:

    Hello, i want to try this script in my program but i don’t get it working. Can you post the C# Project File on a comment or to my mail: wc_ming@163.com

    Thank you!

  32. Chris says:

    Alvan,

    Sorry I can’t provide the project file as I don’t have one that only contains this code.

    If you ask a question here though I might be able to help you …

    Thanks

  33. Fred says:

    I am trying to do something similar and having problems.
    My approach:
    1. Retrieve xml file with version info from our web server and compare to version of running assembly. OK
    2. If new version available download new installer (setup.exe). OK
    3. Launch Setup.exe and close my application. OK

    The problem is that the installer always wants to reboot because it can’t overwrite the app.exe. According to the task manager it has terminated, but Setup.exe seems to think it is still running.

    Any ideas?

    I have the code from the check for updates routine below:

    private void miHelpCheckForUpdates_Click(object sender, EventArgs e)
    {
    frmHelpCheckForUpdates CFU = new frmHelpCheckForUpdates(CFG, _SerialNumber);
    if (CFU.ShowDialog() == DialogResult.OK)
    {
    if (CFU.UpdatesDownloaded)
    {
    ProcessStartInfo startInfo = new ProcessStartInfo();
    startInfo.FileName = CFG.DownloadPath + CFU.NewVersionSetupFile;
    startInfo.WorkingDirectory = CFG.DownloadPath;
    startInfo.UseShellExecute = true;
    Process.Start(startInfo);
    //Close();
    Environment.Exit(0);
    }
    }
    }

  34. Chris says:

    Fred:

    Sorry I haven’t got time to look through all your code right now but I can see that your code has the line startInfo.UseShellExecute = true; whereas my code does not.

    Have you tried not using this line?

    - Chris

  35. Leopold says:

    Steve wrote: “Last night I figured out the final piece of the puzzle, that is getting rid of the need for an Administrator account.”

    Well, even the update mechanism for Reflector fails for an unprivileged user account. So, if the program was installed into “\Program Files\” by an admin, there is now way of writing into this folder, even for the application itself.

  36. Chris says:

    Leopold,

    Yes that’s right. If you want to update the configuration then it should, unless there is a good reason not to, be stored either in HKCU or the user’s Application Data/Local Settings folders. The admin problem comes up because this example updates the application’s executable.

    Good security is important these days and the rights to update Program Files should only be given to certain people anyway.

  37. Jorge says:

    Steve,

    can you send your code that avoids admin rights to jorgegitu@hotmail.com?

    I’m interested doing this kind of updates without MS ClickOnce.

  38. Steve K. says:

    I’m preparing to roll my own ClickOnce-style updater and would be interested in the techniques that “Steve” has discovered. He mentions emailing him offline yet I can’t find an email address.

    Anyone know it? Steve?… you there?

    I can be reached at: st3v3kl3tt @ gmail
    (replace ’3′ with ‘e’)

  39. Steve says:

    Well, I didn’t want to create any new virus creators, as they are plenty of those clowns out there.

    The trick really isn’t so fancy and probably only works on XP. I would imagine that on Vista that you have to play by the rules as I believe that Vista even restricts P-Invoke calls.

    If you use P-Invoke to do thinks that are prohibited by the .net framework you thereby bypass XP security.

    I never did finish a complete example but I did prove that I could do it which was actually my only real goal. I don’t even need a self-updating application I just thought it was interesting how .Net Reflector did it just wan’t to solve the puzzle.

    I don’t have the code samples with me as I am at work.

    You will have to use P-Invoke to call win32 deletefile, movefile, GetShortPathName and even calls to download using wininet.dll.

  40. serans1 says:

    i have been trying some auto update methods for sometimes now and i must say i have to agree on the above.
    MSI updates requires a lot of dealing with the update content not mentioning the versions limitations(for me remove old versions was not very stable on every machine,its heavy and on vista can not run Custom actions).
    as for click once it creates some kind of DLL from the application, and indeed works fine but still no custom actions and i as a general rule it makes you lose control on your application (no free meals…).
    I have implemented this kind of auto update and i am testing it right now but i worry on the following issue:
    1st install is MSI based and creates a GUID and registery values, once replace the exe file i am changing the assebly version of the app without letting windows know about it – i was afraid that it will damage uninstall but it did not.
    can anyone tell if windows uses the assembly version of MSI installed App in any way – any usage of it will give an error once the assebly version is replaced…
    my comments at http://www.commentino.com/serans1

  41. ae says:

    All code please, mister !!! please !!! thanks

    • Chris says:

      Hi ae,

      I don’t have a complete working application that I can share that contains this code although everything you need *should* be in this post. If you have any questions I’ll be happy to answer them though – just post comments here and I’ll help when I can.

      Thanks

  42. Craig says:

    Hi! I LOVE THIS!
    First time I have found decent code on this subject thats not 1 billion lines of code.
    The greatest part is it’s simplicity.
    I hope your still around cause I could really use advice on where to host my .exe update/txt file. I have no idea :’(

    Anyways, I am still testing this, BUT for those that don’t want 2 .exe’s:
    create the second .exe INSIDE THE FIRST .exe (ya that is right)
    C# is capable of making .exes inside of .exes
    SO, you make an .exe that is made inside of %temp% would work I guess, then that .exe just does the same thing as above ^^^

    Thank you sooooooooo much for this code I am completely in love with you right now :P

    Thanks,
    Craig.

  43. Vera Linn says:

    U can use a project in your app where you put your code and an exe wich has dinamicaly linked the dll. So u can update your dll anytime.
    I’m searching for the rights problem for delete the old files and restore with new ones if my user is not an administrator.

  44. Chris says:

    Hi Vera,

    Yes I’m sure you can do that although it’s not something I looked at when the article was written. Please feel free to comment with your own code if you think it will help people. :)

  45. Eva says:

    Could you send me the code, I neede to develop that kind of project, I need example of source code, pls help me on that topic.

  46. Chris says:

    Hi Eva,

    The article above as well as the comments provided by myself and others should be all you need. I don’t have a complete sample application that is appropriate for download, sorry.

    - Chris

  47. Aamir hasan says:

    if i have dll files with project with i replace it or going to delete it is not allowing me to delete

  48. David Bond says:

    Worked like a charm – thanks :-)

  49. Shekar says:

    It is simple what author is doing is having two exe’s

    1. First EXE checks if the source and desination text files are same, if yes call the second exe (which is application exe).
    2. If not same, download the files from source to destination by deleting or overwriting the destination and after copy again call the second exe (which is application exe).

Leave a Reply

Powered by Wordpress | Designed by Elegant Themes