五、调用PowerShell命令
执行外部程序
参考“ NSIS用户手册”,NSIS脚本语言中有三个指令可以执行外部程序:
- Exec:执行一个指定的程序并且立即继续安装。如:Exec '"$INSTDIR\command.exe" 参数'
- ExecShell:使用Windows的外壳关联来执行一个指定的程序,并且立即继续安装。类似于我们在Windows目录浏览窗口以默认打开方式来执行文件。如:ExecShell "open" "$INSTDIR\command.exe"
- ExecWait:执行一个指定的程序并且等待运行处理结束,再继续安装。如:ExecWait '"$INSTDIR\command.exe" 参数' $0($0当产生错误时设置为错误标记,未产生错误则为未指定)
以上命令当不能被运行时则会置一个错误标记,如果命令包含有空格,则要用引号把他们包括起来。
高级一点
如果我们的安装程序需要执行一些后台命令,使用上面的指令时会出现命令行窗口,显得很不和谐,我们就可以使用nsExec。具体的有三种用法:nsExec::Exec/ nsExec::ExecToLog/ nsExec::ExecToStack,不同的是nsExec::ExecToLog会把结果输出到日志窗口, nsExec::ExecToStack会把结果输出到堆栈中。
例如:nsExec::ExecToStack '"$INSTDIR\command.exe" 参数'
具体到我们需要执行PowerShell 命令文件,则 nsExec::ExecToStack 'powershell -inputformat none -ExecutionPolicy RemoteSigned -File "${PSFile}" '
PowerShell封装
NSIS网站上有有对PowerShell的支持,请参见PowerShell support,把其中的脚本保存为"psexec.nsh"文件,在需要使用的“*.nsi”文件中引用该头文件(!include psexec.nsh)。
- Powershell命令调用例子
${PowerShellExec} "Get-WmiObject -Class Win32_ComputerSystem" Pop $R1 detailprint "PowerShell命令执行结果:$R1"
- Powershell文件调用例子
InitPluginsDir SetOutPath $PLUGINSDIR\Powershell File script.ps1 ${PowerShellExecFileLog} "$PLUGINSDIR\Powershell\script.ps1"
扩展能力
像上面介绍的"psexec.nsh"文件那样头文件能在一定程度上扩展NSIS脚本语言的功能,但遇到复杂的情况,更高级的就是使用插件来扩展它的功能。
插件可以使用其他编程语言来写(如:C、C++等),里面有公开的函数,编译后生成DLL文件,把DLL文件放在NSIS安装目录的Plugins文件夹下(如:C:\Program Files (x86)\NSIS\Plugins),NSIS脚本语言使用时通过dll::function“参数”进行调用(如:MSSQL_OLEDB::SQL_Execute "CREATE DATABASE [MyTestDB]")。当 NSIS 编译器开始时它会扫描插件目录的 DLL 文件并且列出找到的插件和输出的函数,在编译时如果遇到有序的冒号如 fred::flintstone编译器将会作为关键字在该列表中查找,如果列表项列入了 fred.dll 并输出 flintstone 则 NSIS 将会把 fred.dll 文件打包到安装程序里。当插件命令执行时 NSIS 将会解压所需的插件 DLL 文件到一个临时目录 ($PLUGINSDIR),把指定的参数全部压入(从右到左次序),然后执行 DLL 函数。
如果你想调用一个用户硬盘或其他地方里的插件,你可以使用CallInstDLL,从一个 NSIS 扩展动态链接库里调用一个函数,需要自行把函数的参数全部压入堆栈,扩展动态链接库可以访问堆栈和变量,如下例子:
Push "参数"
Push "另一个参数"
CallInstDLL $INSTDIR\somedll.dll somefunction
其中用C++写的一个例子Contrib/ExDLL可以参考。另外NSIS网站提供了一些插件,请参见Category:Plugins ,这里面包括我们接下章节要讲解的访问数据库的插件。