- NSIS Discussion
- Using System plug-in to load external dll file
Archive: Using System plug-in to load external dll file
bsayakhom
15th November 2010 14:57 UTC
Using System plug-in to load external dll file
Hi Guys,
My first step in such a community.
I'm currently trying to call a function from external ddli file usinc the system plug-in.
Unfortunately, I always have a returning error. I can't even checked whether the DLL function is called, or whether the DLL is loaded or not.
Here is my Current code :
SetOutPath $TEMP\MyDLL ; Storing my DLL in tmp folder
File MyDLL.dll ; DLL file coopy
;bool MyFunction (const char* sValue) ; The main function declaration in my C Code
${NSD_GetText} $NomTextBox $0 ; Retrieving string value from textbox
SetOutPath $TEMP\
System::Call "MyDLL::MyFunction(*t r0) i .r1"
MessageBox MB_OK $1
If someone has any idea to help me... you're welcome !!
Cheers
MSG
15th November 2010 15:18 UTC
You're extracting the dll to $TEMP\MyDll, then trying to run it from $Temp\.
Also, you should use $PLUGINSDIR as your temp directory, not $TEMP.
Anders
15th November 2010 15:30 UTC
InitPluginsDir
SetOutPath $pluginsdir
File MyDLL.dll
...
System::Call "MyDLL::MyFunction(m r0) i .r1"
You don't need *, t or m is enough (t is LPTSTR, m is always char*)
If MyFunction is cdecl and not stdcall, you need to tell system about it with the "?c" suffix
bsayakhom
15th November 2010 16:19 UTC
Hello Anders
Thanks for reply. I think I need to use the "?c" suffix. sorry, but can you clarify me where and how to use such a parameter ? :)
Thx !
bsayakhom
15th November 2010 16:28 UTC
Thanks ...
But still have the same trouble.
Just tried the Anders' solution below...
Afrow UK
15th November 2010 19:40 UTC
Any dependencies missing? Have you made sure the function is exported correctly?
Stu
bsayakhom
17th November 2010 13:44 UTC
Hello !
I checked the main dependencies, and nothing is missing.
Here is the portion of code , where the function is declared : (Hope this can help)
extern "C" int __declspec( dllexport ) Dummy()
{
::MessageBox(NULL, _T("kjoljkljljl"), _T("kjhjkhkjh"), 0);
return 1;
}
extern "C" bool __declspec( dllexport ) MyFunction (const char* sValue)
{
return AnotherFunction (sValue);
}
I also add a dummy function to make test, but nothing seems to work.
Here is also the NSIS code :
InitPluginsDir
SetOutPath $PLUGINSDIR
File MyFile.dll
SetPluginUnload alwaysoff
${NSD_GetText} $NomTextBox $0 ; where I ask the user to fill a string value
System::Call 'MyFile::MyFunction(m r0) i .r1 ?c'
MessageBox MB_OK $1
I just can't stand it no more !!!!
Please help, you'd make me happy for the day ;o)
Thanks by advance
Anders
17th November 2010 14:43 UTC
!define PLUGINNAME MyFile
!define PLUGINEXPORT MyFunction
SetOutPath $pluginsdir
File ${PLUGINNAME}.dll
System::Call 'kernel32::LoadLibrary(t "$pluginsdir\${PLUGINNAME}")i.r0'
System::Call 'kernel32::GetProcAddress(i r0,m "${PLUGINEXPORT}")i.r1'
MessageBox mb_ok $1
System::Call 'kernel32::FreeLibrary(ir0)'
If this fails, your plugin is broken or the exported function name is decorated. Open it in Dependency Walker and take a look.
To force cdecl, don't just specify "__declspec( dllexport )", use "__declspec( dllexport ) __cdecl"
bsayakhom
17th November 2010 15:06 UTC
First, thanks for your reply.
Just tried to make your modifications, and unfortunately, return value is 0; which means fail if I'm not wrong ...
I will try to check the way you call the DLL function, and investigate...
Btw, thanks for your support...
bsayakhom
17th November 2010 16:16 UTC
The DLL file is correctly loaded : Handle Value is not NULL...
But I've got a NULL value return, when attempting to call the function... something must be wrong with it...
Anders
17th November 2010 20:37 UTC
well, it is impossible to go any further when we don't know anything about your compiler setup
so please use Dependency Walker or dumpbin and check the exports
bsayakhom
18th November 2010 16:08 UTC
Hello again ...
Well, I've uploaded my test Visual project here :
http://bsayakhom.free.fr/VisualProject_test2DLL.zip
Here is also the full NSIS project folder with other script required.
I don't know if this can help you to solve my problem, because I'm completely stuck right now, and as you said, I can't go further now....:igor:
If any good feedback, you're welcome.
PS : I'm currently building the Installer.nsi script
Anders
18th November 2010 18:57 UTC
With the dll you posted:
outfile test.exe
requestexecutionlevel user
!define PLUGINNAME test2
!define PLUGINEXPORT MyFunction
section
initpluginsdir
SetOutPath $pluginsdir
File ${PLUGINNAME}.dll
System::Call 'kernel32::LoadLibrary(t "$pluginsdir\${PLUGINNAME}")i.r0'
System::Call 'kernel32::GetProcAddress(i r0,m "${PLUGINEXPORT}")i.r1'
MessageBox mb_ok $1 ;!=0
System::Call 'kernel32::FreeLibrary(ir0)'
System::Call '${PLUGINNAME}::${PLUGINEXPORT}(&i1 42)i.r0 ?cu'
MessageBox mb_ok $0 ;prints 42
SetOutPath $temp
sectionend
works fine, but just so you know
extern "C" char __declspec ( dllexport )__cdecl MyFunction (char sValue)
{
return (sValue);
}
is just handling a single character (byte), not a string.
bsayakhom
19th November 2010 14:16 UTC
Great , that works :
The requestexecutionlevel was missing, but adding this, function are correcly loaded.
I just have one question :
In the following command, <System::Call 'kernel32::GetProcAddress(i r0,m "${PLUGINEXPORT}")i.r1'>, do you really need to specify the "m" Attribute as output type near the function name ?
You must have understood that I'm little newbie, so sorry for the following question, bu for sure, if my function return a boolean, I have to specify int. type as return value right ?
I think I'm now on the good way, so thanks a lot for all the help you provided me with !!!
Anders
19th November 2010 15:23 UTC
well, yes, you ALWAYS have to specify a type for each parameter, and the 2nd parameter to GetProcAddress is char*