使用NSIS製作驅動安裝包

win10環境安裝驅動的發現:

1.會在C:\Windows\INF目錄下的setupapi.dev.log文件中記錄信息,包括安裝命令,安裝結果。

2.可以使用pnputil安裝驅動。由於安裝後的inf文件會放到C:\Windows\INF目錄下以oem#.inf命名,所以安裝時需要記錄對應的inf文件名。這裏採用瞭如下方法,該方法也是參考stackoverflow上一個網友的回覆:

    (1)記錄下安裝驅動前已有的驅動列表:pnputil /enum-drivers > driverlist_before.txt

    (2)安裝驅動:pnputil /add-driver *.inf  /install

    (3)記錄下安裝驅動後已有的驅動列表:pnputil /enum-drivers > driverlist_after.txt

    (4)比較兩個文件的改動過濾輸出oem#.inf:fc driverlist_after.txt driverlist_before.txt | findstr /C:"oem" > diff.txt  文件內容大致如下:

                           

    (5)使用NSIS的stack將新增的oem#.inf過濾出來輸出到文件,腳本見文末。

    (6)卸載時讀取該文件,卸載相應的inf(腳本見文末):nsExec::ExecToLog '"$SYSDIR\PnPutil.exe" /delete-driver $driver1 /uninstall /force'

3.使用NSIS編寫腳本時直接使用nsExec::ExecToLog "pnputil /enum-drivers > driverlist_after.txt"不能識別">",而寫到腳本中,再通過nsExec::ExecToLog "createDiff.cmd"執行腳本則是可以的。

4.在64位系統中使用上述命令需要在${DisableX64FSRedirection}和${EnableX64FSRedirection}之間。

5.其實在命令行執行pnputil的安裝命令後,返回的安裝結果信息中會有對應的oem#.inf的信息,但使用nsExec::ExecToLog命令調用pnputil來安裝驅動會輸出到窗口,可以使用nsExec::ExecToStack命令,輸出到堆棧,然後通過$1獲得輸出信息,對此信息處理,使上述步驟得以簡化。

有關windows驅動程序的介紹可以參考官方文檔:https://docs.microsoft.com/zh-cn/windows-hardware/drivers/

此番操作僅供參考畢竟對驅動這塊不太懂,有什麼問題歡迎一起探討。有興趣可以看事情經過,沒興趣的可以之間跳到文末擼代碼。

------------------------------------------事情經過--------------------------------------------------------

       最近一個朋友詢問能否幫忙做個windows的安裝包,他本來是使用installshield2009製作的,現在想換inno setup。經過了解,我發現inno setup 和 NSIS功能相似,沒什麼差別,而之前我使用NSIS分分鐘就做好了,就回復說用NSIS試一下。

      朋友發來使用installshield製作的輸出目錄截圖如下:

      installshield輸出目錄

      本來以爲直接把這個安裝包裏的文件全部使用NSIS打包一遍就OK了,然而仔細詢問後才知道是要做一個驅動的安裝包(如上圖的inf文件)。

     於是在網上查找windows下安裝驅動的方法,有幾種驅動安裝的工具,介紹如下:

1.devcon.exe(windows設備控制檯):在 Microsoft Windows 2000 和更高版本的 Windows 上運行,用於更改設備配置(包括更新驅動程序,從驅動程序存儲區添加刪除第三方驅動程序包)。詳細介紹請參考官方文檔:https://docs.microsoft.com/zh-cn/windows-hardware/drivers/devtest/pnputil-command-syntax

2.difxcmd:通過 difxapi.lib 裏的 DriverPackageInstall 來安裝驅動

3.dpinst:使用靜默方式安裝不了驅動,必須要有交互 UI。

4.PnPUtil:從驅動程序存儲區( C:\Windows\System32\DriverStore\FileRepository )中刪除驅動和預安裝驅動。Windows Vista 和更高版本的 Windows 上支持 PnPUtil。 PnPUtil 不適用於 Windows XP,但可以使用驅動程序安裝框架(DIFx)工具來創建和自定義驅動程序包的安裝。只能刪除 oem開頭的驅動(通過該命令安裝的驅動都會以oem開頭,但一個驅動具體是oem?需要自己想辦法獲取)。

