; *********************************************************** *************** ; Tên: Portable ; ; Phiên bản: ; ; Website: ; ; Được viết cho: ; NSIS 2.17 hoặc cao hơn ; Các plugin cần thiết: NewAdvSplash, Registry, FindProcDLL, Messagebox ; ; Giấy phép: ; Copyright© 2006 by ; ; Những thông tin về cài đặt, cấu trúc thư mục v.v có thể đọc trong file readme.txt. ; ; Lưu ý: Khi sao lưu những thư mục và file có sẵn, có thể mất rất nhiều thời gian ; tùy thuộc vào tốc độ ổ cứng USB của bạn. Nhớ lấy điều này! ; Cửa sổ trạng thái cho thấy việc sao chép được cho phép. ; ; Mẫu ứng dụng portable được tạo vào năm 2006 bởi Karl Loncarek, phiên bản 1.4.1 - 2006/11/30 ; Giấy phép của mẫu này xem ở file readme.txt. ; *********************************************************** *************** ; *********************************************************** *************** ; * Định nghĩa các hằng số (Define constants) ; *********************************************************** *************** !define AUTHOR "" ; tên bạn !define APP "" ; chèn tên ứng dụng, Ví dụ "TestApp" !define VER "0.0.0.0" ; chèn phiên bản của chương trình !define EXE "" ; chèn tên file EXE, Ví dụ "testapp.exe" !define PNAME "${App}Portable" ; định dạng tên portable (các thư mục và tên file) !define ICON "${PNAME}.ico" ; chú thích dòng này khi sử dụng icon mặc định !define SPLASHIMAGE "${PNAME}.jpg" ; chú thích dòng này khi không dùng ảnh splashscreen !define REGKEYS "" ; chèn các khóa registry sử dụng, phân cách bởi "||", chú thích khi không dùng !define SETTINGSFILES "" ; chèn các file thiết lập dùng đến, phân cách bởi "||" được lưu trữ trong máy host, Ví dụ "$WINDIR\TEST.INI", chú thích ra khi không dùng !define SETTINGSDIRS "" ; chèn các thư mục thiết lập dùng đến, phân cách bởi "||" được lưu trữ trong máy host, Ví dụ "$PROFILE\TEST", chú thích ra khi không dùng !define INI "${PNAME}.ini" ; có thể thay đổi khi thiết lập của nhiều chương trình được lưu trong 1 file .INI ; *********************************************************** *************** ; * Includes (Bao gồm) ; *********************************************************** *************** !include "Registry.nsh" ; thêm các macro thao tác registry, không được bao gồm mặc định trong NSIS !include "WordFunc.nsh" ; thêm header cho thao tác với word !insertmacro "WordFind" ; thêm chức năng chia tách chuỗi !include "FileFunc.nsh" ; thêm header cho thao tác với file !insertmacro "GetParameters" ; thêm chức năng tìm lại các tham số dòng lệnh ; *********************************************************** *************** ; * Runtime Switches (chuyển đổi thời gian thực) ; *********************************************************** *************** CRCCheck On ; tiến hành CRC (cycle redundancy check) check của launcher trước khi bắt đầu("Off" cho việc nén EXE sau này) WindowIcon Off ; không hiển thị icon của launcher SilentInstall Silent ; bắt đầu như launcher, không phải installer AutoCloseWindow True ; tự động đóng khi kết thúc ; *********************************************************** *************** ; * Định nghĩa các biến (Define variables) ; *********************************************************** *************** Var ACTION Var ACTIONDIRECTORY Var ACTIONPARAMETERS Var SPLASHSCREEN ; thông tin splash screen có được hiện ra không, mặc định là có Var PROGRAMEXE ; tên của file EXE cần chạy Var PROGRAMDIR ; đường dẫn của file EXE ở trên Var PROGRAMPARMS ; các tham số thêm vào khi chạy file EXE Var DATADIR ; đường dẫn tới thư mục nơi lưu tất cả các thiết lập Var INIFILE ; đường dẫn đầy đủ tới file INI tìm được Var SECONDLAUNCH ; file EXE có được chạy lần thứ 2 hay không ; *********************************************************** *************** ; * Set basic information ( thiết lập các thông tin cơ bản) ; *********************************************************** *************** Name "${APP} Portable" !ifdef ICON Icon "${ICON}" !endif Caption "${APP} Portable - ${VER}" OutFile "${PNAME}.exe" ; *********************************************************** *************** ; * Set version information (Thiết lập thông tin phiên bản) ; *********************************************************** *************** LoadLanguageFile "${NSISDIR}\Contrib\Language files\English.nlf" VIProductVersion "${Ver}" VIAddVersionKey /LANG=${LANG_ENGLISH} "Tên sản phẩm" "${APP} Portable" VIAddVersionKey /LANG=${LANG_ENGLISH} "Chú thích" "Cho phép ${APP} chạy trên 1 ổ cứng lưu động." VIAddVersionKey /LANG=${LANG_ENGLISH} "Bản quyền hợp pháp" "© ${AUTHOR}" VIAddVersionKey /LANG=${LANG_ENGLISH} "Tên công ty" "by ${AUTHOR}" VIAddVersionKey /LANG=${LANG_ENGLISH} "Mô tả file" "${APP} Portable" VIAddVersionKey /LANG=${LANG_ENGLISH} "Phiên bản của file" "${VER}" VIAddVersionKey /LANG=${LANG_ENGLISH} "Tên file gốc" "${PNAME}.exe" ; *********************************************************** *************** ; * Hàm: Các khởi chạy khác trước khi chạy chương trình ; *********************************************************** *************** Function Init FunctionEnd ; *********************************************************** *************** ; * Hàm: Các thứ cần dọn sạch trước khi kết thúc chương trình ; *********************************************************** *************** Function CleanUp FunctionEnd ; *********************************************************** *************** ; * Function: Initialize working variables (Hàm chạy các biến làm việc) ; *********************************************************** *************** Function InitVariables ; ; Kiểm tra xem file INI có tồn tại không, thiết lập biến trỏ đến nó ; IfFileExists "$EXEDIR\${INI}" "" CheckPortableINI StrCpy "$INIFILE" "$EXEDIR\${INI}" Goto ReadINIFile CheckPortableINI: IfFileExists "$EXEDIR\${PNAME}\${INI}" "" CheckPortableAppsINI StrCpy "$INIFILE" "$EXEDIR\${PNAME}\${INI}" Goto ReadINIFile CheckPortableAppsINI: IfFileExists "$EXEDIR\PortableApps\${PNAME}\${INI}" "" CheckAppsINI StrCpy "$INIFILE" "$EXEDIR\PortableApps\${PNAME}\${INI}" Goto ReadINIFile CheckAppsINI: IfFileExists "$EXEDIR\Apps\${PNAME}\${INI}" "" CheckDataINI StrCpy "$INIFILE" "$EXEDIR\Apps\${PNAME}\${INI}" Goto ReadINIFile CheckDataINI: IfFileExists "$EXEDIR\Data\${PNAME}\${INI}" "" NoINIFile StrCpy "$INIFILE" "$EXEDIR\Data\${PNAME}\${INI}" Goto ReadINIFile Goto NoINIFile ; ; Read content of the INI file (Đọc nội dung file INI) ; ReadINIFile: ReadINIStr $0 "$INIFILE" "${PNAME}" "Thư mục chương trình" StrCmp $0 "" NoINIFile ; nếu trống rỗng lấy lại thiết lập đúng StrCpy "$PROGRAMDIR" "$EXEDIR\$0" ; lưu thư mục chương trình ReadINIStr $0 "$INIFILE" "${PNAME}" "Thư mục dữ liệu" StrCmp $0 "" NoINIFile ; nếu trống rỗng lấy lại thiết lập đúng StrCpy "$DATADIR" "$EXEDIR\$0" ; lưu thư mục dữ liệu ReadINIStr $0 "$INIFILE" "${PNAME}" "file .EXE của chương trình" StrCpy "$PROGRAMEXE" "$0" ; lưu tên file .exe StrCmp $0 "" "" Splash ; nếu trống rỗng dùng tên mặc định StrCpy "$PROGRAMEXE" "${EXE}" ; cho giá trị mặc định Splash: ReadINIStr $0 "$INIFILE" "${PNAME}" "SplashScreen" StrCpy "$SPLASHSCREEN" "$0" ; lưu trạng thái của màn hình Splashscreen StrCmp "$SPLASHSCREEN" "" "" Các tham số chương trình ; kiểm tra xem biết splashscreen có trống rỗng không StrCpy "$SPLASHSCREEN" "enabled" ; cho giá trị mặc định ProgramParameters: ReadINIStr $0 "$INIFILE" "${PNAME}" "Tham số chương trình" StrCpy "$PROGRAMPARMS" "$0" ; lưu các tham số bổ sung Goto InitVarEnd ; kết thúc việc đọc file INI NoINIFile: ; thiết lập mặc định cho tất cả các biến ; ; Set default values for variables (Cho biến các giá trị mặc định) ; StrCpy "$PROGRAMEXE" "${EXE}" ; dùng thiết lập mặc định StrCpy "$PROGRAMPARMS" "" StrCpy "$SPLASHSCREEN" "enabled" ; cho phép splashscreen ; ; Kiểm tra cấu hình thư mục nào được dùng và thiết lập các biến theo đó ; IfFileExists "$EXEDIR\App\${APP}\$PROGRAMEXE" "" CheckPortableDIR StrCpy "$PROGRAMDIR" "$EXEDIR\App\${APP}" StrCpy "$DATADIR" "$EXEDIR\Data" Goto InitVarEnd CheckPortableDIR: IfFileExists "$EXEDIR\${PNAME}\App\${APP}\$PROGRAMEXE" "" CheckPortableAppsDIR StrCpy "$PROGRAMDIR" "$EXEDIR\${PNAME}\App\${APP}" StrCpy "$DATADIR" "$EXEDIR\${PNAME}\Data" Goto InitVarEnd CheckPortableAppsDIR: IfFileExists "$EXEDIR\PortableApps\${PNAME}\App\${APP}\$PROGRAMEXE" "" CheckAppsDIR StrCpy "$PROGRAMDIR" "$EXEDIR\PortableApps\${PNAME}\App\${APP}" StrCpy "$DATADIR" "$EXEDIR\PortableApps\${PNAME}\Data" Goto InitVarEnd CheckAppsDIR: IfFileExists "$EXEDIR\Apps\${PNAME}\${APP}\$PROGRAMEXE" "" NoDIR StrCpy "$PROGRAMDIR" "$EXEDIR\Apps\${PNAME}\${APP}" StrCpy "$DATADIR" "$EXEDIR\Data\${PNAME}" Goto InitVarEnd NoDIR: ; ; Không tìm thấy cấu hình thư mục được cho phép nào ; MessageBox MB_OK|MB_ICONEXCLAMATION `$PROGRAMEXE không tìm thấy. Xin kiểm tra cấu hình của bạn` Abort ; kết thúc launcher InitVarEnd: ;kết thúc hàm FunctionEnd ; *********************************************************** *************** ; * Hàm: Làm việc với các khóa hoặc cây registry (backup, restore, delete) ; *********************************************************** *************** Function DoAction StrCmp "$ACTIONPARAMETERS" "" Sau vòng lặp ; nếu không có tham số nào thì thôi ngay StrCpy "$R8" "0" ; reset bộ đếm StrCpy "$R2" "$ACTION" 6 # ; chỉ lấy 6 ký tự đầu của hành động đc yêu cầu StrCmp "$R2" "Backup" "" GoOn ; sao lưu thư mục yêu cầu IfFileExists "$ACTIONDIRECTORY\*.*" GoOn ; tạo thư mục sao lưu nếu nó không tồn tại CreateDirectory $ACTIONDIRECTORY GoOn: StrCpy "$R0" "$ACTIONPARAMETERS" ; chép hằng số để làm việc đăng ký Loop: ; ; Lấy tham số đơn ra khỏi danh sách ; StrCmp "$R0" "" Sau vòng lặp ; không phân tích registry, khi không có khóa nào được đưa ra IntOp $R8 $R8 + 1 ; tăng bộ đếm ${WordFind} "$R0" "||" "+01" $R9 ; lưu tham số đầu tiên để đăng ký ${WordFind} "$R0" "||" "+02*}" $R0 ; xóa phần đầu tiên từ giá trị đã lưu StrCmp "$R0" "$R9" LastLoop ; nếu các giá trị đăng ký trùng nhau -> không còn delimiters Goto DoWork ; không xóa danh sách giá trị LastLoop: StrCpy "$R0" "" ; Nếu không có delimiter sẵn có thì làm trống rỗng các biến làm việc ; ;Quyết định làm gì với tham số ; DoWork: StrCpy "$R2" "$ACTION" "" -4 # ; lấy 7 ký tự cuối của biến hoạt động !ifdef REGKEYS StrCmp "$R2" "Keys" DoWorkRegistry ; hành động phải được thực hiện với registry !endif !ifdef SETTINGSFILES StrCmp "$R2" "File" DoWorkFiles ; hành động phải được thực hiện với file !endif !ifdef SETTINGSDIRS StrCmp "$R2" "Dirs" DoWorkDirectory ; hành động phải được thực hiện với các thư mục !endif Goto Continue ; có gì đó không xác định ; ; Thao tác với các khóa registry ; !ifdef REGKEYS DoWorkRegistry: StrCmp "$ACTION" "BackupKeys" BackupRegistryKey ; sao lưu khóa registry StrCmp "$ACTION" "RestoreKeys" RestoreRegistryKey ; phục hồi khóa registry, VD ghi chúng vào registry StrCmp "$ACTION" "DeleteKeys" DeleteRegistryKey ; Xóa các khóa registry Goto Continue ; có gì đó không xác định BackupRegistryKey: ${registry::KeyExists} "$R9" $R7 ; kiểm tra khóa registry có tồn tại hay không StrCmp "$R7" "0" 0 Continue ; khóa registry không tồn tại, không lưu lại gì cả ${registry::SaveKey} "$R9" "$ACTIONDIRECTORY\RegKey$R8.reg" "/G=1" $R7 ; Sao lưu khóa registry Sleep 50 Goto Continue RestoreRegistryKey: IfFileExists "$ACTIONDIRECTORY\RegKey$R8.reg" 0 Continue ; chỉ phục hồi nếu 1 file registry tồn tại ${registry::RestoreKey} "$ACTIONDIRECTORY\RegKey$R8.reg" $R7 ; Phục hồi các khóa registry đã lưu Sleep 50 Goto Continue DeleteRegistryKey: ${registry::DeleteKey} "$R9" $R7 ; Xóa khóa registry Sleep 50 Goto Continue !endif ; ; Thao tác với file ; !ifdef SETTINGSFILES DoWorkFiles: StrCmp "$ACTION" "BackupFile" BackupFile ; thực hiện sao lưu file StrCmp "$ACTION" "RestoreFile" RestoreFile ; phục hồi các file đã lưu, VD ghi nó vào máy host StrCmp "$ACTION" "DeleteFile" DeleteFile ; xóa file từ host computer BackupFile: IfFileExists "$R9" 0 Continue ; kiểm tra xem file có tồn tại hay không CopyFiles "$R9" "$ACTIONDIRECTORY\File$R8.dat" ; sao lưu file Goto Continue RestoreFile: IfFileExists "$ACTIONDIRECTORY\File$R8.dat" 0 Continue ; chỉ phục hồi khi file có sẵn CopyFiles "$ACTIONDIRECTORY\File$R8.dat" "$R9" ; phục hồi file Goto Continue DeleteFile: Delete "$R9" ; xóa file Goto Continue [...]... trước khi chạy chương trình ; -Call Init ; -; Chạy chương trình ; -${GetParameters} $R0 ; thu được các tham số dòng lệnh cuối cùng ExecWait "$PROGRAMDIR\$PROGRAMEXE $PROGRAMPARMS $R0" ; chạy chương trình ; -; Các hành động dọn sạch khác sau khi chương trình đã chạy... Goto EndOfCode ; -; chạy ứng dụng trực tiếp mà không làm gì khác, giống như nó đã đang chạy rồi ; -SimplyStartProgram: ${GetParameters} $R0 ; lấy các tham số dòng lệnh cuối cùng Exec "$PROGRAMDIR\$PROGRAMEXE $PROGRAMPARMS $R0" ; chạy chương trình ${registry::Unload} EndOfCode: SectionEnd ... xóa các khóa registry trong máy host Call DoAction ; thực hiện hành động sleep 500 ; để cho việc xóa các khóa registry kết thúc StrCpy "$ACTIONDIRECTORY" "$DATADIR\RegistryBackup" ; xác định nơi sao lưu các khóa StrCpy "$ACTION" "RestoreKeys" ;phục hồi các khóa đã lưu Call DoAction ; thực hiện hành động sleep 1000 ; để cho việc ghi vào registry kết thúc (cần thiết trước khi xóa file lưu trữ) !endif... "$R9\*.*" 0 Continue ; kiểm tra xem thư mục nguồn có tồn tại hay không IfFileExists "$ACTIONDIRECTORY\Dir$R8.dat" +2 0 ; thư mục đích có tồn tại hay không? CreateDirectory "$ACTIONDIRECTORY\Dir$R8.dat" ; tạo thư mục đích CopyFiles "$R9\*.*" "$ACTIONDIRECTORY\Dir$R8.dat" ; sao lưu thư mục Goto Continue RestoreDirectory: IfFileExists "$ACTIONDIRECTORY\Dir$R8.dat\*.*" 0 Continue ; kiểm tra xem các sao lưu... /NOUNLOAD 2500 200 200 -1 /L $PLUGINSDIR\splash.jpg NoSplash: !endif StrCmp $SECONDLAUNCH "true" SimplyStartProgram ; -; Sao lưu những khóa registry tồn tại, thay thế bằng các khóa registry đã lưu ; -!ifdef REGKEYS StrCpy "$ACTIONPARAMETERS" "${REGKEYS}" ; bàn giao danh sách tham số StrCpy "$ACTIONDIRECTORY" "$DATADIR\RegistryBackup"... định các khóa local ở đâu StrCpy "$ACTION" "RestoreKeys" ;phục hồi các khóa đã lưu Call DoAction ; thực hiện hành động !endif ; -; Sao lưu những cái đã có, thay thế bằng các file thiết lập đã lưu ; -!ifdef SETTINGSFILES StrCpy "$ACTIONPARAMETERS" "${SETTINGSFILES}" ; bàn giao danh sách tham số StrCpy "$ACTIONDIRECTORY" "$DATADIR\SettingsBackup" . ; chèn phiên bản của chương trình !define EXE "" ; chèn tên file EXE, Ví dụ "testapp.exe" !define PNAME "${App }Portable& quot; ; định dạng tên portable (các thư mục. "Thư mục chương trình& quot; StrCmp $0 "" NoINIFile ; nếu trống rỗng lấy lại thiết lập đúng StrCpy "$PROGRAMDIR" "$EXEDIR$0" ; lưu thư mục chương trình ReadINIStr. ; thực hiện hành động !endif ; ; Các thay đổi khác trước khi chạy chương trình ; Call Init ; ; Chạy chương trình ; ${GetParameters} $R0 ; thu được các tham số dòng lệnh cuối