<# .SYNOPSIS Lists all SMB shares of a Windows file server incl. local path, size and permissions — the basis for the include/exclude decision (projektplan §2.6). .DESCRIPTION Run ON the file server (or against a remote one via -ComputerName). Reports per share: name, local path, description, share-level permissions, NTFS groups, plus optional size/file count. Admin shares (C$, ADMIN$, IPC$) are skipped unless -IncludeAdminShares is given. Purely read-only. Requires local admin for Get-SmbShare (part of Windows Server, no extra module needed). .EXAMPLE .\list-shares.ps1 .EXAMPLE # with size per share — run this ON the file server, it then walks the local # paths instead of the UNC paths (far faster). Still minutes to hours on # millions of files; progress is printed every 50k files. .\list-shares.ps1 -WithSize .NOTES Faster alternative when all shares live under one drive (as on Z-FILESERVER, where everything sits under D:): run share-analysis.ps1 once with a matching folder depth instead of measuring every share separately, e.g. .\share-analysis.ps1 -Paths "D:" -FolderDepth 2 That produces size/count per D:\Abteilungen\ in a single pass over the disk, which is what the share list here maps onto. #> param( [string]$ComputerName = $env:COMPUTERNAME, [switch]$IncludeAdminShares, [switch]$WithSize, [string]$OutDir = (Join-Path (Get-Location) "share-list") ) $ErrorActionPreference = 'Continue' New-Item -ItemType Directory -Path $OutDir -Force | Out-Null Write-Host "=== SMB shares on $ComputerName ===" -ForegroundColor Cyan $shares = Get-SmbShare -CimSession $ComputerName -ErrorAction Stop if (-not $IncludeAdminShares) { $shares = $shares | Where-Object { -not $_.Name.EndsWith('$') } } $result = foreach ($sh in $shares) { Write-Host (" {0,-25} {1}" -f $sh.Name, $sh.Path) # share-level permissions $sharePerms = try { (Get-SmbShareAccess -Name $sh.Name -CimSession $ComputerName -ErrorAction Stop | ForEach-Object { "$($_.AccountName)=$($_.AccessRight)" }) -join '; ' } catch { 'n/a' } # NTFS permissions (top level only) — who actually has access $ntfsPerms = try { $uncPath = "\\$ComputerName\$($sh.Name)" ((Get-Acl -LiteralPath $uncPath -ErrorAction Stop).Access | ForEach-Object { "$($_.IdentityReference)=$($_.FileSystemRights)" } | Select-Object -Unique | Select-Object -First 10) -join '; ' } catch { 'n/a' } $sizeGB = $null; $fileCount = $null if ($WithSize) { # Walk the LOCAL path when we are on the server itself — going through # the UNC path (\\server\share) routes every single file through the SMB # stack and is slower by orders of magnitude on large shares. $scanPath = if ($ComputerName -eq $env:COMPUTERNAME -and $sh.Path) { $sh.Path } else { "\\$ComputerName\$($sh.Name)" } $sw = [System.Diagnostics.Stopwatch]::StartNew() $n = 0L; $bytes = 0L Get-ChildItem -LiteralPath $scanPath -Recurse -File -Force -ErrorAction SilentlyContinue | ForEach-Object { $n++; $bytes += $_.Length if ($n % 50000 -eq 0) { Write-Host (" ... {0:N0} files, {1:N1} GB ({2:N0}s)" -f $n, ($bytes / 1GB), $sw.Elapsed.TotalSeconds) -ForegroundColor DarkGray } } $sw.Stop() $sizeGB = [Math]::Round($bytes / 1GB, 2) $fileCount = $n Write-Host (" {0:N0} files, {1:N1} GB in {2:N0}s" -f $n, ($bytes / 1GB), $sw.Elapsed.TotalSeconds) -ForegroundColor DarkGray } [PSCustomObject]@{ Name = $sh.Name Path = $sh.Path Description = $sh.Description SharePermissions = $sharePerms NtfsPermissions = $ntfsPerms SizeGB = $sizeGB FileCount = $fileCount } } $csv = Join-Path $OutDir "smb-shares.csv" $result | Export-Csv $csv -NoTypeInformation -Encoding UTF8 $result | Format-Table Name, Path, SizeGB, FileCount -AutoSize # DFS namespaces (if used) — often the path users actually see Write-Host "`n=== DFS namespaces ===" -ForegroundColor Cyan try { $roots = Get-DfsnRoot -ErrorAction Stop if ($roots) { $dfs = foreach ($r in $roots) { Get-DfsnFolder -Path "$($r.Path)\*" -ErrorAction SilentlyContinue | ForEach-Object { $t = Get-DfsnFolderTarget -Path $_.Path -ErrorAction SilentlyContinue [PSCustomObject]@{ DfsPath = $_.Path; Targets = ($t.TargetPath -join '; ') } } } $dfs | Export-Csv (Join-Path $OutDir "dfs-namespaces.csv") -NoTypeInformation -Encoding UTF8 $dfs | Format-Table -AutoSize } else { Write-Host " none" } } catch { Write-Host " no DFS role / not available on this host" } Write-Host "`nResults in: $OutDir" -ForegroundColor Green