Automatic installer implementation algorithm and source code
Li Anne
Keywords: self-decompressed automatic installer
If my program wants to call a setup.exe program, automatically install a software, then remove all the temporary files after the installation, what should I achieve? Although it is very simple, there is a problem that needs to be solved, how is it judged when installed? Of course, you can use // Wait for Until IT Terminated: while (getExitCodeProcess, & Dwitcode && Dwitcode == STILL_ACTIVE);
To wait for the setup.exe run, but the problem may not be so simple, often setup.exe calls another child process (such as _delis and inst5176), while setup.exe exits, the child process has not exited That is, the task is still not completed. So the delete temporary file and folder will still cause the installation failure and delete file failed. (I judge the early WinRAR created TempMode self-extracting file, the reasonable installation will fail after starting setup.ex, may be deleted because of the judgment error, that is, the temporary file is deleted when the installation is not completed.)
This problem can be resolved (for reference) as follows: 1. Create an event HEVENT; 2, start the release in the temporary directory (such as C: / Windows / Temp / mytemp), after SETUP.EXE Then perform the following statement: // Wait for the self-extract process exit: :: resetEvent (HEILENT); while (:: waitforsingleObject (hevent, 500) == Wait_timeout) {ibeXit ();}
That is, reset the event HEVENT to the signalless state and cycle calls the iSexit () function;
3, list all the processes in the system in the iSexit () function: (1), call the system function CreateToolHelp32Snapshot () and specify the TH32CS_SNAPPROCESS parameter to get a list of all processes in a system (Snapshot); (2), call the system function Process32First ( Get information on the first process; (3), the loop call system function process32next () Gets information about the rest of the process. One parameter LPPE is a processentry32 type structure. The LPPE.TH32PROCESSID parameter contains the acquired process identifier; lppe.szexefile is the executable file path and name for the process. Therefore, in the above processing, each time the LPPE determines whether the path in the LPPE.SZEXEFILE is a temporary directory in the installer. If there is no such process, the installation has been completed, then call the setEvent () function, will The HEVENT event is set to have a signal, thereby ending the cycle in the second step;
4. Turn off the event handle, remove all temporary files and folders of the installer (such as MyTemp), complete the installation. Note: The #include
Below is an example code (debug passed): // mysfx.cpp: defines the entry point "stdafx.h" #include "resource.h"
// foward declarations of functions include in this code module: Bool InitInstance (Hinstance, int); void Removethem (char * strpath); void iSexit ();
Int apientry Winmain (Hinstance Hinstance, Hinstance Hprevinstance, LPSTR LPCMDLINE, INT NCMDSHOW) {// Perform Application Initialization: Return InitInstance (Hinstance, ncmdshow);}
//// Function: InitInstance (Handle, Int) //// Purpose: Saves Instance Handle and Creates Main WINDOW //// Comments: //////// Comments: //////// Comments: //////// Comments: //// in this function, WE Save the Instance Handle in A Global Variable and / / Create and display the main program window.//#if defined (_debug) #define thisfile_length 159785 # Else # define thisfile_length 28672 # Endif
CHAR Spath [256];
BOOL InitInstance (HINSTANCE hInstance, int nCmdShow) {char sModule [256], sTemFile [256]; // Gets temporary directory: :: GetTempPath (255, sPath); strcat (sPath, "Mytemp"); :: CreateDirectory (sPath , NULL); STRCPY (STEMFILE, SPATH); STRCAT (STEMFILE, "// sfx.exe"); :: getModuleFileName (Null, Smodule, 255);
// Opens the module file: HANDLE hFile = :: CreateFile (sModule, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hFile) return 0; // Creates the temprory file: HANDLE hFileTemp =: : CreateFile (sTemFile, GENERIC_WRITE | GENERIC_READ, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (INVALID_HANDLE_VALUE == hFileTemp) {:: CloseHandle (hFile); return 0;} :: SetFilePointer (hFile, THISFILE_LENGTH, NULL, FILE_BEGIN ); // now (true) {byte buf [40 * 1024]; DWORD DWNUMBEROFBYTESREAD; if (: Readfile (HFile, BUF, 40 * 1024, & dwnumberofbytesread, null) == 0) BREAK ; DWORD dwNumberOfBytesWritten; if (dwNumberOfBytesRead> 0) if (:: WriteFile (hFileTemp, buf, dwNumberOfBytesRead, & dwNumberOfBytesWritten, NULL)!) break; if (dwNumberOfBytesRead <40 * 1024) break;} // while (TRUE) :: CloseHandle (HFILE); :: CloseHandle (HfileTemp); // prepare to extract files and setup the application: // create a auto-reset event object: hEvent = :: CreateEvent (null, / / SD false, // reset type false, // initial state null // Object name);
// Executes self-extract file to extract files: STARTUPINFO info; PROCESS_INFORMATION newinfo; :: GetStartupInfo (& info); :: CreateProcess (sTemFile, NULL, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE, NULL, sPath, & info, & newinfo);
// Wait for the self-extract process exit: :: resetEvent (hevent); while (:: waitforsingleObject) == Wait_timeout) {ibeXit ();}
// Executes setup: strcpy (sTemFile, sPath); strcat (sTemFile, "// Setup.exe"); :: CreateProcess (sTemFile, NULL, NULL, NULL, FALSE, CREATE_DEFAULT_ERROR_MODE | CREATE_NO_WINDOW, NULL, sPath, & info, & newinfo ); // Wait for setup process and other started by it exit: :: resetEvent (hevent); while (:: waitforsingleobject); = wait_timeout) {ibexit ();} :: closehandle (hEvent); / / Remove tempary files and folders: RemoveThem (sPath); return FALSE;} void RemoveThem (char * strPath) {char strTemFile [256]; strcpy (strTemFile, strPath); strcat (strTemFile, "//*.*"); WIN32_FIND_DATA FindFileData; HANDLE hFind = FindFirstFile (strTemFile, & FindFileData); if (hFind = INVALID_HANDLE_VALUE!) while (TRUE) {if (FindFileData.cFileName [0] == '.') {if (FindNextFile (hFind, & FindFileData)!) break; continue;} strcpy (strTemFile, strPath); strcat (strTemFile, "//"); strcat (strTemFile, FindFileData.cFileName); if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) RemoveThem (strTemFile); // recursive call if it's A Subdi Reletefile; // delete it if it's a file. if (! FindNextFile (Hfind, & FindfileData)) Break;} :: closehandle (hfind); :: removedirectory (strPath);}
void IsExit () {// Enumerate current processes: // This process do not exit until the processes belonged to setup are all terminated: HANDLE hSnapshot; PROCESSENTRY32 pe; pe.dwSize = sizeof (pe); BOOL blExist = FALSE; size_t Len = Strlen (SPATH);
hSnapshot = :: CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0); if (hSnapshot <0) goto L1; if (:: Process32First (hSnapshot, & pe) == FALSE) {:: (hSnapshot) CloseHandle; goto L1;} if (_strnicmp ( Spath, pe.szexefile, len) == 0) blexist = true; while (blexist == false && :: process32next (hsnapshot, & pE)) {i (_Strnicmp (spath, pe.szeefile, len) == 0) { BLEXIST = True; Break;}} :: closehandle (hsnapshot); l1: if (blexist == false) :: setEvent (hEvent);
The intent of this article is not to develop a tool software (because such a tool on the market), its main purpose is to think about achieving thinking with interested friends, saying that there may be a little help to a friend (if needed) The full code can be credible to the message).
*********************************************************** ****************
Note:
1. Thank you for your encouragement, because more friends who want source code, now please go directly to download the source code:
http://www.9cbs.net/cnshare
2, using the sleep () function is really easier, thank you master point.