Отримайте вільне місце на диску


93

Враховуючи кожен із введених нижче даних, я хотів би отримати вільний простір у цьому місці. Щось на зразок

long GetFreeSpace(string path)

Входи:

c:

c:\

c:\temp

\\server

\\server\C\storage

Точний дублікат: stackoverflow.com/questions/412632
DTB

52
Не дублікат, stackoverflow.com/questions/412632 запитує лише про диски, я також запитую про шляхи UNC, і рішення в 412632 для них не працює.
bh213,

Відповіді:


67

це працює для мене ...

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

Щасти!


7
drive.TotalFreeSpaceу мене не працює, але drive.AvailableFreeSpaceпрацює
knocte

16
Я знаю, що ця відповідь давня, але зазвичай вам потрібно використовувати, AvailableFreeSpaceяк каже @knocte. AvailableFreeSpaceперераховує, скільки насправді доступно для користувача (через квоти). TotalFreeSpaceперелічує те, що є на диску, незалежно від того, що користувач може використовувати.
Рой Т.

Я підтримав коментар @ RoyT, оскільки він знайшов час, щоб пояснити, чому одне рекомендується над іншим.
SoCalCoder

40

DriveInfo допоможе вам з деякими з них (але це не працює з контурами UNC), але насправді я думаю, що вам потрібно буде використовувати GetDiskFreeSpaceEx . Можливо, ви можете досягти певної функціональності за допомогою WMI. GetDiskFreeSpaceEx виглядає як найкращий вибір.

Швидше за все, вам, мабуть, доведеться розчистити свої шляхи, щоб він працював належним чином.


40

Робочий фрагмент коду за GetDiskFreeSpaceExпосиланням 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
Я волів би, щоб він повернувся порожнім, наприклад ... if (!GetDiskFreeSpaceEx(folderName, out free, out total, out dummy)) throw new Win32Exception(Marshal.GetLastWin32Error());. Тут дуже зручно знайти код у будь-якому випадку.
Євген Рябцев

2
Просто перевіряю, але я думаю, що "CameraStorageFileHelper" - це артефакт із цього коду, який копіюється з оригіналу?
Ендрю Текен

На цьому не потрібно закінчувати "\\". Це може бути будь-який існуючий шлях до папки або навіть просто C:. Ось моя версія цього коду: stackoverflow.com/a/58005966/964478
Алекс П.

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
Хоча цей код насправді працює для всіх накопичувачів в системі, він не відповідає вимогам ОП щодо точок монтування, точок з'єднання та спільного використання ...
Адріан Хам,

3

неперевірені:

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

До речі, який результат вільного дискового простору на c: \ temp? ви отримаєте вільний простір c: \


5
Як каже Кенні, вільний простір для будь-якого даного каталогу не обов'язково такий самий, як вільний простір для диска кореневого каталогу. Звичайно, не на моїй машині.
Barry Kelly

3

Ось перероблена та спрощена версія відповіді @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;
    }

Ваш шлях кращий, якщо ви витягнете помилку LastWin32Error
Едді Штеренберг

3

Перевірте це (це робоче рішення для мене)

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

дивіться цю статтю !

  1. визначити UNC пар або локальний шлях диска, шукаючи індекс ":"

  2. якщо це UNC PATH, ви карті UNC шлях

  3. код для запуску назви диска - відображена назва диска <UNC Mapped Drive або Local Drive>.

    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. зняти карту після того, як ви виконаєте вимогу.


1
Хоча цей код насправді працює для всіх накопичувачів в системі, він не відповідає вимогам ОП щодо точок кріплення та точок з'єднання ...
Адріан Хам,

2

Я шукав розмір в Гб, тому я просто вдосконалив код від Супермена вище, з наступними змінами:

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
Ви повертаєте загальну ємність накопичувача.
Нік Бінет

3
Я думав, що кожен може обчислити ГБ, що має байти, але ви показали, що це неправильне припущення. Цей код неправильний, оскільки підрозділ використовує, longале функція повертається double.
Квертій,

2

Як запропонували ця відповідь та @RichardOD, вам слід зробити так:

[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

Я хотів подібний метод для свого проекту, але в моєму випадку вхідні шляхи були або з локальних дискових томів, або з кластерних томів зберігання (CSV). Тож клас DriveInfo у мене не працював. CSV мають точку монтування під іншим диском, як правило, C: \ ClusterStorage \ Volume *. Зверніть увагу, що C: буде іншим томом, ніж C: \ ClusterStorage \ Volume1

Ось що я нарешті придумав:

    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

Ви можете спробувати це:

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

Удачі


2
Хоча цей код може відповісти на питання, надаючи додатковий контекст щодо того, чому та / або як цей код відповідає на питання, покращує його довгострокове значення.
xiawi

var driveName = "C: \\";
Хмара Нім

-1

У мене була та сама проблема, і я побачив, як waruna manjula дає найкращу відповідь. Однак записувати все це на консолі - це не те, що вам може знадобитися. Щоб вимкнути рядок, використовуйте наступне

Крок перший: оголосіть значення на початку

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

Крок 2: фактичний код

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

Я хочу зазначити, що ви можете просто зробити всі коди коментарів консолі для записів ліній, але я вважав, що для вас було б непогано протестувати його. Якщо ви відображаєте все це один за одним, ви отримуєте той самий список, що і waruna majuna

Привід C: \ Тип накопичувача: Фіксована мітка обсягу: Файлова система: NTFS Доступний простір для поточного користувача: 134880153600 байт Загальний доступний простір: 134880153600 байт Загальний розмір накопичувача: 499554185216 байт

Привід D: \ Тип приводу: CDRom

Привід H: \ Тип накопичувача: Фіксована мітка обсягу: HDD Файлова система: NTFS Доступний простір для поточного користувача: 2000010817536 байт Загальний доступний простір: 2000010817536 байт Загальний розмір накопичувача: 2000263573504 байта

Однак тепер ви можете отримати доступ до всієї вільної інформації в рядках


7
Не створюючи клас для 3 симульованих об’єктів, а використовуючи інший if. Я трохи поплакала.
Mathijs Segers

1
Вибачте коду для покриття котла, не використовуєте колекції та не використовуєте перемикач?
Адріан Хам,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.