2011-03-01 64 views
31

如何检查UNC路径是否可用? 我有检查过程约半分钟,如果份额可用的问题:如何(快速)检查UNC路径是否可用

var fi = new DirectoryInfo(@"\\hostname\samba-sharename\directory"); 

if (fi.Exists) 
//... 

是否有检查,如果一个文件夹可用更快的方法? 我正在使用Windows XP和C#。

+2

知道给定文件夹是否可用的唯一方法是尝试使用它 - 任何其他检查可能会给出误报 – 2011-03-01 09:34:30

+0

我同意,这是最快的方法。它需要很长的时间并不是由无效代码引起的,而是服务器的磁盘访问时间。 – 2011-03-01 09:37:29

+1

@Johnny:当共享不可访问时(因此服务器无法访问),我有延迟,并且它很长,就像半分钟。 – thumbmunkeys 2011-03-01 09:40:09

回答

18

这是如何快速和肮脏的方式来检查 - 运行Windows net use命令并解析感兴趣的网络路径(例如\\vault2)和OK的线路的输出。这里有一个输出的例子:

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. 

这不是一个非常.net解决方案,但它非常快,有时更重要:-)。

而这里的代码来做到这一点(和LINQPad告诉我,只需要150毫秒,所以这是很好的)

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

或者你可能会去使用WMI的路线,如提到的this answerHow to ensure network drives are connected for an application?

+2

很酷的东西,谢谢! – thumbmunkeys 2012-08-08 07:27:21

+1

如果路径中包含'OK',可能应将'line.contains(“OK”)''改为'line.StartsWith(“OK”)' – sparkplug 2015-11-02 10:01:37

1

那可能是最快的方式,延迟将是一般的网络速度/磁盘访问等

如果这是造成的延迟对于用户来说,你可以尝试检查这个异步?

+0

我可以使它异步,但用户仍然需要等待半分钟的文件。 – thumbmunkeys 2011-03-01 10:08:47

+1

如果您在资源管理器中导航到相同的UNC路径,您是否仍然看到相同的延迟? – 2011-03-01 10:39:40

+0

@Mark:是的,它的延迟时间相同,这说明在访问不存在的samba共享时,win xp似乎有一个巨大的超时。当浏览器GUI尝试访问共享时(这真的很糟糕),它也挂起半分钟。 – thumbmunkeys 2011-03-01 16:22:37

0

也许你应该尝试创建文件夹,如果它确实存在,它会返回一个你可以捕获的错误。应该没有默认超时。

+1

我试过了,如果共享不可用,创建一个文件夹具有相同的超长超时(如果不是这样的话,它会令人惊讶) – thumbmunkeys 2011-03-01 10:21:34

3

在我的项目中,我不得不检查服务器连接是否建立。我使用了TCP套接字来异步检查是否可以访问服务器。我想知道你是否可以用它来检查网络共享。异步TCP套接字连接变得如此之快,我测试了连接10次60毫秒以下。也许你可以玩一下这一点?


编辑:这里是异步套接字,我用我的项目。使用此类来检查某个IP或地址。希望这是任何使用你

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 

    } 
} 

编辑:请不要只是复制/粘贴。尝试理解代码,以便您可以使用它,并根据需要对其进行微调。

+0

感谢您的建议,我将检查主机是否可访问,如果是,那么尝试访问该共享。 – thumbmunkeys 2011-03-01 10:24:25

1

我用平以上方法建议,因为我现在用的OpenDNS 这并没有对我的工作是为我工作很好的功能:

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

在项目中,我使用System.IO:

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

,它是相当快到目前为止...

+0

当共享不可用时,您是否尝试过? – thumbmunkeys 2016-09-28 10:06:23

+1

是的,这是为了测试是否存在...也许有一种时间从网络管理员设置时,不可用,这就是为什么你必须等待30秒..? – fasa 2016-09-28 10:13:47