65.9K
CodeProject is changing. Read more.
Home

Display device memory information using P/Invoke

starIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIconemptyStarIcon

1.36/5 (4 votes)

Feb 8, 2008

CPOL

1 min read

viewsIcon

27250

downloadIcon

190

P/Invoke with Compact Framework to get the memory status and storage card information.

DeviceMemoryInfo/devicememorystate.jpg

Introduction

I saw in the last few weeks in MSDN forums and CodeProject forums a few guys asking how to get the memory status, storage card capacity, and etc… This article has a static class that you can directly use with your project very easily.

Background

In the class, there are five properties:

  • HasStorageCardPresent - This indicates a storage card is presently installed.
  • FreeBytesAvailable - This gives the long bytes for the free space in the device directory.
  • TotalBytes – This gives the total bytes in the device memory.
  • TotalFreeBytes – This gives the total free space in the device memory.
  • DirectoryName - This specifies which directory capacity you want when you want to set the directory name; if it doesn’t set this, the windows directory is the default.

Using the code

The class name is DeviceMemoryInfo. Basically, this class represents the above properties. These values are take using a P/Invoke method used within the class.

[DllImport("coredll",SetLastError=true)] 
private static extern bool GetDiskFreeSpaceEx(string directoryName, 
        ref long freeBytesAvailable, ref long totalBytes, ref long totalFreeBytes);

The above method is not directly available in the Compact Framework, so we use the P/Invoke technique and call our manager code. See the code below:

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;
    }
}

In this method, I use a struct (DiskFreeSpace) to pass the P/Invoke method.

Here is the struct:

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; 
}

A clear explanation of all native structs for device APIs is available in MSDN.

Here is the full implementation for the DeviceMemoryInfo class:

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; 
        } 
    } 
}

Cons

I hope the above class will sort out a lot of doubts. If you find anything wrong here, please indicate it in the forum below.

History

  • First version - 08:02:2008.