Click here to Skip to main content
Click here to Skip to main content

An AutoUpdate Trick

, 10 Feb 2005
Rate this:
Please Sign up or sign in to vote.
This article provides a simple autoupdate class that can be added to any application.

Sample Image

Introduction

The company I work for, AutoUpdate+, creates software that manages updates for Win32-based software, which is great for mid to large scale users who need such a solution, but is a bit of overkill for the small developer. Many small developers only require a simple update solution, and frequently, it is only required to manage the update of the main project executable. This article will describe an autoupdate class I created, which is very simple to add to a project and which runs a little trick to update the main project executable.

Using the code

A class called CAutoUpdater was designed, with the goals that it is easy to add to any application, fully manages the update process, and correctly handles any errors. To use this class, simply call the CheckForUpdate method passing in the URL of your update server.

void CMFCUpdaterDlg::OnUpdatecheck() 
{
    CAutoUpdater updater;
    if (CAutoUpdater::Success == 
        updater.CheckForUpdate("http://AutoUpdatePlus.com/test/"))
    {
        // ... Notify user of success
    }
}

The update process consists of the following steps:

  1. Ensure that an internet connection is available.
  2. Retrieve the config file from the update server.
  3. Check the version in the config file. Compare to the existing application version.
  4. If an update is required, then download the new application from the update server.
  5. Switch in the latest application version with the existing version.

The first, and frequently overlooked step, is to ensure that an internet connection is available. This is essential to do because otherwise you may trigger an automatic dial-up to the internet, which is likely to make most of your application users unhappy.

// Important step - ensure we have an internet
// connection. We don't want to force a dial-up.
DWORD dwType;
if (!InternetGetConnectedState(&dwType, 0))
{
    return false;
}

Retrieving files from an HTTP server is a simple task using InternetOpenUrl, but it can fail if the URL supplied is not canonicalized. This simply means that bad characters, such as spaces, must be converted into escape characters, which is done using InternetCanonicalizeUrl. The GetSession method manages this process, returning a handle to a file on the HTTP server for a given URL. To check for updates, we must define an update config file on the server which lets us know what application version to expect. In our case, the update config file is called update.txt and contains the version of our application update. You can see it here. After getting a session handle to the update config file, we can retrieve the data into a buffer using the DownloadConfig method. We now have the update version available for our use.

HINTERNET CAutoUpdater::GetSession(CString &URL)
{
    // Canonicalization of the URL converts
    // unsafe characters into escape character equivalents
    TCHAR canonicalURL[1024];
    DWORD nSize = 1024;
    InternetCanonicalizeUrl(URL, canonicalURL, &nSize, ICU_BROWSER_MODE);

    DWORD options = INTERNET_FLAG_NEED_FILE|INTERNET_FLAG_HYPERLINK|
                    INTERNET_FLAG_RESYNCHRONIZE|INTERNET_FLAG_RELOAD;
    HINTERNET hSession = InternetOpenUrl(hInternet, 
                         canonicalURL, NULL, NULL, options, 0);
    URL = canonicalURL;

    return hSession;
}

bool CAutoUpdater::DownloadConfig(HINTERNET hSession, 
                           BYTE *pBuf, DWORD bufSize)
{
    DWORD    dwReadSizeOut;
    InternetReadFile(hSession, pBuf, 
                     bufSize, &dwReadSizeOut);
    if (dwReadSizeOut <= 0)
    {
        return false;
    }

    return true;
}

At this point, we have retrieved the update config file and must now figure out if an update is required. The text in the update config file is a simple version tag, in our case, the update version 2.0.0.1. This must be compared against the version of the executable we are currently running. Surprisingly, getting the version number from the executable and running a version number comparison is not a trivial task and can get a bit messy. If it turns out that our existing application version is out-of-date, we should notify the user and then proceed to download the latest application executable from the update server. Note that our new executable will be downloaded to a temporary user directory given by GetTempPath.

Once the latest executable version is downloaded, it must somehow be switched in to replace the existing out-of-date application executable. However, a problem exists! The current executable is locked, as it is in use, and hence cannot be copied over. Nevertheless, a simple Windows trick does exist. Files in use can still be renamed, leaving space open for the update executable to be switched in to the application directory. Note that this update trick may not always be available as some files can even get locked from renaming. In this case, the MoveFileEx with MOVE_DELAY_UNTIL_REBOOT option can be used, which delays renaming until a reboot occurs to free the file.

bool CAutoUpdater::Switch(CString executable, 
                     CString update, bool WaitForReboot)
{
    int type = (WaitForReboot) ? 
                MOVEFILE_DELAY_UNTIL_REBOOT : MOVEFILE_COPY_ALLOWED;

    const TCHAR *backup = _T("OldExecutable.bak");
    CString directory = executable.Left(executable.ReverseFind(_T('\\')));
    CString backupFile = directory + _T('\\') + CString(backup);

    DeleteFile(backupFile);
    if (!MoveFileEx(executable, backupFile, type)) 
    {
        return false;
    }

    BOOL bMoveOK = (MoveFileEx(update, executable, type) == TRUE);
    int i = GetLastError();

    return bMoveOK;
}

