【问题标题】:Can only read/write 21 chars to InstallShield property from VB.NET只能从 VB.NET 读取/写入 21 个字符到 InstallShield 属性
【发布时间】:2014-08-20 13:39:45
【问题描述】:

我在安装过程中使用 VB.NETInstallShield 中的自定义操作来更新某些属性。

只要我不尝试在属性中读取或写入超过 21 个字符,一切正常,在这种情况下它会崩溃。

为了清楚起见,如果我通过 IS 将这个字符串“123456789112345678921”输入到属性中,然后尝试从 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

有什么想法吗?

【问题讨论】:

    标签: installation windows-installer installshield custom-action dtf


    【解决方案1】:

    尝试使用 DTF 代替 dll 导入。 DTF 是部署工具基础 - 一组丰富的 .NET 程序集类,用于处理 Windows Installer 和自定义操作的所有方面。您不必处理所有 COM 或 Win32 笨拙的问题,并且只能使用 .NET 类进行编写。

    我猜您的实际问题与关于 VB.NET 如何导入 dll 文件的技术细节(可能是一些缓冲区大小问题)有关,但如果 DTF 解决了问题,我不会花任何时间。

    【讨论】:

    • 不错!我不知道DTF。我会尝试并发布结果。
    【解决方案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
    

    【讨论】:

    • 你应该调用一次 MsiGetProperty 并获取 ERROR_MORE_DATA 然后检查 stringSize 需要多少字节。创建一个该大小的字符串,然后再次调用它。或者只使用已经为您完成所有这些工作的 DTF 互操作库。 :)
    猜你喜欢
    • 2014-12-07
    • 2014-07-12
    • 1970-01-01
    • 1970-01-01
    • 2018-08-19
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    • 2011-06-30
    相关资源
    最近更新 更多