This example will not work for me also. Any ideas?Originally Posted by rbchasetfb View Postclaesabrandt, very cool that we got through that one. Thanks for sticking with it too. As a thanks, I thought I would post some code that I use in my .NET dll that CLR.dll is calling. It allows the functions in the .NET dll to update the Details list during the install without have to wait to return to the installer and then do a DetailPrint call with some funky string work. The code is in VB.NET, but could easily be converted to C#. The error handling is a little brute force in the MakeLogEntry function, it just ignores the error and returns, potentially writing nothing to the Details list. Non-the-less, very useful I think.
VB.NET Code Required:
NSIS Code with CLR.dll call to test with:Imports System Imports System.Runtime.InteropServices Imports System.Threading Imports System.IO Imports System.Windows.Forms Namespace NSIS Public Class TestClass //LVITEM Structure Declaration. <StructLayout(LayoutKind.Sequential)> _ Public Structure LVITEM Public mask As Int32 Public iItem As Int32 Public iSubItem As Int32 Public state As Int32 Public stateMask As Int32 Public pszText As String Public cchTextMax As Int32 Public iImage As Int32 Public lParam As IntPtr End Structure //SendMessage API declarations. Public Declare Function SendMessageLV Lib "user32" Alias _ "SendMessageA"(ByVal hwnd As IntPtr, _ ByVal wMsg As Int32, _ ByVal wParam As Integer, _ ByRef lParam As LVITEM) As Integer Public Declare Function SendMessage Lib "user32" Alias _ "SendMessageA"(ByVal hwnd As IntPtr, _ ByVal wMsg As Int32, _ ByVal wParam As Integer, _ ByRef lParam As Integer) As Integer //Constants used by LVITEM and SendMessage Public Const LVM_FIRST as Integer = &H1000 Public Const LVM_GETITEMCOUNT as Integer = LVM_FIRST + 4 Public Const LVM_GETITEM as Integer = LVM_FIRST + 5 Public Const LVM_INSERTITEM as Integer = LVM_FIRST + 7 Public Const LVM_SCROLL as Integer = LVM_FIRST + 20 Public Const LVIF_TEXT as Integer = &H0001 Public Const LVIS_FOCUSED as Integer = &H0001 //Test function for calling from an NSIS installer using CLR.dll Public Function ChopString( _ ByVal hwnd as IntPtr, _ ByVal stringToChop as String, _ ByVal chopToLength as Integer) As String Dim ret as String = "" If stringToChop.Length > chopToLength Then MakeLogEntry(hwnd, "Chopping String '" & stringToChop & "'.") ret = stringToChop.SubString(0,chopToLength) MakeLogEntry(hwnd, "String chopped to '" & ret & "'.") Else MakeLogEntry(hwnd, "String '" & _ stringToChop & _ "' to short to chop to length '" & _ chopToLength & "'.") End If Return ret End Function //Here's the key function that writes to the Details list. Public Sub MakeLogEntry(ByVal hwnd As IntPtr, entry as String) Try //Get current list count Dim c as Integer = SendMessage(hwnd,LVM_GETITEMCOUNT,0,0)+1 //Setup a LVITEM structure for the Insert message Dim lv As New LVITEM lv.iItem = c lv.pszText = entry lv.mask = LVIF_TEXT lv.stateMask = LVIS_FOCUSED lv.state = LVIS_FOCUSED //Insert the LVITEM into the list c = SendMessageLV(hwnd, LVM_INSERTITEM, 0, lv) //Scroll the list so the item is visible SendMessage(hwnd,LVM_SCROLL,0,12) Catch ex As Exception 'Do Nothing, just return End Try End Sub End Class End NameSpace
Lastly, I've attached a zip file of the TestCLRDLL.dll project for VS2005 and included the TESTCLRDLL.nsi as will. Enjoy. I hope it's as useful for use as it is for me.Name "Test CLRDLL MakeLogEntry" OutFile "TestCLRDLL.exe" ShowInstDetails show Var DetailsHWND Page instfiles Section DetailPrint "Starting Test" InitPluginsDir SetOutPath $PLUGINSDIR File "TestCLRDLL.dll" FindWindow $0 "#32770" "" $HWNDPARENT GetDlgItem $DetailsHWND $0 1016 CLR::Call "TestCLRDLL.dll" \ "NSIS.TestClass" \ "ChopString" \ 3 \ $DetailsHWND "Testing Make Log Entry" 9 Pop $0 DetailPrint "ChopString Result = $0" DetailPrint "Test Complete" SectionEnd
Calling managed .NET DLL from NSIS - this works :-)
112 posts
Firstly you don't need to extract plug-in DLL's to use them. NSIS handles that itself. Also, if NSIS says a plug-in call is an invalid command then that means your plug-in DLL isn't in the NSIS Plugins folder.
Stu
Stu
Thank you that worked.Originally Posted by Afrow UK View PostFirstly you don't need to extract plug-in DLL's to use them. NSIS handles that itself. Also, if NSIS says a plug-in call is an invalid command then that means your plug-in DLL isn't in the NSIS Plugins folder.
Stu
I put the CLR.dll in the \Program Files\NSIS\Plugins\ folder. Just like the second sentence of the CLR wiki says to do. Next time I will RTFM
Unicode support
I got stuck for a couple of days when trying to move my installation to a Unicode-based NSIS. All my calls just stopped working. After a vain search for a similar dll, but supporting unicode, I downloaded the original source and upgraded it.
Now this was my first ever experience with c++, so I'm really not sure if I just didn't screw something up, but it worked in a couple of tests I did. I posted the link to the updated code on the Viki page.
I moved all the more or less complex functionality to a .net dll now, because all other means of calling dlls (like System::Call) stopped working in the Unicode release of NSIS.
I got stuck for a couple of days when trying to move my installation to a Unicode-based NSIS. All my calls just stopped working. After a vain search for a similar dll, but supporting unicode, I downloaded the original source and upgraded it.
Now this was my first ever experience with c++, so I'm really not sure if I just didn't screw something up, but it worked in a couple of tests I did. I posted the link to the updated code on the Viki page.
I moved all the more or less complex functionality to a .net dll now, because all other means of calling dlls (like System::Call) stopped working in the Unicode release of NSIS.
Is anyone capable of recompiling this to add 4.0 support? It'll execute 4.0 assemblies, but will fail if you use any 3.5+ features (like simple Linq statements).
Hi Claes,
I have already problems on setting/getting Properties.
It seems that on every call will generated a new object instance of the dll.
Did you already hav fixed this problem? Or have a solution?
Best Regards,
Michael
I have already problems on setting/getting Properties.
namespace testI first call the set_name Property, then the helloworld method. But allways the Propety is empty on the second call.
{
public class test
{
// Properties
private string _Name = "";
public string Name
{
get { return _Name; }
set { _Name = value; }
}
public string helloworld()
{
return "Hello " + Name;
}
}
}
It seems that on every call will generated a new object instance of the dll.
Did you already hav fixed this problem? Or have a solution?
Best Regards,
Michael
To avoid incompatibility issues which can occur with different .NET versions I would put your .NET code into a command-line executable and run it using ExecDos.
Stu
Stu
Hi Stu, thanks for the suggestion.
Well, when i do a simple call it works fine with an exe or the dll as well.
But when i need to do multiple calls, i think i will have a problem with an exe. (ex. i have to do some database related work and in OLEDB-PLUGIN script files are limited to 60k, so i wrote a .net dll )
Best regards
Michael
Well, when i do a simple call it works fine with an exe or the dll as well.
But when i need to do multiple calls, i think i will have a problem with an exe. (ex. i have to do some database related work and in OLEDB-PLUGIN script files are limited to 60k, so i wrote a .net dll )
Best regards
Michael
Plug in doesn't work for me
Hi Claes,
I'm new to NSIS and I'm probably making a lot of beginner's errors...
I tried your plug in and it seems to ignore the /NOUNLOAD setting. When I call my DLL the first time it works, but any time after that I get "object reference not set to an instance of an object" exception. When I try the same DLL with a C# test program it behaves as expected.
Attached is a screenshot of what's happening. I've commented out additional tests as it already fails on the 2nd call. I'll be happy to send you the source code of my DLL.
This DLL is really just a work-around. What I really need is a page like the install log page which shows DetailPrint messages and a progress bar. But I need this page to report findings and progress while I'm scanning the system for installed programs, before the user gets a chance to decide what will be installed and what not. The installer has to handle quite a lot, including external installers for Adobe, Java, Apache, MySQL, some SQL scripts, etc.. So this requires quite a bit of preparation to assess what needs to be installed for a fresh install or for an upgrade of an existing system. Since I can't figure out how to use this page for my purposes I thought that the easiest way would be to create my own in c#. After all it's just a text box and a progress bar.
I would appreciate any advice you can give.
Kind regards, Gilbert
Hi Claes,
I'm new to NSIS and I'm probably making a lot of beginner's errors...
I tried your plug in and it seems to ignore the /NOUNLOAD setting. When I call my DLL the first time it works, but any time after that I get "object reference not set to an instance of an object" exception. When I try the same DLL with a C# test program it behaves as expected.
Attached is a screenshot of what's happening. I've commented out additional tests as it already fails on the 2nd call. I'll be happy to send you the source code of my DLL.
This DLL is really just a work-around. What I really need is a page like the install log page which shows DetailPrint messages and a progress bar. But I need this page to report findings and progress while I'm scanning the system for installed programs, before the user gets a chance to decide what will be installed and what not. The installer has to handle quite a lot, including external installers for Adobe, Java, Apache, MySQL, some SQL scripts, etc.. So this requires quite a bit of preparation to assess what needs to be installed for a fresh install or for an upgrade of an existing system. Since I can't figure out how to use this page for my purposes I thought that the easiest way would be to create my own in c#. After all it's just a text box and a progress bar.
I would appreciate any advice you can give.
Kind regards, Gilbert
You can have more than one InstFiles page. All Sections will be ran for both pages though which means you need to dynamically select/unselect the Sections you want to run before showing the page (i.e. otherwise if you have two InstFiles pages, your Sections will be executed twice). You can use the SelectSection/UnselectSection macros in Sections.nsh for that.
Stu
Stu
Hi all,
I have a little Problem with this issue.
If i have understood the solution correctly, the system.xml.dll must be in the same directory which the Installer.exe. But this isn't working by me.
This is my own dll: (for testing i have only one line)
Here is a Screenshot of the Error MessageBox:
Message in english means: "Exception has been thrown by the target of an invocation."
I hope anybody can help me!
Thanks in advance 🙂
I have a little Problem with this issue.
Another issue is that if want to call a .NET dll from your .NET dll, you will find that the installer cannot find the second .NET dll. For the moment the remedy is to wrap your installer in another installer. This other installer should place the .NET dlls in the same directory as the installer will run from. When the installer runs, the .NET dlls can now be found. There will only be distributed one setup file.I have written a dll in C#, which makes changes on a .config file. In my dll, i use System.xml.dll.
If i have understood the solution correctly, the system.xml.dll must be in the same directory which the Installer.exe. But this isn't working by me.
This is my own dll: (for testing i have only one line)
And here is my call in the NSIS script:public void WriteConfigFile(string path, string datasource, string dbName, string user, string pw)
{
XmlDocument doc = new XmlDocument(); //needs System.xml.dll
}
The NSIS scipt, Installer, WriteConfigFile.dll and System.xml.dll are in the same folder.Section "Test Write" SEC01
SetOutPath $INSTDIR
File "Test Data\InvoiceConfigurator.exe.config"
InitPluginsDir
SetOutPath $PLUGINSDIR
File "WriteConfigFile.dll"
File "system.xml.dll"
CLR::Call /NOUNLOAD "WriteConfigFile.dll" "WriteConfigFile.WriteClass" "WriteConfigFile" 5\
"$INSTDIR\InvoiceConfigurator.exe.config" "test" "test" "testuser" "testpw"
pop $0
MessageBox MB_OK $0
SectionEnd
Here is a Screenshot of the Error MessageBox:
Message in english means: "Exception has been thrown by the target of an invocation."
I hope anybody can help me!
Thanks in advance 🙂
I don't claim to know anything about how .NET libraries are loaded but perhaps the CLR plugin should have a CLR::PreloadLib function that allows you to build a list of libraries that have to be LoadLibrary'd before it makes the actual call inside CLR::Call...
Thank you Anders, unfortunatelly i haven't found anything like that on my Search :/
CLR.DLL compatibility with Windows 2012
Hello,
We have created a installer using NSIS, but on Windows 2012 if we have a feature .net Framwork 3.5 as disabled then installation fails and gives error in temp file "Unable to Load CLR.DLL in installation log file."
is there any dependency for .net framework 3.5, if no please help us to fix this.
Hello,
We have created a installer using NSIS, but on Windows 2012 if we have a feature .net Framwork 3.5 as disabled then installation fails and gives error in temp file "Unable to Load CLR.DLL in installation log file."
is there any dependency for .net framework 3.5, if no please help us to fix this.
If 2.0 is included within 3.5, that would make sense that the plugin fails if .net is disabled since the plugin relies on 2.0.
how can return methods with ref parameter in CLR Plugin?
i use from ref int in method but i cant read return value in NSIS
when i create dll and use the use from this code:
when i pop , get hello in $0
but i cannot return ref int b = "110"
private void button1_Click(object sender, EventArgs e)
{
int gg = 65;
string aa = Two_String_Returner(45, ref gg);
MessageBox.Show(aa);
MessageBox.Show(gg.ToString());
}
public string Two_String_Returner(int a, ref int b)
{
b = a + b;
string Word = "Hello";
return Word;
}
i use from ref int in method but i cant read return value in NSIS
when i create dll and use the use from this code:
CLR::Call "ClassLibrary13.dll" "ClassLibrary13.Class1" "Two_String_Returner" 2 "55" "$2" Pop $0 # return value = exit code CLR::Destroy
but i cannot return ref int b = "110"
I have a problem With The CLR Plugin
i need to call mydll to many times
this Code Create a Folder in Ftp with name MainFolder and inside of that Create Folders Folder1, Folder2 ....
After every run of the loop My application Occupies much more space in memory
also if i use from CLR:😁estroy before Goto STR , application Hangs.
i how can many times use the CLR plugin without Hangs?
i need to call mydll to many times
Var CNTR Section STR: IntOp $CNTR $CNTR + 1 CLR::Call /NOUNLOAD "FTPCityToolkit.dll" "FTPCityToolkit.FTPCityToolkitClass" "FTPMakeDir" 4 "$FTP_Root_Address" "MainFolder/Folder$CNTR" "$FTP_Root_UserName" "$FTP_Root_PassWord" Pop $0 # return value = exit code Goto STR SectionEnd
this Code Create a Folder in Ftp with name MainFolder and inside of that Create Folders Folder1, Folder2 ....
After every run of the loop My application Occupies much more space in memory
also if i use from CLR:😁estroy before Goto STR , application Hangs.
i how can many times use the CLR plugin without Hangs?
CLR Plug-in News
New version of CLR Plug-in released
What's new in version 1.0
New version of CLR Plug-in released
What's new in version 1.0
- Fix bug memory overflow
- If you need to call CLR::Call more than once now this is possible (without hang)
- Removed CLR:😁estroy
CLR Plug-in News
New version of CLR Plug-in released
What's new in version 1.1
New version of CLR Plug-in released
What's new in version 1.1
- Build with Visual Studio 2005 SP1 Professional On Windows 7 SP1 x86
- Solve a problem that does not work on some windows (Change compile settings and use from lower .net framework (net 2.0))
I know this post is quite old, but does this plug-in have an active developer? I have made changes to the plugin for our own usage, and wanted to send those commits back upstream for others. Basically, is there a git repository, or something similar. that would take a code commit?Originally Posted by r2du-soft View PostCLR Plug-in News
New version of CLR Plug-in released
What's new in version 1.1
- Build with Visual Studio 2005 SP1 Professional On Windows 7 SP1 x86
- Solve a problem that does not work on some windows (Change compile settings and use from lower .net framework (net 2.0))
I did find this git repo ( https://github.com/ARLM-Keller/nsis-clr ), but it is for the 0.5 version that is on the wiki page still, and this one seems to be much more refined and because the version number is at 1.1, I am assuming that since this one is higher, it is the one that should be continued.
I noticed what I think was r2du-soft's fork of the CLR 0.5 release
So, I forked, and then did two things:
1. Updated my fork to CLR 1.1
1.1. Dropped r2du-soft's CLR 1.1 zip onto my fork
1.2. Created a pull request for r2du-soft to get his code into his fork
2. Did my needed changes
2.1. Moved to Visual Studio 2019
2.2. Moved to .NET 4.x, because .NET 4.0 released with XP SP3 which is now unsupported by Microsoft, so an assumption of 4.x should be safe now.
2.3. Added a reference to "System.Web.Services" so that assemblies that have "Service Reference" objects can load, I have a .NET 4.7.2 DLL with this situation.
My fork lives here: https://github.com/tbnorris/nsis-clr
So, I forked, and then did two things:
1. Updated my fork to CLR 1.1
1.1. Dropped r2du-soft's CLR 1.1 zip onto my fork
1.2. Created a pull request for r2du-soft to get his code into his fork
2. Did my needed changes
2.1. Moved to Visual Studio 2019
2.2. Moved to .NET 4.x, because .NET 4.0 released with XP SP3 which is now unsupported by Microsoft, so an assumption of 4.x should be safe now.
2.3. Added a reference to "System.Web.Services" so that assemblies that have "Service Reference" objects can load, I have a .NET 4.7.2 DLL with this situation.
My fork lives here: https://github.com/tbnorris/nsis-clr