Correctly identifying FileInfo vs. DirectoryInfo entries

  • Thread starter Thread starter Tom P.
  • Start date Start date
T

Tom P.

I am having the following problem: I create a FileSystemWatcher and
wait for events. When the event does happen I refresh a
FileSystemInfo list and set properties accordingly (IsFile, IsDir,
ReadOnly, etc.). The problem I'm having is in identifying when a
FileSystemInfo entry is a FileInfo or a DirectoryInfo type. I get the
rare, and yet oddly common, "setup.inf" file that for some
inexplicable reason passes the standard (FileSystemInfo.Attributes &
FileAttributes.Directory) test but throws an Illegal Cast exception
when cast to a DirectoryInfo object.

How can I reliably determine the specific type from a FileSystemInfo
object?

Tom Padilla
 
Tom P. said:
I am having the following problem: I create a FileSystemWatcher and
wait for events. When the event does happen I refresh a
FileSystemInfo list and set properties accordingly (IsFile, IsDir,
ReadOnly, etc.). The problem I'm having is in identifying when a
FileSystemInfo entry is a FileInfo or a DirectoryInfo type. I get the
rare, and yet oddly common, "setup.inf" file that for some
inexplicable reason passes the standard (FileSystemInfo.Attributes &
FileAttributes.Directory) test but throws an Illegal Cast exception
when cast to a DirectoryInfo object.

How can I reliably determine the specific type from a FileSystemInfo
object?

if (info is FileInfo)
{
....
}

or

FileInfo file = info as file;
if (file != null)
{
....
}
 
I am having the following problem: I create a FileSystemWatcher and
wait for events. When the event does happen I refresh a
FileSystemInfo list and set properties accordingly (IsFile, IsDir,
ReadOnly, etc.). The problem I'm having is in identifying when a
FileSystemInfo entry is a FileInfo or a DirectoryInfo type. I get the
rare, and yet oddly common, "setup.inf" file that for some
inexplicable reason passes the standard (FileSystemInfo.Attributes &
FileAttributes.Directory) test but throws an Illegal Cast exception
when cast to a DirectoryInfo object.

How can I reliably determine the specific type from a FileSystemInfo
object?

Well, there's always the Object.GetType() method. Depending on what
you're trying to do, often the C# "is" and "as" operators are useful.
"is" allows you to test whether an instance is a specific type, and "as"
is essentially a cast that returns null instead of throwing an exception
when the cast fails.

I don't really get how a file can be rare and common at the same thing.
You're also not clear about where you get the FileSystemInfo instance
from. As far as I know, this isn't something that the FileSystemWatcher
provides you (the event args return paths in strings, not FileSystemInfo
objects). So while there's a way to check the type of the instance, it
would probably make more sense to try to figure out why you get an
apparently incorrect type for the instance in the first place.

Without you having posted any code, it's pretty much impossible for anyone
to assist with that. But until you understand why the Attributes property
doesn't match the type of the instance, I think it's premature to work
around the issue. It may be that things are working as designed, but you
should make sure that's true first. It seems to me that there's a good
chance you're not maintaining your list of FileSystemInfo objects
correctly and it would be a bad idea to obscure that problem with a
workaround.

Pete
 
Well, there's always the Object.GetType() method. Depending on what
you're trying to do, often the C# "is" and "as" operators are useful.
"is" allows you to test whether an instance is a specific type, and "as"
is essentially a cast that returns null instead of throwing an exception
when the cast fails.

I don't really get how a file can be rare and common at the same thing.
You're also not clear about where you get the FileSystemInfo instance
from. As far as I know, this isn't something that the FileSystemWatcher
provides you (the event args return paths in strings, not FileSystemInfo
objects). So while there's a way to check the type of the instance, it
would probably make more sense to try to figure out why you get an
apparently incorrect type for the instance in the first place.

