vb.net - 调用类与结构时抛出错误

标签 vb.net winapi structure

有人可以解释一下为什么会这样吗:

 <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
    Public Class MEMORYSTATUSEX

         Public Sub New()
            Me.dwLength = CType(Marshal.SizeOf(GetType(MEMORYSTATUSEX)), UInt32)
        End Sub

        Public dwLength As UInt32

        Public dwMemoryLoad As UInt32

        Public ullTotalPhys As UInt64

        Public ullAvailPhys As UInt64

        Public ullTotalPageFile As UInt64

        Public ullAvailPageFile As UInt64

        Public ullTotalVirtual As UInt64

        Public ullAvailVirtual As UInt64

        Public ullAvailExtendedVirtual As UInt64
    End Class

这不会:

 <StructLayout(LayoutKind.Sequential, CharSet:=CharSet.Auto)> _
    Structure MEMORYSTATUSEX

        Public Sub New(ByVal dwlength As UInt32)
            Me.dwLength = dwlength
        End Sub

        Public dwLength As UInt32

        Public dwMemoryLoad As UInt32

        Public ullTotalPhys As UInt64

        Public ullAvailPhys As UInt64

        Public ullAvailPageFile As UInt64

        Public ullTotalVirtual As UInt64

        Public ullAvailVirtual As UInt64

        Public ullAvailExtendedVirtual As UInt64
    End Structure

当从另一个类调用两个结构/类时,如下所示:

 Dim newpoint As New Structures.MEMORYSTATUSEX()

        GlobalMemoryStatusEx(newpoint) 

第二个:

 Dim newpoint As New Structures.MEMORYSTATUSEX(CType(Marshal.SizeOf(GetType(Structures.MEMORYSTATUSEX)), UInt32))

            GlobalMemoryStatusEx(newpoint) 

它们都在一个类中,当我使用大小参数调用第二个类时,它会在 GlobalMemoryStatusEx(newpoint) 调用上抛出“第一次机会出现 AccessViolationException”并使应用程序崩溃。

我不明白为什么 dwLength 值是在构造函数中初始化的?我说得对吗?

我想更改第一个示例的原因是因为我将所有结构移动到仅结构类,并且认为这将是一个好主意,直​​到我无法理解为什么这不起作用,因为在调用 API 之前设置相同的值。

P/调用声明:

    <DllImport("kernel32.dll", SetLastError:=True)> _
    Private Shared Function GlobalMemoryStatusEx(lpBuffer As Structures.MEMORYSTATUSEX) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function

错误详细信息:

Client.exe 中第一次出现“System.AccessViolationException”类型的异常

其他信息:尝试读取或写入 protected 内存...

如果我点击继续:

mscorlib.dll 中发生了“System.Reflection.TargetInitationException”类型的第一次机会异常

附加信息:调用目标已引发异常

最佳答案

  Private Shared Function GlobalMemoryStatusEx(lpBuffer As Structures.MEMORYSTATUSEX) ...

lpBuffer参数是一个指针。必需的,以便函数可以写入结构成员。指针在 VB.NET 中隐藏得很好,如果使用不当,它们就会把程序炸成碎片。可能发生的事故有很多,AccessViolationException 是较温和的一种。

在 VB.NET 中获取指针的两种基本方法。您可以声明一个参数 ByRef如果参数是值类型。或者,如果它是引用类型(Class 关键字),则引用在运行时自动变为指针,并且应传递 ByVal .

因此,有效的组合是通过 ByRef 传递的结构或通过 ByVal 传递的类。类还需要显式 <StructLayout>强制 CLR 以可预测的方式对其字段进行排序。您可以通过结构免费获得它。因此这是合乎逻辑的选择。

您应该使用 My.Computer.Info,它已经为您 pinvokes GlobalMemoryStatusEx()。

关于vb.net - 调用类与结构时抛出错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24456975/

相关文章:

.net - ConcurrentQueue(Of T) VS List(Of T) 在多线程应用程序中使用 Synclock 语句

C编程。指向结构的指针

interop - GetPhysicalMonitorsFromHMONITOR 返回的句柄始终为空

asp.net - 移动网络开发?

arrays - 调整图像大小并放置在 CrystalReports BlobField 的字节数组中

c++ - 如何获取驱动器号和装载路径 - MSDN

c++ - 获取 .exe 模块导入表序号并查找导入模块函数名称?

java - 如何检查是否有默认打印机 (Windows)?

c++ - 取消引用结构 union 的结构

asp.net - 调试时无法对 ASP.NET 代码进行更改