分享
 
 
 

创建安装程序的两种方法

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

创建安装程序的两种方法

● 彭 进 赵 昕

创 建 安 装 程 序 是 程 序 员 经 常 遇 到 的 问 题 之 一。 本 文 仅 探 讨 在Windows 平 台 上 创 建 安 装(Setup) 程 序 的 两 种 方 法。

一、 使 用Visual C++ 编 程 生 成Setup 程 序

生 成Setup 程 序 最 直 接 的 方 法 当 然 是 通 过 编 程 来 实 现。 对 于Windows 平 台 来 说, 没 有 比Visual C++ 更 好 的 开 发 工 具 了( 原 因 很 简 单, 有 谁 能 比Microsoft 更 了 解Windows 平 台 呢 ?)。 下 面 的 例 程 就 是 使 用Visual C++ 5.0 编 译 完 成 的。

Setup 程 序 主 要 处 理 两 个 方 面 的 问 题 :

(1) 用 户 界 面。 评 价 一 个Setup 程 序 的 优 劣 时, 用 户 界 面 是 否 美 观 是 其 中 的 一 个 重 要 因 素。 此 外, 通 过 交 互 式 界 面 还 应 能 够 获 得 用 户 的 相 关 信 息( 比 如 目 标 目 录)。

(2) 文 件 拷 贝 与 程 序 组 的 生 成。 也 就 是 按 照 用 户 输 入 的 信 息, 生 成 相 应 的 目 录 并 完 成 文 件 拷 贝 功 能( 这 要 涉 及 到 解 压 缩 问 题)。 一 般 来 说, 还 应 包 括 将 可 执 行 文 件 的 图 标 添 加 到 指 定 的 程 序 组 中。

1、 为Setup 程 序 设 置 背 景

Setup 程 序 的 用 户 界 面 以 对 话 框 为 主, 不 过 若 有 美 丽 的 背 景 则 能 为 你 的 程 序 增 色 不 少。 你 可 以 选 择 一 个 合 适 的BMP 文 件, 将 它 插 入 到 工 程 文 件(project) 中, 并 通 过 重 载 主 窗 口 类 的OnPaint() 函 数 显 示 出 来。 值 得 注 意 的 是, 背 景 图 片 不 应 过 于 眩 目, 否 则 会 有 喧 宾 夺 主 之 感。 例 如, 要 加 入 的BMP 文 件 的ID 号 是IDB_BIT。 下 面 给 出 应 加 在OnPaint() 中 的 函 数。

void Background(CDC *pDC)

{ CDC * pmem;

CBitmap * pback;

CBitmap * pold;

BITMAP ff;

pmem=new CDC;

pbit=new CBitmap;

pbit->LoadBitmap(IDB_BIT);

pmem->CreateCompatibleDC(pDC);

pold=(CBitmap *) pmem->SelectObject(pbit);

pbit->GetObject(sizeof(ff),&ff);

pDC->BitBlt(0,0,bm.bmWidth,bm.bmHeight,pmem,0,0, MERGECOPY );

delete pmem->SelectObject(pold);

delete pmem;

return;

}

2、 显 示 全 屏 效 果

一 般 的 主 窗 口 都 有 边 界(border), 如 果 你 更 欣 赏DOS 界 面 中 的 全 屏 效 果, 则 最 好 在 重 载CWnd:: PreCreateWindow(CREATESTRUCT&cs) 时 保 持cs.style 的 缺 省 值, 并 且 在 创 建 主 窗 口 时 使 用CreateEx(WS_EX_TO PMOST,AfxRegisterWndClass(CS_VREDRAW), NULL,WS_VISIBLE|WS_POPUP,0,0,(GetSystemMetrics (SM_CXSCREEN)),(GetSystemMetrics(SM_CYSCREEN)), HWND_DESKTOP,0);。

3、 保 存 公 用 参 量

