The request was, without accessing to the server, only with a list of DFS path (around 200 path), try to get by script the DFS information such as right clicking on the folder then DFS Tab.

As I have 200 DFS path and multiple ReparsePoint inside I won’t do it manually.
Also please note that I didn’t have the permission to use DFSN module for Powershell.
So the idea was as following:
- The script should take a csv file as input with the DFS path
- The script should found out which folder have ReparsePoint
- The script should extract the DFS Tab information and export it to a csv file
So let’s start:
1. Input
2. Script
2.1. Function : Write-InFile
2.2. Function : StartAnalyse
2.3. Function : Get-DFSDetails
2.4. Execute
2.5. The whole script
Input
As mentionned below, the input is going to be a csv with all the DFS path. Simple csv file, just one column call name and the path below.

Script
- Function : Write-InFile
Nothing very complicated, a function which write in a file.
It take two parameters, the message you want to write in file and the path where the file is.
Function Write-InFile([string]$message, [string]$filepath){ Add-Content $filepath "$message" }
- Function : StartAnalyse
This function is going to parse your DFS to find out the ReparsePoint. I haven’t Recurse in that case, because if it was the case, it will go inside some folders with ReparsePoint which wasn’t my goal. If it didn’t find a ReparsePoint, it will go inside folders until it find one. If it find one, it will get the DFS information through another function.
There are two parameters for this function, $dfs which is use for the export file, and $path which is the actual parsed folder.
Function StartAnalyse{ param( [string]$path, [string]$dfs ) $item = Get-ChildItem -Path $path $item | ForEach-Object{ if($_.Attributes -band [System.IO.FileAttributes]::ReparsePoint){ Write-Host $_.FullName Try { Get-DFSDetails -Path $_.FullName -strdfs $dfs } Catch { Write-Error $Error[0].Exception.Message $Global:Error.Remove($Global:Error[0]) Write-InFile -message "$dfs;$path;;;$($Error[0].Exception.Message);" -filepath "$folderpath" } } else{ StartAnalyse -path $_.FullName -dfs $dfs } } }
- Function : Get-DFSDetails
That’s the one you have been waiting for.
Firstable let’s thanks Darklite1, he made the function to get this details in the following stack overflow post. I have edited a bit (remove things I didn’t needed).
The in parameters you will find the $Path which is the folder where you have your ReparsePoint. And I have added $strdfs which is use for generating the report.
Function Get-DFSDetails { [CmdLetBinding()] Param ( [Parameter(Mandatory, ValueFromPipeline, Position=0)] [ValidateScript({ if (Test-Path -LiteralPath $_ -PathType Container) {$true} else {throw "Could not find path '$_'"} })] [String[]]$Path, [Parameter(Mandatory, Position=0)] [String]$strdfs ) 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 NetDfsGetClientInfo(string DfsPath) { IntPtr buffer = new IntPtr(); List returnList = new List(); 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 { $DFS = [Win32Api]::NetDfsGetClientInfo($P) | Where-Object { $_.State -eq 6 } | Select-Object ServerName, ShareName Write-InFile -message "$strdfs;$Path;$($DFS.ServerName);\\$($DFS.ServerName)\$($DFS.ShareName);;" -filepath "$folderpath" } Catch { Write-Error $Error[0].Exception.Message $Global:Error.Remove($Global:Error[0]) Write-InFile -message "$strdfs;$Path;;;;$($Error[0].Exception.Message)" -filepath "$folderpath" } } } }
- Execute
How to call the functions above.
#Script $folderpath = "Path\To\Output\ReportDFS.csv"; $csv = Import-Csv -Path "Path\To\Input.csv" -Delimiter ";" Write-InFile -message "DFS;DFSPath;Server;ServerPath;Error;" -filepath "$folderpath" foreach($csvI in $csv){ $dfs = $csvI.Name StartAnalyse -path $dfs -dfs $dfs }
- The whole script
Function Write-InFile([string]$message, [string]$filepath){ Add-Content $filepath "$message" } Function Get-DFSDetails { [CmdLetBinding()] Param ( [Parameter(Mandatory, ValueFromPipeline, Position=0)] [ValidateScript({ if (Test-Path -LiteralPath $_ -PathType Container) {$true} else {throw "Could not find path '$_'"} })] [String[]]$Path, [Parameter(Mandatory, Position=0)] [String]$strdfs ) 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 NetDfsGetClientInfo(string DfsPath) { IntPtr buffer = new IntPtr(); List returnList = new List(); 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 { $DFS = [Win32Api]::NetDfsGetClientInfo($P) | Where-Object { $_.State -eq 6 } | Select-Object ServerName, ShareName Write-InFile -message "$strdfs;$Path;$($DFS.ServerName);\\$($DFS.ServerName)\$($DFS.ShareName);;" -filepath "$folderpath" } Catch { Write-Error $Error[0].Exception.Message $Global:Error.Remove($Global:Error[0]) Write-InFile -message "$strdfs;$Path;;;;$($Error[0].Exception.Message)" -filepath "$folderpath" } } } } Function StartAnalyse{ param( [string]$path, [string]$dfs ) $item = Get-ChildItem -Path $path $item | ForEach-Object{ if($_.Attributes -band [System.IO.FileAttributes]::ReparsePoint){ Write-Host $_.FullName Try { Get-DFSDetails -Path $_.FullName -strdfs $dfs } Catch { Write-Error $Error[0].Exception.Message $Global:Error.Remove($Global:Error[0]) Write-InFile -message "$dfs;$path;;;$($Error[0].Exception.Message);" -filepath "$folderpath" } } else{ StartAnalyse -path $_.FullName -dfs $dfs } } } #Script $folderpath = "Path\To\Output\ReportDFS.csv"; $csv = Import-Csv -Path "Path\To\Input.csv" -Delimiter ";" Write-InFile -message "DFS;DFSPath;Server;ServerPath;Error;" -filepath "$folderpath" foreach($csvI in $csv){ $dfs = $csvI.Name StartAnalyse -path $dfs -dfs $dfs }