Can only read/write 21 chars to InstallShield prop

2019-08-10 11:54发布

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?

2条回答
对你真心纯属浪费
2楼-- · 2019-08-10 12:37

Try using DTF instead of the dll imports. DTF is Deployment Tools Foundation - a rich set of .NET assembly classes for dealing with all aspects of Windows Installer and custom actions. You avoid having to deal with all COM or Win32 clunk, and can write using .NET classes only.

I guess your actual problem is related to a technical detail (maybe some buffer size issue) with regards to how VB.NET imports dll files, but I wouldn't spend any time on that if DTF solves the problem.

查看更多
淡お忘
3楼-- · 2019-08-10 12:55

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
查看更多
登录 后发表回答