通 过 对 话 框, 可 与 使 用 者 交 换 信 息。 那 么, 如 何 将 程 序 运 行 时 必 需 的 参 量( 比 如 说 安 装 目 录) 保 存 起 来 呢 ? 当 然, 可 以 生 成 一 个 配 置 文 件, 不 过 更 为 专 业 的 作 法 是 将 相 关 信 息 存 入 到 系 统 的INI 文 件 中。 如 果 开 发 平 台 是Windows 95, 则 一 切 都 将 变 得 很 简 单, 因 为 你 面 对 的 就 是win.ini 文 件, 该 文 件 在Windows 目 录 下。Visual C++ 提 供 了 如 下 的 一 组 函 数 来 操 作 该 文 件。

(1)CWinApp::GetProfileString

CString GetProfileString( LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszDefault = NULL );

用 来 读 取lpszSection 区 域 内 的lpszEntry 参 数, 其 缺 省 值 为lpszDefault。

(2)CWinApp::WriteProfileString

BOOL WriteProfileString( LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue );

用 来 写 入lpszSection 区 域 内 的lpszEntry 参 数, 其 值 为lpszValue。

如 果 你 的 开 发 平 台 是Winnt, 则 要 麻 烦 一 点。 假 如 你 的 变 量 保 存 在e:\\winnt\sdi.ini 中, 则 在 使 用 以 上 函 数 之 前 必 须 调 用 :

free((void*)m_pszProfileName);

m_pszProfileName=_tcsdup(_T("e:\\winnt\\sdi.ini"));

如 果 要 存 取 的 变 量 并 不 多, 则 也 可 将 它 们 保 存 在 注 册 关 键 字(registry key) 中。 假 如 你 的 变 量 保 存 在Moon 注 册 关 键 字( 一 般 是 你 公 司 的 名 字) 下, 则 在 使 用 以 上 函 数 之 前 必 须 调 用 :

free((void*)m_pszRegistryKey);

m_pszRegistryKey=_tcsdup(_T("HKEY_CURRENT_ USER\\Software\\moon"));

4、 文 件 的 拷 贝 与 解 压 缩

如 果 你 的 安 装 程 序 是 针 对 软 盘 的, 则 存 储 空 间 就 成 了 必 须 考 虑 的 问 题。 原 封 不 动 地 把 应 用 程 序 拷 贝 上 去 未 免 太 傻 了, 较 为 合 适 的 方 法 是 将 应 用 程 序 压 缩 在 软 盘 中, 安 装 时 再 解 压 缩 到 相 应 的 目 标 目 录 中。Visual C++ 提 供 了 一 套 以LZ 开 头 的 函 数, 用 来 操 作 用Compress 命 令 压 缩 的 文 件 : 你 可 以 用LzOpenFile() 打 开 原 文 件 和 目 标 文 件, 然 后 用LzCopy() 解 压 缩 拷 贝。 该 组 函 数 调 用Windows 系 统 的lzexpand.dll 动 态 链 接 库, 所 以 编 译 链 接 时 一 定 要 注 意 加 入 头 文 件lzexpand.h, 并 插 入 接 口 库lz32.lib。

还 有 个 更 为 简 单 的 办 法, 即 先 用 像arj.exe 这 类 的 共 享 压 缩 程 序 压 缩 原 程 序, 然 后 调 用system("arj ...") 来 完 成 解 压 缩, 整 个 解 压 缩 过 程 在 后 台 进 行, 用 户 不 会 知 道 你 到 底 用 的 是 什 么 方 法。

5、 显 示 拷 贝 进 度

