Skip to content

Instantly share code, notes, and snippets.

@robert-niestroj
Last active August 25, 2026 21:13
Show Gist options
  • Select an option

  • Save robert-niestroj/1448b6d1cc0736625ee676ceae864960 to your computer and use it in GitHub Desktop.

Select an option

Save robert-niestroj/1448b6d1cc0736625ee676ceae864960 to your computer and use it in GitHub Desktop.
<#
.SYNOPSIS
Diagnoses common Windows 11 SMB / network-sharing problems and prints a
color-coded TUI report with pass/fail checks and recommendations.
.DESCRIPTION
Run this on the PC that is SHARING the folder (e.g. DELL-MICRO).
Optionally run it again on the CLIENT PC that gets the error, using
-TargetComputer to also test connectivity to the host.
.PARAMETER TargetComputer
Name or IP of the other PC. When run on the client, this tests
reachability/port 445 to the sharing PC. When run on the host, this
tests reachability to the client (mostly informational).
.PARAMETER ShareName
Optional. Limit the share/permissions check to one specific share name
instead of listing all shares.
.EXAMPLE
# On DELL-MICRO (the PC sharing the folder), run elevated:
.\Test-NetworkSharing.ps1 -TargetComputer "LIVINGROOM-PC"
.EXAMPLE
# On the client PC that can't open the share:
.\Test-NetworkSharing.ps1 -TargetComputer "DELL-MICRO"
#>
[CmdletBinding()]
param(
[string]$TargetComputer,
[string]$ShareName
)
# ---------------------------------------------------------------------------
# Setup
# ---------------------------------------------------------------------------
$Host.UI.RawUI.WindowTitle = "Network Sharing Diagnostics - $env:COMPUTERNAME"
$script:Findings = New-Object System.Collections.Generic.List[object]
function Add-Finding {
param([ValidateSet('OK','WARN','FAIL','INFO')] [string]$Status, [string]$Message, [string]$Fix = "")
$script:Findings.Add([pscustomobject]@{ Status = $Status; Message = $Message; Fix = $Fix })
}
function Write-Banner {
param([string]$Text)
$w = 78
$line = ('=' * $w)
Write-Host ""
Write-Host $line -ForegroundColor Cyan
$pad = [Math]::Max(0, [int](($w - $Text.Length) / 2))
Write-Host ((' ' * $pad) + $Text) -ForegroundColor Cyan
Write-Host $line -ForegroundColor Cyan
}
function Write-Section {
param([string]$Title)
Write-Host ""
Write-Host " >> $Title" -ForegroundColor Yellow
Write-Host (" " + ('-' * 76)) -ForegroundColor DarkGray
}
function Write-Check {
param(
[ValidateSet('OK','WARN','FAIL','INFO')] [string]$Status,
[string]$Message,
[string]$Detail = "",
[string]$Fix = ""
)
switch ($Status) {
'OK' { $icon = "[ OK ]"; $color = "Green" }
'WARN' { $icon = "[WARN]"; $color = "DarkYellow" }
'FAIL' { $icon = "[FAIL]"; $color = "Red" }
'INFO' { $icon = "[INFO]"; $color = "Gray" }
}
Write-Host " $icon " -ForegroundColor $color -NoNewline
Write-Host $Message
if ($Detail) { Write-Host " $Detail" -ForegroundColor DarkGray }
if ($Fix -and $Status -in @('WARN','FAIL')) {
Write-Host " FIX: $Fix" -ForegroundColor Magenta
}
Add-Finding -Status $Status -Message $Message -Fix $Fix
}
$isAdmin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
# ---------------------------------------------------------------------------
Write-Banner "WINDOWS NETWORK SHARING DIAGNOSTICS"
Write-Host " Host: $env:COMPUTERNAME User: $env:USERNAME Elevated: $isAdmin" -ForegroundColor Gray
if (-not $isAdmin) {
Write-Host ""
Write-Host " NOTE: Not running as Administrator. Some checks (firewall, registry," -ForegroundColor DarkYellow
Write-Host " SMB config) may be incomplete or inaccurate. Re-run elevated for full results." -ForegroundColor DarkYellow
}
# ---------------------------------------------------------------------------
Write-Section "1. Network Profile (Private vs Public)"
try {
$profiles = Get-NetConnectionProfile
foreach ($p in $profiles) {
if ($p.NetworkCategory -eq 'Public') {
Write-Check -Status FAIL -Message "Interface '$($p.InterfaceAlias)' is on network category: Public" `
-Fix "Set-NetConnectionProfile -InterfaceAlias '$($p.InterfaceAlias)' -NetworkCategory Private (or Settings > Network > Properties > Private)"
} elseif ($p.NetworkCategory -eq 'DomainAuthenticated') {
Write-Check -Status OK -Message "Interface '$($p.InterfaceAlias)' is on a Domain network (sharing rules apply per domain profile)"
} else {
Write-Check -Status OK -Message "Interface '$($p.InterfaceAlias)' is on network category: Private"
}
}
if (-not $profiles) { Write-Check -Status WARN -Message "No active network profiles found" }
} catch {
Write-Check -Status WARN -Message "Could not read network profile" -Detail $_.Exception.Message
}
# ---------------------------------------------------------------------------
Write-Section "2. Required Services"
$services = @(
@{ Name = "LanmanServer"; Desc = "Server (needed to HOST shares)" }
@{ Name = "LanmanWorkstation"; Desc = "Workstation (needed to ACCESS shares)" }
@{ Name = "FDResPub"; Desc = "Function Discovery Resource Publication (Network discovery)" }
@{ Name = "fdPHost"; Desc = "Function Discovery Provider Host (Network discovery)" }
@{ Name = "SSDPSRV"; Desc = "SSDP Discovery (Network discovery)" }
@{ Name = "upnphost"; Desc = "UPnP Device Host (Network discovery)" }
)
foreach ($s in $services) {
try {
$svc = Get-Service -Name $s.Name -ErrorAction Stop
if ($svc.Status -eq 'Running') {
Write-Check -Status OK -Message "$($s.Name) is running" -Detail $s.Desc
} else {
Write-Check -Status FAIL -Message "$($s.Name) is $($svc.Status)" -Detail $s.Desc `
-Fix "Start-Service $($s.Name); Set-Service $($s.Name) -StartupType Automatic"
}
} catch {
Write-Check -Status WARN -Message "$($s.Name) service not found" -Detail $s.Desc
}
}
# ---------------------------------------------------------------------------
Write-Section "3. Firewall Rules"
$fwGroups = @("File and Printer Sharing", "Network Discovery")
foreach ($grp in $fwGroups) {
try {
$rules = Get-NetFirewallRule -DisplayGroup $grp -ErrorAction Stop
$enabledPrivate = $rules | Where-Object { $_.Enabled -eq $true -and $_.Profile -match 'Private|Any|Domain' }
if ($enabledPrivate) {
Write-Check -Status OK -Message "'$grp' firewall rules are enabled" -Detail "$($enabledPrivate.Count) of $($rules.Count) rules enabled"
} else {
Write-Check -Status FAIL -Message "'$grp' firewall rules are disabled" `
-Fix "Enable-NetFirewallRule -DisplayGroup '$grp' (or Control Panel > Windows Defender Firewall > Allow an app)"
}
} catch {
Write-Check -Status WARN -Message "Could not read firewall rules for '$grp'" -Detail $_.Exception.Message
}
}
# ---------------------------------------------------------------------------
Write-Section "4. SMB Protocol Configuration"
try {
$smbCfg = Get-SmbServerConfiguration -ErrorAction Stop
if ($smbCfg.EnableSMB2Protocol) {
Write-Check -Status OK -Message "SMB2/3 protocol is enabled on the server"
} else {
Write-Check -Status FAIL -Message "SMB2/3 protocol is disabled" -Fix "Set-SmbServerConfiguration -EnableSMB2Protocol `$true"
}
if ($smbCfg.EnableSMB1Protocol) {
Write-Check -Status WARN -Message "SMB1 is enabled (legacy, insecure)" -Fix "Disable unless required by very old devices: Set-SmbServerConfiguration -EnableSMB1Protocol `$false"
} else {
Write-Check -Status OK -Message "SMB1 is disabled (recommended)"
}
} catch {
Write-Check -Status WARN -Message "Could not read SMB server configuration" -Detail $_.Exception.Message
}
# Guest auth (matters most when run on the CLIENT PC connecting without a matching user account)
try {
$guestAuthPath = "HKLM:\SYSTEM\CurrentControlSet\Services\LanmanWorkstation\Parameters"
$guestAuth = Get-ItemProperty -Path $guestAuthPath -Name AllowInsecureGuestAuth -ErrorAction SilentlyContinue
if ($null -ne $guestAuth) {
if ($guestAuth.AllowInsecureGuestAuth -eq 1) {
Write-Check -Status OK -Message "Insecure guest logons allowed on THIS PC as a client" -Detail "Relevant if connecting via Guest with no matching user account"
} else {
Write-Check -Status WARN -Message "Insecure guest logons are DISABLED on this PC as a client" `
-Detail "If the share requires Guest access (no matching username/password), this causes 'unable to connect' errors" `
-Fix "Only if truly needed: Set-ItemProperty -Path '$guestAuthPath' -Name AllowInsecureGuestAuth -Value 1 -Type DWord (or via gpedit: Computer Config > Admin Templates > Network > Lanman Workstation > Enable insecure guest logons)"
}
} else {
Write-Check -Status INFO -Message "AllowInsecureGuestAuth not explicitly set (uses Windows default: disabled)"
}
} catch {
Write-Check -Status INFO -Message "Could not read guest auth policy" -Detail $_.Exception.Message
}
# ---------------------------------------------------------------------------
Write-Section "5. Guest Account Status"
try {
$guest = Get-LocalUser -Name "Guest" -ErrorAction Stop
if ($guest.Enabled) {
Write-Check -Status INFO -Message "Local Guest account is Enabled" -Detail "Only matters if share is intentionally set up for anonymous/guest access"
} else {
Write-Check -Status OK -Message "Local Guest account is Disabled (normal/secure default)"
}
} catch {
Write-Check -Status INFO -Message "Could not read local Guest account status" -Detail $_.Exception.Message
}
# ---------------------------------------------------------------------------
Write-Section "6. Shared Folders"
try {
$shares = Get-SmbShare -ErrorAction Stop | Where-Object { $_.Name -notmatch '\$$' -and $_.Name -ne 'IPC$' }
if ($ShareName) { $shares = $shares | Where-Object { $_.Name -eq $ShareName } }
if (-not $shares) {
Write-Check -Status FAIL -Message "No (non-admin) shared folders found on this PC" -Fix "Create one with: New-SmbShare -Name 'ShareName' -Path 'C:\Path' -FullAccess 'Everyone' (or specific users)"
}
foreach ($sh in $shares) {
Write-Host ""
Write-Host " - Share: $($sh.Name) -> $($sh.Path)" -ForegroundColor White
# Share-level permissions
try {
$access = Get-SmbShareAccess -Name $sh.Name -ErrorAction Stop
foreach ($a in $access) {
Write-Check -Status INFO -Message "Share permission: $($a.AccountName) = $($a.AccessControlType) $($a.AccessRight)"
}
} catch {
Write-Check -Status WARN -Message "Could not read share permissions for '$($sh.Name)'" -Detail $_.Exception.Message
}
# NTFS permissions on the underlying folder
if (Test-Path $sh.Path) {
try {
$acl = Get-Acl -Path $sh.Path -ErrorAction Stop
$everyoneOrUsers = $acl.Access | Where-Object { $_.IdentityReference -match 'Everyone|Users|Authenticated Users' }
if ($everyoneOrUsers) {
Write-Check -Status OK -Message "NTFS permissions include a broad group (Everyone/Users) on '$($sh.Path)'"
} else {
Write-Check -Status WARN -Message "NTFS permissions on '$($sh.Path)' don't include Everyone/Users/Authenticated Users" `
-Detail "Even if the SHARE permission allows access, restrictive NTFS permissions will still block it (most restrictive wins)" `
-Fix "Grant the specific user/group Read (or Modify) NTFS permission via folder Properties > Security, or: icacls ""$($sh.Path)"" /grant Users:(OI)(CI)RX"
}
} catch {
Write-Check -Status WARN -Message "Could not read NTFS ACL for '$($sh.Path)'" -Detail $_.Exception.Message
}
} else {
Write-Check -Status FAIL -Message "Share path '$($sh.Path)' does not exist on disk" -Fix "Fix or recreate the share pointing to a valid folder path"
}
}
} catch {
Write-Check -Status WARN -Message "Could not enumerate SMB shares" -Detail $_.Exception.Message
}
# ---------------------------------------------------------------------------
Write-Section "7. Remote UAC / Token Filtering"
try {
$lsaPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System"
$tokenPolicy = Get-ItemProperty -Path $lsaPath -Name LocalAccountTokenFilterPolicy -ErrorAction SilentlyContinue
if ($null -ne $tokenPolicy -and $tokenPolicy.LocalAccountTokenFilterPolicy -eq 1) {
Write-Check -Status INFO -Message "LocalAccountTokenFilterPolicy = 1 (remote local-admin connections use full token)"
} else {
Write-Check -Status INFO -Message "LocalAccountTokenFilterPolicy not set to 1 (default)" `
-Detail "Only relevant if connecting with a LOCAL admin account remotely and getting access-denied despite correct permissions" `
-Fix "If needed: New-ItemProperty -Path '$lsaPath' -Name LocalAccountTokenFilterPolicy -Value 1 -PropertyType DWord -Force"
}
} catch {
Write-Check -Status INFO -Message "Could not read LocalAccountTokenFilterPolicy" -Detail $_.Exception.Message
}
# ---------------------------------------------------------------------------
if ($TargetComputer) {
Write-Section "8. Connectivity Test to '$TargetComputer'"
try {
$ping = Test-Connection -ComputerName $TargetComputer -Count 2 -Quiet -ErrorAction SilentlyContinue
if ($ping) {
Write-Check -Status OK -Message "Ping to $TargetComputer succeeded"
} else {
Write-Check -Status WARN -Message "Ping to $TargetComputer failed" -Detail "ICMP may just be blocked by firewall; not always fatal for SMB"
}
} catch {
Write-Check -Status WARN -Message "Ping test error" -Detail $_.Exception.Message
}
try {
$portTest = Test-NetConnection -ComputerName $TargetComputer -Port 445 -WarningAction SilentlyContinue
if ($portTest.TcpTestSucceeded) {
Write-Check -Status OK -Message "TCP port 445 (SMB) reachable on $TargetComputer"
} else {
Write-Check -Status FAIL -Message "TCP port 445 (SMB) NOT reachable on $TargetComputer" `
-Fix "Check firewall on $TargetComputer (allow File and Printer Sharing), confirm both PCs are on the same network/subnet, and that $TargetComputer is powered on and not asleep"
}
} catch {
Write-Check -Status WARN -Message "Port 445 test error" -Detail $_.Exception.Message
}
try {
Resolve-DnsName -Name $TargetComputer -ErrorAction Stop | Out-Null
Write-Check -Status OK -Message "Name resolution for '$TargetComputer' succeeded"
} catch {
Write-Check -Status WARN -Message "Name resolution for '$TargetComputer' failed" `
-Detail "NetBIOS/mDNS name resolution can be flaky between PCs; try connecting by IP instead: \\<IP address>\ShareName" `
-Fix "Find IP with: Resolve-DnsName $TargetComputer or arp -a or check it on $TargetComputer with ipconfig"
}
}
# ---------------------------------------------------------------------------
Write-Banner "SUMMARY"
$fails = $script:Findings | Where-Object { $_.Status -eq 'FAIL' }
$warns = $script:Findings | Where-Object { $_.Status -eq 'WARN' }
$oks = $script:Findings | Where-Object { $_.Status -eq 'OK' }
Write-Host " OK: $($oks.Count) " -ForegroundColor Green -NoNewline
Write-Host "WARN: $($warns.Count) " -ForegroundColor DarkYellow -NoNewline
Write-Host "FAIL: $($fails.Count)" -ForegroundColor Red
if ($fails.Count -eq 0 -and $warns.Count -eq 0) {
Write-Host ""
Write-Host " All checks passed. If the client still can't connect, try:" -ForegroundColor Green
Write-Host " - Run this same script ON THE CLIENT PC with -TargetComputer '$env:COMPUTERNAME'"
Write-Host " - Connect via IP instead of name: \\<IP-of-$env:COMPUTERNAME>\ShareName"
Write-Host " - Note the EXACT error text/code on the client (e.g. 0x80070035, 0x80070005) for further diagnosis"
} else {
if ($fails.Count -gt 0) {
Write-Host ""
Write-Host " Top priority fixes (FAIL):" -ForegroundColor Red
foreach ($f in $fails) {
Write-Host " - $($f.Message)" -ForegroundColor Red
if ($f.Fix) { Write-Host " -> $($f.Fix)" -ForegroundColor DarkGray }
}
}
if ($warns.Count -gt 0) {
Write-Host ""
Write-Host " Worth checking (WARN):" -ForegroundColor DarkYellow
foreach ($w in $warns) {
Write-Host " - $($w.Message)" -ForegroundColor DarkYellow
if ($w.Fix) { Write-Host " -> $($w.Fix)" -ForegroundColor DarkGray }
}
}
}
Write-Host ""
Write-Host ("=" * 80) -ForegroundColor Cyan
Write-Host " Tip: run this script (elevated) on BOTH PCs for the full picture:" -ForegroundColor Gray
Write-Host " On DELL-MICRO (host): .\Test-NetworkSharing.ps1 -TargetComputer 'ClientPCName'"
Write-Host " On the client PC: .\Test-NetworkSharing.ps1 -TargetComputer 'DELL-MICRO'"
Write-Host ("=" * 80) -ForegroundColor Cyan
Write-Host ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment