Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
Question
Tuesday, October 27, 2015 7:36 AM
I'm working on Windows Server 2012 which comes by default with various DFS CmdLets.
What I'm trying to do is get the ComputerName
and the local path
of a specific UNC share, that is hosted by other DFS servers (Win Srv 2008 R2) on the domain by using PowerShell.
An example:
Get-DfsnFolderTarget -Path '\\domain.net\share\folder\'
Expected result:
ComputerName = 'Server1'
Path = 'E\Home\folder'
I'm not really a network engineer, but I can't seem to find a way to retrieve this information based on the UNC path. Every time I try the CmdLet above I get an error:
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
When trying a Test-Path \\domain.net\share\folder\
it does say that it can be found. So I don't really understand.
All replies (2)
Tuesday, October 27, 2015 9:38 AM âś…Answered
After Googling around for hours I found the solution to my own problem. It's not really native PowerShell, but it does the job. For anyone else interested, here is the code:
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 DNS 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])
}
}
}
}
Wednesday, October 28, 2015 8:36 AM
Thank you for sharing the result!
Please remember to mark the replies as answers if they help and un-mark them if they provide no help. If you have feedback for TechNet Support, contact [email protected].