很 多 专 业 安 装 程 序 在 进 行 文 件 拷 贝 时 都 会 显 示 进 度 栏, 甚 至 还 带 有 动 画。 如 何 实 现 这 种 效 果 呢 ? 办 法 是 在 拷 贝 的 同 时 创 建 一 个modeless 对 话 框。 这 种 对 话 框 用create() 函 数 创 建, 类 似 于 创 建 了 一 个 与 主 线 程 独 立 的 新 线 程。 这 样 就 可 在 拷 贝 文 件 的 同 时 在 对 话 框 中 显 示 出 拷 贝 进 度。Visual C++ 提 供 了 两 个 很 有 用 的 控 件, 即CAnimateCtrl 和 CProgressCtrl。 可 在 对 话 框 中 画 出 这 两 个 控 件, 并 用ClassWizard 加 入 相 应 的 类。 其 中,CAnimateCtrl 是 用 来 显 示.avi 文 件 的, 使 用 它 即 可 在 每 个 文 件 拷 贝 成 功 后 启 动 一 个“ 小 纸 片 飞 过” 的 文 件 ;CProgressCtrl 用 来 显 示 拷 贝 进 度, 当 各 个 拷 贝 成 功 后 使 表 示 进 度 的 蓝 条 前 进 到 适 当 的 位 置。

6、 程 序 组 和 程 序 项 的 生 成

程 序 组 的 生 成 实 际 上 是 与 负 责 管 理 程 序 组 的Program Manager 进 行DDE 对 话, 你 可 以 通 过 该 对 话 来 添 加 相 应 的 程 序 组 和 应 用 程 序 的 图 标。 同 时 由 于 该 对 话 是 单 向 的, 所 以 负 责 处 理 反 馈 消 息 的callback() 函 数 不 进 行 任 何 处 理。 下 面 给 出 其 源 程 序 及 其 用 法。

HDDEDATA CALLBACK DDECallback( UINT uType, // transaction type

UINT uFmt, // clipboard data format

HCONV hconv, // handle to the conversation

HSZ hsz1, // handle to a string

HSZ hsz2,

// handle to a string

HDDEDATA hdata, // handle to a global memory object

DWORD dwData1,

// transaction-specific data

DWORD dwData2

// transaction-specific data

)

{return NULL;}

SendDdeCmd(LPSTR cmd)

{

LPDWORD dwDDEInst=0L;

UINT ui;

HSZ hszService,hszTopic,hszItem;

HCONV hConv;

HDDEDATA hexecData;

ui=DdeInitialize((unsigned long *)&dwDDEInst, DDECallback,CBF_FAIL_ALLSVRXACTIONS,0L);

if(ui!=DMLERR_NO_ERROR)

{return FALSE;}

hszService=DdeCreateStringHandle( (DWORD) dwDDEInst,"PROGMAN",CP_WINANSI);

hszTopic=DdeCreateStringHandle((DWORD)dwDDEInst, "PROGMAN",CP_WINANSI);

hszItem=DdeCreateStringHandle((DWORD)dwDDEInst,"GROUP", CP_WINANSI);

hConv=DdeConnect((DWORD)dwDDEInst,hszService, hszTopic,NULL);

DdeFreeStringHandle((unsigned long)dwDDEInst, hszService);

DdeFreeStringHandle((unsigned long)dwDDEInst, hszTopic);

DdeFreeStringHandle((unsigned long)dwDDEInst, hszItem);

if(!hConv)

return FALSE;

hexecData=DdeCreateDataHandle((DWORD)dwDDEInst,(unsigned char *)cmd,lstrlen(cmd)+1,0,NULL,0,0);

DdeClientTransaction((unsigned char *)hexecData, (DWORD)-1,hConv,NULL,0,XTYP_EXECUTE,1000,NULL);

DdeDisconnect(hConv);

DdeUninitialize((unsigned long)dwDDEInst);

return TRUE;

}

如 果 你 想 加 入 一 个 名 叫“demo” 的 程 序 组, 其 中 包 含 有 名 称 为“test” 的 程 序 项, 并 执 行c:\demo\test.exe, 使 用 的 是“test.ico” 图 标, 则 可 按 如 下 方 式 调 用 该 函 数 :

SendDdeCmd("[CreateGroup (demo)] [AddItem (c:\demo\test.exe, test,c:\demo\test.ico)]")

二、 利 用 工 具 软 件 创 建 安 装 程 序

