从 C# 中的 DFS 路径获取 DFS 文件夹目标(本地服务器路径)

Get DFS folder target (local server path) from a DFS path in C#

我有一个DFS文件夹路径...

\domain.name\SharesRoot\DFSShare

我需要获取此根目录的实际文件夹目标 link 或者换句话说,DFSShare 定位的本地服务器路径

本地服务器path/folder目标如下

\MyServer\Share\MyShare

我已经成功地使用 NetDfsGetClientInfo() 方法从给定的 DFS 路径中检索了一些需要的信息

此方法填充的 DFS_STORAGE_INFO 对象为我提供了以下数据

虽然我正在寻找 ServerName,但 ShareName 对我毫无帮助。

我需要找出路径在什么地方 MyServer 那个DFS路径 \domain.name\SharesRoot\DFSShare 正在瞄准

NetDfsGetInfo() 给我 1168 错误,所以那个方法没有帮助,我还没有尝试 NetDfsEnum() ,但是我的希望并不高,因为它填充了与 NetDfsGetClientInfo() 相同的结构...如果有人在这里有任何其他线索,我将非常感激!

看来 NetDfsGetClientInfo() 确实是满足我特殊需求的答案。

问题是它的行为会根据它是在 DFS 客户端计算机上调用还是在 DFS 服务器计算机上调用而改变。

在客户端机器上调用 returns 具有以下数据的 DFS_STORAGE_INFO 对象:

  • 服务器名称:'MyServer'
  • 共享名:'Share'

返回后所需要做的就是附加子路径,可以使用 DFS_INFO_3 对象的入口路径和 NetDfsGetClientInfo() 调用中使用的原始路径删除子路径

我发现在客户端上我需要首先访问 DFS 路径,然后 Windows 中的某些东西缓存它,这样当我执行 NetDfsGetClientInfo() 时我得到了底层路径(不是 dfs路径)

所以这对我有用:

string dfsPath = "\domain.name\SharesRoot\DFSShare";

//by doing Directory.Exists we access the DFS path, causing Windows to resolve it
if (Directory.Exists(dfsPath))
{
    string dfsPath = DFS.GetSharePath(dfsPath);
    MessageBox.Show($"{dfsPath});
}

这是我在别处找到的 class 代码(不是我的)

  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
            {
                Console.WriteLine("User : {0}, Domain= {1}", Environment.UserName, Environment.UserDomainName);
                Console.WriteLine("Path is {0}", DFSPath);
                int Error = NetDfsGetClientInfo(DFSPath, null, null, 3, out Buffer);
                Console.WriteLine("Error code {0}", Error);
                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 (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;
    }


}