一、具體思路
安裝過程:安裝包的制作包括資源文件的打包,資源文件打包到安裝包exe中,安裝的時候需要從exe中提取出對應的資源文件,
然后解壓文件安裝到指定目錄,然后就是對安裝的可執行程序進行注冊表的注冊,以及快捷方式的注冊。
卸載過程:安裝包安裝時,通常會帶有一個卸載程序,此程序的功能就是執行對安裝程序目錄文件的刪除和注冊表的清除。
二、實現
安裝過程分為三部分實現,安裝配置,安裝過程,安裝結束啟動程序。
安裝配置界面如下:
安裝過程實現:
Install類負責對打包文件的釋放,注冊表的寫入,快捷方式的寫入,以及回調界面進度的職責:
1 #pragma once 2 #include<string> 3 #include<functional> 4 5 class Install 6 { 7 public: 8 Install(); 9 virtual ~Install(); 10 static Install& getInstance(){ 11 static Install instance; 12 return instance; 13 } 14 void setStop(){ 15 m_stop = true; 16 } 17 bool install(const std::string & install_path, bool is_shortcut); 18 void setCallBack(const std::function<void(int, const std::string &)> &fun_1,const std::function<void()> &fun_2){ 19 process_fun = fun_1; 20 process_end = fun_2; 21 } 22 private: 23 bool releaseRes(const std::string & file_name, unsigned short res_id, const std::string & file_type); 24 bool setShortCutLink(const std::string & path, const std::string & link_name, bool is_desktop); 25 bool writeToReg(); 26 std::string getDesktopPath(); 27 std::string getStartMenuPath(); 28 private: 29 std::function<void(int, const std::string &)> process_fun; 30 std::function<void()> process_end; 31 std::string m_install_path; 32 bool m_stop; 33 34 };
1)導入資源到exe,
.rc文件添加資源,
1 IDR_en_US APK "res\\bin\\locales\\en-US.pak" 2 IDR_zh_CN APK "res\\bin\\locales\\zh-CN.pak" 3 4 ///////////////////////////////////////////////////////////////////////////// 5 // 6 // EXE 7 // 8 9 IDR_YDDemo EXE "res\\bin\\YDDemo.exe" 10 IDR_Unstall_App EXE "res\\bin\\Unstall_App.exe" 11 IDR_debug LOG "res\\bin\\debug.log" 12 IDR_icudtl DAT "res\\bin\\icudtl.dat" 13 IDR_natives_blob BIN "res\\bin\\natives_blob.bin" 14 IDR_snapshot_blob BIN "res\\bin\\snapshot_blob.bin" 15 IDR_cef APK "res\\bin\\cef.pak" 16 IDR_cef_100_percent APK "res\\bin\\cef_100_percent.pak" 17 IDR_cef_200_percent APK "res\\bin\\cef_200_percent.pak" 18 IDR_cef_extensions APK "res\\bin\\cef_extensions.pak" 19 IDR_devtools_resources APK "res\\bin\\devtools_resources.pak" 20 ///////////////////////////////////////////////////////////////////////////// 21 // 22 // DLL 23 // 24 25 IDR_d3dcompiler_43 DLL "res\\bin\\d3dcompiler_43.dll" 26 IDR_d3dcompiler_47 DLL "res\\bin\\d3dcompiler_47.dll" 27 IDR_DuiLib_u DLL "res\\bin\\DuiLib_u.dll" 28 IDR_libcef DLL "res\\bin\\libcef.dll" 29 IDR_libEGL DLL "res\\bin\\libEGL.dll" 30 IDR_libGLESv2 DLL "res\\bin\\libGLESv2.dll" 31 IDR_widevinecdmadapter DLL "res\\bin\\widevinecdmadapter.dll"
定義資源ID
1 #define IDR_en_US 152 2 #define IDR_zh_CN 153 3 #define IDR_YDDemo 154 4 #define IDR_Unstall_App 155 5 #define IDR_debug 156 6 #define IDR_icudtl 157 7 #define IDR_natives_blob 158 8 #define IDR_snapshot_blob 159 9 #define IDR_cef 160 10 #define IDR_cef_100_percent 161 11 #define IDR_cef_200_percent 162 12 #define IDR_cef_extensions 163 13 #define IDR_devtools_resources 164 14 #define IDR_d3dcompiler_43 165 15 #define IDR_d3dcompiler_47 166 16 #define IDR_DuiLib_u 167 17 #define IDR_libcef 168 18 #define IDR_libEGL 169 19 #define IDR_libGLESv2 170 20 #define IDR_widevinecdmadapter 171
2)釋放資源,並且回調安裝進度,更新界面的顯示
1 bool releaseRes(const std::string & file_name, unsigned short res_id, const std::string & file_type);
releaseRes負責釋放資源
1 bool Install::releaseRes(const std::string & file_name, unsigned short res_id, const std::string & file_type){ 2 DWORD dwWrite = 0; 3 HANDLE hFile = CreateFile(Ecoder::stringToWstring(file_name).c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, 4 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); 5 if (hFile == INVALID_HANDLE_VALUE){ 6 return FALSE; 7 } 8 HRSRC hrsc = FindResource(NULL, MAKEINTRESOURCE(res_id), Ecoder::stringToWstring(file_type).c_str()); 9 HGLOBAL hG = LoadResource(NULL, hrsc); 10 DWORD dwSize = SizeofResource(NULL, hrsc); 11 WriteFile(hFile, hG, dwSize, &dwWrite, NULL); 12 CloseHandle(hFile); 13 return true; 14 }
設置回調函數
std::function<void(int, const std::string &)> process_fun; std::function<void()> process_end;
1 Install::getInstance().setCallBack(std::bind(&MainFrame::setProcessCallBack,this,std::placeholders::_1,std::placeholders::_2), 2 std::bind(&MainFrame::setupEndCallBack,this));
兩個回調函數負責更新資源釋放的進度,當然也可以用一個回調函數。
3)注冊表操作
寫入exe到注冊表
1 bool writeToReg();
創建快捷方式
bool setShortCutLink(const std::string & path, const std::string & link_name, bool is_desktop);
結束安裝,啟動程序。
1 std::string str_tmp = m_install_path + "\\"; 2 m_install_path += "\\YDDemo.exe"; 3 ShellExecute(NULL, L"open", Ecoder::stringToWstring(m_install_path).c_str(), NULL, Ecoder::stringToWstring(str_tmp).c_str(), SW_SHOWNORMAL);
卸載過程也是分三部分實現:卸載選擇,卸載過程,卸載結束,界面操作如下
界面卸載是通過UnInstall類實現,主要負責注冊表的清理,目錄文件的刪除,程序的自刪除以及更新界面進度的職責
1 #pragma once 2 #include<string> 3 #include<functional> 4 5 class UnInstall 6 { 7 public: 8 UnInstall(); 9 virtual ~UnInstall(); 10 static UnInstall& getInstance(){ 11 static UnInstall instance; 12 return instance; 13 } 14 void setCallBack(const std::function<void(int, const std::string &)> &fun_1, const std::function<void()> &fun_2){ 15 process_fun = fun_1; 16 process_end = fun_2; 17 } 18 bool unInstall(); 19 bool deleteRegKey(); 20 bool deleteDirFile(const std::string & path); 21 bool deleteApplicationSelf(); 22 private: 23 std::function<void(int, const std::string &)> process_fun; 24 std::function<void()> process_end; 25 };
具體代碼可以參考https://github.com/karllen/cef3-duilib-YDDemo/tree/master/Setup_App,因為這個是我學習的Demo,
功能還不是特別完善,圖片素材取自網絡,如有侵權,聯系作者刪除。此程序適合入門duilib的C++ 程序員來學習,
程序實現用了C++11的std::thread,std::share_ptr,std::bind等。
技術交流QQ群,歡迎大家加入:347769318