Points of Interest

The class provided manages updates for a simple application, but has a few drawbacks:

  • The update check is a synchronous task which does not provide any user feedback as to its progress.
  • Having the update check within the application limits its capabilities. It is wiser to have the update check run from an external executable.
  • A program that appears trivial quickly becomes complex. The current check cannot manage complex situations, such as multiple file updates.

History

  • 10 Feb, 2005 - First release.

About

The provided source code shows a very simple update mechanism. For a more sophisticated solution, take a look at the product AutoUpdate+ at www.AutoUpdatePlus.com.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

Share

About the Author

Simon Ellis

United States United States
No Biography provided

Comments and Discussions

 
GeneralOne problem: failed in Vista and above Pinmemberjerry_wangjh27-Feb-11 21:15 
GeneralRe: One problem: failed in Vista and above Pinmembervarandas799-Mar-11 23:58 
GeneralMy vote of 5 Pinmemberjerry_wangjh13-Jan-11 15:14 
GeneralMy vote of 4 PinmemberGAJERA21-Oct-10 21:20 
GeneralGreat article&kind man Pinmemberxam_jjf@yahoo.com.cn23-Mar-09 19:25 
Questionwhere is update.txt?? Pinmemberchiyongmin13-Apr-08 22:56 
AnswerRe: where is update.txt?? Pinmembersmokey24127-Aug-08 5:44 
QuestionUpdate on thread? Pinmembernwongfeiying12-Dec-07 18:22 
QuestionRemote file info? Pinmembersuggam13-Aug-07 14:32 
AnswerRe: Remote file info? PinmemberRussell'18-Sep-07 3:37 
GeneralRe: Remote file info? Pinmembersuggam18-Sep-07 6:59 
Questionwhere is update.txt?? Pinmemberjisgod8-Jul-07 3:40 
AnswerRe: where is update.txt?? Pinmember-=Seph=-12-Nov-07 22:24 
QuestionInternetGetConnectedState is never false in XP? PinmemberHoward Anderson22-May-07 12:42 
AnswerRe: InternetGetConnectedState is never false in XP? PinmemberHoward Anderson22-May-07 13:48 
Well, I guess everybody except me already knew about the THREE MINUTE RULE,
i.e., InternetGetConnectedState does not work properly until THREE MINUTES after the Ethernet cable is unplugged.
 
I'm using WinXP Pro, Visual Studio 2005, with everything up to date, all patches applied, etc.
 
Below is code you can use to prove to yourself that InternetGetConnectedState doesn't know that the Ethernet cable has been unplugged until THREE MINUTES after it has been unplugged. I used the code to time the thing...
 
Pretty flakey. No wonder I didn't find it sooner. I can't remember when I had three minutes worth of patience!
 
There must be a better way. The operating system knows immediately when the cable has been unplugged and pops up a little box telling me about it...
 

//Test behavior of InternetGetConnectedState
//just after Disconnecting Ethernet Cable.
DWORD dwFlags = 0;
int milliSeconds = 0;
while (InternetGetConnectedState(&dwFlags, 0))
{
Sleep(100);
milliSeconds += 100;
}
CString msg;
msg.Format("It finally started working after %d Milliseconds", milliSeconds);
MessageBox(msg);
//It takes 3 minutes to get here after the
//Ethernet cable is disconnected!
 
Presumably, AutoUpdate+ is using something a little more reliable?
 
Come on Simon, you can tell us... Smile | :)
 
Thanks,
 
Howard
 
Howard C. Anderson
HTTP://www.astroshow.com

GeneralRe: InternetGetConnectedState is never false in XP? PinmemberSimon Hayden23-May-07 2:17 
GeneralRe: InternetGetConnectedState is never false in XP? PinmemberHoward Anderson23-May-07 4:52 
GeneralRe: InternetGetConnectedState is never false in XP? PinmemberHoward Anderson23-May-07 5:19 
GeneralRe: InternetGetConnectedState is never false in XP? PinmemberSimon Hayden23-May-07 16:56 
GeneralRe: InternetGetConnectedState is never false in XP? PinmemberHoward Anderson24-May-07 4:29 
Questionhow can we check if a file exist PinmemberHassan Iftikhar5-Apr-07 5:36 
AnswerRe: how can we check if a file exist Pinmemberlxnyce26-Apr-07 4:03 
NewsNTLM proxy PinsitebuilderShog91-Nov-05 7:45 
GeneralHelp PinmemberPiccinano21-Feb-05 6:21 
GeneralRe: Help Pinmembertemp0x00715-Nov-09 18:02 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140814.1 | Last Updated 11 Feb 2005
Article Copyright 2005 by Simon Ellis
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid