installationwindows-installerinstallshieldcustom-actiondtf

Can only read/write 21 chars to InstallShield property from VB.NET


I'm using VB.NET and a custom action from within InstallShield to update some properties during an install.

Everything works as long as I don't try to read or write more than 21 characters into the property, in which case it crashes.

Just to be clear, if I enter this string "123456789112345678921" into the property via IS, then try to read it from VB.NET, everything works. If I add another char and read that, it crashes. Writing is similar - if I write (from VB.NET) the first string above it works. If I add another char it fails.

My suspicion is that I have the MsiSetProperty and MsiGetProperty defined incorrectly:

<DllImport(MSI_LIB, EntryPoint:="MsiSetProperty", CharSet:=CharSet.Auto)> _
Public Shared Function MsiSetProperty(hInstall As IntPtr, name As String, value As String) As UInteger
End Function
<DllImport(MSI_LIB, EntryPoint:="MsiGetProperty", CharSet:=CharSet.Auto)> _
Private Shared Function MsiGetProperty_Core(hInstall As IntPtr, szName As String, <Out> szValueBuf As StringBuilder, ByRef pchValueBuf As Integer) As Integer
End Function
Public Shared Function MSIGetProperty(hMSI As IntPtr, PropertyName As String) As String
 Try
  Dim MSIProp As New StringBuilder()
  Dim stringSize As Integer = 256
  Dim value As Integer = MsiGetProperty_Core(hMSI, PropertyName, MSIProp, stringSize)
  Return MSIProp.ToString()
 Catch
  Return "-1"
 End Try
End Function

This is how i'm accessing the fields:

Public Property ReportServerURL As String
  Get
    Return MSIFunctions.MSIGetProperty(_msiHandle, "REPORTSERVERURL")
   End Get
   Set(value As String)
    MSIFunctions.MsiSetProperty(_msiHandle, "REPORTSERVERURL", value)
   End Set
End Property

Any ideas on what's going on?


Solution

  • Problem was with how I was reading the property. You MUST preallocate space for the incoming data. Apparently without specifying space in StringBuilder, it only allocates enough for 21 chars.

    My original (bad) method for reading was this:

    Public Shared Function MSIGetProperty(hMSI As IntPtr, PropertyName As String) As String
        Try
            Dim MSIProp As New StringBuilder()
            Dim stringSize As Integer = 256
            Dim value As Integer = MsiGetProperty_Core(hMSI, PropertyName, MSIProp, stringSize)
            Return MSIProp.ToString()
        Catch
            Return "-1"
        End Try
    End Function
    

    The one that works is this (note the preallocation of space in StringBuilder). I default to 256, but you can probably put in any value you think necessary:

    Public Shared Function MSIGetProperty(hMSI As IntPtr, PropertyName As String) As String
        Try
            Dim stringSize As Integer = 256
            Dim MSIProp As New StringBuilder(stringSize) 'MUST pre-allocate storage
            Dim value As Integer = MsiGetProperty_Core(hMSI, PropertyName, MSIProp, stringSize)
            Return MSIProp.ToString()
        Catch
            Return "-1"
        End Try
    End Function