在.NET中查找总磁盘空间和可用磁盘空间

时间:2022-10-24 17:51:55

I am trying to find a way to determine the total and available disk space in an arbitrary folder from a .NET app. By "total disk space" and "available disk space" in a folder I refer to the total and available disk space that this folder would report if you performed a "dir" command on it, that is, the total and available disk space of the logical drive containing that folder, considering the user account under which the request is being made.

我试图找到一种方法来确定.NET应用程序中任意文件夹中的总磁盘空间和可用磁盘空间。通过文件夹中的“总磁盘空间”和“可用磁盘空间”,我指的是如果对其执行“dir”命令,则该文件夹将报告的总磁盘空间和可用磁盘空间,即,总磁盘空间和可用磁盘空间。考虑到发出请求的用户帐户,包含该文件夹的逻辑驱动器。

I am using C#. The method should work both for local and remote folders given as UNC paths (rather than accessed through mapped drive letters). For example, it should work for:

我正在使用C#。该方法应该作为UNC路径给出的本地和远程文件夹(而不是通过映射的驱动器号访问)。例如,它应该适用于:

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

I am starting with a DirectoryInfo object, but this seems to have no associated disk space information. The DriveInfo class does, but it won't work with remote folders.

我开始使用DirectoryInfo对象,但这似乎没有关联的磁盘空间信息。 DriveInfo类可以,但它不能用于远程文件夹。

Edit. After some exchanges with you guys, I am considering mapping remote folders as local drives, using DriveInfo to obtain the data, and unmapping again. The problem with this approach is that my app needs to collect the data for over 120 folders a few times a day, every day. I am not sure this would be feasible.

编辑。经过与你们的一些交流,我正在考虑将远程文件夹映射为本地驱动器,使用DriveInfo获取数据,然后再取消映射。这种方法的问题是我的应用程序需要每天几次收集120多个文件夹的数据。我不确定这是否可行。

Any ideas? Thanks.

有任何想法吗?谢谢。

9 个解决方案

#1


11  

How about this link from MSDN that uses the System.IO.DriveInfo class?

从MSDN使用System.IO.DriveInfo类的这个链接怎么样?

#2


11  

You can use GetDiskFreeSpaceEx from kernel32.dll which works with UNC-paths and drives. All you need to do is include a DllImport (see link for an example).

您可以使用kernel32.dll中的GetDiskFreeSpaceEx,它与UNC路径和驱动器一起使用。您需要做的就是包含一个DllImport(参见示例链接)。

#3


3  

This may not be what you want, but I'm trying to help, and it has the bonus of slightly secure erasing the free space of your drive.

这可能不是你想要的,但我正在努力提供帮助,它有一点点安全的奖励,可以擦除驱动器的可用空间。

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


2  

Not really a C# example but may give you a hint - a VB.NET function returning both amount of free and total space on drive (in bytes) along specified path. Works for UNC paths as well, unlike System.IO.DriveInfo.

不是一个C#示例,但可能会给你一个提示 - 一个VB.NET函数返回指定路径上的驱动器(以字节为单位)的空闲和总空间量。与System.IO.DriveInfo不同,也适用于UNC路径。

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


1  

System.IO.DriveInfo works fine. I'm attached to two separate Netware servers, with several drives mapped.

System.IO.DriveInfo工作正常。我连接到两个单独的Netware服务器,其中映射了多个驱动器。

Here's for the local C: drive:

这是本地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 

Here's the output for one of the network drives:

这是其中一个网络驱动器的输出:

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 

I used the following code, directly from the MSDN docs on DriveInfo:

我直接从DriveInfo上的MSDN文档中使用了以下代码:

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


1  

Here's one more possibility that I've used for years. The example below is VBScript, but it should work with any COM-aware language. Note that GetDrive() works on UNC shares as well.

这是我多年来使用的另一种可能性。下面的示例是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


1  

Maksim Sestic has given the best answer, as it works on both, local and UNC paths. I have changed his code a little for better error handling and included an example. Works for me like a charm.

Maksim Sestic给出了最佳答案,因为它适用于本地和UNC路径。为了更好的错误处理,我更改了他的代码并包含了一个示例。对我来说就像一个魅力。

You need to put

你需要放

Imports System.Runtime.InteropServices

into your code, to allow DllImport to be recognized.

进入你的代码,允许识别DllImport。

Here is the modified code:

这是修改后的代码:

<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

Call it this way:

这样称呼它:

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

The foldername can also be a local directory like drive:\path\path\...

foldername也可以是本地目录,如drive:\ path \ path \ ...

It is still in VB.NET but shouldn't be a problem to translate into C#.

它仍然在VB.NET中,但转换成C#应该不是问题。

#8


0  

I'm pretty sure this is impossible. In windows explorer, if I try to get the folder properties of a UNC directory, it gives me nothing as far as available space. Used/Available space is a characteristic of drives, not folders, and UNC shares are treated as just folders.

我很确定这是不可能的。在Windows资源管理器中,如果我尝试获取UNC目录的文件夹属性,它就没有任何可用空间。已用/可用空间是驱动器的特征,而不是文件夹,UNC共享仅被视为文件夹。

you have to either:
- Map a drive
- Run something on the remote machine to check disk space.

