我的要求是我需要从系统中测试“如果存在UPS设备,然后再尝试禁用本机电源管理”。
为此,我需要调用drvutil.dll中的以下函数
BOOL IsUPSPresent()
下面是调用该函数的NSIS脚本:
Name "UPSTest"
OutFile "UPSTest.exe"
InstallDir $PROGRAMFILES\UPSTest
Section "UPSTest (required)"
SectionIn RO
DetailPrint "Testing UPS"
; Set output path to the installation directory. Here is the path C:\Program Files\UPSTest
SetOutPath $INSTDIR
; Give the dll path
File E:\Code\PCPE\Install\pcpe301\Common\ValidateUPS.exe
File E:\Code\PCPE\Install\pcpe301\Common\drvutil.dll
File E:\Code\PCPE\Install\pcpe301\Common\ntutil.dll
File E:\Code\PCPE\Install\pcpe301\Common\pdcdll.dll
System::Call "$INSTDIR\drvutil.dll::IsUPSPresent() i.r0"
Pop $0
MessageBox MB_OK "Return value = $R0, lasterr = $0"
IntCmp $R0 1 OkToInstall CancelInstall
CancelInstall:
Abort "Not allowed to install"
OkToInstall:
Do the install
使用上面的代码,当我运行应用程序时,我得到“返回值=,lasterr =错误”。我不确定为什么我会得到“返回值”空白(空)。我在这里想念任何东西吗?
我写了“ System :: Call”和“ MessageBox”,但不确定它们在做什么。 在这里,我想知道System :: Call的“ i.r0”是什么 还有什么是“ Pop $ 0”?
答案 0 :(得分:1)
您使用了错误的寄存器。系统语法中的r0
是$0
,而不是$R0
(R0
和r10
是$R0
)。 System::Call "$INSTDIR\drvutil.dll::IsUPSPresent() i.r0"
将INT32返回值放在$0
中,然后用$0
覆盖Pop
,而堆栈恰好为空。
如果您需要致电GetLastError()
,则必须附加?e
选项:
System::Call "$INSTDIR\drvutil.dll::IsUPSPresent() i.r0 ?e" ; Pushes error code on top of the stack
Pop $1 ; Get error code
DetailPrint "Return=$0 LastError=$1"
?e
将最后一个错误压入the stack,而Pop
则提取堆栈中的第一项。
我可以确认我的代码可以工作,我在一个虚拟的.DLL上进行了测试。如果它对您不起作用,则System::Call
无法加载.DLL或找到导出的函数。最可能的问题是您没有将函数正确导出到.DLL中。
使用Dependency Walker检查您的.DLL,应该看起来像这样:
不是
您也可以尝试在NSIS中手动进行验证:
!include LogicLib.nsh
Section
SetOutPath $InstDir
File drvutil.dll
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\drvutil.dll")p.r8 ?e'
Pop $7
${If} $8 P<> 0
MessageBox MB_OK 'Successfully loaded "$InstDir\drvutil.dll" @ $8'
System::Call 'KERNEL32::GetProcAddress(pr8, m "IsUPSPresent")p.r9 ?e'
Pop $7
${If} $9 P<> 0
MessageBox MB_OK 'Successfully found "IsUPSPresent" @ $9'
${Else}
MessageBox MB_ICONSTOP 'Unable to find "IsUPSPresent", error $7'
${EndIf}
System::Call 'KERNEL32::FreeLibrary(pr8)'
${Else}
MessageBox MB_ICONSTOP 'Unable to load "$InstDir\drvutil.dll", error $7'
${EndIf}