使用 P/Invoke 显示设备内存信息
使用 P/Invoke 和 Compact Framework 获取内存状态和存储卡信息。
引言
过去几周,我在 MSDN 论坛和 CodeProject 论坛上看到一些人询问如何获取内存状态、存储卡容量等。本文提供了一个静态类,您可以非常容易地将其直接用于您的项目中。
背景
在该类中,有五个属性:
HasStorageCardPresent
- 指示是否已安装存储卡。FreeBytesAvailable
- 提供设备目录中可用空闲字节数。TotalBytes
– 提供设备内存中的总字节数。TotalFreeBytes
– 提供设备内存中的总空闲空间。-
DirectoryName
- 指定您希望获取哪个目录的容量;如果未设置此项,则 Windows 目录为默认目录。
使用代码
类名为 DeviceMemoryInfo
。基本上,该类表示上述属性。这些值是通过类中使用的 P/Invoke 方法获取的。
[DllImport("coredll",SetLastError=true)]
private static extern bool GetDiskFreeSpaceEx(string directoryName,
ref long freeBytesAvailable, ref long totalBytes, ref long totalFreeBytes);
上述方法在 Compact Framework 中不可直接使用,因此我们使用 P/Invoke 技术并调用我们的管理器代码。请参阅下面的代码
private static void GetStoreageSize()
{
DiskFreeSpace result = new DiskFreeSpace();
if(string.IsNullOrEmpty(directoryName))
{
directoryName = @"\Windows";
}
if(!GetDiskFreeSpaceEx(directoryName, ref result.FreeBytesAvailable,
ref result.TotalBytes, ref result.TotalFreeBytes))
{
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error(),
"Error retrieving free disk space");
}
else
{
freeBytesAvailable = result.FreeBytesAvailable;
totalBytes = result.TotalBytes;
totalFreeBytes = result.TotalFreeBytes;
}
}
在此方法中,我使用一个结构体 (DiskFreeSpace
) 来传递给 P/Invoke 方法。
这是该结构体:
private struct DiskFreeSpace
{
/// <summary>
/// The total number of free bytes on the disk that are
/// available to the user associated with the calling thread.
/// </summary>
public long FreeBytesAvailable;
/// <summary>
/// The total number of bytes on the disk that are available
/// to the user associated with the calling thread.
/// </summary>
public long TotalBytes;
/// <summary>
/// The total number of free bytes on the disk.
/// </summary>
public long TotalFreeBytes;
}
MSDN 中提供了设备 API 所有原生结构体的清晰解释。
这是 DeviceMemoryInfo
类的完整实现:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Runtime.InteropServices;
namespace GetStorageCard
{
public class DeviceMemoryInfo
{
public static bool HasStorageCardPresent
{
get
{
return DeviceMemoryInfo.IsStorageCard();
}
}
private static long freeBytesAvailable = 0;
public static long FreeBytesAvailable
{
get
{
DeviceMemoryInfo.GetStoreageSize();
return freeBytesAvailable;
}
}
private static long totalBytes = 0;
public static long TotalBytes
{
get
{
DeviceMemoryInfo.GetStoreageSize();
return totalBytes;
}
}
private static long totalFreeBytes = 0;
public static long TotalFreeBytes
{
get
{
DeviceMemoryInfo.GetStoreageSize();
return totalFreeBytes;
}
}
static string directoryName = string.Empty;
/// <summary>
/// Set directory Name before get Memory status, default is windows directory
/// </summary>
public static string DirectoryName
{
get
{
return directoryName;
}
set
{
directoryName = value;
}
}
[DllImport("coredll",SetLastError=true)]
private static extern bool GetDiskFreeSpaceEx(string directoryName,
ref long freeBytesAvailable, ref long totalBytes, ref long totalFreeBytes);
private static void GetStoreageSize()
{
DiskFreeSpace result = new DiskFreeSpace();
if(string.IsNullOrEmpty(directoryName))
{
directoryName = @"\Windows";
}
if(!GetDiskFreeSpaceEx(directoryName, ref result.FreeBytesAvailable,
ref result.TotalBytes,ref result.TotalFreeBytes))
{
throw new System.ComponentModel.Win32Exception(Marshal.GetLastWin32Error(),
"Error retrieving free disk space");
}
else
{
freeBytesAvailable = result.FreeBytesAvailable;
totalBytes = result.TotalBytes;
totalFreeBytes = result.TotalFreeBytes;
}
}
private struct DiskFreeSpace
{
/// <summary>
/// The total number of free bytes on the disk that are
/// available to the user associated with the calling thread.
/// </summary>
public long FreeBytesAvailable;
/// <summary>
/// The total number of bytes on the disk that are available
/// to the user associated with the calling thread.
/// </summary>
public long TotalBytes;
/// <summary>
/// The total number of free bytes on the disk.
/// </summary>
public long TotalFreeBytes;
}
private static bool IsStorageCard()
{
bool hasStorageCard = false;
DirectoryInfo storeageCard = new DirectoryInfo(@"\");
foreach (DirectoryInfo directory in storeageCard.GetDirectories())
{
if (directory.Attributes ==
(FileAttributes.Temporary |FileAttributes.Directory))
{
hasStorageCard = true;
break;
}
else
{
hasStorageCard = false;
}
}
return hasStorageCard;
}
}
}
缺点
我希望上述类能够解决很多疑问。如果您发现此处有任何错误,请在下面的论坛中指出。
历史
- 第一个版本 - 2008 年 08 月 02 日。