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

C# 如何以编程方式在DFS中获取活动UNC路径,c#,wmi,microsoft-distributed-file-system,C#,Wmi,Microsoft Distributed File System,给定DFS路径,我如何知道它当前在编程上的活动路径是什么 对于exmaple,我有两个服务器共享,分别为“\\Server1\Folder\”和“\\Server2\Folder\”,并且它已打开DFS,因此可以在“\\DFS\u Server\Folder\”上访问它,我如何知道当前的活动路径是什么“\\DFS\u Server\Folder\”,它是“\\Server1\Folder\”还是“\\Server2\Folder\”尝试此操作,其中sDFSPath是要查询的路径,sHostSer

给定DFS路径,我如何知道它当前在编程上的活动路径是什么


对于exmaple,我有两个服务器共享,分别为
“\\Server1\Folder\”
“\\Server2\Folder\”
,并且它已打开DFS,因此可以在
“\\DFS\u Server\Folder\”
上访问它,我如何知道当前的活动路径是什么
“\\DFS\u Server\Folder\”
,它是
“\\Server1\Folder\”
还是
“\\Server2\Folder\”

尝试此操作,其中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;
}

希望它有意义

如果我正确理解您的需求,还有一个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;
    }
}

有关API参考,请查看msdn on,和。

谢谢,您的提示很有用。但是,我使用NetDfsGetClientInfo更成功。我还意识到解析过程可能是递归的。我最后至少进行了两次递归调用以获得实际的物理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;
    }
}
公共静态类DFS
{
#地区进口
[DllImport(“Netapi32.dll”,EntryPoint=“NetApiBufferFree”)]
公共静态外部单元NetApiBufferFree(IntPtr Buffer);
[DllImport(“Netapi32.dll”,CharSet=CharSet.Unicode,SetLastError=true)]
公共静态外部int NetDfsGetInfo(
[Marshallas(UnmanagedType.LPWStr)]字符串入口路径,
[Marshallas(UnmanagedType.LPWStr)]字符串服务器名,
[Marshallas(UnmanagedType.LPWStr)]字符串共享名,
整数级,
输出IntPtr缓冲区);
[DllImport(“Netapi32.dll”)]
公共静态外部int NetDfsGetClientInfo(
[Marshallas(UnmanagedType.LPWStr)]字符串入口路径,
[Marshallas(UnmanagedType.LPWStr)]字符串服务器名,
[Marshallas(UnmanagedType.LPWStr)]字符串共享名,
整数级,
输出IntPtr缓冲区);
#端区
#区域结构
公共结构DFS\u信息\u 3
{
[Marshallas(UnmanagedType.LPWStr)]
公共字符串入口路径;
[Marshallas(UnmanagedType.LPWStr)]
公共字符串评论;
公共UInt32州;
公共存储单元32个;
公共IntPtr存储;
}
公共结构DFS\u存储\u信息
{
国家公共部门;
[Marshallas(UnmanagedType.LPWStr)]
公共字符串ServerName;
[Marshallas(UnmanagedType.LPWStr)]
公共字符串共享名;
}
#端区
常量int DFS\u卷\u状态\u OK=0x00000001;
const int DFS\u VOLUME\u STATE\u ONLINE=0x00000004;
const int DFS_STORAGE_STATE_ONLINE=0x00000002;
常量int DFS\u存储\u状态\u活动=0x00000004;
公共静态字符串GetSharePath(字符串DFSPath)
{
如果(!String.IsNullOrEmpty(DFSPath))
{
IntPtr Buffer=IntPtr.Zero;
尝试
{
int Error=NetDfsGetClientInfo(DFSPath,null,null,3,输出缓冲区);
如果(错误==0)
{
DFS_INFO_3 DFSInfo=(DFS_INFO_3)Marshal.ptr结构(缓冲区,类型(DFS_INFO_3));
如果((DFSInfo.State&DFS\u VOLUME\u State\u OK)>0)
{
String SubPath=DFSPath.Remove(0,1+DFSInfo.EntryPath.Length).TrimStart(新字符[]{'\\'});
对于(int i=0;i0)
{
if(String.IsNullOrEmpty(子路径))
{
返回String.Format(@“\\{0}\{1}”、StorageInfo.ServerName、StorageInfo.ShareName);
}
其他的
{
返回GetSharePath(String.Format(@“\{0}\{1}\{2}”、StorageInfo.ServerName、StorageInfo.ShareName、SubPath));
}
}
}
}
}
否则如果(错误==2662)
返回路径;
}
最后
{
NetapipBufferFree(缓冲区);
}
}
返回null;
}
公共静态字符串GetShareName(字符串SharePath)
{
如果(!String.IsNullOrEmpty(SharePath))
{
String[]Tokens=SharePath.Trim(新字符[]{'\\'}).Split(新字符[]{'\\'},StringSplitOptions.RemoveEmptyEntries);

如果(2)我发现了小模式。因此dfs解析是可重复的。假设您正在查找unc a。每次迭代都需要从a的开头删除EntryPath,并重新生成它(前缀为ServerName和ShareName,您从StorageInfo获得),以接收unc b。如果a==b解析已完成。NetDfsGetInfo触发错误1168(未找到),这是有线的,所以我使用了NetDfsGetClientInfo。这一个只返回活动存储的数据。对于非活动存储,它不返回任何数据。解决方法是使用System.IO.Directory.Exists(…)在调用NetDfsGetClientInfo之前在您的unc路径上。NetDfsGetClientInfo是否可以在VBS中使用,也许可以与WMI一起使用?从int Error=NetDfsGetClientInfo(DFSPath,null,null,3,out Buffer)获取2662代码;如果有任何解决问题的建议,上面的内容在VBS中使用WMI时会是什么样子?如果有任何指导,我们将不胜感激。@Raymund我看到您通过了ho
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;
    }
}