Click here to Skip to main content
Click here to Skip to main content
Technical Blog

Tagged as

How to determine active UNC Path in DFS Programatically

, 26 Oct 2010 CPOL
Rate this:
Please Sign up or sign in to vote.
WMI is really helpful specially when you dont have a DLL’s or Assembly that you can reference to or even if its hard to understand how a dll works and how you to define those structures that the assembly is outputting, one of this is finding out what are the active UNC given a DFS [...]

WMI is really helpful specially when you dont have a DLL’s or Assembly that you can reference to or even if its hard to understand how a dll works and how you to define those structures that the assembly is outputting, one of this is finding out what are the active UNC given a DFS Link. To use WMI on .NET is as easy as referencing to:

using System.Management;

then query the WMI objects you need, Now to get which are the active UNC paths given a link or folder location you usually right click a properties of the folder to find out which is active

but programatically you need to query Win32_DfsTarget in the root\cimv2 namespace, by fitlering the results to State = 1 will show all current active connections. Now below is the codes to achieve that on .Net.

Determine active UNC path in DFC using WMI

public static ArrayList GetActiveServers(string sPath)
{
    ArrayList aHostNames = new ArrayList();
    ArrayList aDFSServers = new ArrayList();
    aDFSServers.Add("Server1");
    aDFSServers.Add("Server2");

    foreach (string sHostServer in aDFSServers)
    {
        ManagementObjectCollection oObjectCollection = null;
        if (IsHostOnline(sHostServer, "LinkName", sPath, ref oObjectCollection))
        {
            if (oObjectCollection.Count != 0)
            {
                foreach (ManagementObject oItem in oObjectCollection)
                {
                    aHostNames.Add(oItem.Properties["ServerName"].Value.ToString());
                }
            }
            break;
        }
    }
    return aHostNames;
}

public static bool IsHostOnline(string sHostServer, string sSearchField,
    string sSearchString, ref ManagementObjectCollection oManagementObjectCollection)
{
    try
    {
        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 " + sSearchField + 
            " LIKE '%" + sSearchString.Replace("\\", "\\\\") + "%' and State = 1";

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

        if (oObjectCollection.Count != 0)
        {
            oManagementObjectCollection = oObjectCollection;
            return true;
        }
        return false;
    }
    catch
    {
        return false;
    }
}

To explain a bit on what happens on the code, I had separated them on two Functions, one is to check whether the Host is online and another is to place that query results in a more useable type to be consumed by your application which is an ArrayList Type. Now the Function which checks for the Availability of the host you are querying is also outputting the result set you need so it executes one action for the whole process saving time and resources rather than pinging the server first using WMI then do your stuff, they both go to WMI anyways.

Now if you notice we are checking this for all servers thats why you have that ArrayList aDFSServers on GetActiveServers which ennumerates all your DFS Host, were doing that so in an event that one is down you can still check the other servers on roster thats the reason why you also have DFS anyways, for redundancy. All servers on your DFS Environment will have the same contents on the Win32_DfsTarget anyways.

Now you notice WMI is a bit slow as you are querying a big set of extension data of the Windows Driver Model, if you opt to choose for another option then using Netapi32.dll will be the better option as it is faster but requires more understanding on how it works and the data model that it outputs. Netapi32.dll is a process belonging to the Microsoft Network Program that contains the Windows NET API used so that applications gain access to Microsoft network like DFS. Now to achive the same results as above you need the following codes

Determine active UNC path in DFC using Netapi32.dll

[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,
    ref IntPtr Buffer
    );

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

public static ArrayList GetActiveServersPKI(string sDFSPath)
{
    ArrayList sServers = new ArrayList();
    IntPtr pBuffer = new IntPtr();
    int iResult = NetDfsGetInfo(sDFSPath, null, null, 3, ref pBuffer);
    if (iResult == 0)
    {

        DFS_INFO_3 oDFSInfo = (DFS_INFO_3)Marshal.PtrToStructure(pBuffer, typeof(DFS_INFO_3));
        for (int i = 0; i < oDFSInfo.NumberOfStorages; i++)
        {
            IntPtr pStorage = new IntPtr(oDFSInfo.Storages.ToInt64() + i * Marshal.SizeOf(
                typeof(DFS_STORAGE_INFO)));
            DFS_STORAGE_INFO oStorageInfo = (DFS_STORAGE_INFO)Marshal.PtrToStructure(pStorage,
                typeof(DFS_STORAGE_INFO));

            //Get Only Active Hosts
            if (oStorageInfo.State == 2)
            {
                sServers.Add(oStorageInfo.ServerName);
            }
        }

    }
    return sServers;
}

If you noticed we dont have to ennumerate the servers to query are we are directly communicating with the dll, delivering the result will be fast as well. Now for a bit of an explanation on what the piece of code does.

On the method NetDfsGetInfo you are just importing the Dll called “Netapi32.dll” and exposing thaty to your application, now since the dll methods outputs a buffer you need to understand how that buffer is structured which is defined here. That is why if you notice we defined stuctures DFS_INFO_3 and DFS_STORAGE_INFO to handle that output into a more usable type.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

Raymund Macaalay
Technical Lead
New Zealand New Zealand
http://nz.linkedin.com/in/macaalay
http://macaalay.com/
Follow on   Twitter   Google+   LinkedIn

Comments and Discussions

 
Questioncan not determine which storage server is active Pinmembersteven725-Apr-13 12:16 
QuestionObtaining DFS Link Target Free Space PinmemberMember 829578718-Jan-12 14:02 
AnswerRe: Obtaining DFS Link Target Free Space PinmemberRaymund Macaalay18-Jan-12 14:56 
GeneralRe: Obtaining DFS Link Target Free Space PinmemberMember 829578719-Jan-12 6:01 
GeneralNative American Jewelry | Turquoise Jewelry | SilverTribe Pinmembersilvertribe.links19-Oct-10 6:07 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.141223.1 | Last Updated 26 Oct 2010
Article Copyright 2010 by Raymund Macaalay
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid