一執行個體1.1 安裝程式 1.2 卸載程式 二思路2.1 安裝程式1 如何將目的程式附加在安裝程式裡?一般安裝程式只有一個可執行檔,因而目的程式也放在安裝程式裡面,通過將目標程式放在資源檔,可以使目標程式像資源一樣使用。目標程式在資源的類型是#define RC_BINARYTYPE 256,格式如下://#resource.h#define RC_BINARYTYPE 256#define ID_MAIN 3000 //ID_MAIN表示主程式的資源ID//xxx.rc#include “resource.h”ID_MAIN RC_BINARYTYPE “XXX.exe” //目標程式2 如何將資源裡的檔案解壓到目標路徑?①用FindResource,LoadResource,LockResource等將資源載入到緩衝區,②然後用CreateFile,WriteFile,CloseFile等將緩衝區的資料寫到目標路徑。3 如何對用COMPRESS壓縮的檔案進行解壓?用LZOpenFile,LZCopy,LZClose等解壓。4 如何建立開始菜單和案頭的捷徑?用SHGetSpecialFolderPath(NULL,StartMenuPath,CSIDL_PROGRAMS,0);擷取開始菜單路徑,用SHGetSpecialFolderPath(NULL,StartDeskPath,CSIDL_DESKTOP,0);擷取案頭路徑。用IshellLink建立捷徑 2.2 卸載程式1 刪除已安裝的所有檔案。DeleteFile2 刪除捷徑。DeleteFile3 刪除卸載程式本身。參考文獻:原著:Alex Tilles 翻譯:NorthTibet <<用自刪除DLL實現應用程式的安裝/卸載代碼>>這篇文章是安裝程式的核心思想,而且有代碼,對開發安裝程式非常有協助。 三代碼/*名稱:WriteResourceToFile 功能:將資源中指定的檔案寫到filename 參數:hInstance控制代碼,idResource資源ID,filename產生的檔案*/void WriteResourceToFile(HINSTANCE hInstance,int idResource,char const *filename){ HRSRC hResInfo=FindResource(hInstance,MAKEINTRESOURCE(idResource),MAKEINTRESOURCE(RC_BINARYTYPE)); HGLOBAL hgRes=LoadResource(hInstance,hResInfo); void *pvRes=LockResource(hgRes); DWORD cbRes=SizeofResource(hInstance,hResInfo); HANDLE hFile=CreateFile(filename,GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0); DWORD cbWritten; WriteFile(hFile,pvRes,cbRes,&cbWritten,0); CloseHandle(hFile);}/*名稱:DecompressFile 功能:對COMPRESS壓縮檔進行解壓 參數:source壓縮的檔案,解壓成的檔案*/void DecompressFile(char const *source,char const *dest){ OFSTRUCT ofs; ofs.cBytes=sizeof(ofs); int zhfSource=LZOpenFile(const_cast<char*>(source),&ofs,OF_READ); int zhfDest=LZOpenFile(const_cast<char*>(dest),&ofs,OF_CREATE|OF_WRITE); LZCopy(zhfSource,zhfDest); LZClose(zhfSource); LZClose(zhfDest);}#include <shlobj.h>#pragma comment(lib,"shell32.lib")/*名稱:CreateProgFolder 功能:建立開始菜單程式組 參數:程式組名稱*/int CreateProgFolder(LPSTR folder){ char foldbuff[MAX_PATH]; SHGetSpecialFolderPath(NULL,foldbuff,CSIDL_PROGRAMS,0); //建立開始 sprintf(foldbuff,"%s//%s",foldbuff,folder); CreateDirectory(foldbuff,NULL); return 1;}/*名稱:CreateProgLink 功能:建立開始菜單的捷徑 參數:lpszSrcPath源檔案路徑,linkname捷徑名稱,lpszWorkingPath工作目錄,Desc注釋*/int CreateProgLink(LPSTR lpszSrcPath,LPSTR linkname,LPSTR lpszWorkingPath,LPSTR Desc){ char StartMenuPath[MAX_PATH]; SHGetSpecialFolderPath(NULL,StartMenuPath,CSIDL_PROGRAMS,0); //建立開始 sprintf(StartMenuPath,"%s//%s",StartMenuPath,linkname); CreateLink(lpszSrcPath,StartMenuPath,lpszWorkingPath,Desc); return 1;}/*名稱:CreateDeskLink 功能:建立案頭的捷徑 參數:lpszSrcPath源檔案路徑,linkname捷徑名稱,lpszWorkingPath工作目錄,Desc注釋*/int CreateDeskLink(LPSTR lpszSrcPath,LPSTR linkname,LPSTR lpszWorkingPath,LPSTR Desc){ char StartDeskPath[MAX_PATH]; SHGetSpecialFolderPath(NULL,StartDeskPath,CSIDL_DESKTOP,0); //建立開始 sprintf(StartDeskPath,"%s//%s",StartDeskPath,linkname); CreateLink(lpszSrcPath,StartDeskPath,lpszWorkingPath,Desc); return 1;}/*名稱:CreateLink 功能:建立捷徑 參數:lpszSrcPath源檔案路徑,lpszPathLink捷徑路徑,lpszWorkingPath工作目錄,Desc注釋*/HRESULT CreateLink(LPCSTR lpszSrcPath,LPSTR lpszPathLink,LPSTR lpszWorkingPath,LPSTR lpszDesc){ HRESULT hres ; IShellLink * psl ; IPersistFile * ppf ; WORD wsz[ MAX_PATH] ; CoInitialize(NULL); hres = CoCreateInstance( CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl) ; if( FAILED( hres)) return FALSE ; //設定目標應用程式 psl -> SetPath( lpszSrcPath) ; psl -> SetDescription(lpszDesc); psl -> SetWorkingDirectory(lpszWorkingPath); //從IShellLink擷取其IPersistFile介面 //用於儲存捷徑的資料檔案 (*.lnk) hres = psl -> QueryInterface( IID_IPersistFile, (void**)&ppf); if( FAILED( hres)) { psl -> Release( ) ; return FALSE ; } // 確保資料檔案名為ANSI格式 MultiByteToWideChar( CP_ACP, 0, lpszPathLink, -1,wsz, MAX_PATH) ; //調用IPersistFile::Save //儲存捷徑的資料檔案 (*.lnk) hres = ppf -> Save( wsz, STGM_READWRITE) ; //釋放IPersistFile和IShellLink介面 ppf -> Release( ) ; psl -> Release( ) ; //記錄 WriteFile(hFileLog,lpszPathLink,strlen(lpszPathLink),&bNum,NULL); WriteFile(hFileLog,"/r/n",2,&bNum,0); return 1;}卸載程式自我刪除,需用到一個動態鏈庫,具體應用參考“參考文獻”void SelfDelete(HINSTANCE hInstance){ WriteResourceToFile(hInstance,ID_DLL,"instdll.dll"); //產生命令列 //尋找rudll32.exe char commandLine[MAX_PATH*3]; GetWindowsDirectory(commandLine,sizeof(commandLine)); lstrcat(commandLine,"//rundll32.exe"); if(GetFileAttributes(commandLine)==0xFFFFFFFF) { GetSystemDirectory(commandLine,sizeof(commandLine)); lstrcat(commandLine,"//rundll32.exe"); } //添加rundll32.exe參數 lstrcat(commandLine," instdll.dll,_MagicDel@16 "); char thisName[MAX_PATH]; GetModuleFileName(hInstance,thisName,sizeof(thisName)); lstrcat(commandLine,thisName); PROCESS_INFORMATION procInfo; STARTUPINFO startInfo; memset(&startInfo,0,sizeof(startInfo)); startInfo.dwFlags=STARTF_FORCEOFFFEEDBACK; CreateProcess(0,commandLine,0,0,FALSE,NORMAL_PRIORITY_CLASS,0,0,&startInfo,&procInfo);}