问题
I am trying to load and call a C library DLL's function in my NSIS installer. When I try to load the DLL, an error 126 is emitted (ERROR_MOD_NOT_FOUND).
This is the minimal installer script that I am using to test this:
OutFile Main.exe
ShowInstDetails show
Section
SetOutPath "C:\Program Files (x86)\MyApp"
System::Call 'kernel32::LoadLibraryA(m "C:\Program Files (x86)\MyApp\API.dll")i.r0 ? e'
Pop $9
DetailPrint $9
DetailPrint $0
System::Call 'kernel32::GetProcAddress(i r0,m "GetVersion")i.r1 ? e'
Pop $9
DetailPrint $9
DetailPrint $1
System::Call 'kernel32::FreeLibrary(ir0)'
SectionEnd
You can see that I am setting my outpath to where the DLL is located; where all its dependencies are. In examining at the process in procmon, however, I see that only the Windows system directory is being searched for the dependencies, not the outpath:
Load Image C:\Program Files (x86)\MyApp\API.dll SUCCESS
CreateFile C:\Program Files (x86)\MyApp\API.dll SUCCESS
QueryBasicInformationFiC:\Program Files (x86)\MyApp\API.dll SUCCESS
CloseFile C:\Program Files (x86)\MyApp\API.dll SUCCESS
CloseFile C:\Program Files (x86)\MyApp\API.dll SUCCESS
Thread Create SUCCESS
CreateFile C:\Windows\syswow64\DEPENDENCY_1.dll NAME NOT FOUND
CreateFile C:\Windows\syswow64\msvcr100.dll SUCCESS
QueryBasicInformationFiC:\Windows\syswow64\msvcr100.dll SUCCESS
CloseFile C:\Windows\syswow64\msvcr100.dll SUCCESS
CreateFile C:\Windows\syswow64\DEPENDENCY_2.dll NAME NOT FOUND
CreateFile C:\Windows\syswow64\DEPENDENCY_3.dll NAME NOT FOUND
CreateFile C:\Windows\syswow64\msvcr100.dll SUCCESS
How can I get my outpath to be searched for dependencies? It should be noted that "C:\Program Files (x86)\MyApp" is also in the Path environment variable, so why is that not being searched either?
回答1:
Recent security changes in NSIS have locked down the places it allows you to load libraries from. You can call AddDllDirectory to add other directories:
Section
System::Call 'KERNEL32::AddDllDirectory(w "c:\path")' ; Note: Path must exist at this point
System::Call 'KERNEL32::LoadLibrary(t "c:\path\file.dll")p.r0'
System::Call 'KERNEL32::GetProcAddress(pr0, m "somefunction")p.r1'
${If} $1 P<> 0
...
${EndIf}
System::Call 'KERNEL32::FreeLibrary(pr0)'
SectionEnd
来源:https://stackoverflow.com/questions/45567525/nsis-system-kernel32loadlibrary-does-not-search-outdir-or-path