NSIS調用外部程序的的命令是Exec,比如Exec "notepad", 將啟動Windows的默認文本編輯器Notepad。同樣的道理可以用"java -jar test.jar"啟動test.jar。
Name "Java Launcher"
Caption "Java Launcher"
Icon "Java Launcher.ico"
OutFile "Java Launcher.exe"
SilentInstall silent
AutoCloseWindow true
ShowInstDetails nevershow
Section ""
Exec "java -jar test.jar"
SectionEnd
將上面這段NSIS腳本拷貝到一個nsi文件中,用NSIS編譯器編譯,將產生Java Launcher.exe。雙擊Java Launcher.exe將啟動同一目錄下的test.jar文件,test.jar必須能夠用java -jar test.jar啟動,也就是說test.jar的manifest的Library和Main-Class都要正確設值好。否則的話,你可以用java -classpath jar1;jar2 main_class來啟動。
如何編譯NSIS腳本請參看我之前的一篇隨筆 安裝程序制作系統NSIS(Nullsoft Scriptable Install System)。
上面這個啟動器的一個問題是會打開一個控制臺窗口,這是因為用了java命令,只要改為javaw就不會出現控制臺了。 另外一個問題是不夠健壯,只有當java或者javaw命令在當前目錄下或者在PATH上,才能正確啟動。也許你想帶著一個JRE發布你的程序,那么就不能夠去啟動系統的java命令。下面來加入尋找java命令目錄的功能,尋找的順序為
- 當前目錄下的jre子目錄, 如果你的發布程序里帶了一個jre,優先啟動。
- 環境變量JAVA_HOME
指定的目錄
- 在注冊表中,HKLM\SOFTWARE\JavaSoft\Java Runtime Environment下保存著安裝的JRE的目錄信息。
- 當前目錄和系統環境變量PATH中的目錄
腳本
Name "Java Launcher"
Caption "Java Launcher"
Icon "Java Launcher.ico"
OutFile "Java Launcher.exe"
SilentInstall silent
AutoCloseWindow true
ShowInstDetails nevershow
Section ""
Call GetJRE
Pop $R0
; change for your purpose (-jar etc.)
StrCpy $0 '"$R0" -jar test.jar'
SetOutPath $EXEDIR
ExecWait $0
SectionEnd
Function GetJRE
Push $R0
Push $R1
ClearErrors
StrCpy $R0 "$EXEDIR\jre\bin\javaw.exe"
IfFileExists $R0 JreFound
StrCpy $R0 ""
ClearErrors
ReadEnvStr $R0 "JAVA_HOME"
StrCpy $R0 "$R0\bin\javaw.exe"
IfErrors 0 JreFound
ClearErrors
ReadRegStr $R1 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment" "CurrentVersion"
ReadRegStr $R0 HKLM "SOFTWARE\JavaSoft\Java Runtime Environment\$R1" "JavaHome"
StrCpy $R0 "$R0\bin\javaw.exe"
IfErrors 0 JreFound
StrCpy $R0 "javaw.exe"
JreFound:
Pop $R1
Exch $R0
FunctionEnd
Function GetJRE定義了尋找JRE的函數,找到的javaw命令的路徑可以從R0中取回。R0,R1是NSIS預定義的寄存器,或者說是變量,Push $R0將R0的內容壓進堆棧,Pop $R0從堆棧中取回R0的內容。這一點和匯編程序很像。GetJRE按定義好的順序判斷指定路徑下的是否存在javaw,如果是,返回。比如
ReadEnvStr $R0 "JAVA_HOME" 讀入JAVA_HOME的值到R0
StrCpy $R0 "$R0\bin\javaw.exe"
加上\bin\javaw.exe
IfFileExists $R0 JreFound
如果R0指定的文件存在,跳轉到JreFound
ReadRegStr讀取注冊表中的鍵值。Exch $R0交換R0和堆棧頭元素的值。其他函數從字面上就可以理解了,不需要過多的解釋。
最后要說明的是,這里用Execwait啟動java命令,而不是Exec。區別是Exec馬上退出Java Launcher.exe的進程,而Execwait不退出,也就是說用Execwait在關閉程序之前,有兩個活動進程,Java Launcher.exe和javaw.exe。這正是eclipse3.3之前的EXE啟動器的情況,比如Eclipse3.2啟動后,任務管理器里有eclipse.exe和javaw.exe兩個進程。使用Execwait的原因是Exec在Windows 2000下出現的一個問題,在使用程序的過程中,如果用戶改變了桌面屬性,比如背景圖,系統就掛掉了。Eclipse在3.3之后改成了使用Java的Invocation Interface啟動startup.jar。詳細的情況請看org.eclipse.equinox.executable項目。
轉載請保留
http://m.tkk7.com/xilaile/archive/2007/05/13/117039.html