Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.Net Core Find Free Disk Space on Different OS

Is there a way to find free space on different OS (Mostly Linux & Windows) using C# ASP.NET Core.

I found a way (using DriveInfo) to get free space by passing the Drive Name as a parameter. This is working fine on Windows, but I want the same for Linux as well.

public static int CheckDiskSpace(string driveLetter)
{
    DriveInfo drive = new DriveInfo(driveLetter);

    var totalBytes = drive.TotalSize;
    var freeBytes = drive.AvailableFreeSpace;

    var freePercent = (int)((100 * freeBytes) / totalBytes);

    return freePercent;
}

Passing the Drive (C:/) as below:

var freespace = DriveDetails.CheckDiskSpace("C:/");

Update: This also works for Linux.

like image 703
Dot Net Dev Avatar asked Jul 17 '18 21:07

Dot Net Dev


2 Answers

For Net.Core under Linux you can just call

var freeBytes = new DriveInfo(path).AvailableFreeSpace; 

where path is some relative or absolute folder name, and it automatically provides you with drive information about the partition that stores this path. Tested on Net.Core 2.2.

As a contrast, in Windows you either:

A) Need to provide the drive letter (which unfortunately cannot be derived directly from relative path, so you need to do some additional work, and cannot be computed for UNC path at all).

B) Need to use Windows API (this works also with UNC paths):

[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetDiskFreeSpaceEx(string lpDirectoryName,
    out ulong lpFreeBytesAvailable,
    out ulong lpTotalNumberOfBytes,
    out ulong lpTotalNumberOfFreeBytes);

GetDiskFreeSpaceEx(path, out var freeBytes, out var _, out var __);

There are also some other exceptional cases so in the end my usage looks like following:

#if DEBUG        
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetDiskFreeSpaceEx(string lpDirectoryName,
    out long lpFreeBytesAvailable,
    out long lpTotalNumberOfBytes,
    out long lpTotalNumberOfFreeBytes);
#endif

public long? CheckDiskSpace()
{
    long? freeBytes = null;

    try     
    {
#if DEBUG //RuntimeInformation and OSPlatform seem to not exist while building for Linux platform
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            long freeBytesOut;
            //On some drives (for example, RAM drives, GetDiskFreeSpaceEx does not work
            if (GetDiskFreeSpaceEx(_path, out freeBytesOut, out var _, out var __))
                freeBytes = freeBytesOut;
        }
#endif

        if (freeBytes == null)
        {
            //DriveInfo works well on paths in Linux    //TODO: what about Mac?
            var drive = new DriveInfo(_path);
            freeBytes = drive.AvailableFreeSpace;
        }
    }
    catch (ArgumentException)
    {
        //ignore the exception
    }

    return freeBytes;
}
like image 58
Roland Pihlakas Avatar answered Sep 23 '22 05:09

Roland Pihlakas


You can use System.AppContext.BaseDirectory if you are using .Net Core

(OR)

Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)
like image 25
Rahul Avatar answered Sep 24 '22 05:09

Rahul