DetailPrint From Inside .NET DLL: Difference between revisions
Rbchasetfb (talk | contribs) (Performing a DetailPrint From Inside .NET DLL method.) |
(→Description: Idiots don't know the difference between "your" and "you're" *sigh*) |
||
(5 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
{{PageAuthor| | {{PageAuthor|rbchasetfb}} | ||
== Description == | == Description == | ||
If | If you're using the [[Call .NET DLL methods plug-in]] to call .NET DLL functions to perform work during an install, one of the things that will be useful is to be able to update the Details list in the installer, from the DLL, while a .NET DLL function call is executing. Below is some VB.NET code, easily converted to C# at [http://labs.developerfusion.co.uk/convert/vb-to-csharp.aspx DEVELOPERfusion], that provides a method '''DetailPrint''' that adds an ''entry'' to the end of the Details list. | ||
The VB.NET source code is for a complete namespace and class and includes an example function '''ChopString''' to test with. You'll also find an NSIS test script. Lastly, a zip file is attached with the complete Visual Studio 2005 project for the test .NET DLL and the NSIS test script. Also included in the zip is ''ListViewDeclarations.vb'' that has all the declarations necessary for working with List-view controls from VB.NET. This file also has the '''DetailPrint''' method...all this is contained in a VB.NET <font style="color:blue">#Region</font> you can drop in your .NET DLL. | |||
== VB.NET Source Code == | == VB.NET Source Code == | ||
Line 86: | Line 86: | ||
End NameSpace | End NameSpace | ||
</highlight-vbnet> | </highlight-vbnet> | ||
== DetailPrint C# Source Code == | |||
This code uses C# 3.0 object initializers, which for earlier versions of C# should be changed to standard property initializations. | |||
<highlight-csharp> | |||
public static class NSIS | |||
{ | |||
private const int LVIF_TEXT = 0x1; | |||
private const int LVIS_FOCUSED = 0x1; | |||
private const int LVM_FIRST = 0x1000; | |||
private const int LVM_GETITEMCOUNT = LVM_FIRST + 4; | |||
private const int LVM_INSERTITEM = LVM_FIRST + 7; | |||
private const int LVM_SCROLL = LVM_FIRST + 20; | |||
[DllImport("user32.dll")] | |||
private static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam); | |||
[DllImport("user32.dll")] | |||
private static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, ref LVITEM lParam); | |||
public static void DetailPrint(IntPtr hWndDetail, string entry) | |||
{ | |||
try | |||
{ | |||
int c = SendMessage(hWndDetail, LVM_GETITEMCOUNT, 0, 0) + 1; | |||
var lvitem = new LVITEM | |||
{ | |||
iItem = c, | |||
pszText = entry, | |||
mask = LVIF_TEXT, | |||
stateMask = LVIS_FOCUSED, | |||
state = LVIS_FOCUSED | |||
}; | |||
SendMessage(hWndDetail, LVM_INSERTITEM, 0, ref lvitem); | |||
SendMessage(hWndDetail, LVM_SCROLL, 0, 12); | |||
} | |||
catch | |||
{ | |||
} | |||
} | |||
#region Nested type: LVITEM | |||
[StructLayout(LayoutKind.Sequential)] | |||
public struct LVITEM | |||
{ | |||
public int mask; | |||
public int iItem; | |||
public int iSubItem; | |||
public int state; | |||
public int stateMask; | |||
public string pszText; | |||
public int cchTextMax; | |||
public int iImage; | |||
public IntPtr lParam; | |||
} | |||
#endregion | |||
} | |||
</highlight-csharp> | |||
== NSIS Test Script == | == NSIS Test Script == | ||
Line 127: | Line 189: | ||
== Prerequisites == | == Prerequisites == | ||
You'll need to have the CLR.dll in your NSIS plugins directory. You can get it from the [[Call .NET DLL methods plug-in]] page or here <attach>CLR.zip</attach>. | You'll need to have the CLR.dll in your NSIS plugins directory. You can get it from the [[Call .NET DLL methods plug-in]] page or here <attach>CLR.zip</attach> ''(As Is)''. | ||
== Download == | == Download == | ||
Here's the latest version of this little package including the Visual Studio 2005 project, NSIS Test Script and ''ListViewDeclarations.vb'' file. <attach>TestCLRDLL.zip</attach> | Here's the latest version of this little package including the Visual Studio 2005 project, NSIS Test Script and ''ListViewDeclarations.vb'' file. <attach>TestCLRDLL.zip</attach> ''(As Is)'' | ||
== Acknowledgements == | == Acknowledgements == | ||
Line 138: | Line 200: | ||
• 1.0 First release. | • 1.0 First release. | ||
[http://forums.winamp.com/showthread.php?postid=2403963#post2403963 NSIS Forum Thread] | |||
[[Category:Code Examples]] | [[Category:Code Examples]] |
Latest revision as of 03:44, 22 September 2009
Author: rbchasetfb (talk, contrib) |
Description
If you're using the Call .NET DLL methods plug-in to call .NET DLL functions to perform work during an install, one of the things that will be useful is to be able to update the Details list in the installer, from the DLL, while a .NET DLL function call is executing. Below is some VB.NET code, easily converted to C# at DEVELOPERfusion, that provides a method DetailPrint that adds an entry to the end of the Details list.
The VB.NET source code is for a complete namespace and class and includes an example function ChopString to test with. You'll also find an NSIS test script. Lastly, a zip file is attached with the complete Visual Studio 2005 project for the test .NET DLL and the NSIS test script. Also included in the zip is ListViewDeclarations.vb that has all the declarations necessary for working with List-view controls from VB.NET. This file also has the DetailPrint method...all this is contained in a VB.NET #Region you can drop in your .NET DLL.
VB.NET Source Code
Imports System Imports System.Runtime.InteropServices Namespace NSIS Public Class TestClass 'The LVITEM stucture specifies or receives the attributes of a list-view item. <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. Two different declarations to manage two lparam types. 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 'Here's the key function that writes to the Details list. Public Sub DetailPrint(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, no sense throwing an error just for logging. End Try End Sub '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 DetailPrint(hwnd, "FROM DLL: Chopping String '" & stringToChop & "'") ret = stringToChop.SubString(0,chopToLength) DetailPrint(hwnd, "FROM DLL: String chopped to '" & ret & "'") Else DetailPrint(hwnd, "FROM DLL: String '" & stringToChop & _ "' insufficient length to chop to " & chopToLength & " characters") ret = "error" End If Return ret End Function End Class End NameSpace
DetailPrint C# Source Code
This code uses C# 3.0 object initializers, which for earlier versions of C# should be changed to standard property initializations.
public static class NSIS { private const int LVIF_TEXT = 0x1; private const int LVIS_FOCUSED = 0x1; private const int LVM_FIRST = 0x1000; private const int LVM_GETITEMCOUNT = LVM_FIRST + 4; private const int LVM_INSERTITEM = LVM_FIRST + 7; private const int LVM_SCROLL = LVM_FIRST + 20; [DllImport("user32.dll")] private static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, int lParam); [DllImport("user32.dll")] private static extern int SendMessage(IntPtr hWnd, uint Msg, int wParam, ref LVITEM lParam); public static void DetailPrint(IntPtr hWndDetail, string entry) { try { int c = SendMessage(hWndDetail, LVM_GETITEMCOUNT, 0, 0) + 1; var lvitem = new LVITEM { iItem = c, pszText = entry, mask = LVIF_TEXT, stateMask = LVIS_FOCUSED, state = LVIS_FOCUSED }; SendMessage(hWndDetail, LVM_INSERTITEM, 0, ref lvitem); SendMessage(hWndDetail, LVM_SCROLL, 0, 12); } catch { } } #region Nested type: LVITEM [StructLayout(LayoutKind.Sequential)] public struct LVITEM { public int mask; public int iItem; public int iSubItem; public int state; public int stateMask; public string pszText; public int cchTextMax; public int iImage; public IntPtr lParam; } #endregion }
NSIS Test Script
Name "Test CLRDLL MakeLogEntry" OutFile "TestCLRDLL.exe" ShowInstDetails show Var DetailsHWND Page instfiles Function .onGUIEnd CLR::Destroy FunctionEnd Section InitPluginsDir SetOutPath $PLUGINSDIR File "TestCLRDLL.dll" DetailPrint "====================================" FindWindow $0 "#32770" "" $HWNDPARENT GetDlgItem $DetailsHWND $0 1016 CLR::Call /NOUNLOAD "TestCLRDLL.dll" \ "NSIS.TestClass" \ "ChopString" \ 3 \ $DetailsHWND "Testing Make Log Entry" 9 Pop $0 DetailPrint "ChopString Result = $0" DetailPrint "====================================" DetailPrint "Chopping a short string to gen error" CLR::Call /NOUNLOAD "TestCLRDLL.dll" \ "NSIS.TestClass" \ "ChopString" \ 3 \ $DetailsHWND "Testing" 9 Pop $0 DetailPrint "ChopString Result = $0" SectionEnd
Prerequisites
You'll need to have the CLR.dll in your NSIS plugins directory. You can get it from the Call .NET DLL methods plug-in page or here CLR.zip (35 KB) (As Is).
Download
Here's the latest version of this little package including the Visual Studio 2005 project, NSIS Test Script and ListViewDeclarations.vb file. TestCLRDLL.zip (77 KB) (As Is)
Acknowledgements
Many thanks to claesabrandt (the creator of Call .NET DLL methods plug-in) for the back-and-forth on getting the CLR.dll working smoothly without the need for anything other than .NET 2.0 Framework. That was some great team-work! This tool is awesome and is helping make a potentially ugly install a lot smoother.
Version History
• 1.0 First release.