在实现DelUninstall的卸载软件功能时,我们需要运行软件所指定的卸载程序,并等待其进程结束。
在用API函数WaitForSingleObject来等卸载程序进程结束时:
DWORD WaitForSingleObject( HANDLE hHandle, // 等待对象的句柄 DWORD dwMilliseconds // 等待毫秒数,INFINITE表示无限等待 );
我们需要把进程句柄作为第一个参数传递给它。
要得到卸载程序运行时的进程句柄,我们至少有两个方法:
一、使用API函数ShellExecuteEx来运行卸载程序。
ShellExecuteEx的原型为:
BOOL ShellExecuteEx( LPSHELLEXECUTEINFO lpExecInfo );
其参数所指向的结构SHELLEXECUTEINFO定义为:
typedef struct _SHELLEXECUTEINFO { DWORD cbSize; ULONG fMask; HWND hwnd; LPCTSTR lpVerb; LPCTSTR lpFile; LPCTSTR lpParameters; LPCTSTR lpDirectory; int nShow; HINSTANCE hInstApp; LPVOID lpIDList; LPCTSTR lpClass; HKEY hkeyClass; DWORD dwHotKey; union { HANDLE hIcon; HANDLE hMonitor; } DUMMYUNIONNAME; HANDLE hProcess; } SHELLEXECUTEINFO, *LPSHELLEXECUTEINFO;
我们把卸载程序的命令行字符串首地址赋给SHELLEXECUTEINFO的成员lpFile,在调用成功后,在SHELLEXECUTEINFO的成员hProcess中保存着进程的句柄。
二、使用API函数CreateProcess来运行卸载程序。
CreateProcess的原型为:
BOOL WINAPI CreateProcess( __in_opt LPCTSTR lpApplicationName, __inout_opt LPTSTR lpCommandLine, __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes, __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, __in BOOL bInheritHandles, __in DWORD dwCreationFlags, __in_opt LPVOID lpEnvironment, __in_opt LPCTSTR lpCurrentDirectory, __in LPSTARTUPINFO lpStartupInfo, __out LPPROCESS_INFORMATION lpProcessInformation );
我们把卸载程序的命令行字符串首地址传给第2个参数lpCommandLine,同时我们初始化一个STARTUPINFO结构变量和一个PROCESS_INFORMATION结构变量,并把其地址作为第9和第10个参数传递。
PROCESS_INFORMATION结构定义为:
typedef struct _PROCESS_INFORMATION { HANDLE hProcess; HANDLE hThread; DWORD dwProcessId; DWORD dwThreadId; }PROCESS_INFORMATION, *LPPROCESS_INFORMATION;
调用成功后,进程句柄就存放在PROCESS_INFORMATION结构变量的成员hProcess中。
下面是DelUninstall中有关代码,当常量c_UseshlExec值为1时,我们使用ShellExecuteEx来实现,否则使用CreateProcess:
;lpszUnFile:卸载程序的命令行字符串首地址 UninstallA proc lpszUnFile: LPSTR c_UseshlExec equ 1 if c_UseshlExec eq 1 local siExeInfo: SHELLEXECUTEINFO else local piProcInfo: PROCESS_INFORMATION local siStartInfo: STARTUPINFO endif ; c_UseshlExec if c_UseshlExec eq 1 invoke RtlZeroMemory, addr siExeInfo, sizeof SHELLEXECUTEINFO mov siExeInfo.cbSize, sizeof SHELLEXECUTEINFO mov eax, lpszUnFile mov siExeInfo.lpFile, eax mov siExeInfo.fMask, SEE_MASK_NOCLOSEPROCESS mov siExeInfo.nShow, SW_HIDE invoke ShellExecuteEx, addr siExeInfo test eax, eax jz @F invoke WaitForSingleObject, siExeInfo.hProcess, INFINITE else ; c_UseshlExec invoke RtlZeroMemory, addr siStartInfo, sizeof STARTUPINFO invoke RtlZeroMemory, addr piProcInfo, sizeof PROCESS_INFORMATION mov siStartInfo.cb, sizeof STARTUPINFO xor ebx, ebx invoke CreateProcess, ebx, lpszUnFile,/ ebx,/ ;process security attributes ebx,/ ;primary thread security attributes ebx,/ ;handles are inherited ebx,/ ;creation flags ebx,/ ;use parent's environment ebx,/ ;use parent's current directory addr siStartInfo,/;STARTUPINFO pointer addr piProcInfo ;receives PROCESS_INFORMATION invoke WaitForSingleObject, piProcInfo.hProcess, INFINITE endif ;c_UseshlExec .endif @@: ret UninstallA endp