Ottieni spazio libero su disco


93

Dato ciascuno degli input seguenti, mi piacerebbe avere spazio libero in quella posizione. Qualcosa di simile a

long GetFreeSpace(string path)

Ingressi:

c:

c:\

c:\temp

\\server

\\server\C\storage


52
Non è un duplicato, stackoverflow.com/questions/412632 chiede solo dei dischi, chiedo anche dei percorsi UNC e la soluzione in 412632 non funziona per loro.
bh213

Risposte:


67

questo funziona per me ...

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

in bocca al lupo!


7
drive.TotalFreeSpacenon funziona per me ma drive.AvailableFreeSpacefunziona
knocte

16
So che questa risposta è antica, ma di solito devi usarla AvailableFreeSpacecome dice @knocte. AvailableFreeSpaceelenca quanto è effettivamente disponibile per l'utente (a causa dei quotos). TotalFreeSpaceelenca ciò che è disponibile sul disco, indipendentemente da ciò che l'utente può utilizzare.
Roy T.

Ho votato positivamente il commento di @ RoyT perché si è preso il tempo di spiegare perché uno è consigliato rispetto all'altro.
SoCalCoder

40

DriveInfo ti aiuterà con alcuni di questi (ma non funziona con i percorsi UNC), ma in realtà penso che dovrai usare GetDiskFreeSpaceEx . Probabilmente puoi ottenere alcune funzionalità con WMI. GetDiskFreeSpaceEx sembra la soluzione migliore.

È probabile che dovrai ripulire i tuoi percorsi per farlo funzionare correttamente.


40

GetDiskFreeSpaceExSnippet di codice funzionante utilizzando from link di 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
Preferirei che tornasse vuoto, tipo ... if (!GetDiskFreeSpaceEx(folderName, out free, out total, out dummy)) throw new Win32Exception(Marshal.GetLastWin32Error());. Abbastanza comodo trovare il codice qui comunque.
Eugene Ryabtsev

2
Sto solo controllando, ma penso che "CameraStorageFileHelper" sia un artefatto di questo codice che viene copiato e incollato dall'originale?
Andrew Theken

Non ha bisogno di finire con "\\". Può essere qualsiasi percorso directory esistente o anche solo C:. Ecco la mia versione di questo codice: 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
Sebbene questo codice in effetti funzioni per tutte le unità su un sistema, non soddisfa i requisiti dell'OP per i punti di montaggio, i punti di giunzione e le condivisioni ...
Adrian Hum

3

non testato:

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

A proposito, qual è il risultato dello spazio libero su disco su c: \ temp? avrai lo spazio libero di c: \


5
Come dice Kenny, lo spazio libero per una data directory non è necessariamente lo stesso dello spazio libero per l'unità della directory root. Di certo non è sulla mia macchina.
Barry Kelly

3

Ecco una versione modificata e semplificata della risposta @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;
    }

La tua strada è migliore, dato che hai estratto LastWin32Error
Eddy Shterenberg,

3

Dai un'occhiata (questa è una soluzione funzionante per me)

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

guarda questo articolo !

  1. identificare la par UNC o il percorso dell'unità locale cercando l'indice di ":"

  2. se è UNC PATH, camma il percorso UNC

  3. il codice per eseguire il nome dell'unità è il nome dell'unità mappata <Unità mappata UNC o unità locale>.

    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. annullare la mappatura dopo aver completato il requisito.


1
Sebbene questo codice in effetti funzioni per tutte le unità su un sistema, non soddisfa i requisiti dell'OP per punti di montaggio e punti di giunzione ...
Adrian Hum

2

Stavo cercando la dimensione in GB, quindi ho appena migliorato il codice di Superman sopra con le seguenti modifiche:

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
Stai restituendo la capacità totale dell'unità.
Nick Binnet

3
Pensavo che chiunque potesse calcolare GB con byte, ma hai dimostrato che era un'ipotesi sbagliata. Questo codice è sbagliato come la divisione usa longma la funzione restituisce double.
Qwertiy

2

Come suggerito da questa risposta e da @RichardOD, dovresti fare così:

[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

Volevo un metodo simile per il mio progetto, ma nel mio caso i percorsi di input provenivano da volumi di dischi locali o da volumi di archiviazione cluster (CSV). Quindi la classe DriveInfo non ha funzionato per me. I CSV hanno un punto di montaggio sotto un'altra unità, in genere C: \ ClusterStorage \ Volume *. Notare che C: sarà un volume diverso da C: \ ClusterStorage \ Volume1

Questo è quello che ho finalmente pensato:

    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

Puoi provare questo:

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

In bocca al lupo


2
Sebbene questo codice possa rispondere alla domanda, fornire un contesto aggiuntivo sul perché e / o come questo codice risponde alla domanda ne migliora il valore a lungo termine.
xiawi

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

-1

Ho avuto lo stesso problema e ho visto Waruna Manjula dare la migliore risposta. Tuttavia scrivere tutto sulla console non è quello che potresti desiderare. Per ottenere la stringa da tutte le informazioni utilizzare quanto segue

Fase uno: dichiara i valori all'inizio

    //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 = "";

Passaggio 2: codice effettivo

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

Voglio notare che puoi semplicemente creare tutto il codice di commento delle scritture della console, ma ho pensato che sarebbe stato carino per te testarlo. Se si visualizzano tutti questi dopo l'altro si ottiene lo stesso elenco di waruna majuna

Unità C: \ Tipo di unità: Volume fisso Etichetta: File system: NTFS Spazio disponibile per l'utente corrente: 134880153600 byte Spazio disponibile totale: 134880153600 byte Dimensione totale dell'unità: 499554185216 byte

Unità D: \ Tipo di unità: CD-Rom

Unità H: \ Tipo di unità: Volume fisso Etichetta: HDD File system: NTFS Spazio disponibile per l'utente corrente: 2000010817536 byte Spazio disponibile totale: 2000010817536 byte Dimensione totale dell'unità: 2000263573504 byte

Tuttavia ora puoi accedere a tutte le informazioni sciolte alle stringhe


7
Non creare una classe per 3 oggetti simulari e utilizzare un altro se. Ho pianto un po '.
Mathijs Segers

1
Scusa il codice galvanico della caldaia, non usi le collezioni e non usi un interruttore?
Adrian Hum
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.