一个好的安装程序有助于增加软件的特色、提升软件的品位。 1.在硬盘中创建安装目录 软件由若干文件组成,我们通常将其中大部分文件拷贝至安装目录下, 2.获取特定目录 若软件中包含须拷贝至特定目录的文件,那么应获取所需的特定目录。 3.拷贝文件 创建安装目录和获取特定目录之后,将软件中的所有文件分别拷贝至这些目录中,CopyFile()可完成文件的拷贝。 4.创建快捷方式 完成软件中所有文件的拷贝之后,在“桌面”或“程序”中创建快捷方式,使之与应用程序相关联。 5.具体实现 假定软件中有5个文件:Myprog.exe,Myprog.hlp,Myprog.dll,Example.dat及Myprog.vxd。 5.1 创建基于对话框的项目 项目名称为Setup,资源中对话框至少应有两个编辑控件IDC_EDIT1、IDC_EDIT2(对应的CString变量为m_strEdit1、m_strEdit2), 5.2 编写自定义函数 编写自定义函数ReadConfig()和CreateShortcut()。 5.2.1 配置信息文件Setup.cfg [General] Topic=安装《我的程序》 //对话框的标题 SetupDir=C:/Mysoft //安装目录 Shortcut=我的程序 //快捷方式名称 ProgName=Myprog.exe //应用程序名称 [CopyFiles] //须拷贝的文件 Source1=Myprog.exe //第1个源文件 Target1=Myprog.exe //第1个目标文件(与源文件可不同名) Source2=Myprog.hlp Target2=Myprog.hlp Source3=Myprog.dll Target3=Myprog.dll Source4=Example.dat Target4=Example.dat Source5=Myprog.vxd Target5=>Sy/Myprog.vxd //该文件拷贝至Windows系统目录下 ………… //拷贝的文件数目不限 [End] 5.2.2 读取配置信息函数 BOOL CSetupDlg::ReadConfig(){//从Setup.cfg中读取配置信息 CFile fileCfg; if(!fileCfg.Open("Setup.cfg",CFile::modeRead)){ MessageBox("Can’t open file: Setup.cfg");//打开文件错误 return false; } char pcBuf[1024];//假定文件长度小于1024 fileCfg.Read(pcBuf,fileCfg.GetLength());//配置信息读入到pcBuf[]中 CString strBuf=pcBuf; char pcItem[20][30]={"Topic","SetupDir","Shortcut","ProgName", "Source1","Target1","Source2","Target2","Source3","Target3","Source4","Target4","Source5","Target5","Source6","Target6","Source7","Target7","Source8","Target8"};//配置信息条目,这里列举20个,可根据需要增减 int nLoc=-1;//各条目的起始位置 for(int i=0;i<20;i++){ nLoc=strBuf.Find(pcItem[i]); if(nLoc>=0){ //得到各条目内容char pcCont[][](CSetupDlg成员变量),每条内容最多为30个字符 strcpy(pcCont[i],strBuf.Mid(nLoc+strlen(pcItem[i])+1,30)); for(int j=0;j<30;j++){ if(pcCont[i][j]==0x0d)//遇回车符,则置结束符 pcCont[i][j]=0; } nCopyFiles=(i-2)/2;// 须拷贝的文件个数,CSetupDlg成员变量 } } fileCfg.Close(); return true; } 5.2.3 创建快捷方式函数 BOOL CSetupDlg::CreateShortcut(LPSTR szProgPath,LPSTR szShortcut) {// szProgPath为目标程序路径,szShortcut为快捷方式名称 IShellLink* pISL; IPersistFile* pIPF; HRESULT hr; WCHAR wszShortcut[MAX_PATH]; hr=CoCreateInstance(CLSID_ShellLink,0,1,IID_IShellLink,(void**)&pISL); //创建IShellLink接口 if(FAILED(hr)) return false; pISL->SetPath(szProgPath);//设置目标应用程序 pISL->SetShowCmd(…);//设置显示方式 pISL->SetWorkingDirectory(…);//设置工作目录(其它设置参阅MSDN) hr=pISL->QueryInterface(IID_IPersistFile,(void**)&pIPF); //得到IPersistFile接口 if(FAILED(hr)){ pISL->Release();return false;} MultiByteToWideChar(0,0,szShortcut,-1,wszShortcut,MAX_PATH);//将char*转换为WCHAR*格式 hr=pIPF->Save(wszShortcut,false);//保存快捷方式数据 pIPF->Release(); pISL->Release(); if(FAILED(hr)) return false; SHChangeNotify(SHCNE_ALLEVENTS,SHCNF_PATH|SHCNF_FLUSH,szShortcut,0);//通知系统更新 return true; } 5.3 修改对话框初始化函数 通过ClassWizard映射消息WM_INITDIALOG,生成OnInitDialog()函数。在其中增加初始化的内容。 BOOL CSetupDlg::OnInitDialog() { …………//自动生成的内容 nCopyFiles=0;//初始化须拷贝的文件数 ReadConfig();//读取配置信息 SetWindowText(pcCont[0]);//设置对话框标题 SetDlgItemText(IDC_EDIT1,pcCont[1]);//初始化安装目录 SetDlgItemText(IDC_EDIT2,pcCont[2]);//初始化快捷方式名称 return true; } 5.4 修改OnOK()函数 对话框中的按钮“确定”改为“安装”,但其ID名称仍为IDOK,通过ClassWizard映射该消息,生成OnOK()函数。在其中增加的内容为: (1)创建、设置进度条 (2)取得当前目录 (3)取得Windows特定目录 (4)创建安装目录 (5)拷贝文件 (6)生成快捷方式 void CSetupDlg::OnOK() { GetDlgItemText(IDC_EDIT1,m_strEdit1);//将IDC_EDIT1的值赋给m_strEdit1 GetDlgItemText(IDC_EDIT2,m_strEdit2);//将IDC_EDIT2的值赋给m_strEdit2 GetDlgItem(IDOK)->EnableWindow(false);//不能第二次按“安装” //设置进度条(在对话框中添加进度条控件,为其添加控制变量m_progCtrl) m_prgCtrl.SetRange(0,100);//设置进度条的范围 m_prgCtrl.SetPos(0); //设置进度条的初始位置 //取得当前目录 char szCurrentDir[MAX_PATH]; GetCurrentDirectory(MAX_PATH,szCurrentDir); if(szCurrentDir[strlen(szCurrentDir)-1]=='//') //去掉最后的'/' szCurrentDir[strlen(szCurrentDir)-1]=0; //取得Windows和系统目录 char szWindowsDir[MAX_PATH]; char szSystemDir[MAX_PATH]; GetWindowsDirectory(szWindowsDir,MAX_PATH); GetSystemDirectory(szSystemDir,MAX_PATH); //取得桌面和程序的目录 LPITEMIDLIST lpIIDL; char szDesktopDir[MAX_PATH];//桌面的目录 SHGetSpecialFolderLocation(HWND_DESKTOP,CSIDL_DESKTOP,&lpIIDL); SHGetPathFromIDList(lpIIDL,szDesktopDir); char szProgramDir[MAX_PATH];//程序的目录 SHGetSpecialFolderLocation(HWND_DESKTOP,CSIDL_PROGRAMS,&lpIIDL); SHGetPathFromIDList(lpIIDL,szProgramDir); //创建安装目录 char szDir[MAX_PATH]; if(m_strEdit1.GetAt(m_strEdit1.GetLength()-1)!='//') m_strEdit1+='//';//若m_strEdit1最后不为'/',则加上'/' for(int i=0;i<m_strEdit1.GetLength();i++){//目录必须逐级创建 if(m_strEdit1.GetAt(i)=='//'){ strcpy(szDir,m_strEdit1); szDir[i]=0; CreateDirectory(szDir,NULL); } } m_strEdit1=m_strEdit1.Left(m_strEdit1.GetLength()-1); //去掉最后的'/' //拷贝文件 char szSourceFile[MAX_PATH]; char szTargetFile[MAX_PATH]; for(i=0;i<nCopyFiles;i++){ sprintf(szSourceFile,"%s//%s",szCurrentDir,pcCont[i*2+4]); if(pcCont[i*2+5][0]=='>' && pcCont[i*2+5][3]=='//'){//拷贝至特定目录下 if(pcCont[i*2+5][1]=='W' && pcCont[i*2+5][2]=='i')//Windows目录 sprintf(szTargetFile,"%s//%s",szWindowsDir,&pcCont[i*2+5][4]); else if(pcCont[i*2+5][1]=='S'&&pcCont[i*2+5][2]=='y')//System目录 else return; } else //拷贝至安装目录下 sprintf(szTargetFile,"%s//%s",m_strEdit1,pcCont[i*2+5]); if(!CopyFile(szSourceFile,szTargetFile,FALSE)){ char pcMessage[50]; sprintf(pcMessage,"拷贝文件 %s 失败",pcCont[i*2+4]); MessageBox(pcMessage,"错误信息",MB_ICONERROR|MB_OK); return; |
用VC制作通用安装程序
最新推荐文章于 2024-06-28 10:49:01 发布