前言
市面上有很多安装程序制作软件;但是,要实现个性化安装程序,还是自己动手来写一个更为妥当。本文介绍基本的安装程序制作的步骤。 程序界面见下图:
安装程序可以分为几个功能点:1 资源的嵌入、释放。2 资源的解压。3 生成快捷方式。
1 资源导入和释放
导入 在VS资源视图,点击“”添加资源“,再选择“导入资源”,将需要安装的程序导入即可。导入的资源一般是安装程序的压缩包。
释放:将资源释放到指定目录
//将指定资源释放到指定目录下生成特定文件
//ResName 资源名称;ResType:资源类型;FileName:释放后的文件名。
BOOL FreeMyData(LPCTSTR ResName, LPCTSTR ResType, LPCTSTR FileName, int Type)
{
BOOL bRet = TRUE;
HINSTANCE hInst = AfxGetInstanceHandle();
//先判断我们指定的资源是否存在
HRSRC hResInfo = FindResource(hInst, ResName, ResType);
if (hResInfo == NULL)
return FALSE;
HANDLE hFile = NULL;
DWORD dwWritten = 0;
//开始调入指定的资源到内存
HGLOBAL hResData = LoadResource(hInst, hResInfo);
LPVOID pvResData = LockResource(hResData);
DWORD dwResSize = SizeofResource(hInst, hResInfo);
//再创建目标文件并保存数据至文件
if (Type == 1)//系统加隐藏属性 如果指定类型为1,那么加上系统和隐藏属性,防止普通用户对文件进行破坏
{
hFile = CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, NULL);
WriteFile(hFile, pvResData, dwResSize, &dwWritten, NULL);
}
else
{
hFile = CreateFile(FileName, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
WriteFile(hFile, pvResData, dwResSize, &dwWritten, NULL);
}
if (hFile == INVALID_HANDLE_VALUE)//创建文件失败
{
FreeResource(hResData);
return FALSE;
}
//释放有关内存资源
CloseHandle(hFile);
FreeResource(hResData);
return TRUE;
}
调用示例:
2 资源的解压 暨对zip文件解压。本文采用开源代码解压文件。具体调用不再详述。压缩源代码下载。
3 生成快捷方式 生成快捷方式分为两步:1 获取存放快捷文件的目录; 2 生成快捷方式文件(.lnk)。
1 获取存放目录 一般在“桌面“和“开始菜单”创建快捷方式。“桌面“其实对应于Windows系统特定的目录,一般而言该目录为“C:\Users\admin\Desktop”。windows提供了函数获取该目录。对于“开始菜单”处理亦是如此。
//得到当前桌面路径
BOOL SetupHelper::GetDesktopPath(wchar_t *pszDesktopPath)
{
LPITEMIDLIST ppidl = NULL;
if (SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &ppidl) == S_OK)
{
BOOL flag = SHGetPathFromIDList(ppidl, pszDesktopPath);
CoTaskMemFree(ppidl);
return flag;
}
return FALSE;
}
//得到 开始->程序组 的路径
BOOL SetupHelper::GetProgramsPath(wchar_t *pszProgramsPath)
{
LPITEMIDLIST ppidl;
if (SHGetSpecialFolderLocation(NULL, CSIDL_PROGRAMS, &ppidl) == S_OK)
{
BOOL flag = SHGetPathFromIDList(ppidl, pszProgramsPath);
CoTaskMemFree(ppidl);
return flag;
}
return FALSE;
}
2 生成快捷方式文件(.lnk)
需要调用系统函数生成lnk文件。
/*
函数功能:对指定文件在指定的目录下创建其快捷方式
函数参数:
lpszFileName 指定文件,为NULL表示当前进程的EXE文件。
lpszLnkFileDir 指定目录,不能为NULL。
lpszLnkFileName 快捷方式名称,为NULL表示EXE文件名。
wHotkey 为0表示不设置快捷键
pszDescription 备注
iShowCmd 运行方式,默认为常规窗口
*/
BOOL SetupHelper::CreateFileShortcut(LPWSTR lpszFileName,
LPWSTR lpszLnkFileDir, LPWSTR lpszLnkFileName, LPWSTR lpszWorkDir,
WORD wHotkey, LPWSTR lpszDescription, int iShowCmd )
{
if (lpszLnkFileDir == NULL)
return FALSE;
HRESULT hr;
IShellLink *pLink; //IShellLink对象指针
IPersistFile *ppf; //IPersisFil对象指针
//创建IShellLink对象
hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**)&pLink);
if (FAILED(hr))
return FALSE;
//从IShellLink对象中获取IPersistFile接口
hr = pLink->QueryInterface(IID_IPersistFile, (void**)&ppf);
if (FAILED(hr))
{
pLink->Release();
return FALSE;
}
//目标
if (lpszFileName == NULL)
pLink->SetPath(_wpgmptr);
else
pLink->SetPath(lpszFileName);
//工作目录
if (lpszWorkDir != NULL)
pLink->SetPath(lpszWorkDir);
//快捷键
if (wHotkey != 0)
pLink->SetHotkey(wHotkey);
//备注
if (lpszDescription != NULL)
pLink->SetDescription(lpszDescription);
//显示方式
pLink->SetShowCmd(iShowCmd);
//快捷方式的路径 + 名称
wchar_t szBuffer[MAX_PATH] = {0};
if (lpszLnkFileName != NULL) //指定了快捷方式的名称
wsprintf(szBuffer, L"%s\\%s.lnk", lpszLnkFileDir, lpszLnkFileName);
else
{
//没有指定名称,就从取指定文件的文件名作为快捷方式名称。
wchar_t *pstr;
if (lpszFileName != NULL)
pstr = wcsrchr(lpszFileName, '\\');
else
pstr = wcsrchr(_wpgmptr, '\\');
if (pstr == NULL)
{
ppf->Release();
pLink->Release();
return FALSE;
}
//注意后缀名要从.exe改为.lnk
wsprintf(szBuffer, L"%s\\%s", lpszLnkFileDir, pstr);
int nLen = wcslen(szBuffer);
szBuffer[nLen] = L'l';
szBuffer[nLen+1] = L'n';
szBuffer[nLen +2] = L'k';
}
//保存快捷方式到指定目录下
hr = ppf->Save(szBuffer, TRUE);
ppf->Release();
pLink->Release();
return SUCCEEDED(hr);
}
调用示例
//生成桌面快捷方式
wchar_t szPath[MAX_PATH] = {0};
SetupHelper::GetDesktopPath(szPath);
int ret = 0;
if (SetupHelper::CreateFileShortcut(filePathExe.GetBuffer(),
szPath, L"IOT集群调度系统", NULL, MAKEWORD(VK_F12, HOTKEYF_CONTROL), L"集群调度终端"))
{
ret++;
}