Skip to content
⌘ NSIS Forum Archive

Using System plug-in to load external dll file

15 posts

bsayakhom#

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#
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#

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#
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#
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#

!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#
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#
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#
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#
Hello again ...

Well, I've uploaded my test Visual project here :


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....🧟

If any good feedback, you're welcome.

PS : I'm currently building the Installer.nsi script
Anders#
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#
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#
well, yes, you ALWAYS have to specify a type for each parameter, and the 2nd parameter to GetProcAddress is char*