Archive: How to call NSIS function from plugin via ExecuteCodeSegment


How to call NSIS function from plugin via ExecuteCodeSegment
  Hi
I would like to execute my NSIS function TryMe from plugin (.dll).
This is my NSIS code:

Function TryMe

MessageBox MB_OK "TryMe"
>FunctionEnd

>Function LicensePage
GetDlgItem$0 $HWNDPARENT 1
GetFunctionAddress$2 TryMe # $2 Contains correct values, I checked it
Dll::Dll /NOUNLOAD $2
Pop$1
FunctionEnd
>
And this is my C++ code:


extern "C" __stdcall void Dll(HWND hWndParent, int string_size,

char *variables, stack_t **stacktop, extra_parameters *extra)
{
DLL_INIT();

.....some other code like popping HWND etc...

if(
popstring(tmp)) {
extra->exec_flags->exec_error = TRUE;
return;
}
int iFunc = myatoi(tmp.c_str()); // HERE I GET THE SAME NUMBER
// AS IN ABOVE NSIS CODE - address of function

extra->ExecuteCodeSegment(iFunc, 0); // here I want
// to execute my NSIS function, but it does nothing
I checked everything severaltimes, iFunc is filled with correct value but nothing happens in extra->ExecuteCodeSegment.

What I am doing wrong?

Needs to be iFunc - 1. I forget why.

Stu


Originally posted by Afrow UK
Needs to be iFunc - 1. I forget why.

Stu
These hidden features are killing me!!!!!

Big thanks, now it works fine!

I need that code for my new plugin ThreadTimer.

ThreadTimer plug-in allows you to create simple Timer which runs in a separate thread. It is available since Start until Stop, it ticks in desired interval and calls NSIS function. It can be created for a whole life-cycle of installer because it is NOT tied with any installer page or nsDialogs page.

See more on it's wiki page: http://nsis.sourceforge.net/ThreadTimer_plug-in

Thanks to user bluenet whose Delay plugin gave me some ideas: showthread.php?postid=2350657

Use this topic for questions/comments to this plugin. :)


It's probably better to start a new thread about this plugin. The topic itself has nothing to do with timer plugins, so people aren't likely to find it easily.


Your DLL depends on MSVCRT90 which means the installer will crash on systems without it (e.g. machines without .NET 3.5).

http://nsis.sourceforge.net/Building...%29_dependency

Stu


Originally posted by Afrow UK
Your DLL depends on MSVCRT90 which means the installer will crash on systems without it (e.g. machines without .NET 3.5).
Stu
Thanks for pointing that, I forgot to check it. I removed that dependency :)

Also I updated this list with some of my ideas: http://nsis.sourceforge.net/Building...%29_dependency

Hope it helps someone, I lost 2 hours with linker errors!

By the way in future when you upload files to the Wiki, don't put the version in the file name. You can put the version number as a comment and avoid multiple file names.

Stu


I get this error:
Invalid command: ThreadTimer::Start

I am using as from the example:
ThreadTimer::Start /NOUNLOAD 2345 8 $2

I have copied the dll to the NSIS/Plugins folder.
What else have I missed? Other plugins are working fine.

I am using Nsis 2.46 Special Build-Large strings (http://nsis.sourceforge.net/Special_Builds), does it make any difference?


@mrmls: Did the example work fine for you? Try to compile it and compare to your script.
Plugin is not dependent on any NSIS version, so using Large strings build is fine.


No, the example does not work, I copied and pasted it in a brand new install script (created by the wizard), but it does not compile. Returns the above message.
When I comment out the line containing ThreadTimer commands, it compiles fine.

I'm also on 64-bit OS (Windows 7), maybe this causes some issues.

I will try to build the dll from provided source.


Rebuilt the project on my computer, also on x64 configuration. Still the same error:
Invalid command: ThreadTimer::Start

I have ensured that I copy ThreadTimer.dll to right "Plugins" folder.


It looks to me like the plugin was compiled with the wrong options, the function names are 'decorated' and shouldn't be. Makensisw shows this when I put the release version dll into my plugins folder:

 - ThreadTimer::?Start@@YAXPAUHWND__@@HPADPAPAU_stack_t@@PAUextra_parameters@@@Z
- ThreadTimer::?Stop@@YAXPAUHWND__@@HPADPAPAU_stack_t@@PAUextra_parameters@@@Z
- dumpstate::debug
- metadl::download
- metadl::download_quiet
- nsMSCM::QueryStatus
- nsMSCM::Start
- nsMSCM::Stop
Only the first two lines are from the ThreadTimer dll, the others came from other plugins that were discovered. But you see the difference in the names.

Don

Indeed, now I looked at that output too.
Thanks a lot!


Originally posted by demiller9
It looks to me like the plugin was compiled with the wrong options, the function names are 'decorated' and shouldn't be. Makensisw shows this when I put the release version dll into my plugins folder:
 - ThreadTimer::?Start@@YAXPAUHWND__@@HPADPAPAU_stack_t@@PAUextra_parameters@@@Z
- ThreadTimer::?Stop@@YAXPAUHWND__@@HPADPAPAU_stack_t@@PAUextra_parameters@@@Z
- dumpstate::debug
- metadl::download
- metadl::download_quiet
- nsMSCM::QueryStatus
- nsMSCM::Start
- nsMSCM::Stop
Only the first two lines are from the ThreadTimer dll, the others came from other plugins that were discovered. But you see the difference in the names.

Don
This is very interesting because I can see functions correctly - they are not decorated and NSIS recognize them correctly.
When I analyse dll in DependencyWalker I can see functions correctly too - as C functions.
Also I attached picture of .def file I made to have correct exports of these functions.

You are using a lot of CRT functions and for that reason you are still linking to it, even though you have disabled the manifest. As you have compiled with VC9 all machines will need .NET 3.5 or standalone MSCRT90 installed, which by no means will always be the case. The installer will crash.

There is no need to use functions such as _beginthreadex and memset and you must not use the new operator. These are all functions/features that use or depend on the CRT. There are Win32 API alternatives such as CreateThread and LocalAlloc/GlobalAlloc (and you do not need to zero the memory if you use the right *Alloc options). Finally your exports are wrong. You are missing extern "C" from your function definitions. Also, if you decorate functions with __declspec(dllexport), you do not need a .def file. If you get your plug-in built without CRT it will be ~4KB rather than 55KB.

Stu


Thanks for all suggestions!
I have removed all CRT calls and in Properties -> Linker -> Input I used "Ignore All default libraries" so plug-in is now only 4kB big, but I got a lot of linker errors which I solved by adding tlibc library from http://www.codeproject.com/KB/library/tlibc.aspx to solution.

New version was uploaded - 1.1 + sources on wiki, enjoy :)