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.
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:\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.
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.
Any ideas? Thanks.
How about this link from MSDN that uses the System.IO.DriveInfo
class?
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).
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);
}
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.
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
System.IO.DriveInfo works fine. I'm attached to two separate Netware servers, with several drives mapped.
Here's for the local C: drive:
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:
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); } } } }
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.
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
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.
You need to put
Imports System.Runtime.InteropServices
into your code, to allow DllImport to be recognized.
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\...
It is still in VB.NET but shouldn't be a problem to translate into C#.
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.
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.
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.
Not C# and only gives the avilable space, but . . .
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.
来源:https://stackoverflow.com/questions/1799984/finding-out-total-and-free-disk-space