你好,欢迎来到电脑编程技巧与维护杂志社! 杂志社简介广告服务读者反馈编程社区  
合订本订阅
 
 
您的位置:杂志经典 / 编程语言
用VC制作通用安装程序
 

经过多少日夜的潜心编程,你的软件终于大功告成时,你一定想马上将她呈现在用户面前,于是她的包装(安装程序)便成了当务之急。当然你可以选用InstallShield来制作软件的安装程序,但在它带给你制作简便的同时,却给你匠心独具的软件赋予了千篇一律的包装。

一个好的安装程序有助于增加软件的特色、提升软件的品位。本文介绍用Visual C++来制作通用安装程序的方法,由此你便拥有了一个独具特色的通用安装程序。

1.在硬盘中创建安装目录

软件由若干文件组成,我们通常将其中大部分文件拷贝至安装目录下,另有小部分文件须拷贝至特定的目录(如C:\Windows\System)下。首先应在硬盘中创建安装目录。WindowsAPI函数CreateDirectory()可创建目录。

2.获取特定目录

若软件中包含须拷贝至特定目录的文件,那么应获取所需的特定目录。GetWindowsDirectory()可得到Windows目录;GetSystemDirectory()可得到Windows的系统目录,SHGetSpecialFolderLocation()可得到Windows的特定目录(如DesktopStart  Menu\ProgramsRecentHelp等)。

3.拷贝文件

创建安装目录和获取特定目录之后,将软件中的所有文件分别拷贝至这些目录中,CopyFile()可完成文件的拷贝。在拷贝文件的同时,最好用进度条显示文件拷贝的进度。

4.创建快捷方式

完成软件中所有文件的拷贝之后,在“桌面”或“程序”中创建快捷方式,使之与应用程序相关联。

5.具体实现

假定软件中有5个文件:Myprog.exeMyprog.hlpMyprog.dllExample.datMyprog.vxd。其中前4个文件须拷贝至安装目录下,第5个文件须安装在Windows的系统目录下。

5.1 创建基于对话框的项目

项目名称为Setup,资源中对话框至少应有两个编辑控件IDC_EDIT1IDC_EDIT2(对应的CString变量为m_strEdit1m_strEdit2),分别为“安装目录”、“快捷方式名称”,并且将按钮“确定”改为“安装”,人工输入资源ID的名称IDC_PROGRESSBAR,作为进度条的ID

5.2 编写自定义函数

编写自定义函数ReadConfig()CreateShortcut()。其中ReadConfig()从安装配置文件Setup.cfg中读取安装信息,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;

        }

        m_prgCtrl.SetPos((i+1)*100/nCopyFiles);//显示拷贝文件的进度

    }

    //创建快捷方式

    char szProgPath[MAX_PATH];//应用程序的路径全名

    sprintf(szProgPath,"%s\\%s",m_strEdit1,pcCont[3]);

    char szShortcut[MAX_PATH];//快捷方式名称

    //在桌面创建快捷方式

    sprintf(szShortcut,"%s\\%s.lnk",szDesktopDir,m_strEdit2);

    if(!CreateShortcut(szProgPath,szShortcut)) return;

    //在程序中创建快捷方式

    sprintf(szShortcut,"%s\\%s.lnk",szProgramDir,m_strEdit2);

    if(!CreateShortcut(szProgPath,szShortcut)) return;

    CDialog::OnOK();//关闭安装窗口

}

5.5 定制安装界面

前面介绍了制作安装程序的基本方法,为了使安装程序独具特色,应在界面上下些功夫。如通过重载OnEraseBkgnd()函数,在其中加入显示位图的代码,可制作非常漂亮的安装界面。又如映射WM_CTLCOLOR消息,在生成的函数OnCtlColor()中增加设置文本显示属性的代码,可改变显示文本及背景的颜色,进一步美化安装界面。

5.6 安装程序的使用 

    将上述项目编译链接成发行版的应用程序Setup.exe,须与配置文件Setup.cfg配对使用。在制作安装盘时,首先编辑Setup.cfg文件,以纯文本格式存盘,再将Setup.exeSetup.cfg与须安装的其它文件一同拷入安装盘,运行Setup.exe即可实现软件的安装。

6.说明

    本程序在Windows 98(中文版)、Visual C++ 6.0环境下编译通过。

 

  推荐精品文章

·2024年12月目录 
·2024年11月目录 
·2024年10月目录 
·2024年9月目录 
·2024年8月目录 
·2024年7月目录 
·2024年6月目录 
·2024年5月目录 
·2024年4月目录 
·2024年3月目录 
·2024年2月目录 
·2024年1月目录
·2023年12月目录
·2023年11月目录

  联系方式
TEL:010-82561037
Fax: 010-82561614
QQ: 100164630
Mail:gaojian@comprg.com.cn

  友情链接
 
Copyright 2001-2010, www.comprg.com.cn, All Rights Reserved
京ICP备14022230号-1,电话/传真:010-82561037 82561614 ,Mail:gaojian@comprg.com.cn
地址:北京市海淀区远大路20号宝蓝大厦E座704,邮编:100089