In my C# .NET 2.0 application I'm accessing network paths, and I'd like to be able to tell the difference between paths that don't exist, and paths which do exist but for which I don't have access rights. I tried doing the following:
try
{
string[] contents = Directory.GetFileSystemEntries( path );
}
catch( Exception e )
{
if( e is DirectoryNotFoundException )
MessageBox.Show( "Path not found" );
else
MessageBox.Show( "Access denied" );
}
This works fine for local paths, but for network paths, the exception is always System.IO.IOException, regardless of the reason for the error. The exception Message field shows a different message depending on whether the path exists or not, so clearly the information is available at some point, but I can't get to it. Is there a way to differentiate between "path not found" and "access denied" for network paths?
Edit: So, in case anyone else wants the quick solution to this, as suggested by henrik, and incorporating peSHIr's advice, here is what you can do:
try
{
// Issue this call just to find out whether the path exists
// We don't care about the result
string[] contents = Directory.GetFileSystemEntries( path );
// If we get this far then the path exists.
}
catch( IOException e )
{
uint error = (uint)Marshal.GetHRForException( e );
if( error == (uint)0x80070041 ) // ERROR_NETWORK_ACCESS_DENIED
{
// The poor deluded user doesn't have access rights
this.SuperProprietaryTechniqueForGettingAccessRights();
}
else
{
// Hah! The idiot user specified a path that doesn't exist!
// Chastise them severely, like all good GUI should.
MessageBox.Show( "NO! BAD USER!" );
}
}
catch
{
// Swallow all other types of exception - we only made the call
// to find out whether the path exists.
}
First, I would not catch (Exception)
, but do something like this:
try {
string[] contents = Directory.GetFileSystemEntries(path);
}
catch(DirectoryNotFoundException)
{
MessageBox.Show("Path not found");
}
catch(IOException)
{
MessageBox.Show("Could not access path");
}
But the real question is: why would you actually need to know the difference, if all you do is show a message box to the user with a generic error message?
Also, unfortunately, the path may exist and you don't have access, and the result is that the path appears non-existent to your account. Many companies modify the special privs on a folder to remove "intermediary" folders from visibility, but they are still present.
For example, consider the path \srv\test1\test2\test3\
If you modify the advanced security for the folder named "test2" above, you can prevent users from navigating into it. Attempts to open the folder will result in a not found exception, and viewing the parent folder "test1" will not show the folder as present. However, if you provide the full path above and have sufficient privileges on the folder named "test3" then the folder will open.
Just something to consider, for all intents and purposes the folder doesn't exist for the user, however, if you offer the ability for a user to specify a full path then you should keep the above in mind (e.g. allow users to reach paths by full name, because it's possible they lack privs to view/list/read/see an intermediary, and the error returned doesn't indicate that it's a security restriction, so preventing access to the full path because of an intermediary appeared non-existent coudl be considered bugged app logic.)
Hope that helps.
You can call Marshal.GetHRForException to get more detailed information as in:
if (Marshal.GetHRForException(e) == unchecked((int)0x800704cf)) // ERROR_NETWORK_UNREACHABLE
See WinError.h for error codes.
User contributions licensed under CC BY-SA 3.0