2010-10-15 16 views
6

Bei einem DFS-Pfad, wie würde ich wissen, was ist der aktive Pfad, der es derzeit programmatisch ist.Wie bekomme ich einen aktiven UNC-Pfad in DFS programmatisch

Für exmaple habe ich 2 Server Aktien als "\\Server1\Folder\" und "\\Server2\Folder\" und es hat die DFS eingeschaltet, damit es auf "\\DFS_Server\Folder\" zugegriffen werden kann, wie würde ich wissen, was der aktive Pfad ist derzeit "\\DFS_Server\Folder\" ist, ob es "\\Server1\Folder\" oder "\\Server2\Folder\" ist.

Antwort

4

versuchen Sie dies, wobei sDFPFath der Pfad ist, den Sie abfragen möchten, und sHostServer der Server ist, den Sie auf Ihre WMI abfragen möchten, dies kann jeder der beiden oben erwähnten Server sein. Sie können sogar einen eleganten Code machen, wenn es auf dem ersten Server ausfällt, dann WMI-Abfrage auf dem nächsten Server

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

Hofft, dass es Sinn

+0

Wie der oben Blick in VBS mit WMI würde? Jede Anleitung würde geschätzt werden. – Lizz

5

macht Wenn ich Ihre Anforderung richtig verstehe, gibt es auch eine API, die scheint Sie, was Sie brauchen:

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

Verwenden Sie es wie folgt aus:

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

Für eine API-Referenz, überprüfen Sie msdn auf NetDfsGetInfo, DFS_INFO_3, DFS_STORAGE_INFO und NetApiBufferFree.

+0

Großartige Lösung, könnten Sie bitte 'using System.Runtime.InteropServices;' nach oben hinzufügen? – MKesper

+0

@MKesper Fühlen Sie sich frei, einen Bearbeitungsvorschlag einzureichen ... – takrl

4

Vielen Dank, Ihre Hinweise waren nützlich. Ich war jedoch erfolgreicher mit NetDfsGetClientInfo. Es wurde auch erkannt, dass der Auflösungsprozess rekursiv sein kann. Ich endete mit mindestens 2 rekursiven Aufrufen, um die tatsächliche physische UNC-Freigabe zu erhalten, und hier ist mein Beispiel.

Ich weiß nicht, wie

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

Ich fand wenig Modus. Also dfs Auflösung ist recuresive. Angenommen du suchst nach unc a. Bei jeder Iteration müssen Sie EntryPath am Anfang von a entfernen und es neu erstellen (Präfix mit ServerName und ShareName, das Sie von StorageInfo erhalten) und unc b empfangen. Wenn eine == b Auflösung abgeschlossen ist. – user3042599

+0

NetDfsGetInfo ausgelöst Fehler 1168 (nicht gefunden), die verdrahtet ist, so habe ich NetDfsGetClientInfo verwendet. Dieser gibt Daten nur für aktiven Speicher zurück. Für nicht aktiven Speicher gibt es nichts zurück. Workaround-Hack ist die Verwendung von System.IO.Directory.Exists (...) auf Ihrem Unc-Pfad vor dem Aufruf von NetDfsGetClientInfo. – user3042599

+0

Kann NetDfsGetClientInfo in VBS verwendet werden, vielleicht mit WMI? – Lizz

Verwandte Themen