#Requires -RunAsAdministrator
<#
.SYNOPSIS
Comprehensive Thunderbolt/Docking Station Diagnostic Scanner
.DESCRIPTION
Scans all relevant settings, drivers, registry keys, and configurations
that affect Thunderbolt dock Ethernet connectivity at pre-login.
.NOTES
Author: System Diagnostic Tool
Version: 1.0
Run this on BOTH the working HP image AND your custom image for comparison
#>
# Set output file
$outputPath = "$env:USERPROFILE\Desktop\TB_Dock_Diagnostic_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"
$jsonPath = "$env:USERPROFILE\Desktop\TB_Dock_Diagnostic_$(Get-Date -Format 'yyyyMMdd_HHmmss').json"
# Function to write both to console and file
function Write-Output-Both {
param([string]$Message)
Write-Host $Message
Add-Content -Path $outputPath -Value $Message
}
# Start transcript
Start-Transcript -Path "$env:USERPROFILE\Desktop\TB_Dock_Transcript_$(Get-Date -Format 'yyyyMMdd_HHmmss').txt"
Write-Output-Both "============================================"
Write-Output-Both "THUNDERBOLT DOCK DIAGNOSTIC SCANNER"
Write-Output-Both "Scan Date: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
Write-Output-Both "Computer: $env:COMPUTERNAME"
Write-Output-Both "============================================`n"
# Create hashtable for JSON export
$diagnosticData = @{}
# ============================================
# 1. SYSTEM INFORMATION
# ============================================
Write-Output-Both "`n[1] === SYSTEM INFORMATION ===`n"
$computerInfo = Get-ComputerInfo | Select-Object `
WindowsProductName, WindowsVersion, WindowsBuildLabEx, `
OsHardwareAbstractionLayer, BiosFirmwareType, BiosVersion, `
BiosManufacturer, CsManufacturer, CsModel
$diagnosticData['SystemInfo'] = $computerInfo
$computerInfo | Format-List | Out-String | Write-Output-Both
# BIOS Version
$bios = Get-CimInstance -ClassName Win32_BIOS
Write-Output-Both "BIOS Version: $($bios.SMBIOSBIOSVersion)"
Write-Output-Both "BIOS Release Date: $($bios.ReleaseDate)"
$diagnosticData['BIOS'] = @{
Version = $bios.SMBIOSBIOSVersion
ReleaseDate = $bios.ReleaseDate
}
# ============================================
# 2. KERNEL DMA PROTECTION STATUS
# ============================================
Write-Output-Both "`n[2] === KERNEL DMA PROTECTION STATUS ===`n"
$dmaProtection = Get-CimInstance -Namespace root\Microsoft\Windows\DeviceGuard -ClassName Win32_DeviceGuard -ErrorAction SilentlyContinue
if ($dmaProtection) {
Write-Output-Both "Kernel DMA Protection Available: $($dmaProtection.VirtualizationBasedSecurityStatus -ne 0)"
$diagnosticData['KernelDMAProtection'] = @{
Available = $dmaProtection.VirtualizationBasedSecurityStatus -ne 0
Status = $dmaProtection
}
}
# Check via msinfo32 alternative
$msinfo = systeminfo | Select-String "Kernel DMA Protection"
Write-Output-Both $msinfo
# ============================================
# 3. REGISTRY KEYS - DMA & THUNDERBOLT
# ============================================
Write-Output-Both "`n[3] === CRITICAL REGISTRY KEYS ===`n"
$registryKeys = @{
# Kernel DMA Protection
'DMA_DeviceEnumerationPolicy' = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Kernel DMA Protection'
# BitLocker DMA Settings
'BitLocker_DMA' = 'HKLM:\SOFTWARE\Policies\Microsoft\FVE'
# Device Guard / VBS
'DeviceGuard' = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\DeviceGuard'
# Power Settings
'PowerSettings' = 'HKLM:\SYSTEM\CurrentControlSet\Control\Power'
# Thunderbolt Settings
'Thunderbolt_DTBT' = 'HKLM:\SYSTEM\CurrentControlSet\Services\DTBT'
'Thunderbolt_Policy' = 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Thunderbolt'
# Fast Startup
'FastStartup' = 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Power'
# Network related
'Dot3Svc' = 'HKLM:\SYSTEM\CurrentControlSet\Services\dot3svc'
'Wired AutoConfig' = 'HKLM:\SYSTEM\CurrentControlSet\Services\dot3svc'
}
$diagnosticData['RegistryKeys'] = @{}
foreach ($key in $registryKeys.GetEnumerator()) {
Write-Output-Both "`n--- $($key.Key) ---"
Write-Output-Both "Path: $($key.Value)"
if (Test-Path $key.Value) {
$regValues = Get-ItemProperty -Path $key.Value -ErrorAction SilentlyContinue
$regValues | Format-List | Out-String | Write-Output-Both
$diagnosticData['RegistryKeys'][$key.Key] = $regValues
} else {
Write-Output-Both "Registry path does not exist"
$diagnosticData['RegistryKeys'][$key.Key] = "NOT_FOUND"
}
}
# Specific important values
Write-Output-Both "`n--- SPECIFIC DMA POLICY VALUES ---"
$specificKeys = @(
@{Path='HKLM:\SOFTWARE\Policies\Microsoft\Windows\Kernel DMA Protection'; Name='DeviceEnumerationPolicy'},
@{Path='HKLM:\SOFTWARE\Policies\Microsoft\FVE'; Name='DisableExternalDMAUnderLock'},
@{Path='HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Power'; Name='HiberbootEnabled'},
@{Path='HKLM:\SOFTWARE\Policies\Microsoft\Windows\DeviceGuard'; Name='EnableVirtualizationBasedSecurity'},
@{Path='HKLM:\SOFTWARE\Policies\Microsoft\Windows\DeviceGuard'; Name='HypervisorEnforcedCodeIntegrity'}
)
$diagnosticData['SpecificPolicies'] = @{}
foreach ($item in $specificKeys) {
try {
$value = Get-ItemProperty -Path $item.Path -Name $item.Name -ErrorAction Stop
Write-Output-Both "$($item.Path)\$($item.Name) = $($value.$($item.Name))"
$diagnosticData['SpecificPolicies']["$($item.Path)\$($item.Name)"] = $value.$($item.Name)
} catch {
Write-Output-Both "$($item.Path)\$($item.Name) = NOT SET"
$diagnosticData['SpecificPolicies']["$($item.Path)\$($item.Name)"] = "NOT_SET"
}
}
# ============================================
# 4. THUNDERBOLT / USB4 DRIVERS & DEVICES
# ============================================
Write-Output-Both "`n[4] === THUNDERBOLT & USB4 DRIVERS ===`n"
# Thunderbolt Controllers
$tbControllers = Get-PnpDevice -Class System | Where-Object {
$_.FriendlyName -match "Thunderbolt|USB4|TBT|JHL"
}
Write-Output-Both "Thunderbolt/USB4 Controllers:"
$diagnosticData['ThunderboltControllers'] = @()
foreach ($ctrl in $tbControllers) {
Write-Output-Both "`nDevice: $($ctrl.FriendlyName)"
Write-Output-Both "Status: $($ctrl.Status)"
Write-Output-Both "Instance ID: $($ctrl.InstanceId)"
# Get driver info
$driver = Get-PnpDeviceProperty -InstanceId $ctrl.InstanceId -KeyName DEVPKEY_Device_DriverVersion -ErrorAction SilentlyContinue
if ($driver) {
Write-Output-Both "Driver Version: $($driver.Data)"
}
# DMA Remapping Policy
$dmaPolicy = Get-PnpDeviceProperty -InstanceId $ctrl.InstanceId -KeyName DEVPKEY_Device_DmaRemappingPolicy -ErrorAction SilentlyContinue
if ($dmaPolicy) {
Write-Output-Both "DMA Remapping Policy: $($dmaPolicy.Data)"
}
$diagnosticData['ThunderboltControllers'] += @{
Name = $ctrl.FriendlyName
Status = $ctrl.Status
InstanceId = $ctrl.InstanceId
DriverVersion = $driver.Data
DMARemappingPolicy = $dmaPolicy.Data
}
}
# USB4 Host Router
$usb4Routers = Get-PnpDevice | Where-Object {
$_.FriendlyName -match "USB4.*Router"
}
Write-Output-Both "`n--- USB4 Routers ---"
$diagnosticData['USB4Routers'] = @()
foreach ($router in $usb4Routers) {
Write-Output-Both "`nRouter: $($router.FriendlyName)"
Write-Output-Both "Status: $($router.Status)"
$routerDriver = Get-PnpDeviceProperty -InstanceId $router.InstanceId -KeyName DEVPKEY_Device_DriverVersion -ErrorAction SilentlyContinue
Write-Output-Both "Driver Version: $($routerDriver.Data)"
$diagnosticData['USB4Routers'] += @{
Name = $router.FriendlyName
Status = $router.Status
DriverVersion = $routerDriver.Data
}
}
# ============================================
# 5. NETWORK ADAPTERS (DOCK & INTERNAL)
# ============================================
Write-Output-Both "`n[5] === NETWORK ADAPTERS ===`n"
$networkAdapters = Get-NetAdapter | Select-Object Name, InterfaceDescription, Status, MacAddress, DriverVersion, DriverProvider
Write-Output-Both "All Network Adapters:"
$networkAdapters | Format-Table -AutoSize | Out-String | Write-Output-Both
$diagnosticData['NetworkAdapters'] = $networkAdapters
# Detailed info for each adapter
foreach ($adapter in $networkAdapters) {
Write-Output-Both "`n--- $($adapter.Name) ---"
# Advanced properties
$advProps = Get-NetAdapterAdvancedProperty -Name $adapter.Name -ErrorAction SilentlyContinue
if ($advProps) {
$advProps | Format-Table RegistryKeyword, DisplayValue -AutoSize | Out-String | Write-Output-Both
}
# Power Management
$powerMgmt = Get-NetAdapterPowerManagement -Name $adapter.Name -ErrorAction SilentlyContinue
if ($powerMgmt) {
Write-Output-Both "Power Management Settings:"
$powerMgmt | Format-List | Out-String | Write-Output-Both
}
}
# Specifically check for dock NICs
$dockNics = Get-NetAdapter | Where-Object {
$_.InterfaceDescription -match "Thunderbolt|Dock|RTL|Intel.*I219|Realtek"
}
Write-Output-Both "`n--- POTENTIAL DOCK NICS ---"
$diagnosticData['DockNICs'] = @()
foreach ($nic in $dockNics) {
Write-Output-Both "NIC: $($nic.InterfaceDescription)"
Write-Output-Both "Status: $($nic.Status)"
Write-Output-Both "Driver: $($nic.DriverVersion) ($($nic.DriverProvider))"
# Get PnP Device info
$pnpDevice = Get-PnpDevice | Where-Object {
$_.FriendlyName -eq $nic.InterfaceDescription
} | Select-Object -First 1
if ($pnpDevice) {
# Check DMA Remapping
$dmaRemap = Get-PnpDeviceProperty -InstanceId $pnpDevice.InstanceId -KeyName DEVPKEY_Device_DmaRemappingPolicy -ErrorAction SilentlyContinue
Write-Output-Both "DMA Remapping Policy: $($dmaRemap.Data)"
$diagnosticData['DockNICs'] += @{
Name = $nic.InterfaceDescription
Status = $nic.Status
DriverVersion = $nic.DriverVersion
DMARemapping = $dmaRemap.Data
}
}
}
# ============================================
# 6. SERVICES STATUS
# ============================================
Write-Output-Both "`n[6] === CRITICAL SERVICES ===`n"
$services = @(
'dot3svc', # Wired AutoConfig
'WinHttpAutoProxySvc',
'NlaSvc', # Network Location Awareness
'Dhcp',
'Dnscache',
'ThunderboltService' # If Intel TB software installed
)
$diagnosticData['Services'] = @{}
foreach ($svc in $services) {
$service = Get-Service -Name $svc -ErrorAction SilentlyContinue
if ($service) {
Write-Output-Both "$($svc): Status=$($service.Status), StartType=$($service.StartType)"
$diagnosticData['Services'][$svc] = @{
Status = $service.Status
StartType = $service.StartType
}
} else {
Write-Output-Both "$($svc): NOT INSTALLED"
$diagnosticData['Services'][$svc] = "NOT_INSTALLED"
}
}
# ============================================
# 7. GROUP POLICIES
# ============================================
Write-Output-Both "`n[7] === APPLIED GROUP POLICIES ===`n"
Write-Output-Both "Running GPResult..."
$gpResult = gpresult /r /scope:computer 2>&1 | Out-String
Write-Output-Both $gpResult
# Export detailed GP report
$gpReportPath = "$env:USERPROFILE\Desktop\GPReport_$(Get-Date -Format 'yyyyMMdd_HHmmss').html"
gpresult /h $gpReportPath /f
Write-Output-Both "`nDetailed GP Report saved to: $gpReportPath"
# ============================================
# 8. BOOT CONFIGURATION
# ============================================
Write-Output-Both "`n[8] === BOOT CONFIGURATION ===`n"
# BCDEdit settings
Write-Output-Both "BCDEdit Settings:"
$bcdOutput = bcdedit /enum | Out-String
Write-Output-Both $bcdOutput
$diagnosticData['BCDEdit'] = $bcdOutput
# ============================================
# 9. UEFI/BIOS SETTINGS (from WMI)
# ============================================
Write-Output-Both "`n[9] === FIRMWARE SETTINGS (if available) ===`n"
# Try to get HP BIOS settings
try {
$hpBios = Get-CimInstance -Namespace root/HP/InstrumentedBIOS -ClassName HP_BIOSSetting -ErrorAction Stop
Write-Output-Both "HP BIOS Settings found:"
$hpBios | Where-Object {
$_.Name -match "Thunderbolt|Network|PXE|Wake|DMA|Virtualization|VT-d|IOMMU"
} | Format-Table Name, Value -AutoSize | Out-String | Write-Output-Both
$diagnosticData['HPBIOSSettings'] = $hpBios | Where-Object {
$_.Name -match "Thunderbolt|Network|PXE|Wake|DMA|Virtualization|VT-d|IOMMU"
}
} catch {
Write-Output-Both "HP BIOS WMI namespace not accessible (normal for non-HP or restricted access)"
}
# ============================================
# 10. DRIVER STORE - ETHERNET DRIVERS
# ============================================
Write-Output-Both "`n[10] === INSTALLED ETHERNET DRIVERS (Driver Store) ===`n"
$drivers = Get-WindowsDriver -Online | Where-Object {
$_.ClassName -match "Net" -and $_.ProviderName -match "Intel|Realtek|HP"
}
Write-Output-Both "Relevant Network Drivers in Driver Store:"
$diagnosticData['DriverStore'] = @()
foreach ($drv in $drivers) {
Write-Output-Both "`nDriver: $($drv.Driver)"
Write-Output-Both "Class: $($drv.ClassName)"
Write-Output-Both "Provider: $($drv.ProviderName)"
Write-Output-Both "Version: $($drv.Version)"
Write-Output-Both "Date: $($drv.Date)"
$diagnosticData['DriverStore'] += @{
Driver = $drv.Driver
Class = $drv.ClassName
Provider = $drv.ProviderName
Version = $drv.Version
Date = $drv.Date
}
}
# ============================================
# 11. INSTALLED THUNDERBOLT SOFTWARE
# ============================================
Write-Output-Both "`n[11] === THUNDERBOLT SOFTWARE ===`n"
$tbSoftware = Get-Package -Name "*Thunderbolt*","*Intel*Connection*" -ErrorAction SilentlyContinue
if ($tbSoftware) {
Write-Output-Both "Installed Thunderbolt/Intel Software:"
$tbSoftware | Format-Table Name, Version -AutoSize | Out-String | Write-Output-Both
$diagnosticData['ThunderboltSoftware'] = $tbSoftware
} else {
Write-Output-Both "No Intel Thunderbolt software detected (using Microsoft USB4 stack)"
$diagnosticData['ThunderboltSoftware'] = "Microsoft_USB4_Stack_Only"
}
# ============================================
# 12. SECURITY FEATURES
# ============================================
Write-Output-Both "`n[12] === SECURITY FEATURES ===`n"
# Secure Boot
$secureBoot = Confirm-SecureBootUEFI
Write-Output-Both "Secure Boot: $secureBoot"
# BitLocker Status
$bitlocker = Get-BitLockerVolume -MountPoint C: -ErrorAction SilentlyContinue
if ($bitlocker) {
Write-Output-Both "BitLocker Protection Status: $($bitlocker.ProtectionStatus)"
Write-Output-Both "BitLocker Encryption Percentage: $($bitlocker.EncryptionPercentage)%"
$diagnosticData['BitLocker'] = @{
ProtectionStatus = $bitlocker.ProtectionStatus
EncryptionPercentage = $bitlocker.EncryptionPercentage
}
}
# Credential Guard / HVCI
$deviceGuardStatus = Get-CimInstance -ClassName Win32_DeviceGuard -Namespace root\Microsoft\Windows\DeviceGuard -ErrorAction SilentlyContinue
if ($deviceGuardStatus) {
Write-Output-Both "`nDevice Guard Status:"
Write-Output-Both "Virtualization Based Security: $($deviceGuardStatus.VirtualizationBasedSecurityStatus)"
Write-Output-Both "Security Services Running: $($deviceGuardStatus.SecurityServicesRunning -join ', ')"
$diagnosticData['DeviceGuard'] = $deviceGuardStatus
}
# ============================================
# 13. CURRENT DOCK CONNECTION (if connected)
# ============================================
Write-Output-Both "`n[13] === CURRENT THUNDERBOLT DOCK CONNECTION ===`n"
$tbDevices = Get-PnpDevice -Class System,USB | Where-Object {
$_.FriendlyName -match "Thunderbolt|TBT|Dock|G4"
}
Write-Output-Both "Connected Thunderbolt/Dock Devices:"
$diagnosticData['ConnectedDockDevices'] = @()
foreach ($dev in $tbDevices) {
Write-Output-Both "`nDevice: $($dev.FriendlyName)"
Write-Output-Both "Status: $($dev.Status)"
Write-Output-Both "Instance: $($dev.InstanceId)"
# Get all properties
$allProps = Get-PnpDeviceProperty -InstanceId $dev.InstanceId
$relevantProps = $allProps | Where-Object {
$_.KeyName -match "FirmwareVersion|DriverVersion|HardwareId|CompatibleId|Manufacturer"
}
$relevantProps | Format-Table KeyName, Data -AutoSize | Out-String | Write-Output-Both
$diagnosticData['ConnectedDockDevices'] += @{
Name = $dev.FriendlyName
Status = $dev.Status
InstanceId = $dev.InstanceId
Properties = $relevantProps
}
}
# ============================================
# 14. WINDOWS UPDATE / FEATURE UPDATE
# ============================================
Write-Output-Both "`n[14] === WINDOWS UPDATE INFO ===`n"
$updateSession = New-Object -ComObject Microsoft.Update.Session
$updateSearcher = $updateSession.CreateUpdateSearcher()
$historyCount = $updateSearcher.GetTotalHistoryCount()
Write-Output-Both "Total Update History Count: $historyCount"
# Get recent updates
$recentUpdates = $updateSearcher.QueryHistory(0, 20) | Where-Object {
$_.Title -match "Thunderbolt|Network|Driver|Firmware|USB"
} | Select-Object Title, Date, ResultCode
if ($recentUpdates) {
Write-Output-Both "`nRecent Relevant Updates:"
$recentUpdates | Format-Table -AutoSize | Out-String | Write-Output-Both
$diagnosticData['RecentUpdates'] = $recentUpdates
}
# ============================================
# FINALIZE & EXPORT
# ============================================
Write-Output-Both "`n============================================"
Write-Output-Both "DIAGNOSTIC SCAN COMPLETE"
Write-Output-Both "============================================"
Write-Output-Both "`nOutput Files:"
Write-Output-Both "Text Report: $outputPath"
Write-Output-Both "JSON Data: $jsonPath"
# Export to JSON for easy comparison
$diagnosticData | ConvertTo-Json -Depth 10 | Out-File -FilePath $jsonPath -Encoding UTF8
Write-Host "`n`nDiagnostic scan complete!" -ForegroundColor Green
Write-Host "Files saved to Desktop:" -ForegroundColor Green
Write-Host " - $outputPath" -ForegroundColor Cyan
Write-Host " - $jsonPath" -ForegroundColor Cyan
Write-Host "`nRun this script on both your working HP image AND your custom image," -ForegroundColor Yellow
Write-Host "then compare the JSON files to find differences." -ForegroundColor Yellow
Stop-Transcript