Может только читать / записывать 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 решит проблему.