2011-03-01 92 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

相關問題