如何以编程方式获取 DFS 中的活动 UNC 路径

发布于 2024-09-27 21:31:35 字数 319 浏览 9 评论 0原文

给定 DFS 路径,我如何以编程方式知道它当前所在的活动路径是什么。

例如,我有 2 个服务器共享为 "\\Server1\Folder\""\\Server2\Folder\" 并且它已打开 DFS,因此可以访问它在 "\\DFS_Server\Folder\" 上,我如何知道当前 "\\DFS_Server\Folder\" 打开的活动路径是什么,是否是 “\\Server1\Folder\”“\\Server2\Folder\”

Given a DFS path how would I know what is the active path it is currently on programatically.

For exmaple I have 2 Servers shares as "\\Server1\Folder\" and "\\Server2\Folder\" and it has DFS turned on so it can be accessed on "\\DFS_Server\Folder\", how would I know what is the active path currently "\\DFS_Server\Folder\" is on, whether it is "\\Server1\Folder\" or "\\Server2\Folder\".

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

云朵有点甜 2024-10-04 21:31:35

如果我正确理解您的要求,还有一个 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 参考,请检查 msdn NetDfsGetInfoDFS_INFO_3DFS_STORAGE_INFO NetApiBufferFree

If I understand your requirement correctly, there's also an API that seems to do what you need:

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

Use it like this:

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

For an API reference, check msdn on NetDfsGetInfo, DFS_INFO_3, DFS_STORAGE_INFO and NetApiBufferFree.

冰雪梦之恋 2024-10-04 21:31:35

尝试一下,其中 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;
}

希望它有意义

try this where sDFSPath is the path you want to query and sHostServer is the Server you want to query your WMI, this can be any of the two servers you mentioned above. You can even make a more elegant code when it fails on first server then query WMI on the next servers

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

Hope it makes sense

梦明 2024-10-04 21:31:35

谢谢你,你的提示很有用。不过,我使用 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;
    }
}

Thank you, your hints were useful. However I was more successfull with NetDfsGetClientInfo. Also realized that resolving process may be recursive. I ended up with at least 2 recursive calls to get the actual physical UNC share and here is my example.

I don't know, how

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;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文