I can't do the hard work for you (unless you pay me...) but I would compare the project properties between 32 bit and 64 bit. Check the project type, build settings, etc. I am sure you will find the answer.
Thank you for your efforts, it's great solution for auto updator.
I have one question, sometimes updating program need not only exe file change, also need to change dlls, and some extra files, then how to change this solution ?
or do you have any good idea how to apply this case ?
if you have any good idea , plz let me know.
It is ok if this line returns TRUE, but it happens to return FALSE from time to time.
This line returns FALSE to result2 and GetLastError() is 5 which is ERROR_ACCESS_DENIED.
Then, _U_SG_AutoUpdate.exe continues working to the end without executing CreateProcess("SG_AutoUpate.exe").
And finally, _U_SG_AutoUpdate.exe is stays but SG_AutoUpdate.exe has gone.
Therefore, next time, we have to manually rename _U_SG_AutoUpdate.exe to SG_AutoUpdate.exe.
although real life scenario is little more complicated than this renaming schema that you mention.
the software is usually packed with run-time and several new dependency .
my suggestion :
1-run you application and create seperate thread to check for update at the beginning.
2- the update thread send query request to server about running product and version and architecture.
3- the server replay with JSON result set
4- JSON format is table of row consisting (product name, version , arch , download url , file hash).
5- after parsing the json and download the new version , you store the installation in application directory , put flag in registry about pending update.
6- in the application next run , check the flag , lunch installed in quite(silent) mode , clear the flage , and then delete the installer.
7- restart you application
We are proud to have always developed applications having only a single file. These applications are portable and we use this scheme to update them, and it works for thousands of users. The auto update is smooth and does not require any interaction by the user. The article is especially for cases where there is no server side software. That widen the number of users who can use this scheme. Of course some of our products have server side software, and in these cases, we use a client-server-client protocol for inquiring for new versions. However when you don't want to create a server software, this scheme is ideal for inquiring whether the version on the server is newer.
I tested your software and ran it in the debugger.
The update process is based on the current file version and it will only update to a version in a sequential order by adding 1. This means that a sleeping user, which not have used his computer for a while, receives multiple updates and not a final cummulative update. This also means that the download server must contains not only the last version but all previous versions too.
That is why I prefer downloading a script which can specify the name of the final current update for download.
That's why I wrote at the end a list of things left to be done:
"- Allowing automatic update to a version that comes after the next one, for example going from 1.0.0.1 to 1.0.0.5. "
You don't need a script for that but to enhance the current code. In your example, the sleeping user will find out that he missed version 1.0.0.4 but the auto update mechanism will download version 1.0.0.6 so no harm was done...
I think this will not work. How can the application detect that version 1.0.0.6 is the last one?
Say, that the user is using 1.0.0.4 and the current one is 1.0.0.25, then the application tries all versions from 1.0.0.5 up to 1.0.0.25. But what if 1.0.0.5 is the last one, then the application tries to download forever. The only way it can work if the download have a fixed name or getting a directory list with filenames to select from, but that is not the way you have design it.
First a tip: don't post a new comment but reply to our thread.
The method shown in my article is meant to software products that don't have a server side software running. When there is a server software running, it can be used for a client-server communication. As part of such communication, the client asks the server if there is a more recent version than its current one and if so, the download takes place. We use such protocol for some of our products.
In this case, if there is a small product and the developer wasn't to save the need to have a server side software running, my approach allows such developer to just place the updated version on the server.
You pointed 2 possible problems:
1. A scenario in which program version 1.0.0.1 was not running for a while and next time it is running, the most recent version is 1.0.0.3 (or 1.2.0.0 for that matter).
2. The next update is a more significant one, so from version 1.0.0.25 it goes to version 1.0.1.0 (for example).
Here is my solution for both problems starting with the last one:
First, I will update my code to make 2 checks:
1. Check for the next version under the same level (1.0.0.1 will check for version 1.0.0.2)
2. If such version isn't found, look for the next version in the next level (i.e. 1.0.1.0).
That will address a single promotion regardless of the method.
If the next version is a more significant one, the check for the next revision will fail so we can assume that if there isn't version 1.0.0.25, there is also no 1.0.0.26 and 1.0.0.27.
As for the first issue, since our purpose is to avoid the need of a server side software, the way we use to check for updates it attempting to download a file. The result of such attempt can be:
- file not found.
- file is found and software is updated.
According to your "sleep" scenario, the software will be updated but the update won't be the most recent version. In that case, the update will run and look for updates, download the next version and run it, and so on, until the product will be the most recent one.
The solution presented here is nice for a single file application update!
I think it works great for a server or background application running under an administrator UAC.
If the application is running under a user UAC, the UAC must be elevated or switched to an admininstrator UAC. Else you can not rename a file in a current running process or access restricted folders and registry settings. After the update the original user UAC must be restored so that the user settings and files are available again.
If you have to maintain an application with a lot of support files, it don't work very well. A better way is to put the update process in companian appplication (updater) which using a script that is downloaded from a website. That script must be close connected with the updater. If the version of the script is changed, the updater must do a self update. This way you can change at any time the whole update process to do single replacements of files or running a setup application.
Thank you for your comments. We, at Secured Globe, Inc. tend to create applications with a single file (and in case we need several files, a single file extracts them during the first run). For these reasons it works for us. As for UAC, if you check my update you will see that in general, if your program requires Administration rights, then you assume the user ran it and confirmed the Elevation Prompt and after that point, the automatic updates will run smoothly and with no prompts (silent updates), and the reason is because an elevated process can invoke another elevated process
No, I have not run your example program, but I have read the article. My opinion is based on that. I understand that if running the main application, it checks for the an update and if valid, it downloads a executable file and run it in a secondary process while the main process quits. The new process is an setup application that do it things and then starts the new main application again with the same UAC as started. No external script needed but only a filename convention and a fixed place for download. The only drawback is that if you have to replace a support file then you have to replace the main application too, because of the changed version number.
Yes. You understood correctly. This is why since the new version is defined as such that it requires Administration Privileges, it won't have any problems to start the new process elevated already with no prompts.
I know how a subprocess inherit the UAC settings of the caller process, but first the user have to allow the elevation (or not) and expected after the update to be back at the same UAC level as started.
In my application I did it like this:
Elevation
C++
SHELLEXECUTEINFO sei = { sizeof(sei) };
// elevate the user with the administrator credentials
sei.hwnd = pSU->m_hWnd;
sei.lpVerb = L"runas";
sei.lpFile = strExeFile;
sei.lpParameters = strVersion;
sei.nShow = SW_NORMAL;
if (!ShellExecuteEx(&sei))
{
DWORD dwError = GetLastError();
if (dwError == ERROR_CANCELLED)
{
// The user refused to allow privileges elevation.
pSU->MessageBox(L"The user refused to allow privileges elevation.");
}
}
else
{
return1; // quit application
}
De-elevation
C++
SHELLEXECUTEINFO sei = { sizeof(sei) };
// de-elevate the user without the administrator credentials
sei.hwnd = pWnd->m_hWnd;
sei.lpVerb = NULL;
sei.lpFile = L"explorer.exe";
// Note: the parameter string must have the double quotes!
// sei.lpParameters = L"\"C:\\Windows\\System32\\Calc.exe\"";
CString str = L"\"" + GetAppPath() + "\\" + m_strArg + L"\"";
sei.lpParameters = str;
sei.lpDirectory = NULL;
sei.nShow = SW_NORMAL;
if (!ShellExecuteEx(&sei))
{
DWORD dwError = GetLastError();
if (dwError == ERROR_CANCELLED)
{
// The user refused to allow privileges elevation.
pWnd->MessageBox(L"The user cancelled the program");
}
returnfalse;
}
Thanks for your input. I can read my article about that. Elevating during runtime.
Of course you can set your application to start elevated (in your code, you start not elevated and you are requiring the user to elevate during runtime).
Please note that I recommend CreateProcess over ShellExecute. Cheers. Michael