Обнаружение общего и свободного дискового пространства в .NET.

Я пытаюсь найти способ определить общее и доступное дисковое пространство в произвольной папке из приложения .NET. Под "общим дисковым пространством" и "доступным дисковым пространством" в папке я ссылаюсь на общее и доступное дисковое пространство, которое эта папка сообщит, если вы выполнили на нем команду "dir", то есть общее и доступное дисковое пространство логический диск, содержащий эту папку, с учетом учетной записи пользователя, под которой выполняется запрос.

Я использую С#. Метод должен работать как для локальных, так и для удаленных папок, указанных как UNC-пути (а не для доступа через сопоставленные буквы дисков). Например, он должен работать для:

  • C:\Temp
  • \\Silfen\Resources\Temp2

Я начинаю с объекта DirectoryInfo, но, похоже, у него нет связанной информации о диске. Класс DriveInfo делает, но он не будет работать с удаленными папками.

Изменить.. После некоторых обменов с вами, ребята, я рассматриваю возможность отображения удаленных папок в качестве локальных дисков, используя DriveInfo для получения данных и повторного разворачивания. Проблема с этим подходом заключается в том, что моему приложению нужно собирать данные для более чем 120 папок несколько раз в день, каждый день. Я не уверен, что это будет возможно.

Любые идеи? Спасибо.

Ответы

Ответ 2

Вы можете использовать GetDiskFreeSpaceEx из kernel32.dll, который работает с UNC-путями и дисками. Все, что вам нужно сделать, это включить DllImport (см. Ссылку для примера).

Ответ 3

Это может быть не то, что вы хотите, но я пытаюсь помочь, и у него есть бонус немного безопасного стирания свободного места вашего диска.

public static string DriveSizeAvailable(string path)
{
    long count = 0;
    byte toWrite = 1;
    try
    {
        using (StreamWriter writer = new StreamWriter(path))
        {
            while (true)
            {
                writer.Write(toWrite);
                count++;
            }
        }
    }
    catch (IOException)
    {                
    }

    return string.Format("There used to be {0} bytes available on drive {1}.", count, path);
}

public static string DriveSizeTotal(string path)
{
    DeleteAllFiles(path);
    int sizeAvailable = GetAvailableSize(path);
    return string.Format("Drive {0} will hold a total of {1} bytes.", path, sizeAvailable);
}

Ответ 4

Не действительно пример С#, но может дать вам подсказку - функция VB.NET, возвращающая как объем свободного, так и общего пространства на диске (в байтах) по указанному пути. Работает также с UNC-путями, в отличие от System.IO.DriveInfo.

VB.NET:

<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function GetDiskFreeSpaceEx(lpDirectoryName As String, ByRef lpFreeBytesAvailable As ULong, ByRef lpTotalNumberOfBytes As ULong, ByRef lpTotalNumberOfFreeBytes As ULong) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function

Public Shared Function GetDriveSpace(folderName As String, ByRef freespace As ULong, ByRef totalspace As ULong) As Boolean
    If Not String.IsNullOrEmpty(folderName) Then
        If Not folderName.EndsWith("\") Then
            folderName += "\"
        End If

        Dim free As ULong = 0, total As ULong = 0, dummy2 As ULong = 0
        If GetDiskFreeSpaceEx(folderName, free, total, dummy2) Then
            freespace = free
            totalspace = total
            Return True
        End If
    End If
End Function

Ответ 5

System.IO.DriveInfo работает нормально. Я подключен к двум отдельным серверам Netware, с несколькими картами.

Здесь для локального диска C:

Drive C:\
  File type: Fixed
  Volume label: Drive C
  File system: NTFS
  Available space to current user:   158558248960 bytes
  Total available space:             158558248960 bytes
  Total size of drive:               249884004352 bytes 

Здесь вывод для одного из сетевых дисков:

Drive F:\
  File type: Network
  Volume label: SYS
  File system: NWFS
  Available space to current user:     1840656384 bytes
  Total available space:               1840656384 bytes
  Total size of drive:                 4124475392 bytes 

Я использовал следующий код непосредственно из документов MSDN на DriveInfo:

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("  File 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);
            }
        }
    }
}

Ответ 6

Вот еще одна возможность, которую я использовал годами. Ниже приведен пример VBScript, но он должен работать с любым языком, поддерживающим COM. Обратите внимание, что GetDrive() работает и с UNC-кодами.

Dim Tripped
Dim Level

Tripped = False
Level   = 0

Sub Read(Entry, Source, SearchText, Minimum, Maximum)

    Dim fso
    Dim disk

    Set fso  = CreateObject("Scripting.FileSystemObject")

    Set disk = fso.GetDrive(Source)

    Level = (disk.AvailableSpace / (1024 * 1024 * 1024))

    If (CDbl(Level) < CDbl(Minimum)) or (CDbl(Level) > CDbl(Maximum)) Then
        Tripped = True
    Else
        Tripped = False
    End If

End Sub

Ответ 7

Максим Сестик дал лучший ответ, поскольку он работает как на локальном, так и на UNC-пути. Я немного изменил свой код для лучшей обработки ошибок и включил пример. Работает для меня как шарм.

Вам нужно поставить

Imports System.Runtime.InteropServices

в ваш код, чтобы можно было распознать DllImport.

Вот модифицированный код:

<DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function GetDiskFreeSpaceEx(lpDirectoryName As String, ByRef lpFreeBytesAvailable As ULong, ByRef lpTotalNumberOfBytes As ULong, ByRef lpTotalNumberOfFreeBytes As ULong) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function

Public Shared Function GetDriveSpace(folderName As String, ByRef freespace As ULong, ByRef totalspace As ULong) As Boolean

Dim free As ULong = 0
Dim total As ULong = 0
Dim dummy2 As ULong = 0

Try

    If Not String.IsNullOrEmpty(folderName) Then

         If Not folderName.EndsWith("\") Then
             folderName += "\"
         End If

         If GetDiskFreeSpaceEx(folderName, free, total, dummy2) Then
             freespace = free
             totalspace = total
             Return True
         End If

     End If

Catch
End Try

    Return False

End Function

Назовите его так:

dim totalspace as ulong = 0
dim freespace as ulong = 0
if GetDriveSpace("\\anycomputer\anyshare", freespace, totalspace) then
    'do what you need to do with freespace and totalspace
else
    'some error
end if

Имя папки также может быть локальным каталогом, например drive:\path\path\...

Он все еще находится в VB.NET, но не должен быть проблемой для перевода на С#.

Ответ 8

Я уверен, что это невозможно. В проводнике Windows, если я пытаюсь получить свойства папки в каталоге UNC, это не дает мне ничего до доступного пространства. Используемое/доступное пространство является характеристикой для дисков, а не для папок, а общие ресурсы UNC рассматриваются как просто папки.

вам нужно:
 - Карта диска
 - Запустите что-то на удаленном компьютере, чтобы проверить дисковое пространство.

Вы также можете столкнуться с проблемами с чем-то вроде распределенной файловой системы, в которой UNC/Mapped share НЕ привязан к какому-либо конкретному диску, поэтому вам нужно будет фактически суммировать несколько дисков.

А как насчет пользовательских квот? Возможно, диск не заполнен, но учетная запись, которую вы используете для записи в эту папку, возможно, достигла своего предела.

Ответ 9

Не С# и дает только avilable пространство, но.,.

dir \\server\share | find /i "bytes free"

дает вам часть пути. Я ищу или одно и то же решение, но, похоже, не очень приятно - особенно при попытке избежать отображения дисков.