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制作的输出目录截图如下:
本来以为直接把这个安装包里的文件全部使用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