引导程序
1、引导程序
mian函数
//不显示控制台界面
#pragma comment( linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"" )
// 第一个参数:程序本身运行路径
// 第二个参数:被添加的资源程序
int main(int argc, char *argv[])
int main(int argc, char *argv[])
{
if(argc== 1)
executeInstall(argv[0]);
if(argc== 2)
executePackage(argv[0], argv[1]);
return 1;
}
启动安装界面
void executeInstall(const char *exePath)
{
std::string folder;
std::string zipFile = virtualFolderName(argv[0], folder);
releaseResource(zipFile); unzipFile(zipFile, folder);
std::string exeFile = folder;
exeFile += "\\bin\\doxygen.exe " + std::string(argv[0]);
PROCESS_INFORMATION pi; STARTUPINFOA si = { sizeof(si) };
ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); ZeroMemory(&pi, sizeof(pi));
BOOL bRet = CreateProcessA(NULL, LPSTR(exeFile.c_str()), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if(bRet)
{
::CloseHandle(pi.hThread);
::CloseHandle(pi.hProcess);
}
}
此处注意:exeFile += "\bin\doxygen.exe ",在后面会用到。
创建隐藏文件夹
std::string virtualFolderName(const std::string &exeFile, std::string &folder)
{
size_t pos = exeFile.find_last_of("\\");
std::string dir = exeFile.substr(0, pos);
std::string exeName = exeFile.substr(pos);
pos = exeName.find_last_of(".");
std::string fName = exeName.substr(0, pos);
dir += fName; if(_access(dir.c_str(), 0) == -1)
_mkdir(dir.c_str()); folder = dir;
SetFileAttributesA(dir.c_str(), FILE_ATTRIBUTE_HIDDEN);
dir += fName; dir += ".zip"; return dir;
}
释放资源文件(安装界面)
bool releaseResource(const std::string &zipFile)
{
char fileName[255] = { 0 };
HMODULE hModule = GetModuleHandle(NULL);
GetModuleFileNameA(hModule, fileName, 255);
HMODULE hexe = LoadLibraryA(fileName);
HANDLE hFile = CreateFileA(zipFile.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if(hFile == INVALID_HANDLE_VALUE) return false;
HRSRC src = FindResourceExA(hexe, "安装程序", "安装程序", 0);
if(src)
{
HGLOBAL glb = LoadResource(hexe, src);
if(glb == NULL) return false;
int dwSize = SizeofResource(hexe, src);
if(dwSize == 0) return false; DWORD dwWrite = 0;
WriteFile(hFile, LockResource(glb), dwSize, &dwWrite, NULL);
UnlockResource(glb); FreeResource(glb); CloseHandle(hFile);
}
//释放可执行文件
FreeLibrary(hexe);
return true;
}
解压资源文件(安装界面)
void unzipFile(const std::string &zipFile, const std::string &folder)
{
HZIP hZip = OpenZip(zipFile.c_str(), "");
ZIPENTRY ze;
DWORD zResult = ZR_OK;
GetZipItem(hZip, -1, &ze);
int numitems = ze.index;
for(int zi = 0; zi < numitems; zi++)
{
ZIPENTRY ze;
GetZipItem(hZip, zi, &ze);
char filePath[255] = { 0 };
sprintf(filePath, "%s\\%s", folder.c_str(), ze.name);
zResult = UnzipItem(hZip, zi, filePath);
}
CloseZip(hZip); remove(zipFile.c_str());
}
将安装界面作为资源写入exe
void executePackage(const std::string &exeFile, const std::string &path)
{
size_t pos = exeFile.find_last_of(".");
std::string zipFile = exeFile.substr(0, pos);
std::string newExe = zipFile + "_install.exe";
zipFile += ".zip";
HZIP hZip = CreateZip(zipFile.c_str(), "");
CopyFileA(exeFile.c_str(), newExe.c_str(), true);
compressResource(path, hZip, "");
CloseZip(hZip);
addResourceFile(zipFile, newExe);
DeleteFileA(zipFile.c_str());
}
压缩文件(安装界面)
bool compressResource(const char *path, HZIP hZip, const char *dir)
{
HANDLE hFile;
char buffer[MAX_PATH] = { 0, };
WIN32_FIND_DATA pNextInfo;
sprintf(buffer, "%s\\*", path);
hFile = FindFirstFile(buffer, &pNextInfo);
if(!hFile) return false; std::string t;
while(FindNextFile(hFile, &pNextInfo))
{
if(pNextInfo.cFileName[0] == '.')//过滤.和..
continue;
if(pNextInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
ZeroMemory(buffer, MAX_PATH); char folder[255] = { 0 };
sprintf(buffer, "%s\\%s", path, pNextInfo.cFileName);
if(strlen(dir) == 0)
sprintf(folder, "%s", pNextInfo.cFileName);
else
sprintf(folder, "%s\\%s", dir, pNextInfo.cFileName);
compressResource(buffer, hZip, folder); continue;
}
char dstzn[255] = { 0 };
if(strlen(dir) == 0)
sprintf(dstzn, "%s", pNextInfo.cFileName);
else
sprintf(dstzn, "%s\\%s", dir, pNextInfo.cFileName);
sprintf(buffer, "%s\\%s", path, pNextInfo.cFileName);
ZipAdd(hZip, dstzn, buffer);
}
return true;
}
将压缩的安装界面作为资源文件写入exe中
void addResourceFile(const std::string &zipFile, const std::string &exeFile)
{
HANDLE hFile = CreateFileA(zipFile.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_ALWAYS, FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
if(hFile == INVALID_HANDLE_VALUE) return;
SECURITY_ATTRIBUTES sa; SECURITY_DESCRIPTOR sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, nullptr, FALSE);
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
sa.lpSecurityDescriptor = &sd;
sa.bInheritHandle = FALSE;
struct _stat info;
_stat(zipFile.c_str(), &info);
HANDLE mapping = CreateFileMappingA(hFile, &sa, PAGE_READONLY, 0, info.st_size, nullptr);
if(mapping == nullptr)
{
CloseHandle(hFile);
return;
}
LPVOID addr = MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0);
int ret = GetLastError();
if(addr == nullptr)
{
CloseHandle(mapping);
CloseHandle(hFile);
return;
}
HANDLE hexe = BeginUpdateResource(exeFile.c_str(), FALSE); if(!hexe) return;
BOOL r = UpdateResource(hexe, "安装程序", "安装程序", 0, addr, info.st_size);
UnmapViewOfFile(addr); BOOL er = EndUpdateResource(hexe, FALSE);
CloseHandle(mapping); CloseHandle(hFile); CloseHandle(hexe); return;
}
到此引导程序完成。
2、使用引导程序
2.1、安装界面文件结构
启动cmd命令行工具,将引导程序(package.exe)直接拖入命令行工具中,然后将安装界面的路径添加到引导程序(package.exe)的后面,如下所示:
E:\frameware\software\安装程序
E:\frameware\software\安装程序\bin
安装界面的配置文件
等待一会之后,在引导程序同文件夹下面会有一个后缀_install.exe的文件(package_install.exe)。
双击执行exe,就会执行之前安装界面路径中的bin\doxygen.exe程序。这个执行文件可以自行修改。
安装程序界面:
启动界面显示是startpicture.bmp图片
软件许可是读取license.lic文件中的内容。
软件信息读取information.inf文件中的内容
安装路径
安装进度界面
上面一部分显示的是一个动画,中间是显示详细的安装信息,下面显示的是安装进度。