我可以在 NSIS 中使用 LoadLibrary 加载多个 dll 吗?
Can I load multiple dlls using LoadLibrary in NSIS?
作为项目的一部分,我在 NSIS 脚本中使用 LoadLibrary 加载了多个 dll。因为其他的dll都是对主dll的引用。
之后如何使用 GetProcAddress 调用该函数?因为我加载了多个DLL。
下面是我的代码片段:
!include LogicLib.nsh
Section
SetOutPath $InstDir
File testutil.dll
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\Testutil.dll")p.r8 ?e'
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\TestControls.dll")p.r8 ?e'
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\TestDevice.dll")p.r8 ?e'
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\loadtestdll.dll")p.r8 ?e'
Pop
${If} P<> 0
MessageBox MB_OK 'Successfully loaded "$InstDir\testutil.dll" @ '
System::Call 'KERNEL32::GetProcAddress(pr8, m "IsTherePower")p.r9 ?e'
Pop
${If} P<> 0
MessageBox MB_OK 'Successfully found "IsTherePower" @ '
${Else}
MessageBox MB_ICONSTOP 'Unable to find "IsTherePower", error '
${EndIf}
System::Call 'KERNEL32::FreeLibrary(pr8)'
${Else}
MessageBox MB_ICONSTOP 'Unable to load "$InstDir\testutil.dll", error '
${EndIf}
当我运行这个脚本时,它正在成功加载DLL。但它没有加载功能。你能帮我解决这个问题吗?
When I run this script, it is loading the DLL successfully.
您在发布的示例中检查了错误的 HMODULE!您只是检查 pdcdll.dll 是否正确加载,而不是您要检查的 .DLL。
理想情况下,您在使用系统插件时应该对 Win32 有相当多的经验。
LoadLibrary
将为您加载依赖的 .DLL,在大多数情况下您不必手动执行此操作。一个潜在的问题是 避免加载劫持-.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} P= 0 ${|} MessageBox MB_ICONSTOP "DEBUG: Failed to load pdcdll.dll" ${|}
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\UPSDevice.dll")p.r8'
${IfThen} P= 0 ${|} MessageBox MB_ICONSTOP "DEBUG: Failed to load UPSDevice.dll" ${|}
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\UPSControls.dll")p.r8'
${IfThen} P= 0 ${|} MessageBox MB_ICONSTOP "DEBUG: Failed to load UPSControls.dll" ${|}
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\drvutil.dll")p.r8 ?e'
Pop ; Get ?e result
${IfThen} P= 0 ${|} MessageBox MB_ICONSTOP "Failed to load drvutil.dll, error " ${|}
${If} P<> 0
System::Call 'KERNEL32::GetProcAddress(pr8, m "IsUPSPresent")p.r9 ?e'
Pop ; Get ?e result
${IfThen} P= 0 ${|} MessageBox MB_ICONSTOP "Failed to find the exported function, error . Inspect the .DLL with Dependency Walker to make sure the function is exported with the correct un-decorated name!" ${|}
${EndIf}
SectionEnd
如果您收到 "Failed to load drvutil.dll" 消息,那么您需要查看 .DLL 依赖项等。
如果您收到 "Failed to find the exported function" 消息,那么您还没有 exported the function correctly. The function name should not be decorated. Dependency Walker 将显示导出的函数名称。如果您无法移除修饰,那么您可以将修饰后的名称直接传递给 GetProcAddress
但是您需要记住,如果您编译为 64 位或更改为,名称可能不一样另一个编译器供应商。
它应该是这样的:
作为项目的一部分,我在 NSIS 脚本中使用 LoadLibrary 加载了多个 dll。因为其他的dll都是对主dll的引用。 之后如何使用 GetProcAddress 调用该函数?因为我加载了多个DLL。
下面是我的代码片段:
!include LogicLib.nsh
Section
SetOutPath $InstDir
File testutil.dll
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\Testutil.dll")p.r8 ?e'
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\TestControls.dll")p.r8 ?e'
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\TestDevice.dll")p.r8 ?e'
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\loadtestdll.dll")p.r8 ?e'
Pop
${If} P<> 0
MessageBox MB_OK 'Successfully loaded "$InstDir\testutil.dll" @ '
System::Call 'KERNEL32::GetProcAddress(pr8, m "IsTherePower")p.r9 ?e'
Pop
${If} P<> 0
MessageBox MB_OK 'Successfully found "IsTherePower" @ '
${Else}
MessageBox MB_ICONSTOP 'Unable to find "IsTherePower", error '
${EndIf}
System::Call 'KERNEL32::FreeLibrary(pr8)'
${Else}
MessageBox MB_ICONSTOP 'Unable to load "$InstDir\testutil.dll", error '
${EndIf}
当我运行这个脚本时,它正在成功加载DLL。但它没有加载功能。你能帮我解决这个问题吗?
When I run this script, it is loading the DLL successfully.
您在发布的示例中检查了错误的 HMODULE!您只是检查 pdcdll.dll 是否正确加载,而不是您要检查的 .DLL。
理想情况下,您在使用系统插件时应该对 Win32 有相当多的经验。
LoadLibrary
将为您加载依赖的 .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} P= 0 ${|} MessageBox MB_ICONSTOP "DEBUG: Failed to load pdcdll.dll" ${|}
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\UPSDevice.dll")p.r8'
${IfThen} P= 0 ${|} MessageBox MB_ICONSTOP "DEBUG: Failed to load UPSDevice.dll" ${|}
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\UPSControls.dll")p.r8'
${IfThen} P= 0 ${|} MessageBox MB_ICONSTOP "DEBUG: Failed to load UPSControls.dll" ${|}
System::Call 'KERNEL32::LoadLibrary(t "$InstDir\drvutil.dll")p.r8 ?e'
Pop ; Get ?e result
${IfThen} P= 0 ${|} MessageBox MB_ICONSTOP "Failed to load drvutil.dll, error " ${|}
${If} P<> 0
System::Call 'KERNEL32::GetProcAddress(pr8, m "IsUPSPresent")p.r9 ?e'
Pop ; Get ?e result
${IfThen} P= 0 ${|} MessageBox MB_ICONSTOP "Failed to find the exported function, error . Inspect the .DLL with Dependency Walker to make sure the function is exported with the correct un-decorated name!" ${|}
${EndIf}
SectionEnd
如果您收到 "Failed to load drvutil.dll" 消息,那么您需要查看 .DLL 依赖项等。
如果您收到 "Failed to find the exported function" 消息,那么您还没有 exported the function correctly. The function name should not be decorated. Dependency Walker 将显示导出的函数名称。如果您无法移除修饰,那么您可以将修饰后的名称直接传递给 GetProcAddress
但是您需要记住,如果您编译为 64 位或更改为,名称可能不一样另一个编译器供应商。
它应该是这样的: