views:

285

answers:

5

We have a web application that attempts to use some resources on a Samba mount. If the mount has somehow failed, I need a way to quickly detect and report an error, however File.Exists and Directory.Exists are taking 30 seconds to return false when the mount goes away. What is the best way to quickly determine if a mount is available in C#?

A: 

Hi there.

Appologies for having no code examples, but you could try WMI to get the information you need? Check out this post. It might or might not work for you, but I thought I'd mention it just in case.

Cheers. Jas.

Jason Evans
+1  A: 

The issue with this is that the underlying operating system (Windows) takes for ever to return the fact that there's no share available.

The quickest way I can think of off the top of my head is initiate a ping to see if you get a response from the remote device, if the ping is successful (which should be verifiable inside of a second), then theoretically you should get a response back from the mount reasonably quickly. If the remote device is not available, then you will have some kind of idea that is the case relatively quickly too. It is dirty but will definitely give you quicker results than waiting for the Windows check to timeout.

This wouldn't of course verify the availability of the share on the remote device... do you have the ability to run software on the remote server? If so you could write a sentinel that could check for share availability which you could ping with a share name. It would then theoretically respond a lot quicker as there would be no need to timeout - either the sentinel would respond with true or false, or would fail to respond immediately. In any case you'd have a quick answer.

That is all for now... maybe I'll have some more thoughts shortly.

BenAlabaster
+3  A: 

If a successful check with File.Exists always completes within 5 seconds (or some shorter time), you could assume that any call that takes longer than that will fail.

Here's a pseudo-code possible solution:

const int CUSTOM_TIMEOUT = 5;
bool isMountedVar = false;

bool isMounted ( string path) {
   Thread mythread = executeNewThread(&isMountedThread, path);
   sleep(CUSTOM_TIMEOUT);
   if( mythread.finished() )
      return isMountedVar;
   // Otherwise
   mythread.kill();
   return false;
}

void isMountedThread(string path) {
   isMountedVar = File(path).Exists;
}
Steven
You may want to add some state management logic to avoid firing off multiple threads.
jdigital
+1  A: 

I would suggest looking into the WIN32 Windows Networking Functions, because this functionality is not directly accessible from .NET. A likely starting point is the WNetGetResourceInformation Function, with it's error return codes.

WNetGetResourceInformation

When provided with a remote path to a network resource, the WNetGetResourceInformation function identifies the network provider that owns the resource and obtains information about the type of the resource. If the function fails, the return value is a system error code, such as one of the following values.

Return code - Description

ERROR_BAD_NET_NAME - The input lpRemoteName member is not an existing network resource for any network.

ERROR_BAD_DEV_TYPE -The input dwType member does not match the type of resource specified by the lpRemoteName member.

ERROR_EXTENDED_ERROR - A network-specific error occurred. Call WNetGetLastError to obtain a description of the error.

ERROR_MORE_DATA - The buffer pointed to by the lpBuffer parameter is too small.

ERROR_NO_NETWORK - The network is unavailable.

In order to call Wnet functions from .NET, search for examples on Pinvoke.net. A quick search did not come up with a WNetGetResourceInformation example, but there are enough calls to other Wnet functions. See WNetAddConnection2 for a similar use.

The WNetAddConnection2 function makes a connection to a network resource. The function can redirect a local device to the network resource.

gimel
+1  A: 

The Win32 Windows Networking Functions are the only way to get this information. You should be able to use either WNetGetResourceInformation or WNetGetConnection. I think WNetGetConnection might be the best option. The return values you would be most interested in are:

ERROR_CONNECTION_UNAVAIL The device is not currently connected, but it is a persistent connection. For more information, see the following Remarks section.

ERROR_NO_NETWORK The network is unavailable.

All of that aside, I understand the desire to be proactive in being able to read/write from a backup location, but it seems to me that would be more properly handled on the hardware and/or operating system side rather than the application. The hardware and/or operating system is much more likely to be able to detect that a read/write failed or some other network related event occurred and take the appropriate actions.

Scott Dorman