We have a server that has a network share for each user in our organization to back up their files to. All of the shares sit physically on the server in the same folder. ie D:\UserArchives\user1$, d:\UserArchives\user2$. All shares are suffixed with a dollar sign to be hidden.
I am trying to pull the amount of free space that is available to each user in their respective share using c#.
I am enumerating the shares using the chosen answer from here: Enumerating Network Shares with C#.
I have been trying to pull the free space using GetDiskFreeSpaceEx from here: http://social.msdn.microsoft.com/Forums/ar-SA/csharpgeneral/thread/b7db7ec7-34a5-4ca6-89e7-947190c4e043
If I run my app as user1 it pulls the right amount of free space for their share, and I get a security exception because they cannot access user2's share, and vice versa. This is expected. When I run my app as an administration account that has access to both share, I get back the amount of free space for user1 + user2.
This too makes sense as the documentation for GetDiskFreeSpaceEx states:
"Retrieves information about the amount of space that is available on a disk volume, which is the total amount of space, the total amount
of free space, and the total amount of free space available to the
user that is associated with the calling thread."
My question is how do I do achieve this in C# across the network. I do not want a solution that is local to the server.
My code so far:
static void Main(string[] args)
{
string server = "filesvr1";
try
{
//Impersonator is a class for impersonating a different windows account
using (new Impersonator("UserName", "Domain", "Password"))
{
GetUserShareInfo(server);
}
}
catch (Exception ex)
{
Console.WriteLine("ERROR: " + ex.Message);
}
}
static void GetUserShareInfo(string server)
{
ShareCollection shi;
if (server != null && server.Trim().Length > 0)
{
Console.WriteLine("\nShares on {0}:", server);
shi = ShareCollection.GetShares(server);
if (shi != null)
{
foreach(Share si in shi)
{
// If you don't have permissions to the share you will get security exceptions.
if (si.IsFileSystem)
{
string userName = si.NetName.Substring(0, si.NetName.Length - 1);
try
{
//Network Share Size
Console.WriteLine(FreeSpace("\\\\" + server + "\\" + si.Root.Name));
}
catch (Exception ex)
{
Console.WriteLine(userName + " - " + ex.Message);
}
}
}
}
else
Console.WriteLine("Unable to enumerate the shares on {0}.\n"
+ "Make sure the machine exists, and that you have permission to access it.", server);
}
}
public static long FreeSpace(string folderName)
{
if (string.IsNullOrEmpty(folderName))
{
throw new ArgumentNullException("folderName");
}
if (!folderName.EndsWith("\\"))
{
folderName += '\\';
}
long free = 0, dummy1 = 0, dummy2 = 0;
if (GetDiskFreeSpaceEx(folderName, ref free, ref dummy1, ref dummy2))
{
return free;
}
else
{
return -1;
}
}
[SuppressMessage("Microsoft.Security", "CA2118:ReviewSuppressUnmanagedCodeSecurityUsage"), SuppressUnmanagedCodeSecurity]
[DllImport("Kernel32", SetLastError = true, CharSet = CharSet.Auto)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetDiskFreeSpaceEx
(
string lpszPath, // Must name a folder, must end with '\'.
ref long lpFreeBytesAvailable,
ref long lpTotalNumberOfBytes,
ref long lpTotalNumberOfFreeBytes
);