Obtenga espacio libre en disco


93

Dada cada una de las entradas a continuación, me gustaría obtener espacio libre en esa ubicación. Algo como

long GetFreeSpace(string path)

Entradas:

c:

c:\

c:\temp

\\server

\\server\C\storage


52
No es un duplicado, stackoverflow.com/questions/412632 solo pregunta sobre discos, también pregunto sobre rutas UNC y la solución en 412632 no funciona para ellos.
bh213

Respuestas:


66

esto funciona para mi ...

using System.IO;

private long GetTotalFreeSpace(string driveName)
{
    foreach (DriveInfo drive in DriveInfo.GetDrives())
    {
        if (drive.IsReady && drive.Name == driveName)
        {
            return drive.TotalFreeSpace;
        }
    }
    return -1;
}

¡buena suerte!


7
drive.TotalFreeSpaceno funciona para mí, pero drive.AvailableFreeSpace
knocte

16
Sé que esta respuesta es antigua, pero generalmente debes usarla AvailableFreeSpacecomo dice @knocte. AvailableFreeSpaceenumera cuánto está realmente disponible para el usuario (debido a las citas). TotalFreeSpaceenumera lo que está disponible en el disco, independientemente de lo que pueda usar el usuario.
Roy T.

Elegí el comentario de @ RoyT porque se tomó el tiempo de explicar por qué se recomienda uno sobre el otro.
SoCalCoder

40

DriveInfo lo ayudará con algunos de esos (pero no funciona con rutas UNC), pero realmente creo que necesitará usar GetDiskFreeSpaceEx . Probablemente pueda lograr alguna funcionalidad con WMI. GetDiskFreeSpaceEx parece su mejor opción.

Lo más probable es que tenga que limpiar sus caminos para que funcione correctamente.


40

Fragmento de código de trabajo utilizando el GetDiskFreeSpaceExenlace de RichardOD.

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

public static bool DriveFreeBytes(string folderName, out ulong freespace)
{
    freespace = 0;
    if (string.IsNullOrEmpty(folderName))
    {
        throw new ArgumentNullException("folderName");
    }

    if (!folderName.EndsWith("\\"))
    {
        folderName += '\\';
    }

    ulong free = 0, dummy1 = 0, dummy2 = 0;

    if (GetDiskFreeSpaceEx(folderName, out free, out dummy1, out dummy2))
    {
        freespace = free;
        return true;
    }
    else
    {
        return false;
    }
}

1
Prefiero que vuelva vacío, como ... if (!GetDiskFreeSpaceEx(folderName, out free, out total, out dummy)) throw new Win32Exception(Marshal.GetLastWin32Error());. De todos modos, es muy conveniente encontrar el código aquí.
Eugene Ryabtsev

2
Solo comprobando, pero creo que "CameraStorageFileHelper" es un artefacto de este código que se copia y pega del original.
Andrew Theken

No necesita terminar con "\\". Puede ser cualquier ruta de directorio existente o incluso solo C:. Aquí está mi versión de este código: stackoverflow.com/a/58005966/964478
Alex P.

7
using System;
using System.IO;

class Test
{
    public static void Main()
    {
        DriveInfo[] allDrives = DriveInfo.GetDrives();

        foreach (DriveInfo d in allDrives)
        {
            Console.WriteLine("Drive {0}", d.Name);
            Console.WriteLine("  Drive type: {0}", d.DriveType);
            if (d.IsReady == true)
            {
                Console.WriteLine("  Volume label: {0}", d.VolumeLabel);
                Console.WriteLine("  File system: {0}", d.DriveFormat);
                Console.WriteLine(
                    "  Available space to current user:{0, 15} bytes", 
                    d.AvailableFreeSpace);

                Console.WriteLine(
                    "  Total available space:          {0, 15} bytes",
                    d.TotalFreeSpace);

                Console.WriteLine(
                    "  Total size of drive:            {0, 15} bytes ",
                    d.TotalSize);
            }
        }
    }
}
/* 
This code produces output similar to the following:

Drive A:\
  Drive type: Removable
Drive C:\
  Drive type: Fixed
  Volume label: 
  File system: FAT32
  Available space to current user:     4770430976 bytes
  Total available space:               4770430976 bytes
  Total size of drive:                10731683840 bytes 
Drive D:\
  Drive type: Fixed
  Volume label: 
  File system: NTFS
  Available space to current user:    15114977280 bytes
  Total available space:              15114977280 bytes
  Total size of drive:                25958948864 bytes 
Drive E:\
  Drive type: CDRom

The actual output of this code will vary based on machine and the permissions
granted to the user executing it.
*/

