本程序拟设计为在windows操作系统常见的升级更新过程。主要核心是:
1、嗅探原程序的安装路径。
2、复制或解压下载的更新安装包至安装路径下,覆盖旧文件。(这里可能还要考虑一个还原)
3、界面显示进度条,严格与安装时间同步。
对于第一个问题,我可以偷点懒,因为源程序也是我写的。为了使我们方便嗅探,需要修改源程序代码,使程序在第一次启动时将路径写入注册表。这样的话,更新时就可以轻而易举的读取到安装路径了。
在此需研究和复习一些常用的windows函数和注册表操作:
首先是获取当前运行程序的路径;
CString m_FilePath; // GetModuleFileName获取的是当前运行程序完整路径(包括名称和后缀)(in/out,out,in) GetModuleFileName(NULL,m_FilePath.GetBufferSetLength(MAX_PATH+1),MAX_PATH);
可以进一步提取安装文件所在文件夹;
int n=m_FilePath.ReverseFind('\\'); m_FilePath=m_FilePath.Left(n);
可将以上操作封装到一个函数里,这里我起名叫做GetProductDir(CString& szPath),然后还需要写一个写入注册表的函数;
BOOL SetProductRegString(LPCTSTR szKey,LPCTSTR lpszEntry,LPCTSTR lpszValue) { // 向注册表中写入字符串 ASSERT(lpszEntry != NULL); CString szSubKey = szBaseKey+"\\"+szKey; HKEY hSecKey; RegCreateKey(HKEY_LOCAL_MACHINE,szSubKey,&hSecKey); LONG lResult = RegSetValueEx(hSecKey, lpszEntry, NULL, REG_SZ, (LPBYTE)lpszValue, (lstrlen(lpszValue)+1)*sizeof(TCHAR)); RegCloseKey(hSecKey); return lResult == ERROR_SUCCESS; }
BOOL SetFilePath() { // 设置路径 CString filePath; GetProductDir(filePath); return SetProductRegString("File","Path",filePath); }
当我的更新程序需要获取路径时,获取本程序指定注册表路径下File文件夹中的Path字段内容即可。
在更新程序中也需要一个读注册表的函数;
CString GetProductRegString(LPCTSTR lpszKey,LPCTSTR lpszEntry, LPCTSTR strDefVal) { // 获取注册表中的字符串 CString strValue = strDefVal; ASSERT(lpszEntry != NULL); CString szSubKey = szBaseKey+"\\"+lpszKey; HKEY hSecKey; if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, szSubKey, 0, KEY_QUERY_VALUE, &hSecKey) == ERROR_SUCCESS) { DWORD dwType, dwCount; LONG lResult = RegQueryValueEx(hSecKey, (LPTSTR)lpszEntry, NULL, &dwType, NULL, &dwCount); if (lResult == ERROR_SUCCESS) { ASSERT(dwType == REG_SZ); lResult = RegQueryValueEx(hSecKey, (LPTSTR)lpszEntry, NULL, &dwType, (LPBYTE)strValue.GetBuffer(dwCount/sizeof(TCHAR)), &dwCount); strValue.ReleaseBuffer(); } RegCloseKey(hSecKey); } return strValue; }
然后通过GetProductRegString("File","Path","")便可以获取到该路径了,这样我们的第一个目标就基本实现了。
对于第二个和第三个问题,其实要深度研究的就是一个函数:CopyFileEx,并了解其回调函数。这个将在下一步的工作中进行,这个小项目的原型基本告一段落。(目前安装程序很小的情况下,CopyFile就完全可以达到我们的要求)