views:

1191

answers:

2

I work on a thick-client app that often runs into "issues" accessing network shares. Before doing any IO with the server, my app tests whether the share (usually of the form \\server\share$) exists. This works fine for detecting those scenarios in which the client has lost its connection to the server, but there are still those odd scenarios where the hidden share exists but the user does not have the rights to read from the within the share. Can someone share (no pun intended) the C# code required to test whether the current user can read files on a share? Should I be querying the share's ACL or the files within the share? What if the share is empty? What if the user is a local non-admin in a mixed environment (XP Pro workstation, Windows 2003 server without a domain on a Novell network)?

+2  A: 

The #1 most reliable way to determine if you used to have permission to read from the share is to

  1. Try and read from the share
  2. Handle errors that could occur while reading and consider that a failed attempt

Unfortunately though based on your description you are trying to determine if you will have read permission to the share. There is no way to reliably determine this.

No matter how many ACLs, directories, etc ... you look at the moment you're done looking at them you could lose access to the share via any number of mechanisms. The most obvious one is the network share going down. All you can determine is that you used to have permission to the share.

JaredPar
I understand it is more accurate to just read and wait for the error, but won't that be pretty annoying for the user? Certainly reading one ACL ahead of time might save some frustration. Can you point me to some sample code?
flipdoubt
@flipdoubt but the read of the ACL is as likely to hang. Both require reading from the share. You should always design for a FS operation (especially remote) with the assumption it will hang. Typically a background thread is your best friend here. What type of sample code are you looknig for?
JaredPar
Thanks again for the reply, Jared. Eric's code is probably enough. By the way, is "FS operation" shorthand for a "fail-safe operation"?
flipdoubt
+3  A: 

The easiest way is to just do it (i.e. try to read a file, for example). As Jared mentioned, there is no way to make sure that you will be able to read in the future (network failure, change of permissions, etc).

As far as code goes, you could use the DirectoryInfo class for some attempts at an answer:

        string remotePath = @"\\server\share$";
        bool haveAccess = false;

        DirectoryInfo di = new DirectoryInfo(remotePath);
        if (di.Exists)
        {
            try
            {
                // you could also call GetDirectories or GetFiles
                // to test them individually
                // this will throw an exception if you don't have 
                // rights to the directory, though
                var acl = di.GetAccessControl();
                haveAccess = true;
            }
            catch (UnauthorizedAccessException uae)
            {
                if (uae.Message.Contains("read-only"))
                {
                    // seems like it is just read-only
                    haveAccess = true;
                }
                // no access, sorry
                // do something else...
            }
        }

There are a lot of short-commings in this code (such as the hard-coded "read-only" test), but it is just to illustrate what you could do. DirectoryInfo has a few other helper methods that you can use to list the files in the folder. If you don't have access, the methods will throw an UnauthorizedAccessException exception which you can use to test why the access failed. Check out the info on GetAccessControl for further details on the exceptions it throws.

Erich Mirabal
This works for me, except I had to take out the `if (di.Exists)` because it returns false if you're not authenticated to the network. If you try the `.GetAccessControl()`, you can catch the `InvalidOperationException` and, in my case, do: `if (ioe.Message.Contains("1326"))` which is the Windows error code for *Logon failure: unknown user name or bad password.*
Jared Harley