軟體開發最後一哩路是安裝程式。雖有 InstallShield 等工具,但自製安裝程式體積小、風格獨特、流程可控。本文詳細說明用 Delphi 開發安裝程式的九大核心步驟與關鍵程式碼。
myres.rc 腳本:
MYDBSRC MYDBSRCFILE c:\resdemo\mynbdb.mdb
MYDBJET MYDBJETFILE c:\resdemo\mdac_typ.exe
MYDBAPP MYDBAPPFILE c:\resdemo\Tnbdemo.exe
7001 ICON c:\resdemo\setup.ico
編譯:brcc32.exe myres.rc 產生 myres.res。專案 .dpr 加入 {$R myres.res}。
procedure TForm1.FormCreate(Sender: TObject);
var
i, H: Integer;
R: TRect;
begin
WindowState := wsMaximized;
H := ClientHeight;
for i := 0 to 255 do
begin
Canvas.Brush.Color := RGB(0, 0, 255 - i); // 藍到黑漸層
R := Rect(0, i * 2, ClientWidth, (i + 1) * 3);
Canvas.FillRect(R);
Canvas.TextRect(R, 30, 40, '寧波大學課件管理系統 v1.0');
end;
end;
if not DirectoryExists(EdtDir.Text) then
try
ForceDirectories(EdtDir.Text);
except
MessageBox(0, '建立目錄失敗!', '資訊', MB_OK);
Exit;
end;
var
SetupIni: TIniFile;
begin
SetupIni := TIniFile.Create(EdtDir.Text + '\setup.ini');
try
SetupIni.WriteString('Access', 'WorkDbPath', EdtDir.Text + '\mynbdb.mdb');
SetupIni.WriteString('Access', 'BackDbPath', EdtDir.Text + '\mynbdbbak.mdb');
finally
SetupIni.Free;
end;
end;
var
Res: TResourceStream;
begin
// 還原資料庫
Res := TResourceStream.Create(HInstance, 'MYDBSRC', PChar('MYDBSRCFILE'));
try
Res.SaveToFile(EdtDir.Text + '\mynbdb.mdb');
finally
Res.Free;
end;
// 還原主程式
Res := TResourceStream.Create(HInstance, 'MYDBAPP', PChar('MYDBAPPFILE'));
try
Res.SaveToFile(EdtDir.Text + '\Tnbdemo.exe');
finally
Res.Free;
end;
// 登錄表記錄主程式路徑供升級用
with TRegIniFile.Create do
try
RootKey := HKEY_LOCAL_MACHINE;
WriteString('SOFTWARE\MyNB', 'ExePath', EdtDir.Text + '\Tnbdemo.exe');
finally
Free;
end;
end;
var
CmdLine: array[0..259] of Char;
SI: TStartupInfo;
PI: TProcessInformation;
begin
Screen.Cursor := crHourGlass;
StrPCopy(CmdLine, EdtDir.Text + '\mdac_typ.exe /q');
FillChar(SI, SizeOf(SI), 0);
SI.cb := SizeOf(SI);
SI.dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
SI.wShowWindow := SW_HIDE;
if CreateProcess(nil, CmdLine, nil, nil, True, 0, nil, nil, SI, PI) then
begin
WaitForSingleObject(PI.hProcess, INFINITE);
CloseHandle(PI.hProcess);
CloseHandle(PI.hThread);
end;
Screen.Cursor := crDefault;
DeleteFile(EdtDir.Text + '\mdac_typ.exe');
end;
if DdeClientConv1.OpenLink then
begin
// 建立群組
DdeClientConv1.ExecuteMacro('[CreateGroup("寧波大學課件系統","寧波大學課件系統 v1.0")]', False);
// 新增項目
DdeClientConv1.ExecuteMacro('[AddItem("' + EdtDir.Text + '\Tnbdemo.exe","寧波大學課件系統")]', False);
DdeClientConv1.CloseLink;
end;
uses ShlObj, ComObj, ActiveX;
var
Unk: IUnknown;
Link: IShellLink;
Persist: IPersistFile;
PIDL: PItemIDList;
DeskPath: array[0..MAX_PATH] of Char;
LinkName: WideString;
begin
Unk := CreateComObject(CLSID_ShellLink);
Link := Unk as IShellLink;
Persist := Unk as IPersistFile;
Link.SetPath(PChar(EdtDir.Text + '\Tnbdemo.exe'));
Link.SetWorkingDirectory(PChar(EdtDir.Text));
SHGetSpecialFolderLocation(0, CSIDL_DESKTOPDIRECTORY, PIDL);
SHGetPathFromIDList(PIDL, DeskPath);
LinkName := DeskPath + '\MyApp.lnk';
Persist.Save(PWChar(LinkName), False);
// 強制桌面重新整理
PostMessage(FindWindowEx(FindWindowEx(FindWindow('Progman', nil), 0, 'SHELLDLL_DefView', nil), 0, 'SysListView32', nil),
WM_KEYDOWN, VK_F5, 0);
end;
ExitWindowsEx(EWX_REBOOT, 0);
自製安裝程式可精確控制每個細節:資源嵌入、目錄建立、組態產生、驅動靜默安裝、捷徑建立、重開機提示。程式碼精簡、無第三方依賴、風格完全可自訂,適合中小型專案。