使用duilib开发简单的Window安装包

时间:2023-02-11 09:32:38

一、具体思路

安装过程:安装包的制作包括资源文件的打包,资源文件打包到安装包exe中,安装的时候需要从exe中提取出对应的资源文件,

然后解压文件安装到指定目录,然后就是对安装的可执行程序进行注册表的注册,以及快捷方式的注册。

卸载过程:安装包安装时,通常会带有一个卸载程序,此程序的功能就是执行对安装程序目录文件的删除和注册表的清除。

二、实现

安装过程分为三部分实现,安装配置,安装过程,安装结束启动程序。

安装配置界面如下:

使用duilib开发简单的Window安装包

安装过程实现:

Install类负责对打包文件的释放,注册表的写入,快捷方式的写入,以及回调界面进度的职责:

 #pragma once
#include<string>
#include<functional> class Install
{
public:
Install();
virtual ~Install();
static Install& getInstance(){
static Install instance;
return instance;
}
void setStop(){
m_stop = true;
}
bool install(const std::string & install_path, bool is_shortcut);
void setCallBack(const std::function<void(int, const std::string &)> &fun_1,const std::function<void()> &fun_2){
process_fun = fun_1;
process_end = fun_2;
}
private:
bool releaseRes(const std::string & file_name, unsigned short res_id, const std::string & file_type);
bool setShortCutLink(const std::string & path, const std::string & link_name, bool is_desktop);
bool writeToReg();
std::string getDesktopPath();
std::string getStartMenuPath();
private:
std::function<void(int, const std::string &)> process_fun;
std::function<void()> process_end;
std::string m_install_path;
bool m_stop; };

1)导入资源到exe,

.rc文件添加资源,

 IDR_en_US              APK                    "res\\bin\\locales\\en-US.pak"
IDR_zh_CN APK "res\\bin\\locales\\zh-CN.pak" /////////////////////////////////////////////////////////////////////////////
//
// EXE
// IDR_YDDemo EXE "res\\bin\\YDDemo.exe"
IDR_Unstall_App EXE "res\\bin\\Unstall_App.exe"
IDR_debug LOG "res\\bin\\debug.log"
IDR_icudtl DAT "res\\bin\\icudtl.dat"
IDR_natives_blob BIN "res\\bin\\natives_blob.bin"
IDR_snapshot_blob BIN "res\\bin\\snapshot_blob.bin"
IDR_cef APK "res\\bin\\cef.pak"
IDR_cef_100_percent APK "res\\bin\\cef_100_percent.pak"
IDR_cef_200_percent APK "res\\bin\\cef_200_percent.pak"
IDR_cef_extensions APK "res\\bin\\cef_extensions.pak"
IDR_devtools_resources APK "res\\bin\\devtools_resources.pak"
/////////////////////////////////////////////////////////////////////////////
//
// DLL
// IDR_d3dcompiler_43 DLL "res\\bin\\d3dcompiler_43.dll"
IDR_d3dcompiler_47 DLL "res\\bin\\d3dcompiler_47.dll"
IDR_DuiLib_u DLL "res\\bin\\DuiLib_u.dll"
IDR_libcef DLL "res\\bin\\libcef.dll"
IDR_libEGL DLL "res\\bin\\libEGL.dll"
IDR_libGLESv2 DLL "res\\bin\\libGLESv2.dll"
IDR_widevinecdmadapter DLL "res\\bin\\widevinecdmadapter.dll"

定义资源ID

 #define IDR_en_US                       152
#define IDR_zh_CN 153
#define IDR_YDDemo 154
#define IDR_Unstall_App 155
#define IDR_debug 156
#define IDR_icudtl 157
#define IDR_natives_blob 158
#define IDR_snapshot_blob 159
#define IDR_cef 160
#define IDR_cef_100_percent 161
#define IDR_cef_200_percent 162
#define IDR_cef_extensions 163
#define IDR_devtools_resources 164
#define IDR_d3dcompiler_43 165
#define IDR_d3dcompiler_47 166
#define IDR_DuiLib_u 167
#define IDR_libcef 168
#define IDR_libEGL 169
#define IDR_libGLESv2 170
#define IDR_widevinecdmadapter 171

2)释放资源,并且回调安装进度,更新界面的显示

 bool releaseRes(const std::string & file_name, unsigned short res_id, const std::string & file_type);

releaseRes负责释放资源

 bool Install::releaseRes(const std::string & file_name, unsigned short res_id, const std::string & file_type){
DWORD dwWrite = ;
HANDLE hFile = CreateFile(Ecoder::stringToWstring(file_name).c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE){
return FALSE;
}
HRSRC hrsc = FindResource(NULL, MAKEINTRESOURCE(res_id), Ecoder::stringToWstring(file_type).c_str());
HGLOBAL hG = LoadResource(NULL, hrsc);
DWORD dwSize = SizeofResource(NULL, hrsc);
WriteFile(hFile, hG, dwSize, &dwWrite, NULL);
CloseHandle(hFile);
return true;
}

设置回调函数

    std::function<void(int, const std::string &)> process_fun;
std::function<void()> process_end;
 Install::getInstance().setCallBack(std::bind(&MainFrame::setProcessCallBack,this,std::placeholders::_1,std::placeholders::_2),
std::bind(&MainFrame::setupEndCallBack,this));

两个回调函数负责更新资源释放的进度,当然也可以用一个回调函数。

3)注册表操作

写入exe到注册表

     bool writeToReg();

创建快捷方式

    bool setShortCutLink(const std::string & path, const std::string & link_name, bool is_desktop);

结束安装,启动程序。

     std::string str_tmp = m_install_path + "\\";
m_install_path += "\\YDDemo.exe";
ShellExecute(NULL, L"open", Ecoder::stringToWstring(m_install_path).c_str(), NULL, Ecoder::stringToWstring(str_tmp).c_str(), SW_SHOWNORMAL);

卸载过程也是分三部分实现:卸载选择,卸载过程,卸载结束,界面操作如下

使用duilib开发简单的Window安装包

界面卸载是通过UnInstall类实现,主要负责注册表的清理,目录文件的删除,程序的自删除以及更新界面进度的职责

 #pragma once
#include<string>
#include<functional> class UnInstall
{
public:
UnInstall();
virtual ~UnInstall();
static UnInstall& getInstance(){
static UnInstall instance;
return instance;
}
void setCallBack(const std::function<void(int, const std::string &)> &fun_1, const std::function<void()> &fun_2){
process_fun = fun_1;
process_end = fun_2;
}
bool unInstall();
bool deleteRegKey();
bool deleteDirFile(const std::string & path);
bool deleteApplicationSelf();
private:
std::function<void(int, const std::string &)> process_fun;
std::function<void()> process_end;
};

具体代码可以参考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