【问题标题】:Unbalanced stack error when using GetDiskFreeSpaceExA使用 GetDiskFreeSpaceExA 时出现不平衡堆栈错误
【发布时间】:2011-04-27 09:19:00
【问题描述】:

以下代码(调用 proc DiskFreeSpace)会引发“堆栈不平衡”错误消息。

Private Declare Function GetDiskFreeSpaceEx Lib "kernel32" Alias "GetDiskFreeSpaceExA" (ByVal lpDirectoryName As String, _
                ByVal lpFreeBytesAvailableToCaller As Long, _
                ByVal lpTotalNumberOfBytes As Long, _
                ByVal lpTotalNumberOfFreeBytes As Long) As Long

Friend Shared Function DiskFreeSpace(ByVal sdirDrive As String) As Long
            Dim Status As Long
            Dim TotalBytes As Long
            Dim FreeBytes As Long
            Dim BytesAvailableToCaller As Long

            Status = GetDiskFreeSpaceEx(sdirDrive, BytesAvailableToCaller, TotalBytes, FreeBytes)

            Return FreeBytes

        End Function

这里有什么问题?

确切的错误信息是:

调用 PInvoke 函数 '测试!XYZ.Test.FN.MyFileSystem::GetDiskFreeSpaceEx' 使堆栈不平衡。这是 可能是因为托管的 PInvoke 签名与非托管的不匹配 目标签名。检查 调用约定和参数 PInvoke 签名匹配目标 非托管签名。

附加说明:我的函数确实需要也适用于 UNC 路径(本地和/或网络)。

【问题讨论】:

  • 这段代码甚至不应该编译!开启Option Strict!
  • @Konrad:我同意,但我总是将 Option Strict 设置为 On!它编译没有任何错误。
  • 我的错。我没有看到 WinAPI 函数声明中的第一个参数,并假设第一个参数的类型是Long。而且由于您将sdirDrive 作为第一个参数传递,因此无法正常工作。

标签: c# vb.net


【解决方案1】:

我认为您的签名有问题。尝试使用这个(from pinvoke):

<DllImport("Kernel32.dll", EntryPoint:="GetDiskFreeSpaceEx", SetLastError:=True, CharSet:=CharSet.Auto)> _
  Private Shared Function GetDiskFreeSpaceEx( _
   ByVal lpDirectoryName As String, _
   ByRef lpFreeBytesAvailable As ULong, _
   ByRef lpTotalNumberOfBytes As ULong, _
   ByRef lpTotalNumberOfFreeBytes As ULong) As Boolean
  End Function

返回值的不同

【讨论】:

  • 这个函数应该和UNC一起工作。导出函数的 DLL 名称有错误,但我已修复此问题。
  • 这会引发异常:“无法加载 DLL 'coredll.dll':找不到指定的模块。(来自 HRESULT 的异常:0x8007007E)”。我使用的是 Win7/64。
  • 是的,现在可以了 :)。你能解释一下为什么我的方法不起作用(使用“声明函数”而不是“DLLImport”属性)吗?我已经对这个可行的解决方案感到满意,但只是想知道;)。
  • @Marc:我认为您的方法不起作用是因为返回值而不是因为声明。在您之前的版本中,返回值为Long(.NET 上为 64 位),实际上它是作为整数(32 位)传递的。并且 Diring marshaling Pinvoke 总是试图从堆栈中读取 Long 值。所以在你的情况下 pinvoke 必须从堆栈中读取额外的 32 位数据,这是错误的原因
【解决方案2】:

我不太确定此代码,但您也可以使用代码My.Computer.FileSystem.Drives 并找出可用空间、已用空间和总空间。我觉得使用 .NET 内置函数比尝试使用来自 Windows DLL 的调用更容易,因为毕竟 .NET 应用程序只能在 .NET 版本相同或更高版本的计算机上运行应用程序已构建!

干杯

【讨论】:

  • 感谢您的回答,但这仅适用于本地驱动器 afaik;不适用于 UNC 路径。我宁愿避免直接使用 WinAPI,但在这种情况下,我似乎别无选择。
  • 是的!我明白!谢谢你让我知道干杯! :D
猜你喜欢
  • 1970-01-01
  • 2011-04-29
  • 2016-10-15
  • 2016-05-06
  • 1970-01-01
  • 1970-01-01
  • 2011-05-22
  • 1970-01-01
  • 2014-01-10
相关资源
最近更新 更多