Может только читать / записывать 21 символ в свойство InstallShield из VB.NET

Я использую VB.NET и пользовательское действие из InstallShield для обновления некоторых свойств во время установки.

Все работает, пока я не пытаюсь прочитать или записать более 21 символа в свойство, и в этом случае происходит сбой.

Просто для ясности, если я введу эту строку "123456789112345678921" в свойство через IS, то попробуйте прочитать ее из VB.NET, все работает. Если я добавлю еще один символ и прочту его, он вылетит. Запись похожа - если я пишу (из VB.NET) первая строка выше, она работает. Если я добавлю еще один символ, он потерпит неудачу.

Я подозреваю, что у меня неправильно определены MsiSetProperty и MsiGetProperty:

<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

Вот как я получаю доступ к полям:

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

Есть идеи о том, что происходит?

2 ответа

Решение

Проблема была в том, как я читал собственность. Вы ДОЛЖНЫ заранее выделить место для входящих данных. Очевидно, что без указания пространства в StringBuilder, он выделяет только 21 символ.

Мой оригинальный (плохой) метод чтения был такой:

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

Вот что работает (обратите внимание на предварительное распределение пространства в StringBuilder). Я по умолчанию 256, но вы, вероятно, можете ввести любое значение, которое вы считаете необходимым:

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

Попробуйте использовать DTF вместо импорта DLL. DTF - это Deployment Tools Foundation - богатый набор классов сборок.NET для работы со всеми аспектами установщика Windows и настраиваемых действий. Вы избегаете иметь дело со всеми COM или Win32 clunk и можете писать только с использованием классов.NET.

Я предполагаю, что ваша настоящая проблема связана с технической деталью (возможно, с проблемой размера буфера) в отношении того, как VB.NET импортирует dll-файлы, но я бы не стал тратить на это время, если DTF решит проблему.

Другие вопросы по тегам