Obtenez de l'espace disque libre


93

Compte tenu de chacune des entrées ci-dessous, j'aimerais obtenir de l'espace libre à cet endroit. Quelque chose comme

long GetFreeSpace(string path)

Contributions:

c:

c:\

c:\temp

\\server

\\server\C\storage


52
Pas un doublon, le stackoverflow.com/questions/412632 ne pose que des questions sur les disques, je pose également des questions sur les chemins UNC et la solution dans 412632 ne fonctionne pas pour eux.
bh213

Réponses:


67

cela fonctionne pour moi ...

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

bonne chance!


7
drive.TotalFreeSpacene fonctionne pas pour moi mais le drive.AvailableFreeSpacefait
knocte

16
Je sais que cette réponse est ancienne, mais vous devez généralement utiliser AvailableFreeSpacecomme @knocte le dit. AvailableFreeSpaceliste la quantité réellement disponible pour l'utilisateur (en raison de quotos). TotalFreeSpacerépertorie ce qui est disponible sur le disque, indépendamment de ce que l'utilisateur peut utiliser.
Roy T.20

J'ai voté pour le commentaire de @ RoyT parce qu'il a pris le temps d'expliquer pourquoi l'un est recommandé par rapport à l'autre.
SoCalCoder du

40

DriveInfo vous aidera avec certains d'entre eux (mais cela ne fonctionne pas avec les chemins UNC), mais je pense vraiment que vous devrez utiliser GetDiskFreeSpaceEx . Vous pouvez probablement obtenir certaines fonctionnalités avec WMI. GetDiskFreeSpaceEx semble être votre meilleur pari.

Il y a de fortes chances que vous deviez nettoyer vos chemins pour que cela fonctionne correctement.


40

Extrait de code de travail utilisant un GetDiskFreeSpaceExlien 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
Je préfère le faire revenir vide, comme ... if (!GetDiskFreeSpaceEx(folderName, out free, out total, out dummy)) throw new Win32Exception(Marshal.GetLastWin32Error());. Assez pratique pour trouver le code ici de toute façon.
Eugene Ryabtsev

2
Juste vérifier, mais je pense que "CameraStorageFileHelper" est un artefact de ce code copié à partir de l'original?
Andrew Theken

Cela n'a pas besoin de se terminer par "\\". Il peut s'agir de n'importe quel chemin de répertoire existant ou même simplement C:. Voici ma version de ce code: 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
Bien que ce code fonctionne en fait pour tous les lecteurs d'un système, il ne répond pas aux exigences de l'OP concernant les points de montage, les points de jonction et les partages ...
Adrian Hum

3

non testé:

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

Btw quel est le résultat de l'espace disque libre sur c: \ temp? vous obtiendrez l'espace libre de c: \


5
Comme le dit Kenny, l'espace libre pour un répertoire donné n'est pas nécessairement le même que l'espace libre pour le lecteur du répertoire racine. Certainement pas sur ma machine.
Barry Kelly

3

Voici une version refactorisée et simplifiée de la réponse @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;
    }

Votre chemin est meilleur, étant donné que vous avez extrait le LastWin32Error
Eddy Shterenberg le

3

Vérifiez ceci (c'est une solution de travail pour moi)

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

voir cet article !

  1. identifier le chemin UNC par ou le lecteur local en recherchant l'index de ":"

  2. si c'est UNC PATH vous cam map chemin UNC

  3. le code pour exécuter le nom du lecteur est le nom du lecteur mappé <Lecteur mappé UNC ou lecteur 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. unmap une fois l'exigence terminée.


1
Bien que ce code fonctionne en fait pour tous les lecteurs d'un système, il ne répond pas aux exigences de l'OP concernant les points de montage et les points de jonction ...
Adrian Hum

2

Je cherchais la taille en Go, j'ai donc simplement amélioré le code de Superman ci-dessus avec les modifications suivantes:

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
Vous renvoyez la capacité totale du lecteur.
Nick Binnet

3
Je pensais que n'importe qui pouvait calculer le Go ayant des octets, mais vous avez montré que c'était une mauvaise supposition. Ce code est faux car la division utilise longmais la fonction retourne double.
Qwertiy

2

Comme cette réponse et @RichardOD l'ont suggéré, vous devriez faire comme ceci:

[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

Je voulais une méthode similaire pour mon projet mais dans mon cas, les chemins d'entrée provenaient soit de volumes de disque locaux, soit de volumes de stockage en cluster (CSV). La classe DriveInfo n'a donc pas fonctionné pour moi. Les CSV ont un point de montage sous un autre lecteur, généralement C: \ ClusterStorage \ Volume *. Notez que C: sera un volume différent de C: \ ClusterStorage \ Volume1

C'est ce que j'ai finalement trouvé:

    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

Vous pouvez essayer ceci:

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

Bonne chance


2
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant la raison et / ou la manière dont ce code répond à la question améliore sa valeur à long terme.
xiawi le

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

-1

J'ai eu le même problème et j'ai vu waruna manjula donner la meilleure réponse. Cependant, tout écrire sur la console n'est pas ce que vous pourriez souhaiter. Pour obtenir une chaîne sur toutes les informations, utilisez ce qui suit

Première étape: déclarer les valeurs au début

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

Étape 2: code réel

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

Je tiens à noter que vous pouvez simplement créer le code de commentaire de tous les écrits de la console, mais j'ai pensé que ce serait bien pour vous de le tester. Si vous affichez tout cela les uns après les autres, vous obtenez la même liste que waruna majuna

Lecteur C: \ Type de lecteur: Étiquette de volume fixe: Système de fichiers: NTFS Espace disponible pour l'utilisateur actuel: 134880153600 octets Espace disponible total: 134880153600 octets Taille totale du lecteur: 499554185216 octets

Lecteur D: \ Type de lecteur: CDRom

Lecteur H: \ Type de lecteur: Fixe Étiquette de volume: HDD Système de fichiers: NTFS Espace disponible pour l'utilisateur actuel: 2000010817536 octets Espace disponible total: 2000010817536 octets Taille totale du lecteur: 2000263573504 octets

Cependant, vous pouvez maintenant accéder à toutes les informations en vrac dans les chaînes


7
Ne pas créer de classe pour 3 objets simulaires et utiliser un else if. J'ai pleuré un peu.
Mathijs Segers

1
Désolé, code de placage de chaudière, n'utilisant pas de collections et n'utilisant pas d'interrupteur?
Adrian Hum
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.