用VC制作通用安装程序



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

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

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

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

2.获取特定目录

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

3.拷贝文件

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

4.创建快捷方式

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

5.具体实现

假定软件中有5个文件:Myprog.exe,Myprog.hlp,Myprog.dll,Example.dat及Myprog.vxd。
其中前4个文件须拷贝至安装目录下,第5个文件须安装在Windows的系统目录下。

5.1 创建基于对话框的项目

项目名称为Setup,资源中对话框至少应有两个编辑控件IDC_EDIT1、IDC_EDIT2(对应的CString变量为m_strEdit1、m_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;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值