當我們開發完Pocket PC或者Smartphone的軟件後,都需要考慮如何製作給最終用戶使用的軟件安裝包。專門用於製作安裝包的軟件有很多,如Install Shield等。但在許多情況下,我們僅僅需要一些比較簡單的安裝過程,這時候我們完全可以利用SDK中提供的工具和一些免費的軟件來製作安裝包。另外,我們製作的軟件經常會需要在不同的平臺下運行,例如筆者開發的一個軟件同時支持HPC,PPC,Smartphone等平臺,HPC和PPC平臺上還有3 種CPU類型。如果每一步操作完成後都需要人工介入進行操作的話,每一次構建過程都會相當的繁瑣和耗時。所以我們會考慮如何將一系列的操作採用腳本串接起來,只需要運行一個命令就能夠生成最終需要的所有安裝包。
用命令行編譯鏈接程序
雖然EVC裏提供了Batch Build的功能,但該功能只能用於同一平臺的不同CPU版本的編譯鏈接操作。在切換不同平臺進行編譯時,需要在GUI環境中手工執行,無法達到我們要求。所以我們需要研究如何在命令行狀態下進行程序的編譯運行。實際上EVC程序本身是提供了一系列的命令可以用於命令行編譯的。
D:/Program Files/Microsoft eMbedded Tools/Common/EVC/Bin>evc /?
Usage:
EVC [myprj.vcp|mywksp.vcw] - load project/workspace
[<filename>] - load source file
/? - display usage information
/EX <macroname> - execute a VBScript macro
/OUT <filename> - redirect command line output to a file
/USEENV - ignore tools.options.directories settings
/MAKE [<target>] [...] - build specified target(s)
[<project> - <platform> <configname>]
[[<project>|ALL] - [DEBUG|RELEASE|ALL]]
/CLEAN - delete intermediate files but don't build
/REBUILD - clean and build
/NORECURSE - don't build dependent projects
/CECONFIG [<configuration>] - use specified configuration
其中主要是運用MAKE命令。假設我們需要編譯的程序名叫做Demo,工作環境文件名爲demo.vcw,PPC版的工程項目文件爲 Demo.vcp,Smartphone版本的項目文件爲DemoSP.vcp.我們爲EVC3編寫好的批處理文件build.bat如下:
REM @echo off
set EVC="D:/Program Files/Microsoft eMbedded Tools/Common/EVC/Bin/EVC.EXE" <-指向EVC 3.0程序所在目錄
set CFG=
set CECONFIG=
%EVC% Demo.vcw /make "%CFG%" /CEConfig=%CECONFIG% /rebuild <-執行編譯並生成目標可執行文件
if errorlevel 1 goto :eof <-如果編譯失敗則終止批處理
:pocketpc
set CFG=Demo - Win32 (WCE ARM) Release<-將要進行編譯的項目名稱和編譯出來的目標代碼的平臺和CPU類型。其中“-”前面的是項目名稱,“-”後面的部分是平臺和CPU 類型以及編譯的是Release版還是Debug版。格式可以參照在EVC的Build->Configurations中的寫法, EVC3 和 EVC4的表達方式略有不同。
set CECONFIG="Pocket PC" <-編譯PPC平臺版本
%EVC% Demo.vcw /make "%CFG%" /CEConfig=%CECONFIG% /rebuild
if errorlevel 1 goto :eof
set CFG=Demo - Win32 (WCE MIPS) Release
%EVC% Demo.vcw /make "%CFG%" /CEConfig=%CECONFIG% /rebuild
if errorlevel 1 goto :eof
set CFG=Demo - Win32 (WCE SH3) Release
%EVC% Demo.vcw /make "%CFG%" /CEConfig=%CECONFIG% /rebuild
if errorlevel 1 goto :eof
:sp2002
set CFG=DemoSP - Win32 (WCE ARM) Release
set CECONFIG="Smartphone 2002" <-編譯Smartphone平臺版本
%EVC% Demo.vcw /make "%CFG%" /CEConfig=%CECONFIG% /rebuild
if errorlevel 1 goto :eof
echo build successfully finished!!
pause
根據上面的代碼,現在我們只需要運行一次build.bat文件即可編譯生成PPC,Smartphone等不同平臺的目標文件。
製作cab文件
生成目標文件後,我們就需要考慮如何將程序安裝到設備上。cab文件是一種壓縮並且帶有各種安裝信息的打包文件,所有的安裝軟件實際上都是將軟件的 cab文件拷貝到相應設備上,然後利用設備上的wceload程序進行最後的設備安裝步驟。我們可以使用PocketPC或者Smartphone SDK中附帶的cabwiz.exe (在Smartphone上是CabWizSP.exe)對程序進行打包生成cab文件。
在製作cab文件之前,我們通常需要做好以下的規劃:
- 程序的詳細信息,例如公司名稱,程序名稱等等
- 目標的硬件平臺,如PPC還是Smartphone,什麼類型的CPU
- 有哪些源文件,源文件存放在PC機上面的什麼目錄中
- 拷貝到設備上的文件存放在什麼路徑下
- 是否需要創建快捷方式,快捷方式到什麼文件,圖標是什麼
- 是否需要修改註冊表,修改項目和內容是什麼
cab文件的生成需要製作一個.inf文件作爲cabwiz程序的輸入。當我們做好計劃之後就可以動手編寫這個.inf文件。這個文件是整個製作過程中最關鍵的一步,也是最困難的一步。.inf文件與windows裏的ini文件十分相似,都是用文本方式保存的,裏面包含若干的段(Section),關鍵字(Key)和值(Value)組成的描述信息。我們同樣是採用對例子進行解釋說明的方式進行介紹。
一般來說,inf文件都有四個主要組成部分,PPC的寫法和Smartphone的寫法略有不同,我們先介紹PPC的寫法。
inf文件的第一部分是一些全局信息的定義:
[Version] <-版本信息,必須有該段
Signature = "$Windows NT$" <-必須是$Windows NT$或者$Windows 98$, 不要改動
Provider = "Demo Soft" <-提供商, 完整的程序名字會是"<Provider> <AppName>"
CESignature = "$Windows CE$" <-必須是該值
[CEStrings] <-該段主要是定義安裝程序用到的一些字符串,必須有該段
AppName = "DemoApp" <-程序的名字
InstallDir = “%CE1%/Octopus Studio/%AppName%” <-定義程序在目標設備中的安裝目錄
[Strings] <-該段用於用戶自己定義的字符串, 該段可選
ExeBaseDir = "C:/ProjectHome/demo/Release/platform" <-和平臺相關的文件放在這個目錄下
CommonDir = "C:/ProjectHome/demo/Release" <-與平臺無關的文件放在這個目錄裏
其中InstallDir中出現的“%CE1%”是inf文件定義的系統目錄標記,下面列出的是PPC 2002和Smartphone 2002下可以使用的目錄宏:
目錄標記 | 目錄路徑 |
---|---|
%CE1% | /Program Files |
%CE2% | /Windows |
%CE4% | /Windows/StartUp |
%CE5% | /My Documents |
%CE8% | /Program Files/Games |
%CE11% | /Windows/Start Menu/Programs |
%CE14% | /Windows/Start Menu/Programs/Games |
%CE15% | /Windows/Fonts |
%CE17% | /Windows/Start Menu |
%CE19% | /Application Data(僅用於Smartphone) |
這些目錄標記在進行安裝的時候會替換成相應的系統目錄路徑。此外這些系統目錄在安裝過程中會自動根據需要進行自動調節。例如%CE1%是指系統缺省的程序安裝目錄,指向“/Program Files”。而當用戶選擇程序安裝在存儲卡中時,該目錄也會做相應改變。
[CEString]和[Strings]中定義的變量以及上面提到的目錄標記可以用於替換inf文件中的任意部分。下面的說明中會有使用的例子。
第二部分是用來聲明支持的設備CPU類型,操作系統類型和版本號要求:
[CEDevice.ARM] <-目標設備聲明,如果支持多種設備/CPU就會有多個CEDevice段,並且在用設備標號作爲後綴表示。如果只支持一種設備,可以直接用[CEDevice]表示
ProcessorType = 2577 <-該目標設備是StrongARM CPU
UnsupportedPlatforms = “Smartphone”,"HPC","Jupiter","Palm PC2" <-不支持smarthphone和HPC等舊設備
VersionMin = 3.00 <-對應設備德操作系統的最低版本號要求是3.0,版本號說明見下面的說明
VersionMax = 5.00 <-假設我們的程序要求的操作系統最高版本號是5.0
[CEDevice.MIPS]
ProcessorType = 4000 <-CPU要求是 MIPS_R4000
UnsupportedPlatforms = “Smartphone”,"HPC","Jupiter","Palm PC2"
VersionMin = 3.00
VersionMax = 5.00
[CEDevice.SH3]
ProcessorType = 10003 <- CPU要求是 Hitachi_SH3
UnsupportedPlatforms = “Smartphone”,"HPC","Jupiter","Palm PC2"
VersionMin = 3.00
VersionMax = 5.00
WinCE各個平臺的表示法和相應的版本號如下表,UnsupportedPlatform和VersionMin/VersionMax的值可以參考該表進行填寫。
Platform | Platform type | Windows CE version |
---|---|---|
Smartphone 2003 | Smartphone | 4.2 |
Smartphone 2002 | Smartphone | 3.0 |
Pocket PC 2003 | Pocket PC | 4.2 |
Pocket PC 2002 | Pocket PC | 3.0 |
Pocket PC 2000 | Palm PC2 | 3.0 |
Palm Size PC v2 | Palm PC | 2.11 |
Palm Size PC v1 | Palm PC | 2.1 |
Handheld PC 2000 | Jupiter | 3.0 |
Handheld PC Pro | Jupiter | 2.11 |
Handheld PC | HPC | 2.0 |
inf文件的第三部分是定義源文件的組成和其在桌面機器的目錄:
[SourceDisksNames] <-源文件所在目錄,段名稱不加後綴表示與平臺無關的文件所在目錄.必須有該段
1=, "SourceDisk01",,%CommonDir% <-格式爲 <source ID> = ,<label>,,<source directory>其中Source ID用來在後續內容中指定源文件目錄用,label只是說明,無用處。Source directory則是指源文件在PC系統中的所在目錄。
[SourceDisksNames.ARM] <-段名稱的後綴與前面的CEDevice段相對應
2=, "SourceDisk02",,%ExeBaseDir%/ppc/arm
[SourceDisksNames.MIPS]
2=, "SourceDisk03",,%ExeBaseDir%/ppc/mips
[SourceDisksNames.SH3]
2=, "SourceDisk04",,%ExeBaseDir%/ppc/sh3
[SourceDisksFiles] <-說明源文件分別放在什麼目錄下,必須有該段
"demo.htm" = 1 <- 格式爲<filename> = <source ID>,其中filename是文件名,Source ID是指上面SourceDiskName中定義的源目錄ID.“demo.htm”=1表示demo.htm文件是放在SourceDiskNames 裏定義的%CommonDir%目錄裏。
"demo.exe" = 2
"demo.dll" = 2
inf文件的第四部分是定義安裝的操作
[DefaultInstall] <-指明安裝包需要進行的操作,例如文件拷貝,快捷方式創建等。必須有該段
CopyFiles = Files.InstallDir, Files.Windows <-指明需要進行文件拷貝的說明段,參看下面的說明
CEShortcuts = Links <-指定需要生成的快捷方式定義. 除了這連個安裝操作外,開發人員還可以指定註冊表修改(AddReg), 自定的安裝/卸載時的可執行代碼(CESetupDLL), 註冊DLL文件(CESelfRegister).具體可以參考SDK幫助文件
[Files.InstallDir] <-文件拷貝操作中指明的文件拷貝操作定義,用於定義每個文件如何被拷貝到設備上
"demo.htm",,,0x40000001 <- 格式爲<dest filename>,<source filename>,,<copy flags>, 其中dest filename 表示拷貝到目標設備後文件名; source filename源文件的文件名,如果爲空則dest filename用來表示源文件文件名;copy flags表示拷貝文件時的方式,該值是一些標誌位的組合,可用的標誌如下:
標誌 | 含義 |
---|---|
0x00000001 | 警告用戶如果在拷貝該文件時發生錯誤, 而用戶採用跳過操作的話 |
0x00000002 | 不允許用戶在拷貝該文件時發生錯誤才取跳過操作 |
0x00000010 | 當目標目錄中有同名文件存在時不進行覆蓋操作 |
0x00000400 | 當目標目錄存在同名文件時才進行拷貝(覆蓋)操作 |
0x20000000 | 如果目標文件比該文件新則不進行拷貝操作 |
0x40000000 | 拷貝文件時不檢查文件日期 |
0x80000000 | 創建一個對該文件的鏈接,主要是用於共享dll文件 |
"demo.exe",,,0x40000003
[Files.Windows] <-同上,用戶定義文件拷貝操作
"demo.dll",,,0x80000013
[DestinationDirs] <-定義設備上的目標文件目錄
Files.InstallDir = 0,%InstallDir% <- 格式爲<section name> = 0,<dest directory>, 其中section name 對應[DefaultInstall] CopyFiles中的值。dest directory則是目標設備上的目的目錄。例如Files.InstallDir裏列出的文件將會拷貝到目標設備的%InstallDir%目錄下。
Files.Windows = 0, %CE2%
Links = 0, %CE11%
[Links] <- 該段對應[DefaultInstall]中CEShortcuts的定義,用來說明需要創建的快捷方式
%AppName%,0,"demo.exe",%CE11% <- 格式爲<shortcut filename>,<shortcut type>,<target file/path>,<standard dest path>。其中 shortcut filename是指生成的快捷方式的文件名; shortcut type 指明鏈接的是文件名還是目錄,0表示文件,非0表示目錄; target file/path 是指被鏈接的文件的文件名或者目錄路徑; standard dest path 指快捷方式存放在那個目錄下。
以上是針對PPC的inf文件寫法。由於PPC支持多種的CPU所以比較複雜一些,而Smartphone目前實際上目前只支持一種CPU類型,所以我們可以對inf文件進行簡化。其中文件的第1和第4部分的內容還是和PPC一樣。而第2和第3部分則可以簡化成:
[CEDevice]
ProcessorType = 2577
UnsupportedPlatforms = “Pocket PC“,"HPC","Jupiter","Palm PC2" <-不支持PPC和HPC等設備
VersionMin = 3.00
VersionMax = 5.00
[SourceDisksNames]
1=, "SourceDisk01",,%CommonDir%
2=, "SourceDisk02",,%ExeBaseDir%/sp
[SourceDisksFiles]
"demo.htm" = 1
"demo.exe" = 2
"demo.dll" = 2
把以上四個部分拼成一個文件就是一個完整的inf文件了。製作完inf文件後,我們就可以使用cabwiz.exe文件來生成.cab文件。該命令的語法如下:
cabwiz.exe "inf_file"
[/dest dest_directory]
[/err error_file]
[/cpu cpu_type [cpu_type]]
參數的含義爲:
inf_file – 指向inf文件的全路徑
dest_directory – 生成的cab文件的存放路徑,如不指定則生成在inf文件所在目錄
error_file – 錯誤報告文件,將所有的執行信息都輸出到該文件。不指定該參數時,所有的錯誤信息都會用消息框來顯示。該參數主要用於自動化構建
cpu_type – 指定需要生成的CPU類型,需要與inf文件中定義的CEDevice段的後綴一致。可以同時指定多個CPU類型
假設我們前面例子中的inf文件名爲demo.inf文件。則對應的執行命令爲:
cabwiz demo.inf /err buildppc.err /cpu ARM MIPS SH3
這樣就會生成 demo.arm.cab, demo.mips.cab, demo.sh3.cab 三個文件,分別對應3種不同的CPU(平臺)的安裝文件。
製作自動安裝執行文件
生成了cab文件並不意味着大功告成。雖然用戶可以手工將cab文件拷貝到設備上安裝,但這樣需要用戶自己懂得區分CPU類型等許多的專業知識。所以我們通常都會進一步生成一個可執行的自動化安裝包,達到傻瓜化安裝的目的。如果你的安裝過程比較簡單的話,可以使用Spb Software House(http://www.spbsoftwarehouse.com)公司提供的免費軟件ezsetup進行可執行安裝文件的製作。該軟件生的安裝程序功能比較簡單:顯示產品信息和軟件授權協議,然後安裝cab文件。雖然功能比較少,但大部分的PPC/Smartphone軟件的安裝過程也只需要這幾個功能就足夠了。
首先我們需要製作一個demo.ini文件。該文件的格式很簡單,PPC和Smartphone對應的格式都一樣。例子如下:
[CEAppManager]
Version = 1.0 <- 這個是CeAppMgr程序的版本號,不是要安裝的軟件的版本號,不必修改
Component = Demo <- 軟件的模塊,與下面的段的名稱一致
[Demo]
Description = Demo App For PPC <- 軟件的描述
CabFiles = demo.arm.cab,demo.mips.cab,demo.sh3.cab <-列出需要所有的cab文件,注意文件名之間不要有空格
ezsetup程序是一個命令行運行的程序,這可以方便我們進行自動化構建。命令的使用方法如下:
ezsetup <-l language> <-i inifilename> <-r readme.txt>
<-e eula.txt> <-o outputexe>
-l language 是指定安裝過程中使用的語言,暫時不支持中文,所以我們選English
-i inifilename ini文件的全路徑
-r readme.txt readme文件的全路徑,用於在安裝過程中顯示給用戶
-e eula.txt最終用戶授權協議文件的全路徑,用於安裝過程中授權協議界面的顯示
-o outputexe 生成的exe文件的名稱
我們可以用下面的命令來生成可執行安裝文件:
ezsetup -l english -i demo.ini -r Readme.txt -e License.txt -o demo_setup.exe
自動化構建
前面分別介紹瞭如何在命令行編譯鏈接目標程序,製作cab文件,以及生成自動化安裝程序。這些步驟都是可以通過命令行方式執行的,所以我們可以把這些命令在批處理腳本中串接起來製作自動化構建腳本。這樣我們就可以“一鍵”完成從代碼編譯到生成最終可執行安裝包的全過程。