作为项目的一部分,我在NSIS脚本中使用LoadLibrary加载了多个dll。因为其他dll是主dll的引用。 之后,如何使用GetProcAddress调用函数?因为我已经加载了多个DLL。
下面是我的代码段:
!include LogicLib.nsh
Section
SetOutPath $InstDir
File drvutil.dll
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\drvutil.dll")p.r8 ?e'
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\UPSControls.dll")p.r8 ?e'
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\UPSDevice.dll")p.r8 ?e'
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\pdcdll.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}
运行此脚本时,它正在成功加载DLL。但是它没有加载功能。您能帮我解决问题吗?
答案 0 :(得分:2)
运行此脚本时,它正在成功加载DLL。
您正在检查发布的示例中的HMODULE错误!您只是在检查pdcdll.dll是否正确加载,而不是要检查的.DLL。
理想情况下,使用系统插件时,您应该对Win32有一定的经验。
LoadLibrary
将为您加载依赖的.DLL,在大多数情况下,您无需手动进行此操作。一个潜在的问题是NSIS activates some extra hardening protections避免加载hijacking-.DLL,这可能会阻止.DLL加载其依赖项。
在这里,我将为您提供一个完整的示例,该示例手动加载每个.DLL,但您不应正常执行此操作,只需加载所需的.DLL,然后让Windows为您解决其余的问题。
!include LogicLib.nsh
Section
SetOutPath $InstDir
File drvutil.dll
File UPSControls.dll
File UPSDevice.dll
File pdcdll.dll
System::Call 'KERNEL32::AddDllDirectory(w "$InstDir")' ; Tell Windows we trust all .DLLs in this directory
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\pdcdll.dll")p.r8'
${IfThen} $8 P= 0 ${|} MessageBox MB_ICONSTOP "DEBUG: Failed to load pdcdll.dll" ${|}
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\UPSDevice.dll")p.r8'
${IfThen} $8 P= 0 ${|} MessageBox MB_ICONSTOP "DEBUG: Failed to load UPSDevice.dll" ${|}
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\UPSControls.dll")p.r8'
${IfThen} $8 P= 0 ${|} MessageBox MB_ICONSTOP "DEBUG: Failed to load UPSControls.dll" ${|}
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\drvutil.dll")p.r8 ?e'
Pop $7 ; Get ?e result
${IfThen} $8 P= 0 ${|} MessageBox MB_ICONSTOP "Failed to load drvutil.dll, error $7" ${|}
${If} $8 P<> 0
System::Call 'KERNEL32::GetProcAddress(pr8, m "IsUPSPresent")p.r9 ?e'
Pop $7 ; Get ?e result
${IfThen} $9 P= 0 ${|} MessageBox MB_ICONSTOP "Failed to find the exported function, error $7. Inspect the .DLL with Dependency Walker to make sure the function is exported with the correct un-decorated name!" ${|}
${EndIf}
SectionEnd
如果收到“无法加载drvutil.dll”消息,则需要查看.DLLs依赖项等。
如果收到“无法找到导出的函数”消息,则您没有exported the function correctly。函数名称不应为decorated。 Dependency Walker将为您显示导出的函数名称。如果您无法删除修饰,则可以将修饰的名称直接传递给GetProcAddress
,但是请记住,如果您使用64位编译或更改为,则名称可能不相同。另一个编译器供应商。
它应该像这样: