从 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 共享的 ComputerName
和 local 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\
时,它确实说可以找到它。所以我不太明白。
我正在尝试检索此信息(ComputerName
和 local 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 服务器名称和本地路径的主要内容,如果未能解决你的问题,请参考以下文章