建立安裝程式的兩種方法 (轉)
建立安裝程式的兩種方法 (轉)[@more@]
● 彭 進 趙 昕
創 建 安 裝 程 序 是 程 序 員 經 常 遇 到 的 問 題 之 一。 本 文 僅 探 討 在 平 臺 上 創 建 安 裝(Setup) 程 序 的 兩 種 方 法。
一、 使 用Visual C++ 編 程 生 成Setup 程 序
生 成Setup 程 序 最 直 接 的 方 法 當 然 是 通 過 編 程 來 實 現。 對 於Windows 平 臺 來 說, 沒 有 比Visual C++ 更 好 的 開 發 工 具 了( 原 因 很 簡 單, 有 誰 能 比 更 了 解Windows 平 臺 呢 ?)。 下 面 的 例 程 就 是 使 用Visual C++ 5.0 編 譯 完 成 的。
Setup 程 序 主 要 處 理 兩 個 方 面 的 問 題 :
(1) 用 戶 界 面。 評 價 一 個Setup 程 序 的 優 劣 時, 用 戶 界 面 是 否 美 觀 是 其 中 的 一 個 重 要 因 素。 此 外, 通 過 交 互 式 界 面 還 應 能 夠 獲 得 用 戶 的 相 關 信 息( 比 如 目 標 目 錄)。
(2) 文 件 拷 貝 與 程 序 組 的 生 成。 也 就 是 按 照 用 戶 輸 入 的 信 息, 生 成 相 應 的 目 錄 並 完 成 文 件 拷 貝 功 能( 這 要 涉 及 到 解 壓 縮 問 題)。 一 般 來 說, 還 應 包 括 將 可 執 行 文 件 的 圖 標 添 加 到 指 定 的 程 序 組 中。
1、 為Setup 程 序 設 置 背 景
Setup 程 序 的 用 戶 界 面 以 對 話 框 為 主, 不 過 若 有 美 麗 的 背 景 則 能 為 你 的 程 序 增 色 不 少。 你 可 以 選 擇 一 個 合 適 的BMP 文 件, 將 它 插 入 到 工 程 文 件(project) 中, 並 通 過 重 載 主 窗 口 類 的OnPaint() 函 數 顯 示 出 來。 值 得 注 意 的 是, 背 景 圖 片 不 應 過 於 眩 目, 否 則 會 有 喧 賓 奪 主 之 感。 例 如, 要 加 入 的BMP 文 件 的ID 號 是I_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->(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), 如 果 你 更 欣 賞D界 面 中 的 全 屏 效 果, 則 最 好 在 重 載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:winntsdi.ini 中, 則 在 使 用 以 上 函 數 之 前 必 須 調 用 :
free((void*)m_pszProfileName);
m_pszProfileName=_tcsdup(_T("e:winntsdi.ini"));
如 果 要 存 取 的 變 量 並 不 多, 則 也 可 將 它 們 保 存 在 注 冊 關 鍵 字(registry key) 中。 假 如 你 的 變 量 保 存 在Moon 注 冊 關 鍵 字( 一 般 是 你 公 司 的 名 字) 下, 則 在 使 用 以 上 函 數 之 前 必 須 調 用 :
free((void*)m_pszRegistryKey);
m_pszRegistryKey=_tcsdup(_T("HKEY_CURRENT_ USERSoftwaremoon"));
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
D 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);
DdeDinnect(hConv);
DdeUninitialize((unsigned long)dwDDEInst);
return TRUE;
}
如 果 你 想 加 入 一 個 名 叫“demo” 的 程 序 組, 其 中 包 含 有 名 稱 為“test” 的 程 序 項, 並 執 行c:demotest.exe, 使 用 的 是“test.ico” 圖 標, 則 可 按 如 下 方 式 調 用 該 函 數 :
SendDdeCmd("[CreateGroup (demo)] [AddItem (c:demotest.exe, test,c:demotest.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、 Customwork 等 多 種 安 裝 類 型。
(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);
現 在 修 改Re 項, 其 中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 創 建 安 裝 程 序 的 過 程 宣 告 結 束。
建立的兩種方法
● 彭 進 趙 昕
創 建 安 裝 程 序 是 程 序 員 經 常 遇 到 的 問 題 之 一。 本 文 僅 探 討 在 平 臺 上 創 建 安 裝(Setup) 程 序 的 兩 種 方 法。
一、 使 用Visual C++ 編 程 生 成Setup 程 序
生 成Setup 程 序 最 直 接 的 方 法 當 然 是 通 過 編 程 來 實 現。 對 於Windows 平 臺 來 說, 沒 有 比Visual C++ 更 好 的 開 發 工 具 了( 原 因 很 簡 單, 有 誰 能 比 更 了 解Windows 平 臺 呢 ?)。 下 面 的 例 程 就 是 使 用Visual C++ 5.0 編 譯 完 成 的。
Setup 程 序 主 要 處 理 兩 個 方 面 的 問 題 :
(1) 用 戶 界 面。 評 價 一 個Setup 程 序 的 優 劣 時, 用 戶 界 面 是 否 美 觀 是 其 中 的 一 個 重 要 因 素。 此 外, 通 過 交 互 式 界 面 還 應 能 夠 獲 得 用 戶 的 相 關 信 息( 比 如 目 標 目 錄)。
(2) 文 件 拷 貝 與 程 序 組 的 生 成。 也 就 是 按 照 用 戶 輸 入 的 信 息, 生 成 相 應 的 目 錄 並 完 成 文 件 拷 貝 功 能( 這 要 涉 及 到 解 壓 縮 問 題)。 一 般 來 說, 還 應 包 括 將 可 執 行 文 件 的 圖 標 添 加 到 指 定 的 程 序 組 中。
1、 為Setup 程 序 設 置 背 景
Setup 程 序 的 用 戶 界 面 以 對 話 框 為 主, 不 過 若 有 美 麗 的 背 景 則 能 為 你 的 程 序 增 色 不 少。 你 可 以 選 擇 一 個 合 適 的BMP 文 件, 將 它 插 入 到 工 程 文 件(project) 中, 並 通 過 重 載 主 窗 口 類 的OnPaint() 函 數 顯 示 出 來。 值 得 注 意 的 是, 背 景 圖 片 不 應 過 於 眩 目, 否 則 會 有 喧 賓 奪 主 之 感。 例 如, 要 加 入 的BMP 文 件 的ID 號 是I_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->(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), 如 果 你 更 欣 賞D界 面 中 的 全 屏 效 果, 則 最 好 在 重 載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:winntsdi.ini 中, 則 在 使 用 以 上 函 數 之 前 必 須 調 用 :
free((void*)m_pszProfileName);
m_pszProfileName=_tcsdup(_T("e:winntsdi.ini"));
如 果 要 存 取 的 變 量 並 不 多, 則 也 可 將 它 們 保 存 在 注 冊 關 鍵 字(registry key) 中。 假 如 你 的 變 量 保 存 在Moon 注 冊 關 鍵 字( 一 般 是 你 公 司 的 名 字) 下, 則 在 使 用 以 上 函 數 之 前 必 須 調 用 :
free((void*)m_pszRegistryKey);
m_pszRegistryKey=_tcsdup(_T("HKEY_CURRENT_ USERSoftwaremoon"));
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
D 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);
DdeDinnect(hConv);
DdeUninitialize((unsigned long)dwDDEInst);
return TRUE;
}
如 果 你 想 加 入 一 個 名 叫“demo” 的 程 序 組, 其 中 包 含 有 名 稱 為“test” 的 程 序 項, 並 執 行c:demotest.exe, 使 用 的 是“test.ico” 圖 標, 則 可 按 如 下 方 式 調 用 該 函 數 :
SendDdeCmd("[CreateGroup (demo)] [AddItem (c:demotest.exe, test,c:demotest.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、 Customwork 等 多 種 安 裝 類 型。
(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);
現 在 修 改Re 項, 其 中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 創 建 安 裝 程 序 的 過 程 宣 告 結 束。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10752043/viewspace-988005/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 完全解除安裝MacOS應用程式的兩種方法Mac
- FC5硬碟安裝的兩種方法介紹(轉)硬碟
- Linux安裝MySQL的兩種方法LinuxMySql
- 分享兩種完全解除安裝MacOS應用程式的方法Mac
- mac安裝mysql的兩種方法(含配置)MacMySql
- MyEclipse SVN外掛的兩種安裝方法Eclipse
- linux製作安裝包的兩種方法Linux
- 兩種動態建立表格的方法
- ubuntu下安裝程式的三種方法Ubuntu
- MySQL建立資料庫的兩種方法MySql資料庫
- python之建立類的兩種方法Python
- vue 跳轉的兩種方法Vue
- 選擇一種安裝方法安裝Linux(轉)Linux
- zabbix agent 的兩種安裝方式
- 安裝aab包的兩種方式
- Java 建立 PDF 檔案包的兩種方法Java
- laravel建立新model資料的兩種方法Laravel
- 建立連結串列兩種方法的區別
- PostgreSQL建立自增主鍵的兩種方法SQL
- 安裝Linux的五種方法和心得(轉)Linux
- ASP建立SQL Server資料庫的兩種方法SQLServer資料庫
- LINUX下安裝ORACLE時SWAP不足的兩種解決方法LinuxOracle
- PHP呼叫java類的兩種方法(轉)PHPJava
- AJAX 開發的兩種不同的方法(轉)
- 開發JAVA程式設計中字串分割的兩種方法(轉)Java程式設計字串
- C++中建立物件的兩種方法及其區別C++物件
- 在儲存過程中建立表的兩種方法儲存過程
- LAMP兩種編譯安裝模式LAMP編譯模式
- 分享:N-Gage上各種遊戲的安裝方法(轉)遊戲
- 建立後臺任務的兩種程式碼模式模式
- SQL SERVER日誌清除的兩種方法(轉)SQLServer
- Drawable轉換為Bitmap兩種方法
- 在Linux系統中儲存裝置的兩種表示方法(轉)Linux
- Sumblime Text2安裝Package Control兩種方法+安裝外掛+註冊碼Package
- 建立Session物件的兩種方式Session物件
- Win8.1RTM英文版安裝中文語言包的兩種方法
- 強行關閉病毒程式的兩種方法
- Spark SQL中列轉行(UNPIVOT)的兩種方法SparkSQL