引言
解壓縮軟件不應該固步自封,完全可以擴展到安裝制作領域,本文引入觸發器的概念,權作拋磚引玉。
一 、觸發器
純粹的解包過程就是把包裡的目錄和文件還原到指定物理路徑中的過程,我們常用的Winzip、WinRAR等解壓縮軟件就屬於這一類。安裝過程實際上就是解包過程加上某種配置和控制過程,例如,需要自注冊COM組件,需要創建虛擬目錄,需要向注冊表寫信息,需要創建快捷方式等等。觸發器就是用來控制和擴展解包過程的插件,通過定制觸發器就可以完成大部分的安裝配制過程。軟件廠商可以提供事先定制好的具有某些功能的觸發器,用戶只要按指定格式配置就能完成需要的配置和控制操作,同時用戶又可以自定義觸發器。共有四種類型的觸發器:
(1) 解包前
(2) 分解元素前
(3) 分解元素後
(4) 解包後
元素:指文件或目錄,包也是一種元素。
分解:指還原。
分解元素:指還原文件或還原目錄。
“分解目錄後”是指該目錄下的所有子目錄和文件都被還原結束後。
二、設計觸發器
觸發器是按照一定規范開發出來的普通DLL,該DLL必須導出一個名為Execute的函數。
每個元素都可以有多個觸發器。也就是說,每個元素可以有多個分解前觸發器,也可以有多個分解後觸發器,這些觸發器會被依次執行。但是,只要有一個分解前觸發器表示反對,則該元素的分解過程將被取消,分解後觸發器也將不會被執行。
(1)原型聲明:
extern “C” __declspec(dllexport) long __stdcall Execute(ELEMENT *pEle)
(2)枚舉常量:
enum {etFile, etDir, etPack}; // 元素類型:文件、目錄、包。
enum {tsBefore, tsAfter}; // 觸發條件:分解前、分解後。
(3)輸入參數:
typedef struct
{
HWND m_hWnd; // 主窗口句柄
IDispatch* m_pXmlDoc; // 解包用XML控制文件
char m_szPackPath[MAX_PATH]; // 用戶指定的解包物理全路徑。
char m_szElementPath[MAX_PATH]; // 當前要分解的文件或目錄在包裡的全路徑。
long m_nElementType; // 元素類型。
long m_nTriggerSituation; // 觸發條件。
} ELEMENT;
(4)返回值:
(A)-1:退出整個解包過程;
(B)0:取消本元素的分解過程;(僅對分解前觸發器有效)
(C)1:成功;
(5)錯誤描述
解包過程在調用觸發器時可能會發生錯誤,原因如下:
(A) 不是有效的DLL文件;
(B) DLL文件不存在;
(C) 未導出Execute函數;
(D) Execute函數原型不正確;
(E) Execute函數體執行異常;
解包過程在檢測到上述錯誤時將詢問是繼續運行還是退出整個解包過程。
顯然,如果上述錯誤發生在元素分解前,則該元素的分解過程將被取消,分解後觸發器也將不會被執行。
三、配置觸發器
(1)格式
<XyUnPack Package=”XySetup.cpd” UnPackPath=”C:\Program Files\Software\Freesky\Budget”>
<Trigger>
<Common FileName="xx1.dll" For="FILE/DIR/PACK/ALL" When="BEFORE/AFTER/ALL" />
<Single FileName="xx1.dll" For="Test1\1.doc" When="BEFORE/AFTER/ALL" />
<Single FileName="xx2.dll" For="Test1\Test2" When="BEFORE/AFTER/ALL" />
<Single FileName="xx3.dll" For="" When="BEFORE/AFTER/ALL" />
</Trigger>
</XyUnPack>
(2)說明
(A) 可以為每個元素配置獨立觸發器,此時使用<Single>標記,FileName表示觸發器的文件名,For表示目標元素在包裡的全路徑,When表示觸發條件。特別注意的是,For=""表示的是包。
(B) 可以為所有元素設置通用觸發器,此時使用<Common>標記,FileName表示觸發器的文件名,For表示元素類型,When表示觸發條件。
(C) 如果一個元素上既有“通用觸發器”又有“獨立觸發器”,則不管是在分解前還是在分解後,總是先執行“通用觸發器”後執行“獨立觸發器”。
四、內置觸發器
比如,解包過程可以內置一些“包分解後”類型的觸發器,功能及配置如下所述。
(1) 創建虛擬目錄
<XyUnPack>
<Trigger>
</Trigger>
<VirtualDirectory>
<Add Name=”Budget” Path=”Test1” />
<Add Name=”BudgetWebService1” Path=”Test2\Test3” CreateNew=”1” />
<Add Name=”BudgetWebService2” Path=”” />
</VirtualDirectory>
</XyUnPack>
注:Name表示虛擬目錄名,Path表示和該虛擬目錄對應的包裡的目錄的全路徑。特別注意的是,Path=""表示的是用戶指定的解包的物理路徑。當虛擬目錄已經存在且CreateNew=”1”時則先刪除再創建。
(2) 注冊COM組件
<XyUnPack>
<Trigger>
</Trigger>
<VirtualDirectory>
</VirtualDirectory>
<RegServer>
<Add Path=”Test1\1.dll” />
<Add Path=”Test1\Test2\2.dll” CopyTo=”%WIN%” />
<Add Path=”Test1\Test2\3.dll” CopyTo=”%WIN%” NoReg=”1” />
</RegServer>
</XyUnPack>
注:Path表示需要注冊的包裡的文件的全路徑。CopyTo表示先拷貝到指定的物理目錄(也可以是%WIN%,%SYS%,%TEMP%)再注冊,指定的物理目錄如果不存在將自動創建。有時可能僅僅要把文件拷貝到其他物理目錄而不需要注冊,就可以設置NoReg屬性。
(3) 寫注冊表
<XyUnPack>
<Trigger>
</Trigger>
<VirtualDirectory>
</VirtualDirectory>
<RegServer>
</RegServer>
<RegEdit>
<Add Key=” HKEY_LOCAL_MacHINE\SOFTWARE\Microsoft” Name=”User” Value=”sa” />
<Add Key=” HKEY_CURRENT_USER\SOFTWARE\Microsoft” Name=”User” Value=”sa” />
</RegEdit>
</XyUnPack>
(4) 運行EXE程序
<XyUnPack>
<Trigger>
</Trigger>
<VirtualDirectory>
</VirtualDirectory>
<RegServer>
</RegServer>
<RegEdit>
</RegEdit>
<ExeName>
<Add Path=”Test1\hello.exe” />
<Add Path=”Test1\Test2\world.exe” WaitExit=”1” />
</ExeName>
</XyUnPack>
注:Path表示需要運行的包裡的文件的全路徑。WaitExit表示解包過程是否需要等待運行的EXE結束。
(5) 創建快捷方式
暫緩
(6) 略