Without you having posted any code, it's pretty much impossible for anyone
to assist with that. But until you understand why the Attributes property
doesn't match the type of the instance, I think it's premature to work
around the issue. It may be that things are working as designed, but you
should make sure that's true first. It seems to me that there's a good
chance you're not maintaining your list of FileSystemInfo objects
correctly and it would be a bad idea to obscure that problem with a
workaround.

Pete

Fair enough.

First off the file "setup.inf" is rare in that it is only created as a
result of building an install (*.msi). But, being a developer this is
actually a common occurrence _for me_ so I keep running into this more
than your average user. It's a temporary file but the
FileSystemWatcher will see it before it gets deleted.

You are correct in asserting that FileSystemWatcher only returns a
path. I have to then do a this.Invoke() to call a method on the main
thread that refreshes the watched directory (which is stored in a
member variable so there's no need to pass it). I don't believe the
problem lies in the FileSystemWatcher (since I don't do anything but
call a Refresh() method). The following is the code snippet that I
believe is causing the conflict:

Create a DirectoryInfo for this Path
CurrentDirInfo = new DirectoryInfo(Path);

//Get an array of all the file system objects in the directory
FileSystemInfoList = CurrentDirInfo.GetFileSystemInfos();

//Loop through each object in the array...
foreach (FileSystemInfo CurrentFileSystemInfo in FileSystemInfoList)
{
FileSystemListViewItem CurrentListViewItem;

//...and determine if it is a Directory (has the
FileAttributes.Directory flag)
if ((CurrentFileSystemInfo.Attributes & FileAttributes.Directory)
== FileAttributes.Directory) //[TAG01]
{
CurrentListViewItem = new
FileSystemListViewItem((DirectoryInfo)CurrentFileSystemInfo); //
[TAG02]
}
else
{
CurrentListViewItem = new
FileSystemListViewItem((FileInfo)CurrentFileSystemInfo);
}

this.Items.Add(CurrentListViewItem);
}

The if at [TAG01] was copied directly from MSDN.

I've used Console.WriteLine to print out the FileAttributes flags and
the file "setup.inf" writes a "-1" rather than "Directory" but the
"if" statement above still evaluates to "true" for the file. When the
code at [TAG01] evaluates "true" then the code at [TAG02] obviously
throws an Illegal Cast exception when it casts the "setup.inf" file to
a DirectoryInfo.

I could get a list of DirectoryInfo objects and then a second list of
FileInfo objects but this seemed more efficient at the time.

It looks as if the "is" keyword is what I need here. A simple test of
whether the particular item is a DirectoryInfo object or a FileInfo
object. Then I don't have to rely on the FileAttributes flags at all.

Thanks,
Tom Padilla
 
[Snip all context]

Just because of the subject of the thread, I thought I would post this. Even
though it's not really revant to the discussion....

There is actually a 3rd very similar Info class called "FileVersionInfo",
and is found in System.Diagnostics.

For years now, i've been making Win32 calls to get this. Why on earth isn't
it in the normal File Class?
 
[...]
It looks as if the "is" keyword is what I need here. A simple test of
whether the particular item is a DirectoryInfo object or a FileInfo
object. Then I don't have to rely on the FileAttributes flags at all.

I guess. For that matter, it's not clear to me why the
FileSystemListViewItem class doesn't just take a FileSystemInfo reference
in a constructor and then handle that logic (whether checking the type or
the Attributes property) inside the constructor, rather than forcing each
client of the class to perform the test.

Still, I would want to know why you're getting -1 as the Attributes
property value for that file. I don't have an answer to that, but it
seems wrong to me. It looks more like an error condition or something,
since it's not a valid value for the enumeration at all.

It's true that if the real issue is being able to cast the object to the
right thing, the type-checking operators are a very direct and reliable
way to do that. But I would be concerned about using a FileSystemInfo
object that has an invalid value for one of its properties. That could
lead to problems in the future. I almost wonder if you should try to
reacquire the FileSystemInfo object for objects that have that property
set to -1, and/or just ignore them as invalid data.

Pete
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Back
Top