c# unc

c# - Cómo(rápidamente) verificar si la ruta UNC está disponible



(6)

¿Cómo puedo verificar si hay una ruta UNC disponible? Tengo el problema de que el cheque demora aproximadamente medio minuto si el recurso compartido no está disponible:

var fi = new DirectoryInfo(@"//hostname/samba-sharename/directory"); if (fi.Exists) //...

¿Hay una manera más rápida de verificar si una carpeta está disponible? Estoy usando Windows XP y C #.


¿Qué significa esto para una forma rápida y sucia de comprobar? Ejecute el comando de Windows net use y analice la salida de la línea con la ruta de red de interés (por ejemplo, //vault2 ) y OK . Aquí hay un ejemplo de la salida:

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.

No es una solución muy simple, pero es muy rápida, y algunas veces eso es más importante :-).

Y aquí está el código para hacerlo (y LINQPad me dice que solo lleva 150ms , así que está bien)

void Main() { bool available = QuickBestGuessAboutAccessibilityOfPath(@"//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; }

O quizás podría ir por la ruta de usar WMI , como se alude en esta respuesta a ¿Cómo asegurar que las unidades de red estén conectadas para una aplicación?


En mi proyecto uso System.IO:

if (Directory.Exists(@"//hostname/samba-sharename/directory")) { ...

y es bastante rápido hasta ahora ...


En un proyecto mío, tuve que verificar si se estableció o no una conexión de servidor. Utilicé un Socket TCP para verificar asincrónicamente si se podía llegar al servidor o no. Me pregunto si podría usar esto para verificar un recurso compartido de red. La conexión asincrónica de Socket TCP va tan rápido que probé la conexión 10 veces en menos de 60 milisegundos. ¿Quizás podrías jugar un poco con eso?

EDITAR: Aquí está el zócalo asincrónico que utilicé para mi proyecto. Use esta clase para verificar cierta IP o dirección. Espero que te sirva de algo

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 } }

Editar: no lo copie / pegue. Intente comprender el código para que pueda usarlo en su beneficio y afinarlo según sus necesidades.


Esa es probablemente la forma más rápida, la demora será la velocidad general de la red / acceso al disco, etc.

Si esto está causando un retraso para el usuario, puede intentar comprobar esto de forma asincrónica.


Tal vez deberías tratar de crear la carpeta, si existe, devolverá un error que podrías atrapar. No debe haber un tiempo de espera predeterminado.


Usé el método de ping sugerido anteriormente y no funcionó para mí ya que estoy usando OpenDNS. Aquí hay una función que me funcionó bien:

// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - /// <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); }