1
Si bien este código de hecho funciona para todas las unidades de un sistema, no aborda el requisito de OP para puntos de montaje y puntos de unión y recursos compartidos ...
Adrian Hum

3

no probado:

using System;
using System.Management;

ManagementObject disk = new
ManagementObject("win32_logicaldisk.deviceid="c:"");
disk.Get();
Console.WriteLine("Logical Disk Size = " + disk["Size"] + " bytes");
Console.WriteLine("Logical Disk FreeSpace = " + disk["FreeSpace"] + "
bytes"); 

Por cierto, ¿cuál es el resultado del espacio libre en disco en c: \ temp? obtendrás el espacio libre de c: \


5
Como dice Kenny, el espacio libre para cualquier directorio dado no es necesariamente el mismo que el espacio libre para la unidad del directorio raíz. Ciertamente no está en mi máquina.
Barry Kelly

3

Aquí hay una versión refactorizada y simplificada de la respuesta de @sasha_gud:

    [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);

    public static ulong GetDiskFreeSpace(string path)
    {
        if (string.IsNullOrEmpty(path))
        {
            throw new ArgumentNullException("path");
        }

        ulong dummy = 0;

        if (!GetDiskFreeSpaceEx(path, out ulong freeSpace, out dummy, out dummy))
        {
            throw new Win32Exception(Marshal.GetLastWin32Error());
        }

        return freeSpace;
    }

Su camino es mejor, dado que extrajo el LastWin32Error
Eddy Shterenberg

3

Mira esto (esta es una solución que funciona para mí)

public long AvailableFreeSpace()
{
    long longAvailableFreeSpace = 0;
    try{
        DriveInfo[] arrayOfDrives = DriveInfo.GetDrives();
        foreach (var d in arrayOfDrives)
        {
            Console.WriteLine("Drive {0}", d.Name);
            Console.WriteLine("  Drive type: {0}", d.DriveType);
            if (d.IsReady == true && d.Name == "/data")
            {
                Console.WriteLine("Volume label: {0}", d.VolumeLabel);
                Console.WriteLine("File system: {0}", d.DriveFormat);
                Console.WriteLine("AvailableFreeSpace for current user:{0, 15} bytes",d.AvailableFreeSpace);
                Console.WriteLine("TotalFreeSpace {0, 15} bytes",d.TotalFreeSpace);
                Console.WriteLine("Total size of drive: {0, 15} bytes \n",d.TotalSize);
                }
                longAvailableFreeSpaceInMB = d.TotalFreeSpace;
        }
    }
    catch(Exception ex){
        ServiceLocator.GetInsightsProvider()?.LogError(ex);
    }
    return longAvailableFreeSpace;
}

2

¡mira este artículo !

  1. identifique el par UNC o la ruta de la unidad local buscando en el índice ":"

  2. si es UNC PATH, usted puede mapear la ruta UNC

  3. El código para ejecutar el nombre de la unidad es el nombre de la unidad asignada <Unidad asignada UNC o Unidad local>.

    using System.IO;
    
    private long GetTotalFreeSpace(string driveName)
    {
    foreach (DriveInfo drive in DriveInfo.GetDrives())
    {
        if (drive.IsReady && drive.Name == driveName)
        {
            return drive.TotalFreeSpace;
        }
    }
    return -1;
    }
  4. desmapear después de completar el requisito.


1
Si bien este código de hecho funciona para todas las unidades de un sistema, no aborda el requisito de OP para puntos de montaje y puntos de unión ...
Adrian Hum

2

Estaba buscando el tamaño en GB, así que acabo de mejorar el código de Superman anterior con los siguientes cambios:

public double GetTotalHDDSize(string driveName)
{
    foreach (DriveInfo drive in DriveInfo.GetDrives())
    {
        if (drive.IsReady && drive.Name == driveName)
        {
            return drive.TotalSize / (1024 * 1024 * 1024);
        }
    }
    return -1;
}

8
Está devolviendo la capacidad total de la unidad.
Nick Binnet

3
Pensé que cualquiera puede calcular GB con bytes, pero demostró que era una suposición incorrecta. Este código es incorrecto ya que la división usa longpero la función regresa double.
Qwertiy

2

Como sugirieron esta respuesta y @RichardOD, debería hacer esto:

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

ulong FreeBytesAvailable;
ulong TotalNumberOfBytes;
ulong TotalNumberOfFreeBytes;

bool success = GetDiskFreeSpaceEx(@"\\mycomputer\myfolder",
                                  out FreeBytesAvailable,
                                  out TotalNumberOfBytes,
                                  out TotalNumberOfFreeBytes);
if(!success)
    throw new System.ComponentModel.Win32Exception();

Console.WriteLine("Free Bytes Available:      {0,15:D}", FreeBytesAvailable);
Console.WriteLine("Total Number Of Bytes:     {0,15:D}", TotalNumberOfBytes);
Console.WriteLine("Total Number Of FreeBytes: {0,15:D}", TotalNumberOfFreeBytes);

1

Quería un método similar para mi proyecto, pero en mi caso, las rutas de entrada eran de volúmenes de disco local o volúmenes de almacenamiento en clúster (CSV). Así que la clase DriveInfo no funcionó para mí. Los CSV tienen un punto de montaje debajo de otra unidad, generalmente C: \ ClusterStorage \ Volume *. Tenga en cuenta que C: será un volumen diferente de C: \ ClusterStorage \ Volume1

Esto es lo que finalmente se me ocurrió:

    public static ulong GetFreeSpaceOfPathInBytes(string path)
    {
        if ((new Uri(path)).IsUnc)
        {
            throw new NotImplementedException("Cannot find free space for UNC path " + path);
        }

        ulong freeSpace = 0;
        int prevVolumeNameLength = 0;

        foreach (ManagementObject volume in
                new ManagementObjectSearcher("Select * from Win32_Volume").Get())
        {
            if (UInt32.Parse(volume["DriveType"].ToString()) > 1 &&                             // Is Volume monuted on host
                volume["Name"] != null &&                                                       // Volume has a root directory
                path.StartsWith(volume["Name"].ToString(), StringComparison.OrdinalIgnoreCase)  // Required Path is under Volume's root directory 
                )
            {
                // If multiple volumes have their root directory matching the required path,
                // one with most nested (longest) Volume Name is given preference.
                // Case: CSV volumes monuted under other drive volumes.

                int currVolumeNameLength = volume["Name"].ToString().Length;

                if ((prevVolumeNameLength == 0 || currVolumeNameLength > prevVolumeNameLength) &&
                    volume["FreeSpace"] != null
                    )
                {
                    freeSpace = ulong.Parse(volume["FreeSpace"].ToString());
                    prevVolumeNameLength = volume["Name"].ToString().Length;
                }
            }
        }

        if (prevVolumeNameLength > 0)
        {
            return freeSpace;
        }

        throw new Exception("Could not find Volume Information for path " + path);
    }

1

Puedes probar esto:

var driveName = "C:\\";
var freeSpace = DriveInfo.GetDrives().Where(x => x.Name == driveName && x.IsReady).FirstOrDefault().TotalFreeSpace;

Buena suerte


2
Si bien este código puede responder a la pregunta, proporcionar un contexto adicional sobre por qué y / o cómo este código responde a la pregunta mejora su valor a largo plazo.
xiawi

var driveName = "C: \\";
Nime Cloud

-1

Tuve el mismo problema y vi a waruna manjula dando la mejor respuesta. Sin embargo, escribirlo todo en la consola no es lo que podría querer. Para sacar la cadena de toda la información, use lo siguiente

Paso uno: declare los valores al comienzo

    //drive 1
    public static string drivename = "";
    public static string drivetype = "";
    public static string drivevolumelabel = "";
    public static string drivefilesystem = "";
    public static string driveuseravailablespace = "";
    public static string driveavailablespace = "";
    public static string drivetotalspace = "";

    //drive 2
    public static string drivename2 = "";
    public static string drivetype2 = "";
    public static string drivevolumelabel2 = "";
    public static string drivefilesystem2 = "";
    public static string driveuseravailablespace2 = "";
    public static string driveavailablespace2 = "";
    public static string drivetotalspace2 = "";

    //drive 3
    public static string drivename3 = "";
    public static string drivetype3 = "";
    public static string drivevolumelabel3 = "";
    public static string drivefilesystem3 = "";
    public static string driveuseravailablespace3 = "";
    public static string driveavailablespace3 = "";
    public static string drivetotalspace3 = "";

Paso 2: código real

                DriveInfo[] allDrives = DriveInfo.GetDrives();
                int drive = 1;
                foreach (DriveInfo d in allDrives)
                {
                    if (drive == 1)
                    {
                        drivename = String.Format("Drive {0}", d.Name);
                        drivetype = String.Format("Drive type: {0}", d.DriveType);
                        if (d.IsReady == true)
                        {
                            drivevolumelabel = String.Format("Volume label: {0}", d.VolumeLabel);
                            drivefilesystem = String.Format("File system: {0}", d.DriveFormat);
                            driveuseravailablespace = String.Format("Available space to current user:{0, 15} bytes", d.AvailableFreeSpace);
                            driveavailablespace = String.Format("Total available space:{0, 15} bytes", d.TotalFreeSpace);
                            drivetotalspace = String.Format("Total size of drive:{0, 15} bytes ", d.TotalSize);
                        }
                        drive = 2;
                    }
                    else if (drive == 2)
                    {
                        drivename2 = String.Format("Drive {0}", d.Name);
                        drivetype2 = String.Format("Drive type: {0}", d.DriveType);
                        if (d.IsReady == true)
                        {
                            drivevolumelabel2 = String.Format("Volume label: {0}", d.VolumeLabel);
                            drivefilesystem2 = String.Format("File system: {0}", d.DriveFormat);
                            driveuseravailablespace2 = String.Format("Available space to current user:{0, 15} bytes", d.AvailableFreeSpace);
                            driveavailablespace2 = String.Format("Total available space:{0, 15} bytes", d.TotalFreeSpace);
                            drivetotalspace2 = String.Format("Total size of drive:{0, 15} bytes ", d.TotalSize);
                        }
                        drive = 3;
                    }
                    else if (drive == 3)
                    {
                        drivename3 = String.Format("Drive {0}", d.Name);
                        drivetype3 = String.Format("Drive type: {0}", d.DriveType);
                        if (d.IsReady == true)
                        {
                            drivevolumelabel3 = String.Format("Volume label: {0}", d.VolumeLabel);
                            drivefilesystem3 = String.Format("File system: {0}", d.DriveFormat);
                            driveuseravailablespace3 = String.Format("Available space to current user:{0, 15} bytes", d.AvailableFreeSpace);
                            driveavailablespace3 = String.Format("Total available space:{0, 15} bytes", d.TotalFreeSpace);
                            drivetotalspace3 = String.Format("Total size of drive:{0, 15} bytes ", d.TotalSize);
                        }
                        drive = 4;
                    }
                    if (drive == 4)
                    {
                        drive = 1;
                    }
                }

                //part 2: possible debug - displays in output

                //drive 1
                Console.WriteLine(drivename);
                Console.WriteLine(drivetype);
                Console.WriteLine(drivevolumelabel);
                Console.WriteLine(drivefilesystem);
                Console.WriteLine(driveuseravailablespace);
                Console.WriteLine(driveavailablespace);
                Console.WriteLine(drivetotalspace);

                //drive 2
                Console.WriteLine(drivename2);
                Console.WriteLine(drivetype2);
                Console.WriteLine(drivevolumelabel2);
                Console.WriteLine(drivefilesystem2);
                Console.WriteLine(driveuseravailablespace2);
                Console.WriteLine(driveavailablespace2);
                Console.WriteLine(drivetotalspace2);

                //drive 3
                Console.WriteLine(drivename3);
                Console.WriteLine(drivetype3);
                Console.WriteLine(drivevolumelabel3);
                Console.WriteLine(drivefilesystem3);
                Console.WriteLine(driveuseravailablespace3);
                Console.WriteLine(driveavailablespace3);
                Console.WriteLine(drivetotalspace3);

Quiero señalar que puede hacer todo el código de comentario de las líneas de escritura de la consola, pero pensé que sería bueno que lo probara. Si muestra todos estos uno después del otro, obtendrá la misma lista que waruna majuna

Unidad C: \ Tipo de unidad: Etiqueta de volumen fijo: Sistema de archivos: NTFS Espacio disponible para el usuario actual: 134880153600 bytes Espacio total disponible: 134880153600 bytes Tamaño total de la unidad: 499554185216 bytes

Unidad D: \ Tipo de unidad: CDRom

Unidad H: \ Tipo de unidad: Fijo Etiqueta de volumen: HDD Sistema de archivos: NTFS Espacio disponible para el usuario actual: 2000010817536 bytes Espacio total disponible: 2000010817536 bytes Tamaño total de la unidad: 2000263573504 bytes

Sin embargo, ahora puede acceder a toda la información suelta en cadenas


7
No crear una clase para 3 objetos simulares y usar un else if. Lloré un poco.
Mathijs Segers

1
Disculpe el código de revestimiento de la caldera, ¿no usa colecciones y no usa un interruptor?
Adrian Hum
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.