5.dism

       瞭解這些後,研究了一下已有的安裝包的信息,發現這個文件夾也有devcon.exe和difxcmd.exe,是不是安裝時使用了這兩個程序呢?於是又學習了一下installshield的安裝腳本文件——Packet文件夾下的.ism文件和Script Files文件夾下的Setup.Rul。在裏面找到了一些蛛絲馬跡。Setup.Rul部分內容如下:

安裝:

卸載:

後來瞭解到驅動安裝會在setupapi.dev.log中記錄,通過查看這個文件內容如下:

安裝:

卸載:

得出的結論還是直接看這個文件好一些。。。

       由於installshield安裝包在win10 64位系統,即使用了devcon.exe又使用了文件夾下的DIFxCmd.exe,卸載時則是使用的文件夾下的DIFxCmd.exe。爲了不依賴提供的DIFxCmd.exe,嘗試了使用PnPutil.exe。根據setupapi.dev.log內容看驅動都安裝成功了。設備能否正常工作還沒有驗證。

歡迎有需要的網友嘗試使用此方法安裝,驗證一下,在留言區回覆我,謝謝。

附:

createDiff.cmd

@echo off
pnputil /enum-drivers > driverlist_before.txt
pnputil /add-driver *.inf /install
pnputil /enum-drivers > driverlist_after.txt
fc driverlist_after.txt driverlist_before.txt | findstr /C:"oem" > diff.txt

使用NSIS的stack過濾新增oem#.inf

;store three driver oem name
var driver1
var driver2
var driver3

!include "TextFunc.nsh"

...

Function findTarget
${LineSum} "$INSTDIR\diff.txt" $R9
;MessageBox MB_OK $R9
StrCpy $R8 1
${While} $R8 <= $R9
    ${LineRead} "$INSTDIR\diff.txt" $R8 $R7
    ;MessageBox MB_OK $R7
    ;first just push
    ${If} $R8 == 1
        push $R7
        ;MessageBox MB_OK 'first push $R7'
    ;then pop first compare with new, if not equal push two
    ${Else}
        pop $0
        ;MessageBox MB_OK 'pop $0'
        StrCmp $0 $R7 +3 0
            push $0
            push $R7
        ;for debug
        ;StrCmp $0 $R7 +5 0
        ;push $0
        ;MessageBox MB_OK '$0 $R7 not equal push $0'
        ;push $R7
        ;MessageBox MB_OK '$0 $R7 not equal push $R7'
    ${EndIf}
    IntOp $R8 $R8 + 1
${EndWhile}

;pop and get "oem#.inf\r\n" string
pop $driver1
${WordFind} $driver1 " " "-1}" $R0
StrCpy $driver1 $R0
;MessageBox MB_OK 'final pop $str1'

pop $driver2
${WordFind} $driver2 " " "-1}" $R0
StrCpy $driver2 $R0
;MessageBox MB_OK 'final pop $str2'

pop $driver3
${WordFind} $driver3 " " "-1}" $R0
StrCpy $driver3 $R0
;MessageBox MB_OK 'final pop $driver3'

;write to file InstallInfo.txt
ClearErrors
FileOpen $0 "$INSTDIR\InstallInfo.txt" w
IfErrors done
FileWrite $0 $driver1
FileWrite $0 $driver2
FileWrite $0 $driver3
FileClose $0
done:
FunctionEnd

卸載腳本:

!include "WordFunc.nsh"

...

Function un.uninstallDrivers
ClearErrors
FileOpen $0 "$INSTDIR\InstallInfo.txt" r
IfErrors done
FileRead $0 $driver1
FileRead $0 $driver2
FileRead $0 $driver3
FileClose $0

;cut off last "\r\n" string
${WordReplace} $driver1 "$\r$\n" "" "-" $driver1
${WordReplace} $driver2 "$\r$\n" "" "-" $driver2
${WordReplace} $driver3 "$\r$\n" "" "-" $driver3

${DisableX64FSRedirection}
nsExec::ExecToLog '"$SYSDIR\PnPutil.exe" /delete-driver $driver1 /uninstall /force'
nsExec::ExecToLog '"$SYSDIR\PnPutil.exe" /delete-driver $driver2 /uninstall /force'
nsExec::ExecToLog '"$SYSDIR\PnPutil.exe" /delete-driver $driver3 /uninstall /force'
${EnableX64FSRedirection}
done:
FunctionEnd

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章