上一頁 | 目錄 | 下一頁

D.3 使用 System.dll 來調用一個外部 DLL

某些安裝程序需要調用包含於第三方開發的 DLL 中的函數。最佳的例子就是安裝一個 Palm(TM) 通道。

一些關於 System.dll 的背景資料
System.dll 插件 (由 Brainsucker 開發) 使你可以通過提供 Call 函數來調用外部 DLL。有大量的由 System.dll 提供的函數,但是它們並不適合放在這裡。若要得到更多關於其它函數的詳細訊息,請鎖上門,取下電話,System 說明文件,並閱讀。

資料類型
System.dll 可以識別一下資料類型 :

將 System.dll 變量映射為 NSIS 裡的內置變量
如果你不需要返回任何資料,那麼這裡沒有什麼可以用來調用一個外部函數的指向。System.dll 可以通過以下方式將函數變量映射為 NSIS 腳本變量:

NSIS $0..$9 可與 System.dll r0..r9 相對應;NSIS $R0..$R9 也可與 System.dll r10..r19 相對應

每個參數由類型,輸入和輸出指定。可以用一個點跳過輸入或輸出。例如:

字元串 (一個字元數組的指針),輸入為 '輕鬆調用' :

t '輕鬆調用'

字元串 (一個字元數組的指針), 輸入從 $5 取值,並且經轉換為由調用產生的數組後,最後儲存到 $R8 :

t r5R8

一個整數指針,從 $1 取值並放入 $2 :

*i r1r2

一個 64-bit 整數指針,輸出送入堆棧,沒有輸入 :

*l .s

通過 System.dll::Call 調用第三方 DLL 中的一個函數,Call 的用法如下 :

System::Call 'YourDllName::YourDllFunction(i, *i, t) i(r0, .r1, r2) .r3'

後面的的 (r0, .r1, r2) .r3 段是用來傳送 DLL 和 NSIS 腳本之間的參數。就像在這個參數列表中看到的一樣,類型和輸入、輸出是可以分開的。每個 "(參數列表) 返回值" 塊不用考慮和/或新增上一個。在這裡,第一塊指定類型而第二塊指定輸入和輸出。

開始編輯 NSIS 腳本之前
在開始編輯 NSIS 代碼之前,首先需要瞭解要調用函數的原型。在這個例子裡,我們使用 Palm 'CondMgr.dll' 中的'CmGetHotSyncExecPath' 函數。這個函數用來返回 'HotSync.exe' 的完整路徑。

函數定義

int CmGetHotSyncExecPath(TCHAR *pPath, int *piSize);

參數

返回值:

同樣的,如果 buffer 太小,*int 中的值為緩衝應當的大小 (TCHAR 類型)。

上面的函數的定義轉換到 System.dll 定義:

CmGetHotSyncExecPath(t, *i) i

也就是,它有一個文字變量,一個整數指針,並返回一個整數值。

使用外部 DLL 函數
在選出了函數所要做的事情,以及它是如何轉換到 System.dll 格式之後,就可以在 NSIS 腳本中使用這個函數了。

首先,推薦在需要多次調用 System.dll 時,禁止插件卸載。 根據 Brainsucker (以及其他人) 的說法,這樣可以提高安裝包的執行速度 (減少了卸載 - 重新裝載的時間)。

其次,你必須將輸出目錄更改為你要用的 DLL 所在的目錄。如果 DLL 在系統路徑中,那麼它也能工作,但並沒有經過測試。

下面的代碼段會將 condmgr.dll 釋放到一個臨時目錄中,然後執行 CmGetHotSyncExecPath 函數,顯示返回的資料並最終卸載 System.dll 插件。

; **** snip ****
SetPluginUnload  alwaysoff

Function loadDll

  SetOutPath $TEMP\eInspect             ; 建立臨時目錄
  File bin\CondMgr.dll                  ; 釋放 DLL
  StrCpy $1 ${NSIS_MAX_STRLEN}          ; assign memory to $0
  System::Call 'CondMgr::CmGetHotSyncExecPath(t, *i) i(.r0, r1r1).r2'
  DetailPrint '路徑: "$0"'
  DetailPrint "路徑長度: $1"
  DetailPrint "返回值: $2"

; 最後一次插件調用必須沒有 /NOUNLOAD 參數,否則 NSIS 將不能在安裝結束後刪除
; 臨時的 DLL 檔案

  SetPluginUnload manual
; 什麼都不作 (目的就是為了卸載 System.dll)
  System::Free 0
FunctionEnd
; **** snip ****

這個函數將在觀看詳細訊息頁面產生下面的輸出:

輸出目錄: c:\windows\TEMP\eInspect
解壓: CondMgr.dll
路徑: "C:\Dave\palm\Hotsync.exe"
路徑長度: 24
返回值: 0

Written by djc

感謝
在此感謝 kichik Sunjammer 花費了大量時間解決這些問題。同時感謝 brainsucker 首先做了這個 System.dll 插件。祝你好運!

上一頁 | 目錄 | 下一頁