使 用Visual C++ 编 程 能 够 生 成 功 能 强 大 的Setup 程 序。 不 过, 如 果 你 更 喜 欢 利 用 现 成 的 工 具, 则 不 妨 试 一 试 用 于 创 建 安 装 程 序 的 工 具 软 件InstallShield5 Free Edition。 该 软 件 提 供 了 一 种 类 似 于Basic 的 编 程 语 言, 清 晰 易 懂。

创 建 一 个 新 的 安 装 程 序 时, 可 从Project Wizard 开 始, 首 先 启 动 的 是 一 个Welcome 对 话 框, 它 包 括 以 下 几 项 内 容 :

(1)Application Name (edit box)

在 这 个 对 话 框 中 输 入 你 想 要 安 装 的 应 用 程 序 的 名 字, InstallShield 将 用 该 名 字 注 册 登 记 并 生 成 你 的 程 序 组。

(2)Development Environment (list box)

选 择 开 发 该 应 用 程 序 的 环 境( 如Visual C++)。

(3)Application Type (list box)

选 择 你 的 应 用 程 序 的 类 别。

(4)Application Version (edit box)

选 择 你 的 应 用 程 序 的 版 本。

(5)Application Executable (edit box)

输 入 应 用 程 序 的 主 运 行 文 件, 或 单 击 ... 寻 找 该 文 件。

(6) 单 击“ 下 一 步”,select dialogs

选 择 你 的 安 装 程 序 所 需 要 的 对 话 框, 如 果 你 暂 时 还 不 能 确 定 的 话, 则 可 按Preview 键 预 览 一 下。

(7) 单 击“ 下 一 步”, 选 择 适 合 于 该 应 用 程 序 的 操 作 系 统 平 台。 你 可 以 选 择Win 95、Winnt 3.x 或Winnt4.0。

(8) 单 击“ 下 一 步”, 选 择 安 装 程 序 使 用 的 语 言。 在 这 种free 版 本 中, 你 所 能 作 的 唯 一 选 择 就 是“ 英 语”。

(9) 如 果 你 想 在 你 的 安 装 程 序 中 包 括 多 种 安 装 类 型 选 择, 则 单 击“ 下 一 步”。 启 动 的 对 话 框 中 提 供 了 上 述 功 能, 从 中 你 可 选 择Compact、 Typical、 Custom 及Network 等 多 种 安 装 类 型。

(10) 单 击“ 下 一 步”, 选 择 你 想 要 安 装 的 组 件, 这 些 组 件 的 不 同 组 合 即 是 你 在 上 面 选 择 的 不 同 安 装 类 型。

(11) 单 击“ 下 一 步”, 选 择 你 想 要 创 建 的 文 件 组, 该 文 件 组 是 你 的 应 用 程 序 所 包 括 文 件 的 逻 辑 分 组, 这 种 逻 辑 分 组 对 应 于 上 面 的 组 件。

(12) 单 击“ 下 一 步”, 概 括( 即“Summary” ) 你 所 输 入 的 信 息。 如 果 不 满 意, 则 还 可 以 修 改 ; 如 果 满 意 的 话, 则 按“ 完 成” 键, 一 个 安 装 程 序 的 框 架 就 大 功 告 成 了。

下 面 介 绍 制 作 供 安 装 程 序 使 用 的 工 程 文 件。

