FAQ:WinAPI VCPP:самообновление запущенной программы

Материал из Весельчак У

Перейти к: навигация, поиск

Каким способом exe файл может заменить самого себя?

К примеру, программа должна обновляется через Internet и хочет обновить свой exe-файл. Но так как он в данный момент запущен, это будет, естественно, невозможно сделать напрямую. Один из способов - сделать копию экзешника и из него обновиться

// путь к старому файлу
#define def_exeNAMEup "c:\\myprog_toupdate.exe"
 
// путь к новому файлу (уже "скачали":) )
#define def_exeNAMEdnld "c:\\myprog_downloaded.exe"
 
#define def_keyUdate "/update"
 
void CTESTFAQApp::UpdateItself()
{
// добыча полного имени экзешника
CString csFullExeName;
{
CString csAppName = GetCommandLine();
csAppName.Delete(0,1);
csAppName.Replace('\"', '\0');
csFullExeName = (const char*)csAppName;
}
// теперь csFullExeName - содержит искомый путь
 
// делаем копию экзешника с другим именем
CopyFile(csFullExeName, def_exeNAMEup, 0);
 
// передаём в параметры нового процесса ключ и путь к текущему файлу
CString csParams = def_keyUdate;
 
csParams += " ";
csParams += csFullExeName;
 
// запускаем копию
STARTUPINFO si;
PROCESS_INFORMATION pi;
 
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
 
if (CreateProcess(def_exeNAMEup, def_keyUdate, 0, 0, 0, 0, 0, 0, &si, &pi))
{
// завершаем текущий процесс
ExitFromMyApp();
}
}
 
void CTESTFAQApp::ExitFromMyApp()
{
exit(0);
}
 
BOOL CTESTFAQApp::InitInstance()
{
// смотрим, не запущено ли для апдейта?
CString txt;
 
txt = m_lpCmdLine;
 
if (txt.Find(def_keyUdate) == 0)
{
// делаем айдейт
txt.Replace(def_keyUdate, "");
txt.TrimLeft();
 
CString csFullExeName = txt;
 
// берём откуда то уже скачанный файл обновления
// ...
CString csFull_Downloaded_ExeName = def_exeNAMEdnld;
 
// копируем файл (обновляем старый то есть)
CopyFile(csFull_Downloaded_ExeName, csFullExeName, 0);
 
// запускаем обновлённого мученника
STARTUPINFO si;
PROCESS_INFORMATION pi;
 
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
 
if (CreateProcess(csFullExeName, 0, 0, 0, 0, 0, 0, 0, &si, &pi))
ExitFromMyApp();
}
 
// ...
// ...
}