您必须: - 映射驱动器 - 在远程计算机上运行某些内容以检查磁盘空间。

You could also run into problems with something like Distributed file system, in which a UNC/Mapped share is NOT tied to any specific drive, so there youd have to actually sum up several drives.

你也可能遇到像分布式文件系统这样的问题,其中UNC / Mapped共享没有绑定到任何特定的驱动器,所以你必须实际总结几个驱动器。

And what about user quotas? The drive may not be full, but the account you are using to write to that folder may have hit its limit.

用户配额怎么样?驱动器可能未满,但您用于写入该文件夹的帐户可能已达到其限制。

#9


0  

Not C# and only gives the avilable space, but . . .

不是C#,只给出了可用的空间,但是。 。 。

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

gets you part of the way. I'm looking or the same solution but there doesn't seem to be a nice one - especially when trying to avoid mapping drives.

让你成为一部分。我正在寻找或者相同的解决方案,但似乎没有一个好的 - 特别是在试图避免映射驱动器时。

#1


11  

How about this link from MSDN that uses the System.IO.DriveInfo class?

从MSDN使用System.IO.DriveInfo类的这个链接怎么样?

#2


11  

You can use GetDiskFreeSpaceEx from kernel32.dll which works with UNC-paths and drives. All you need to do is include a DllImport (see link for an example).

您可以使用kernel32.dll中的GetDiskFreeSpaceEx,它与UNC路径和驱动器一起使用。您需要做的就是包含一个DllImport(参见示例链接)。

#3


3  

This may not be what you want, but I'm trying to help, and it has the bonus of slightly secure erasing the free space of your drive.

这可能不是你想要的,但我正在努力提供帮助,它有一点点安全的奖励,可以擦除驱动器的可用空间。

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


2  

Not really a C# example but may give you a hint - a VB.NET function returning both amount of free and total space on drive (in bytes) along specified path. Works for UNC paths as well, unlike System.IO.DriveInfo.

不是一个C#示例,但可能会给你一个提示 - 一个VB.NET函数返回指定路径上的驱动器(以字节为单位)的空闲和总空间量。与System.IO.DriveInfo不同,也适用于UNC路径。

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


1  

System.IO.DriveInfo works fine. I'm attached to two separate Netware servers, with several drives mapped.

System.IO.DriveInfo工作正常。我连接到两个单独的Netware服务器,其中映射了多个驱动器。

Here's for the local C: drive:

这是本地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 

Here's the output for one of the network drives:

这是其中一个网络驱动器的输出:

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 

I used the following code, directly from the MSDN docs on DriveInfo:

我直接从DriveInfo上的MSDN文档中使用了以下代码:

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


1  

Here's one more possibility that I've used for years. The example below is VBScript, but it should work with any COM-aware language. Note that GetDrive() works on UNC shares as well.

这是我多年来使用的另一种可能性。下面的示例是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


1  

Maksim Sestic has given the best answer, as it works on both, local and UNC paths. I have changed his code a little for better error handling and included an example. Works for me like a charm.

Maksim Sestic给出了最佳答案,因为它适用于本地和UNC路径。为了更好的错误处理,我更改了他的代码并包含了一个示例。对我来说就像一个魅力。

You need to put

你需要放

Imports System.Runtime.InteropServices

into your code, to allow DllImport to be recognized.

进入你的代码,允许识别DllImport。

Here is the modified code:

这是修改后的代码:

<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

Call it this way:

这样称呼它:

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

The foldername can also be a local directory like drive:\path\path\...

foldername也可以是本地目录,如drive:\ path \ path \ ...

It is still in VB.NET but shouldn't be a problem to translate into C#.

它仍然在VB.NET中,但转换成C#应该不是问题。

#8


0  

I'm pretty sure this is impossible. In windows explorer, if I try to get the folder properties of a UNC directory, it gives me nothing as far as available space. Used/Available space is a characteristic of drives, not folders, and UNC shares are treated as just folders.

我很确定这是不可能的。在Windows资源管理器中,如果我尝试获取UNC目录的文件夹属性,它就没有任何可用空间。已用/可用空间是驱动器的特征,而不是文件夹,UNC共享仅被视为文件夹。

you have to either:
- Map a drive
- Run something on the remote machine to check disk space.

您必须: - 映射驱动器 - 在远程计算机上运行某些内容以检查磁盘空间。

You could also run into problems with something like Distributed file system, in which a UNC/Mapped share is NOT tied to any specific drive, so there youd have to actually sum up several drives.

你也可能遇到像分布式文件系统这样的问题,其中UNC / Mapped共享没有绑定到任何特定的驱动器,所以你必须实际总结几个驱动器。

And what about user quotas? The drive may not be full, but the account you are using to write to that folder may have hit its limit.

用户配额怎么样?驱动器可能未满,但您用于写入该文件夹的帐户可能已达到其限制。

#9


0  

Not C# and only gives the avilable space, but . . .

不是C#,只给出了可用的空间,但是。 。 。

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

gets you part of the way. I'm looking or the same solution but there doesn't seem to be a nice one - especially when trying to avoid mapping drives.

让你成为一部分。我正在寻找或者相同的解决方案,但似乎没有一个好的 - 特别是在试图避免映射驱动器时。