P
Phil Rayner
Basically put I am trying to get the disk-space used of a directory from a
web application.
The problem arises when the application (more the user that the process runs
as) doesn't have access to one of the subdirectories (in this case the logs
directory).
I want the application to add the filespace used by files that the process
does have access to.
I have writen diskspace functions which I have included at the end of this
post.
Now the problem is quite strange. When I run this code on my development box
(windows XP) it runs flawlessly, and works as expected. When I run this code
on our staging server (2003 Server) it runs flawlessly, but when I run this
on our production server, the process seems to get into an endless loop and
I have to do an IISRESET to fix the problem (recycling the APP pool doesn't
fix it). On the production server each time I run the diskspace report (the
code that calls the above functions) the process will get in to an endless
loop and take 100% of CPU.
Is there some problem with how I am nesting the Try catches?
Can anyone tell me what I might be doing wrong, and if there is a reference
implementation for getting directory sizes that works when you don't have
the security ACLs to some of the files or directories within the directory?
Other code that might help is not using try catches, but first checking the
ACLs on a file. The only code I have found to do this uses the
FileIOPermission object, and requires statements such as
filePermission.Demand(), which in themselves must use a try catch, and seem
to have more problems than the code I have provided above (using
filePermission.Demand() the code still runs on my development box, but not
on our staging server or our production server).
Any help on this would be much appreciated.
PS. As a side note can anyone suggest how to test this on our production
server without requiring an IISRESET each time it crashes/endless loops?
// Diskspace functions:
public long DirSize(DirectoryInfo d)
{
if (d.Exists)
{
long Size = 0;
// Add file sizes.
FileInfo[] fis = d.GetFiles();
foreach (FileInfo fi in fis)
{
Size += fi.Length;
}
// Add subdirectory sizes.
DirectoryInfo[] dis = d.GetDirectories();
foreach (DirectoryInfo di in dis)
{
try
{
long dirSize = DirSize(di);
Size += dirSize;
}
catch {}
}
return (Size);
}
return 0;
}
public Decimal SitePathSizeNoError(String path)
{
Decimal size = 0;
//Get the parent directory as the path we have is the Htdocs, and we
want to include the logs too
DirectoryInfo dir = Directory.GetParent (path);
if (!dir.Exists)
return -1;
DirectoryInfo[] subdirs = dir.GetDirectories();
foreach (DirectoryInfo subdir in subdirs)
{
if (subdir.Name != "vhost")
//foreach child (except 'vhost' folder') get size;
size += DirSize (subdir);
}
//Convert size to MB
size = size/1048576;
return Math.Round (size, 2);
}
public String SitePathSizeString(String path)
{
Decimal size;
try
{
size = SitePathSizeNoError(path);
}
catch (Exception ex)
{
return String.Format("Error accessing path {0}.
{1}",path,ex.Message);
}
if (size >= 0)
{
_planDiskUsage += size;
return String.Format("{0} Mb",size);
}
else
return String.Format("Path Not found. {0}",path);
}
web application.
The problem arises when the application (more the user that the process runs
as) doesn't have access to one of the subdirectories (in this case the logs
directory).
I want the application to add the filespace used by files that the process
does have access to.
I have writen diskspace functions which I have included at the end of this
post.
Now the problem is quite strange. When I run this code on my development box
(windows XP) it runs flawlessly, and works as expected. When I run this code
on our staging server (2003 Server) it runs flawlessly, but when I run this
on our production server, the process seems to get into an endless loop and
I have to do an IISRESET to fix the problem (recycling the APP pool doesn't
fix it). On the production server each time I run the diskspace report (the
code that calls the above functions) the process will get in to an endless
loop and take 100% of CPU.
Is there some problem with how I am nesting the Try catches?
Can anyone tell me what I might be doing wrong, and if there is a reference
implementation for getting directory sizes that works when you don't have
the security ACLs to some of the files or directories within the directory?
Other code that might help is not using try catches, but first checking the
ACLs on a file. The only code I have found to do this uses the
FileIOPermission object, and requires statements such as
filePermission.Demand(), which in themselves must use a try catch, and seem
to have more problems than the code I have provided above (using
filePermission.Demand() the code still runs on my development box, but not
on our staging server or our production server).
Any help on this would be much appreciated.
PS. As a side note can anyone suggest how to test this on our production
server without requiring an IISRESET each time it crashes/endless loops?
// Diskspace functions:
public long DirSize(DirectoryInfo d)
{
if (d.Exists)
{
long Size = 0;
// Add file sizes.
FileInfo[] fis = d.GetFiles();
foreach (FileInfo fi in fis)
{
Size += fi.Length;
}
// Add subdirectory sizes.
DirectoryInfo[] dis = d.GetDirectories();
foreach (DirectoryInfo di in dis)
{
try
{
long dirSize = DirSize(di);
Size += dirSize;
}
catch {}
}
return (Size);
}
return 0;
}
public Decimal SitePathSizeNoError(String path)
{
Decimal size = 0;
//Get the parent directory as the path we have is the Htdocs, and we
want to include the logs too
DirectoryInfo dir = Directory.GetParent (path);
if (!dir.Exists)
return -1;
DirectoryInfo[] subdirs = dir.GetDirectories();
foreach (DirectoryInfo subdir in subdirs)
{
if (subdir.Name != "vhost")
//foreach child (except 'vhost' folder') get size;
size += DirSize (subdir);
}
//Convert size to MB
size = size/1048576;
return Math.Round (size, 2);
}
public String SitePathSizeString(String path)
{
Decimal size;
try
{
size = SitePathSizeNoError(path);
}
catch (Exception ex)
{
return String.Format("Error accessing path {0}.
{1}",path,ex.Message);
}
if (size >= 0)
{
_planDiskUsage += size;
return String.Format("{0} Mb",size);
}
else
return String.Format("Path Not found. {0}",path);
}