相關(guān)資訊
本類常用軟件
-
福建農(nóng)村信用社手機(jī)銀行客戶端下載下載量:584204
-
Windows優(yōu)化大師下載量:416898
-
90美女秀(視頻聊天軟件)下載量:366961
-
廣西農(nóng)村信用社手機(jī)銀行客戶端下載下載量:365699
-
快播手機(jī)版下載量:325855
便攜軟件制作的系列教程
2012/3/27 8:27:02 出處:本站原創(chuàng) 人氣:1971次 字號(hào):小 中 大
在NSIS中怎么導(dǎo)入注冊(cè)表。
這有何難,用registry插件嘛:
${registry::RestoreKey} file.reg $var
可是,如果你經(jīng)常在 RestoreKey 后面用 ${registry:write} ,就會(huì)發(fā)現(xiàn),往往導(dǎo)入注冊(cè)表會(huì)失敗,或者寫入的鍵值被reg文件中的舊鍵值覆蓋了,這是為什么呢?
原來(lái),${registry::RestoreKey} 這個(gè)命令并不會(huì)等待導(dǎo)入完成。作者在文檔中寫了:
${registry::RestoreKey} simply exec regedit: regedit /s “[file]“
執(zhí)行的是 Exec 而非 ExecWait 。那么,可能 regedit.exe 尚未啟動(dòng),就開始執(zhí)行下一行命令了。制作一般的安裝包問(wèn)題不大,但便攜軟件對(duì)執(zhí)行步驟的順序要求更加精確。所以,有些人的代碼是這樣寫的:
${registry::RestoreKey} file.reg $0
Sleep 200
睡一會(huì)。睡多久?睡一秒還是一年,這種盲人摸象的做法,我們完美主義者是不會(huì)使用的。因?yàn)檫@個(gè)命令,有些朋友凡是用到registry插件,都習(xí)慣性地加上個(gè) sleep,這是完全沒(méi)有必要的,作者說(shuō)了:
問(wèn):So my question is, what other functions in your plugin behave in the same way (ie do not wait for the registry operation to finish)?
答:registry::RestoreKey is the only one.
那么,用:
ExecWait 'regedit /s "[file]"' $var
不就行了嗎?
你又錯(cuò)了,我們制作便攜軟件的時(shí)候,要對(duì)自己嚴(yán)格要求,在Vista以上的系統(tǒng)中,不經(jīng)過(guò)UAC驗(yàn)證,是無(wú)法執(zhí)行 regedit /s 這個(gè)命令的(即使導(dǎo)入HKCU中的鍵值也不行)。難道你的每個(gè)軟件都要用戶通過(guò)UAC驗(yàn)證以管理員權(quán)限運(yùn)行嗎,完全是別有居心!
可是,在UAC環(huán)境的測(cè)試中,你會(huì)發(fā)現(xiàn),即使不通過(guò)UAC驗(yàn)證,${registry::RestoreKey} 這個(gè)命令也可以完成注冊(cè)表導(dǎo)入,難道,作者隱瞞了什么?
于是,作為代碼盲的你,充滿狐疑地打開 NSIS\Include\Registry.nsh ,找到這樣一段代碼:
!define registry::RestoreKey !insertmacro registry::RestoreKey
!macro registry::RestoreKey _FILE _ERR
registry::_RestoreKey /NOUNLOAD ${_FILE}
Pop ${_ERR}
IntCmp ${_ERR} -2 0 0 +10 ;REGEDIT4 ansi file
SetDetailsPrint none
IfFileExists "$SYSDIR\reg.exe" 0 +4 ;reg.exe used in Windows2K/XP/Vista/7
nsExec::ExecToStack "$SYSDIR\reg.exe" import "${_FILE}"
Pop ${_ERR}
StrCmp ${_ERR} 0 +5 0
IfFileExists "$WINDIR\regedit.exe" 0 +3 ;regedit.exe used in Wine
ExecWait "$WINDIR\regedit.exe" /s "${_FILE}"
${_ERR}
IfErrors 0 +2
StrCpy ${_ERR} -1
SetDetailsPrint lastused
!macroend
真是狡兔三窟!registry::RestoreKey失敗后,用reg.exe import,失敗后,又用 regedit.exe /s,我們就要有這種不屈不撓的精神,不要讓一次執(zhí)行的失敗變成Bug。
眼尖的你發(fā)現(xiàn),關(guān)鍵在于這一行:
nsExec::ExecToStack "$SYSDIR\reg.exe" import "${_FILE}"
原來(lái),雖然regedit /s需要管理員權(quán)限,但reg import命令并不需要,這就是${registry::RestoreKey}成功的秘訣。
但是,${registry::RestoreKey}首先嘗試用插件導(dǎo)入,而插件并不等待導(dǎo)入結(jié)束,所以,我們?cè)趹?yīng)用的時(shí)候,要把順序顛倒一下:
nsExec::ExecToStack "$SYSDIR\reg.exe" import "${_FILE}"
Pop $0
${IfNot} $0 == 0
${registry::RestoreKey} "${_FILE}" $0
Sleep 500
${IfNotThen} $0 == 0 ${|} StrCpy ${_OutVar} Error ${|}
${Endif}
nsExec::ExecToStack是等待運(yùn)行結(jié)束的,首先執(zhí)行,假如失敗,再用${registry::RestoreKey},并暫停0.5秒(比較安全的數(shù)值)。當(dāng)以上動(dòng)作始終返回Error的時(shí)候,我們就應(yīng)該考慮做個(gè)標(biāo)記,在便攜軟件結(jié)束的時(shí)候跳過(guò)這一次軟件運(yùn)行中的注冊(cè)表修改,不覆蓋原先的reg文件了。
不過(guò),當(dāng)你翻閱 PortableApps.com Launcher 的源代碼時(shí),卻發(fā)現(xiàn)關(guān)于注冊(cè)表導(dǎo)入,僅僅用了一行:
${registry::RestoreKey} $DataDirectory\settings\$0.reg $R9
可為什么感覺(jué)上PAL那么穩(wěn)定,極少出錯(cuò)呢?我猜是因?yàn)镻AL的代碼非常繁雜,每個(gè)實(shí)際動(dòng)作以前都有一堆工作,又是讀Launcher.ini,又是轉(zhuǎn)換變量,又是檢測(cè)PAF平臺(tái),慢悠悠的,慢工出細(xì)活吧!
本文導(dǎo)航
- 第1頁(yè): 首頁(yè)
- 第2頁(yè): 盤符替換與路徑替換
- 第3頁(yè): 善用DefaultData