How to (quickly) check if UNC Path is available

前端 未结 7 655
太阳男子
太阳男子 2020-12-05 06:45

How can I check if a UNC Path is available? I have the problem that the check takes about half a minute if the share is not available :

var          


        
相关标签:
7条回答
  • 2020-12-05 07:02

    I used the ping method suggested above and it did not work for me since I am using OpenDNS Here is a function that worked well for me:

    // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    /// <summary>
    /// A quick method to test is the path exists 
    /// </summary>
    /// <param name="s"></param>
    /// <param name="timeOutMs"></param>
    /// <returns></returns>
    public static bool CheckPathExists(string s, int timeOutMs = 120) {
        if (s.StartsWith(@"\\")) {
            Uri uri = new Uri(s);
            if (uri.Segments.Length == 0 || string.IsNullOrWhiteSpace(uri.Host))
                return false;
            if (uri.Host != Dns.GetHostName()) {
                WebRequest request;
                WebResponse response;
                request = WebRequest.Create(uri);
                request.Method = "HEAD";
                request.Timeout = timeOutMs;
                try {
                    response = request.GetResponse();
                } catch (Exception ex) {
                    return false;
                }
                return response.ContentLength > 0;
    
                // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
                // Do a Ping to see if the server is there
                // This method doesn't work well using OPenDNS since it always succeeds
                // regardless if the IP is a valid or not
                // OpenDns always maps every host to an IP. If the host is not valid the 
                // OpenDNS will map it to 67.215.65.132
                /* Example:
                    C:\>ping xxx
    
                    Pinging xxx.RT-AC66R [67.215.65.132] with 32 bytes of data:
                    Reply from 67.215.65.132: bytes=32 time=24ms TTL=55
                    */
    
                //Ping pingSender = new Ping();
                //PingOptions options = new PingOptions();
                // Use the default Ttl value which is 128,
                // but change the fragmentation behavior.
                //options.DontFragment = true;
    
                // Create a buffer of 32 bytes of data to be transmitted.
                //string data = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
                //byte[] buffer = Encoding.ASCII.GetBytes(data);
                //int timeout = 120;
                //PingReply reply = pingSender.Send(uri.Host, timeout, buffer, options);
                //if (reply == null || reply.Status != IPStatus.Success)
                //    return false;
            }
        }
        return File.Exists(s);
    }
    
    0 讨论(0)
  • 2020-12-05 07:14

    Thats probably the quickest way, the delay will be the general network speed/disk access etc.

    If this is causing a delay for the user, you could try checking this asynchronously?

    0 讨论(0)
  • 2020-12-05 07:17

    Maybe you should try to create the folder, if it does exist, it will return an error that you could catch. There should be no default timeout.

    0 讨论(0)
  • 2020-12-05 07:18

    How's this for a quick and dirty way to check - run the windows net use command and parse the output for the line with the network path of interest (e.g. \\vault2) and OK. Here's an example of the output:

    C:\>net use
    New connections will be remembered.
    
    Status       Local     Remote                    Network
    
    -------------------------------------------------------------------------------
    OK           O:        \\smarty\Data       Microsoft Windows Network
    Disconnected P:        \\dummy\Data       Microsoft Windows Network
    OK                     \\vault2\vault2           Microsoft Windows Network
    The command completed successfully.
    

    It's not a very .netish solution, but it's very fast, and sometimes that matters more :-).

    And here's the code to do it (and LINQPad tells me that it only takes 150ms, so that's nice)

    void Main()
    {
        bool available = QuickBestGuessAboutAccessibilityOfNetworkPath(@"\\vault2\vault2\dir1\dir2");
        Console.WriteLine(available);
    }
    
    public static bool QuickBestGuessAboutAccessibilityOfNetworkPath(string path)
    {
        if (string.IsNullOrEmpty(path)) return false;
        string pathRoot = Path.GetPathRoot(path);
        if (string.IsNullOrEmpty(pathRoot)) return false;
        ProcessStartInfo pinfo = new ProcessStartInfo("net", "use");
        pinfo.CreateNoWindow = true;
        pinfo.RedirectStandardOutput = true;
        pinfo.UseShellExecute = false;
        string output;
        using (Process p = Process.Start(pinfo)) {
            output = p.StandardOutput.ReadToEnd();
        }
        foreach (string line in output.Split('\n'))
        {
            if (line.Contains(pathRoot) && line.Contains("OK"))
            {
                return true; // shareIsProbablyConnected
            }
        }
        return false;
    }
    

    Or you could probably go the route of using WMI, as alluded to in this answer to How to ensure network drives are connected for an application?

    0 讨论(0)
  • 2020-12-05 07:20

    In a project of mine, i had to check whether a server connection was established or not. I used a TCP Socket to asynchronically check whether the server could be reached or not. I wonder if you could use this to check on a network share. The async TCP Socket connect goes so fast i tested for the connection 10 times under 60 miliseconds. Maybe you could play around with that a bit ?


    EDIT: Here is the Asynchronous Socket i used for my project. Use this class to check for a certain IP or address. Hope it is of any use to you

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Net.Sockets;
    using System.Net;
    using System.Threading;
    
    namespace Base.BaseObjects
    {
        public class AsynchronousClient
        {
            #region Properties
    
            private int _port = 0000, currentTry = 0, _buffersize, _fastpingdelay = 80;
            private string _server = "localhost";
            private Socket client;
            private static IPEndPoint remoteEP;
    
            // Delegates & Events
            public delegate void SendMessageDelegate(string message);
            public event SendMessageDelegate SendMessageEvent;
            public delegate void ConnectionStatusDelegate(bool connected, bool reconnect);
            public event ConnectionStatusDelegate ConnectionStatusChanged;
    
            // ManualResetEvent instances signal completion.
            private static ManualResetEvent connectDone = new ManualResetEvent(false);
            private static ManualResetEvent sendDone = new ManualResetEvent(false);
            private static ManualResetEvent receiveDone = new ManualResetEvent(false);
    
            /// <summary>
            /// Port to monitor
            /// </summary>
            public int Port { get { return _port; } }
    
            /// <summary>
            /// Number of packages to buffer until system reports connection loss
            /// </summary>
            public int BufferSize { get { return _buffersize; }  }
    
            /// <summary>
            /// Time in milliseconds between two pings
            /// </summary>
            public int FastPingDelay { get { return _fastpingdelay; } }
    
            /// <summary>
            /// Servername to connect to
            /// </summary>
            public string Server
            {
                get { return _server; }
                set
                {
                    _server = value;
                    // Resolve the remote endpoint for the socket.
                    try
                    {
                        IPAddress ipAddress = (IPAddress)Dns.GetHostAddresses(value)[0];
                        remoteEP = new IPEndPoint(ipAddress, Port);
                    }
                    catch (SocketException ex)
                    {
                        SendMessage(ex.Message);
                    }
                }
            }
    
            #endregion
    
            #region Events & Delegates
    
            protected void SendMessage(string message)
            {
                if (SendMessageEvent != null)
                    SendMessageEvent(message);
            }
    
            protected void UpdateConnectionStatus(bool connected, bool reconnect)
            {
                if (ConnectionStatusChanged != null)
                    ConnectionStatusChanged(connected, reconnect);
            }
    
            private void ConnectCallback(IAsyncResult ar)
            {
                try
                {
                    // Retrieve the socket from the state object.
                    Socket client = (Socket)ar.AsyncState;
    
                    // Complete the connection.
                    client.EndConnect(ar);
    
                    SendMessage(String.Format("Socket connected to {0}", client.RemoteEndPoint.ToString()));
                    //UpdateConnectionStatus(true, false);
    
                    // Signal that the connection has been made.
                    connectDone.Set();
                }
                catch (Exception e)
                {
                    SendMessage(e.ToString());
                    UpdateConnectionStatus(false, true);
                }
            }
    
            #endregion
    
            #region methods
    
            public AsynchronousClient(int port, string server)
            {
                _port = port;
                Server = server;
                _buffersize = 10;
                _fastpingdelay = 20;
            }
    
            public void CreateSocket()
            {
                try
                {
                    StopClient();
                }
                catch (Exception ex)
                {
                    SendMessage(ex.Message);
                }
                finally
                {
                    client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                }
            }
    
            public bool FastPingSocket()
            {
                for (currentTry = 0; currentTry <= BufferSize; currentTry++)
                {
                    try
                    {
                        CreateSocket();
                        client.BeginConnect(remoteEP, new AsyncCallback(ConnectCallback), client);
                        connectDone.WaitOne();
                        System.Threading.Thread.Sleep(FastPingDelay);
                        client.Shutdown(SocketShutdown.Receive);
                        connectDone.WaitOne();
                        client.Close();
                        return true;
                    }
                    catch (SocketException ex)
                    {
                        SendMessage(ex.Message);
                    }
                    catch (ObjectDisposedException ex)
                    {
                        currentTry--;
                        SendMessage(ex.Message);
                        CreateSocket();
                    }
                    catch (NullReferenceException ex)
                    {
                        currentTry--;
                        SendMessage(ex.Message);
                        CreateSocket();
                    }
                    catch (ArgumentNullException ex)
                    {
                        SendMessage(ex.Message);
                        CreateSocket();
                    }
                    catch (InvalidOperationException ex)
                    {
                        SendMessage(ex.Message);
                        CreateSocket();
                        currentTry--;
                    }
                    finally
                    {
                        StopClient();
                    }
                }
                UpdateConnectionStatus(false, true);
                return false;
            }
    
            public void StopClient()
            {
                // Release the socket.
                try
                {
                    client.Shutdown(SocketShutdown.Both);
                    client.Close();
                }
                catch (Exception) { }
                finally
                {
                    UpdateConnectionStatus(false, false);
                }
            }
    
            #endregion
    
        }
    }
    
    

    Edit: Please don't just copy/paste it. Try to understand the code so you can use it for your benefit, and finetune it for your needs.

    0 讨论(0)
  • 2020-12-05 07:21

    I ended up "cheating" and just pinging the host, which is reasonable as that in reality is the case that I'm checking for.

    private bool HostExists(string PCName)
    {
        Ping pinger = new Ping();
    
        try
        {
            PingReply reply = pinger.Send(PCName);
            return reply.Status == IPStatus.Success;
        }
        catch
        {
            return false;
        }
        finally
        {
            pinger.Dispose();
        }
    
    }
    

    This way suits me best because of its speed, simplicity, and reliability.

    0 讨论(0)
提交回复
热议问题