2010-10-15 50 views
6

給定一個DFS路徑我怎麼會知道什麼是有效的路徑是目前編程。我怎樣才能在DFS得到一個積極的UNC路徑編程

對於〔實施例我有2個服務器股份"\\Server1\Folder\""\\Server2\Folder\",它有DFS開啓,以便它可以在"\\DFS_Server\Folder\"訪問,我怎麼會知道什麼是活動路徑目前"\\DFS_Server\Folder\"是,無論是"\\Server1\Folder\""\\Server2\Folder\"

回答

4

試試這個地方sDFSPath是您要查詢和sHostServer是你想查詢你的WMI服務器的路徑,它可以是任何你上面提到的兩個服務器。你甚至可以使一個更優雅的代碼時,它失敗第一臺服務器上,然後查詢WMI的下一個服務器上

public static ArrayList GetActiveServers(string sDFSPath, string sHostServer) 
{ 
    ArrayList sHostNames = new ArrayList(); 

    ManagementPath oManagementPath = new ManagementPath(); 
    oManagementPath.Server = sHostServer; 
    oManagementPath.NamespacePath = @"root\cimv2"; 

    oManagementScope = new ManagementScope(oManagementPath); 
    oManagementScope.Connect(); 

    SelectQuery oSelectQuery = new SelectQuery(); 
    oSelectQuery.QueryString = @"SELECT * FROM Win32_DfsTarget WHERE LinkName LIKE '%" + sDFSPath.Replace("\\", "\\\\") + "%' and State = 1"; 

    ManagementObjectSearcher oObjectSearcher = new ManagementObjectSearcher(oManagementScope, oSelectQuery); 
    ManagementObjectCollection oObjectCollection = oObjectSearcher.Get(); 

    if (oObjectCollection.Count != 0) 
    { 
     foreach (ManagementObject oItem in oObjectCollection) 
     { 
      sHostNames.Add(oItem.Properties["ServerName"].Value.ToString()); 
     } 
    } 

    return sHostNames; 
} 

希望這是有道理的

+0

會如何VBS上述外觀使用WMI?任何指導將不勝感激。 – Lizz 2014-01-29 04:51:13

5

如果我正確理解您的需求,還有還有,似乎一個API你需要什麼:

// mscorlib (no additional assemblies needed) 
using System.Runtime.InteropServices; 

public static class Dfs 
{ 
    private enum NetDfsInfoLevel 
    { 
     DfsInfo1 = 1, 
     DfsInfo2 = 2, 
     DfsInfo3 = 3, 
     DfsInfo4 = 4, 
     DfsInfo5 = 5, 
     DfsInfo6 = 6, 
     DfsInfo7 = 7, 
     DfsInfo8 = 8, 
     DfsInfo9 = 9, 
     DfsInfo50 = 50, 
     DfsInfo100 = 100, 
     DfsInfo150 = 150, 
    } 

    [DllImport("netapi32.dll", SetLastError = true)] 
    private static extern int NetApiBufferFree(IntPtr buffer); 

