从 UNC 路径获取 DFS 服务器名称和本地路径

Posted

技术标签:

【中文标题】从 UNC 路径获取 DFS 服务器名称和本地路径【英文标题】:Get DFS Server name and local path from UNC path 【发布时间】:2016-01-25 15:55:06 【问题描述】:

我正在使用 Windows Server 2012,它默认带有各种 DFS CmdLets。

我要做的是获取特定 UNC 共享的 ComputerNamelocal path,该共享由域上的其他 DFS 服务器 (Win Srv 2008 R2) 托管。

一个例子:

Get-DfsnFolderTarget -Path '\\domain.net\share\folder\'

预期结果:

ComputerName = 'Server1'
Path         = 'E\Home\folder'

我并不是真正的网络工程师,但我似乎无法找到基于 UNC 路径检索此信息的方法。每次我尝试上面的 CmdLet 时都会出错:

Get-DfsnFolderTarget : Cannot get DFS folder properites on "\\domain.net\share\folder\"
At line:1 char:1
+ Get-DfsnFolderTarget -Path '\\domain.net\share\folder\'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (MSFT_DfsNamespaceFolderTarget:ROOT\Microsoft\...aceFolderTarget) [Ge 
   t-DfsnFolderTarget], CimException
    + FullyQualifiedErrorId : Windows System Error 1168,Get-DfsnFolderTarget

Get-DfsnFolderTarget : The requested object could not be found.
At line:1 char:1
+ Get-DfsnFolderTarget -Path '\\domain.net\share\folder\'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ObjectNotFound: (MSFT_DfsNamespaceFolderTarget:ROOT\Microsoft\...aceFolderTarget) [Ge 
   t-DfsnFolderTarget], CimException
    + FullyQualifiedErrorId : MI RESULT 6,Get-DfsnFolderTarget

当尝试Test-Path \\domain.net\share\folder\ 时,它确实说可以找到它。所以我不太明白。

我正在尝试检索此信息(ComputerNamelocal path):

【问题讨论】:

【参考方案1】:

我通过几个小时的谷歌搜索和调整一些东西解决了我自己的问题。这是我为其他感兴趣的人最终得到的结果:

Function Get-DFSDetails 
<# 
    .SYNOPSIS   
        Gets DFS details for a UNC path.
    
    .DESCRIPTION
        The Get-DFSDetails CmdLet gets DFS details like DFS Server name, DFS Share name and the local path on the DFS Server for a specific UNC path.
    
    .PARAMETER Credentials 
        PowerShell credential object used to connect to the DFS Server to retrieve the local path on the server.
    
    .PARAMETER Path 
        Specifies a UNC path for the folder.
    
    .EXAMPLE
        Get-DFSDetails -Path '\\domain.net\HOME\Bob' -Credentials $Credentials
        Gets the DFS details for the UNC path '\\domain.net\HOME\Bob'
    
        Path         : \\domain.net\HOME\Bob
        ComputerName : SERVER1.DOMAIN.NET
        ComputerPath : E:\HOME\Bob
        ShareName    : HOME
    
    .EXAMPLE
        '\\domain.net\HOME\Mike', '\\domain.net\HOME\Jake' | Get-DFSDetails -Credentials $Credentials
        Gets the DFS details for the UNC paths '\\domain.net\HOME\Mike' and '\\domain.net\HOME\Jake'
    
        Path         : \\domain.net\HOME\Mike
        ComputerName : SERVER1.DOMAIN.NET
        ComputerPath : E:\HOME\Mike
        ShareName    : HOME 
            
        Path         : \\domain.net\HOME\Jake
        ComputerName : SERVER2.DOMAIN.NET
        ComputerPath : E:\HOME\Jake
        ShareName    : HOME    
    
    .NOTES
        CHANGELOG
        2015/10/27 Function born #>
    
    [CmdLetBinding()]
    Param (
        [Parameter(Mandatory, Position=0)]
        [PSCredential]$Credentials,
        [Parameter(Mandatory, ValueFromPipeline, Position=1)]
        [ValidateScript(
            if (Test-Path -LiteralPath $_ -PathType Container) $true
            else throw "Could not find path '$_'"
        )]
        [String[]]$Path
    )
    
    Begin 
$signature = @'
using System;
using System.Collections.Generic;
using System.Management.Automation;
using System.Runtime.InteropServices;
    
public class Win32Api

    [DllImport("netapi32.dll", SetLastError = true)]
    private static extern int NetApiBufferFree(IntPtr buffer);
    
    [DllImport("Netapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    private static extern int NetDfsGetClientInfo
    (
    [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 List<PSObject> NetDfsGetClientInfo(string DfsPath)
    
        IntPtr buffer = new IntPtr();
        List<PSObject> returnList = new List<PSObject>();
    
        try
        
            int result = NetDfsGetClientInfo(DfsPath, null, null, 3, ref buffer);
    
            if (result != 0)
            
                throw (new SystemException("Error getting DFS information"));
            
            else
            
                DFS_INFO_3 dfsInfo = (DFS_INFO_3)Marshal.PtrToStructure(buffer, typeof(DFS_INFO_3));
    
                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));
    
                    PSObject psObject = new PSObject();
    
                    psObject.Properties.Add(new PSNoteProperty("State", storageInfo.State));
                    psObject.Properties.Add(new PSNoteProperty("ServerName", storageInfo.ServerName));
                    psObject.Properties.Add(new PSNoteProperty("ShareName", storageInfo.ShareName));
    
                    returnList.Add(psObject);
                
            
        
        catch (Exception e)
        
            throw(e);
        
        finally
        
            NetApiBufferFree(buffer);
        
        return returnList;
    

'@
    
        if (-not ('Win32Api' -as [Type])) 
            Add-Type -TypeDefinition $signature
        
    
    
    Process 
        foreach ($P in $Path) 
            Try 
                # State 6 notes that the DFS path is online and active
                $DFS = [Win32Api]::NetDfsGetClientInfo($P) | Where-Object  $_.State -eq 6  | 
                    Select-Object ServerName, ShareName
    
                $SessionParams = @
                    Credential    = $Credentials
                    ComputerName  = $DFS.ServerName
                    SessionOption = New-CimSessionOption -Protocol Dcom
                
                $CimParams = @
                    CimSession = New-CimSession @SessionParams
                    ClassName  = 'Win32_Share'
                
                $LocalPath = Get-CimInstance @CimParams | Where-Object Name -EQ $DFS.ShareName | 
                    Select-Object -ExpandProperty Path
    
                [PSCustomObject][Ordered]@
                    Path         = $P
                    ComputerName = $DFS.ServerName
                    ComputerPath = $LocalPath + ($P -split $DFS.ShareName, 2)[1]
                    ShareName    = $DFS.ShareName
                
            
            Catch 
                Write-Error $Error[0].Exception.Message
                $Global:Error.Remove($Global:Error[0])
            
        
    

【讨论】:

以上是关于从 UNC 路径获取 DFS 服务器名称和本地路径的主要内容,如果未能解决你的问题,请参考以下文章

从FTP服务器获取文件并将其复制到UNC目录

获取本地网络服务器上所有 UNC 共享文件夹的列表

从映射的网络驱动器获取 UNC 路径

Windows 7 - 无网络 - 我需要在本地伪造 UNC 路径以进行开发/测试吗?

无法访问 Powershell 远程会话中的 UNC 路径

File.Move 不适用于 UNC 路径