实 际 上,Project Wizard 已 经 为 你 作 好 了 大 部 分 的 工 作。 为 了 创 建 一 个 完 整 的 安 装 程 序, 首 先 要 弄 清 楚 工 程 文 件 中 各 个 项 目 间 的 关 系。 这 要 从File Group 说 起。File Group 是 应 用 程 序 文 件 的 逻 辑 分 组, 在 每 个 文 件 夹 下 都 有link 项, 用 右 键 单 击 该 位 置, 选 择 插 入 项, 则 可 将 你 的 应 用 文 件 进 行 适 当 分 组。 每 个File Group 中 含 有 若 干 属 性 值, 单 击 该 属 性 则 可 对 其 进 行 修 改。 比 如, 对 于Compress 项, 你 可 以 选 择 是 否 对 该File Group 下 的 文 件 进 行 压 缩。 几 个File Group 可 以 同 属 于 一 个Component, 通 过 划 分Component 你 可 以 区 分 不 同 的 安 装 方 式。 每 个Component 也 有 若 干 属 性 : 其 中,Destination 项 供 你 选 择 该Component 将 要 安 装 到 的 目 标 目 录 ;Installation 项 供 你 选 择 遇 到 相 同 文 件 名 时 的 处 理 方 式 ;SetupType 项 供 你 选 择 不 同 的 安 装 类 型 所 安 装 的 组 件(Component)。 下 面, 你 将 进 入Script Files 项, 它 是 你 的 安 装 程 序 的 脚 本 程 序, 如 果 你 只 想 创 建 一 个 标 准 的 安 装 程 序, 则 只 需 对 其 作 很 小 的 改 动 即 可。 由 于 系 统 没 有 为 你 生 成 创 建 程 序 组 的 部 分, 所 以 必 须 手 工 修 改function SetupFolders() 函 数, 在DialogShowSdSelectFolder() 中, 安 装 脚 本 已 经 将 要 生 成 的 目 标 程 序 组 存 入 到 变 量svDefGroup 中, 所 以 你 只 需 在SetupFolders() 中 加 入 以 下 几 行 内 容( 假 设 你 想 加 入 一 个 名 为“demo” 的 项, 执 行c:\demo.exe 文 件, 使 用 的 图 标 是“c:\demo.ico”, 工 作 目 录 为“c:\test”, 用“Ctrl + Alt + 1” 作 为 热 键, 并 且 该 程 序 项 将 作 为 该 程 序 组 的 第 一 项, 该 程 序 执 行 时 将 被 最 大 化)。

STRING szProgram ="c:\demo.exe"

STRING szParam = " "

LongPathToQuote (szProgram, TRUE);

LongPathToShortPath (szParam);

STRING szCommandLine = szProgram + " " + szParam;

AddFolderIcon(svDefGroup, "demo",szCommandLine, "c:\test","c:\demo.ico",0, "Ctrl +Alt + 1", REPLACE |RUN_MAXIMIZED);

现 在 修 改Resource 项, 其 中String Table 存 储 的 是 显 示 在 对 话 框 里 的 各 种 字 符 变 量。 例 如,FOLDER_NAME 是 你 的 程 序 组 的 缺 省 名 字,PRODUCT_KEY 是 你 的 程 序 项 的 运 行 文 件,PRODUCT_NAME 是 你 的 程 序 项 的 名 字,TITLE_CAPTIONBAR 将 显 示 在 你 的 安 装 程 序 背 景 窗 口 的 上 边 框 内,TITLE_MAIN 将 显 示 在 你 的 安 装 程 序 背 景 窗 口 上。 对 于Win 95、Winnt 4.0 的 用 户,UNINST_DISPLAY_NAME 将 显 示 在 控 制 面 板 的“ 添 加/ 删 除 程 序” 的 列 表 中。

在Setup file 这 一 项 中, 你 可 以 修 改 安 装 程 序 开 始 时 显 示 的 图 片, 只 需 将 编 辑 好 的 文 件 插 入 到Splash Screen 的Language Independent 下, 并 改 名 为Setup.bmp 即 可。

如 果 你 已 经 正 确 地 添 如 了 上 述 各 项 内 容, 则 下 面 所 要 做 的 事 情 就 是 打 开Media 项 单 击 右 键 选 择 其 中 的Media Build Wizard 以 便 创 建 应 用 程 序 的 物 理 存 储 结 构。 如 果 你 选 择 的 是 软 盘 方 式, 则 自 动 生 成 按 照Disk 划 分 的 目 标 程 序。 至 此, 利 用 工 具 软 件InstallShield 创 建 安 装 程 序 的 过 程 宣 告 结 束。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有