I am writing C # programs for a company where several hundred people use them. From time to time new functions are added and there is a problem of updating versions.
I decided not to look for standard bulky solutions, but to invent my own bike to automatically update the installed programs.

')
Honestly, I myself don’t really like applications that always download updates, but in my case it’s easier to automate this process than to write job descriptions and force colleagues to download updates manually (and then run across all floors and do it myself).
Goals
Before starting work on this project, I formulated the goals that the future auto-update module should meet.
- The update should occur automatically when a new version is available.
- After the update, the program should automatically restart.
- After updating the program name should remain the same.
- The module must be embedded in the project exe file.
And what would seem to be the problem? Checked for a new version. Download the file. Launched. Everything!
The task becomes a bit confusing due to the fact that the launched exe file cannot delete or rename itself, another process must do this while the program is closed.
And to perform all the necessary actions in a single program:
- download new version
- remove the old program
- rename downloaded file
- it is necessary to restart it several times to consistently perform the listed actions.
Block diagram
To clarify at what stage what needs to be done, I made a flowchart of the whole process.
From my own experience I know that it takes an hour to draw up a chart, and it saves the day.

I always draw schemes by hand, redrawing them several times, new details are added each time, and I really like the process itself.
Stages
The flowchart highlights three stages of the update process.
Stage A. The program is launched as usual (without keys).get up_version
We read and check the version number on the server.my_version == up_version?
If the server version matches ours, skip the update module.download new.name.exe
We upload a new program to the file new.name.exe.%%%%%
We are waiting for the end of the boot process.start new.name.exe / u
After the download is complete, launch the downloaded file.We close the program to remove it later.
Stage B. The program is started with the / u key.del name.exe
Remove the program name.exe.copy new.name.exe name.exe
Copy new.name.exe to name.exe.start name.exe / d
Run name.exe with the / d key.We close the program to remove it later.
Stage C. The program is started with the / d key:del new.name.exe
Delete the temporary copy of the program new.name.exeRun the main program.
Now we come to the practical part, as I implemented all this in a class in C #.
Primary data fields
We begin the module review with an introduction to the data fields, that is, working constants and variables.
Run!
The work of the module begins with its launch. Where does the program do best? I tried various options, and the most successful option seemed to me to launch it from the
Program.cs file.
static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false);
All update module logic is executed in the constructor, without visual display. The form is displayed only in the process of downloading the file.
The
download () method informs that at stage “A” an asynchronous download of a new version of the program started, in connection with which you need to display a visual form on which a ProgressBar with a text field is placed, and wait for the process to complete. The rest of the update process is performed silently and the form is skipped.
The
skipped () method informs you that the update is skipped (or completed), the program can be started normally. Otherwise, the program must close to proceed to the next stage.
Constructor
We will write a class constructor, which, using the command-line arguments, will establish what stage of the update we are in and call the appropriate class methods.
private FormUpdater() {
A few words about the helper method
get_exec_filename () . In C #, you can get the name of the running file only with the full path. To remove the pure file name, I wrote my method, which breaks the path into parts by the “\” symbol and returns the last part of it - the file name being searched for.
private string get_exec_filename() { string fullname = Application.ExecutablePath;
The remaining methods that are invoked from the constructor will be considered at the appropriate stages.
Stage "A"
The
do_check_update () method checks for an update on the server and, depending on the result, either starts the update process or allows the launch of the main program.
private void do_check_update() {
The
get_server_version () method uses the standard method of the
WebClient class to read the version number.
If the version number is not read, it is logical to assume that the update will also not be able to download, so we assume that there is no update.
private string get_server_version() { try { WebClient webClient = new WebClient(); return webClient.DownloadString(url_version).Trim(); } catch {
The
do_download_update () method displays the screen form and starts the asynchronous download of the updated program file.
private void do_download_update () { InitializeComponent();
The
download_file () method starts an asynchronous download and connects two events:
to display progress and to complete the file download stage.
private void download_file () { try { WebClient webClient = new WebClient();
In case of an error, the
error () method is called, which displays the text of the error and offers to download the file on its own, in this case the browser will be launched and the corresponding page will be opened. The text of this method, I think, can be omitted.
From stage "A" it remains to implement the processing of two events:
change the progress of the download and the processing of its end.
The method of changing progress is written trivially.
private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e) { progress_download.Value = e.ProgressPercentage; }
Upon completion of the download, you must go to stage "B" and complete the work.
private void Completed(object sender, AsyncCompletedEventArgs e) { run_program(up_filename, "/u \"" + my_filename + "\""); this.Close (); }
Note that in addition to the / u switch, the original name of the program is transferred to the program so that the newly launched program knows how to rename the file according to the 3rd goal:
after the update, the program name should remain the same.The file name in the command line parameter must be enclosed in quotes in case there are spaces in it.
The fields of the
is_download ,
is_skipped method in this method are not necessary to set, since the stage of their verification in the
Program.cs file was completed immediately after the launch of the download.
The method for running the program may look like this.
private void run_program(string filename, string keys) { try {
So, with the stage "A" we figured out.
If something seemed confusing, I recommend to review the block diagram again and compare the module's methods with the elements on the block diagram.
Stage "B"
Moving on to stage "B", it will be much easier. From the constructor, the
do_copy_downloaded_program (string filename) method is
called , which copies the downloaded version of the program to the old one.
void do_copy_downloaded_program(string filename) { try_to_delete_file(filename);
A few words about the
try_to_delete_file (string filename) method. It may turn out that we are trying to delete a file that is still blocked by an incomplete process of the previous program. This method attempts to delete a file several times in a row for a few seconds with short delays.
private void try_to_delete_file(string filename) { int loop = 10;
Stage "C"
There is the last, shortest stage “C”, which removes the “garbage” and launches the main program. For this purpose, the
do_delete_old_program (string filename) method is called from the constructor.
void do_delete_old_program(string filename) { try_to_delete_file(filename); is_download = false;
If the version of the program on the server does not coincide with the recorded version in a text file, then at each launch, the “new” version will be reloaded. After that, the program will still be launched regardless of the difference in versions: the program version is no longer checked according to the flowchart at the “C” stage. So it should be! Additional testing at this stage risks looping the download process forever ...
By the way, this "chip" can be used to run the program without checking for updates, just run it with the "/ u" key.
Conclusion
The update module constructed in this way satisfies all the goals formulated at the beginning of the article:
- The update is downloaded only with the new version.
- The updated program automatically starts after downloading.
- There is a mechanism for saving the original file name of the program.
- The module is not made by a separate program, but is built into the project file.
The operation of the module is demonstrated in the following figure.

I can also demonstrate the work of the module on my own program of learning English words by ear. Download the “old” version of “Sound Cards” here:
http://www.DoubleEnglish.ru/soft/old.ListenCards.exeThe source code of the update module in the test project can be downloaded here:
http://www.fformula.net/docs/updater/updater.zipThanks for attention.
Volosatov Eugene.