    [DllImport("Netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
    private static extern int NetDfsGetInfo(
     [MarshalAs(UnmanagedType.LPWStr)] string DfsEntryPath, // DFS entry path for the volume 
     [MarshalAs(UnmanagedType.LPWStr)] string ServerName, // This parameter is currently ignored and should be NULL 
     [MarshalAs(UnmanagedType.LPWStr)] string ShareName, // This parameter is currently ignored and should be NULL. 
     NetDfsInfoLevel Level,         // Level of information requested 
     out IntPtr Buffer          // API allocates and returns buffer with requested info 
     ); 

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
    private struct DFS_INFO_3 
    { 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string EntryPath; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string Comment; 
     public int State; 
     public int NumberOfStorages; 
     public IntPtr Storage; 
    } 

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] 
    private struct DFS_STORAGE_INFO 
    { 
     public int State; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string ServerName; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string ShareName; 
    } 

    private static T GetStruct<T>(IntPtr buffer, int offset=0)where T:struct 
    { 
     T r = new T(); 
     r = (T) Marshal.PtrToStructure(buffer + offset * Marshal.SizeOf(r), typeof(T)); 
     return r; 
    } 

    public static string GetDfsInfo(string server) 
    { 
     string rval = null; 
     IntPtr b; 
     int r = NetDfsGetInfo(server, null, null, NetDfsInfoLevel.DfsInfo3, out b); 
     if(r != 0) 
     { 
      NetApiBufferFree(b); 

      // return passed string if not DFS 
      return rval; 
     } 

     DFS_INFO_3 sRes = GetStruct<DFS_INFO_3>(b); 
     if(sRes.NumberOfStorages > 0) 
     { 
      DFS_STORAGE_INFO sResInfo = GetStruct<DFS_STORAGE_INFO>(sRes.Storage); 
      rval = string.Concat(@"\\", sResInfo.ServerName, @"\", sResInfo.ShareName, @"\"); 
     } 

     NetApiBufferFree(b); 

     return rval; 
    } 
} 

使用方法如下:

string dfsPath = @"\\DFS_Server\Folder\"; 
string share = Dfs.GetDfsInfo(dfsPath) 

對於一個API參照,檢查NetDfsGetInfoDFS_INFO_3DFS_STORAGE_INFONetApiBufferFree MSDN。

+0

偉大的解決方案,你可以添加'使用System.Runtime.InteropServices;'到頂部? – MKesper 2016-01-21 09:36:56

+0

@MKesper隨意提交編輯建議... – takrl 2016-01-21 13:04:29

4

謝謝你,你的提示是有用的。不過,我對NetDfsGetClientInfo更成功。也意識到解析過程可能是遞歸的。我結束了至少2次遞歸調用以獲得實際的物理UNC共享,這裏是我的例子。

我不知道,怎麼

public static class DFS 
{ 
    #region Import 

    [DllImport("Netapi32.dll", EntryPoint = "NetApiBufferFree")] 
    public static extern uint NetApiBufferFree(IntPtr Buffer); 

    [DllImport("Netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] 
    public static extern int NetDfsGetInfo(
     [MarshalAs(UnmanagedType.LPWStr)] string EntryPath, 
     [MarshalAs(UnmanagedType.LPWStr)] string ServerName, 
     [MarshalAs(UnmanagedType.LPWStr)] string ShareName, 
     int Level, 
     out IntPtr Buffer); 

    [DllImport("Netapi32.dll")] 
    public static extern int NetDfsGetClientInfo(
     [MarshalAs(UnmanagedType.LPWStr)] string EntryPath, 
     [MarshalAs(UnmanagedType.LPWStr)] string ServerName, 
     [MarshalAs(UnmanagedType.LPWStr)] string ShareName, 
     int Level, 
     out IntPtr Buffer); 

    #endregion 

    #region Structures 

    public struct DFS_INFO_3 
    { 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string EntryPath; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string Comment; 
     public UInt32 State; 
     public UInt32 NumberOfStorages; 
     public IntPtr Storages; 
    } 

    public struct DFS_STORAGE_INFO 
    { 
     public Int32 State; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string ServerName; 
     [MarshalAs(UnmanagedType.LPWStr)] 
     public string ShareName; 
    } 

    #endregion 

    const int DFS_VOLUME_STATE_OK = 0x00000001; 
    const int DFS_VOLUME_STATE_ONLINE = 0x00000004; 
    const int DFS_STORAGE_STATE_ONLINE = 0x00000002; 
    const int DFS_STORAGE_STATE_ACTIVE = 0x00000004; 

    public static String GetSharePath(String DFSPath) 
    { 
     if (!String.IsNullOrEmpty(DFSPath)) 
     { 
      IntPtr Buffer = IntPtr.Zero; 
      try 
      { 
       int Error = NetDfsGetClientInfo(DFSPath, null, null, 3, out Buffer); 
       if (Error == 0) 
       { 
        DFS_INFO_3 DFSInfo = (DFS_INFO_3)Marshal.PtrToStructure(Buffer, typeof(DFS_INFO_3)); 
        if ((DFSInfo.State & DFS_VOLUME_STATE_OK) > 0) 
        { 
         String SubPath = DFSPath.Remove(0, 1 + DFSInfo.EntryPath.Length).TrimStart(new Char[] { '\\' }); 
         for (int i = 0; i < DFSInfo.NumberOfStorages; i++) 
         { 
          IntPtr Storage = new IntPtr(DFSInfo.Storages.ToInt64() + i * Marshal.SizeOf(typeof(DFS_STORAGE_INFO))); 
          DFS_STORAGE_INFO StorageInfo = (DFS_STORAGE_INFO)Marshal.PtrToStructure(Storage, typeof(DFS_STORAGE_INFO)); 
          if ((StorageInfo.State & DFS_STORAGE_STATE_ACTIVE) > 0) 
          { 
           if (String.IsNullOrEmpty(SubPath)) 
           { 
            return String.Format(@"\\{0}\{1}", StorageInfo.ServerName, StorageInfo.ShareName); 
           } 
           else 
           { 
            return GetSharePath(String.Format(@"\\{0}\{1}\{2}", StorageInfo.ServerName, StorageInfo.ShareName, SubPath)); 
           } 
          } 
         } 
        } 
       } 
       else if (Error == 2662) 
        return DFSPath; 
      } 
      finally 
      { 
       NetApiBufferFree(Buffer); 
      } 
     } 
     return null; 
    } 

    public static String GetShareName(String SharePath) 
    { 
     if (!String.IsNullOrEmpty(SharePath)) 
     { 
      String[] Tokens = SharePath.Trim(new Char[] { '\\' }).Split(new Char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries); 
      if (2 <= Tokens.Length) 
       return Tokens[1]; 
     } 
     return null; 
    } 
} 
+0

我發現了小模式。所以dfs解析是可以修復的。假設你正在尋找unc a。每次迭代需要從a的開始處移除EntryPath,並重新構建它(前綴ServerName和ShareName的前綴,您從StorageInfo獲取),接收unc b。如果a == b分辨率完成。 – user3042599 2014-01-27 12:41:24

+0

NetDfsGetInfo觸發錯誤1168(未找到),這是有線的,所以我使用NetDfsGetClientInfo。這一個只返回主動存儲的數據。對於非活動存儲,它什麼都不返回。解決辦法 - 在調用NetDfsGetClientInfo之前,在unc路徑上使用System.IO.Directory.Exists(...)。 – user3042599 2014-01-27 12:48:11

+0

可以在VBS中使用NetDfsGetClientInfo,也許使用WMI? – Lizz 2014-01-29 04:46:14

相關問題