5

How can I determine if a remote drive has enough space for me to upload a given file using C# in .Net?

MrDatabase
  • 43,245
  • 41
  • 111
  • 153
  • What type of remote drive: network drive, website, etc.? – Brettski Sep 26 '08 at 01:33
  • Keep in mind, even when you can determine this, it's only accurate for a single moment in time - your upload can still fail if other users / processes are writing to the drive. – Shog9 Sep 26 '08 at 01:54

4 Answers4

10

There are two possible solutions.

  1. Call the Win32 function GetDiskFreeSpaceEx. Here is a sample program:

    internal static class Win32
    {
        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        internal static extern bool GetDiskFreeSpaceEx(string drive, out long freeBytesForUser, out long totalBytes, out long freeBytes);
    
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            long freeBytesForUser;
            long totalBytes;
            long freeBytes;
    
            if (Win32.GetDiskFreeSpaceEx(@"\\prime\cargohold", out freeBytesForUser, out totalBytes, out freeBytes)) {
                Console.WriteLine(freeBytesForUser);
                Console.WriteLine(totalBytes);
                Console.WriteLine(freeBytes);
            }
        }
    }
    
  2. Use the system management interface. There is another answer in this post which describes this. This method is really designed for use in scripting languages such as PowerShell. It performs a lot of fluff just to get the right object. Ultimately, I suspect, this method boils down to calling GetDiskFreeSpaceEx.

Anybody doing any serious Windows development in C# will probably end up calling many Win32 functions. The .NET framework just doesn't cover 100% of the Win32 API. Any large program will quickly uncover gaps in the .NET libraries that are only available through the Win32 API. I would get hold of one of the Win32 wrappers for .NET and include this in your project. This will give you instant access to just about every Win32 API.

Mike Thompson
  • 6,708
  • 3
  • 32
  • 39
  • Does GetDiskFreeSpaceEx work with network shares? What about authentication? – FlySwat Sep 26 '08 at 02:04
  • Code is incorrect. You have to use `ulong` instead of `long`. – Liviu Mandras Jan 03 '11 at 15:20
  • Technically, yes, the code is incorrect, although it compiles since the DllImport uses longs instead of ulongs. It will only start failing when a disk is larger than 2^63 bytes. A 1TB disk is about 2^40 bytes. We have to get past petabyte drives to exabyte drives before it fails. – Mike Thompson Jan 12 '11 at 03:48
5

Use WMI

using System.Management;

// Get all the network drives (drivetype=4)
SelectQuery query = new SelectQuery("select Name, VolumeName, FreeSpace from win32_logicaldisk where drivetype=4");
ManagementObjectSearcher searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject drive in searcher.Get())
{
    string Name = (string)drive["Name"];
    string VolumeName = (string)drive["VolumeName"];
    UInt64 freeSpace = (UInt64)drive["FreeSpace"];
}

based on (stolen from) http://www.dreamincode.net/code/snippet1576.htm

s d
  • 2,666
  • 4
  • 26
  • 42
2

Are you talking about mapping a network share to a logical drive on you computer?

If so you can use DriveInfo.

    DriveInfo info = new DriveInfo("X:");

    info.AvailableFreeSpace;

DriveInfo only works with logical drives so if you are just using the full share (UNC) name I don't think the above code will work.

Kepboy
  • 3,733
  • 2
  • 30
  • 43
2

I'm not sure if GetDiskFreeSpaceEx works on UNC shares, but if it does use that, otherwise here is how to mount a UNC share to a logal drive:

EDIT GetDiskFreeSpaceEx does work on UNC shares, use that...however, this code was too much effort to just delete, and is handy if you ever want to mount a UNC share as a local drive in your code.

public class DriveWrapper
{                    
    [StructLayout(LayoutKind.Sequential)]
    public struct NETRESOURCEA
    {
        public int dwScope;
        public int dwType;
        public int dwDisplayType;
        public int dwUsage;
        [MarshalAs(UnmanagedType.LPStr)]
        public string lpLocalName;
        [MarshalAs(UnmanagedType.LPStr)]
        public string lpRemoteName;
        [MarshalAs(UnmanagedType.LPStr)]
        public string lpComment;
        [MarshalAs(UnmanagedType.LPStr)]
        public string lpProvider;
        public override String ToString()
        {
            String str = "LocalName: " + lpLocalName + " RemoteName: " + lpRemoteName
                  + " Comment: " + lpComment + " lpProvider: " + lpProvider;
            return (str);
        }
    }

    [DllImport("mpr.dll")]
    public static extern int WNetAddConnection2A(
          [MarshalAs(UnmanagedType.LPArray)] NETRESOURCEA[] lpNetResource,
          [MarshalAs(UnmanagedType.LPStr)] string lpPassword,
          [MarshalAs(UnmanagedType.LPStr)] string UserName,
          int dwFlags);       
    [DllImport("mpr.dll", CharSet = System.Runtime.InteropServices.CharSet.Auto)]
    private static extern int WNetCancelConnection2A(
          [MarshalAs(UnmanagedType.LPStr)]
        string lpName,
          int dwFlags,
          int fForce
          );

    public int GetDriveSpace(string shareName, string userName, string password)
    {
        NETRESOURCEA[] n = new NETRESOURCEA[1];
        n[0] = new NETRESOURCEA();

        n[0].dwScope = 0;
        n[0].dwType = 0;
        n[0].dwDisplayType = 0;
        n[0].dwUsage = 0;

        n[0].dwType = 1;

        n[0].lpLocalName = "x:";
        n[0].lpRemoteName = shareName;
        n[0].lpProvider = null;

        int res = WNetAddConnection2A(n, userName, password, 1);

        DriveInfo info = new DriveInfo("x:");
        int space = info.AvailableFreeSpace;

        int err = 0;
        err = WNetCancelConnection2A("x:", 0, 1);

        return space;
    }
}
FlySwat
  • 172,459
  • 74
  • 246
  • 311