Thanks — understood: you want the script to never change PortName (COM number) and only create the selective‑suspend / serial‑enumerator values if they’re missing, and to reboot only if the script actually created something.
Below are (A) quick checks to confirm what happened on your run, (B) a corrected idempotent script that does NOT touch PortName at all and WILL reboot only if it created at least one property, and (C) short one‑liner alternatives you can run immediately. Run everything in an elevated PowerShell session.
A — Quick checks (run elevated)
1) Show the last script log (so we can confirm whether the script reported any changes):
Get-ChildItem "$env:USERPROFILE\Desktop\FTDI
ApplyIfMissing*.log" |
Sort-Object LastWriteTime -Descending |
Select-Object -First 1 |
ForEach-Object { Get-Content -Path $_.FullName -Tail 200 }
Paste the summary lines here if you want me to read them.
2) Confirm one device’s Device Parameters and existing keys (replace <INSTANCE> with a real InstanceId returned by Get-PnpDevice):
list FTDI ports
Get-PnpDevice -Class Ports -PresentOnly |
Where-Object { ($
.Manufacturer -like 'FTDI') -or ($.InstanceId -match 'VID_0403') } |
Format-List FriendlyName,InstanceId
inspect one instance (paste the InstanceId from previous command)
$inst = '<PASTE_INSTANCEID_HERE>'
Get-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Enum\$($inst -replace '\','\')\Device Parameters" -ErrorAction SilentlyContinue | Format-List
Look for DeviceIdleEnabled, DefaultIdleState, UserSetDeviceIdleEnabled, SSIdleTimeout and any Serial‑Enumerator property names. If the four selective‑suspend values already exist, the script correctly skipped them and therefore did not reboot.
B — Idempotent script (DOES NOT touch PortName)
Save this exact script as Disable-FTDI-SelectiveSuspend-OnlyIfMissing-NoPortName.ps1 and run elevated.
What it does: for each FTDI COM port it will create DeviceIdleEnabled, DefaultIdleState, UserSetDeviceIdleEnabled and SSIdleTimeout = 0 only if the property does not already exist. It will set existing serial‑enumerator properties to 0 only if the property exists (it will NOT create new vendor serial names). It will NOT touch PortName. If it created at least one value (and you did not run -WhatIf), it will reboot after 15s. Use -WhatIf to dry run.
Script:
param(
[switch]$WhatIf,
[switch]$NoReboot)
require elevation
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator) {
Write-Error "Run as Administrator"; exit 1
}
$log = Join-Path $env:USERPROFILE ("Desktop\FTDI
ApplyIfMissing{0}.log" -f (Get-Date -Format yyyyMMdd_HHmmss)
"Started: $(Get-Date)" | Out-File $log
$serialEnumRegex = '(serial.
enum|enum.serial|serialenumerator|enable.*serial)'
$changedCount = 0
$ports = Get-PnpDevice -Class Ports -PresentOnly -ErrorAction SilentlyContinue |
Where-Object { ($
.Manufacturer -and $.Manufacturer -like '
FTDI') -or ($
.InstanceId -and $.InstanceId -match 'VID_0403') }
if (-not $ports) {
"No FTDI ports found." | Tee-Object -FilePath $log -Append
Write-Output "No FTDI ports found. See $log"
exit 0
}
foreach ($p in $ports) {
"----" | Tee-Object -FilePath $log -Append
"Device: $($p.FriendlyName) [$($p.InstanceId)]" | Tee-Object -FilePath $log -Append
$inst = $p.InstanceId
$base = "HKLM:\SYSTEM\CurrentControlSet\Enum\$inst"
$candidates = @("$base\Device Parameters", "$base\0000\Device Parameters")
$dpFound = $false
foreach ($dp in $candidates) {
if (Test-Path $dp) {
$dpFound = $true
"Using $dp" | Tee-Object -FilePath $log -Append
Code:
# Only create if missing $props = @{ 'DeviceIdleEnabled' = 0 'DefaultIdleState' = 0 'UserSetDeviceIdleEnabled' = 0 'SSIdleTimeout' = 0 } foreach ($kv in $props.GetEnumerator { $name = $kv.Key; $val = $kv.Value $exists = $false try { $exists = (Get-ItemProperty -Path $dp -Name $name -ErrorAction SilentlyContinue) -ne $null } catch { $exists = $false } if ($exists) { "$name exists — skipping" | Tee-Object -FilePath $log -Append } else { if ($WhatIf) { "WhatIf: would create $name = $val at $dp" | Tee-Object -FilePath $log -Append $changedCount++ } else { try { New-Item -Path $dp -Force | Out-Null New-ItemProperty -Path $dp -Name $name -PropertyType DWord -Value $val -Force -ErrorAction Stop | Out-Null "Created $name = $val" | Tee-Object -FilePath $log -Append $changedCount++ } catch { "ERROR creating $name at $dp: $($_.Exception.Message)" | Tee-Object -FilePath $log -Append } } } } # If serial-enum props exist, set them to 0 (but do NOT create new unknown names) try { $existing = (Get-ItemProperty -Path $dp -ErrorAction SilentlyContinue).PSObject.Properties | ForEach-Object { $_.Name } } catch { $existing = @ } foreach ($nm in $existing) { if ($nm -match $serialEnumRegex) { # read current try { $cur = (Get-ItemProperty -Path $dp -Name $nm -ErrorAction SilentlyContinue).$nm } catch { $cur = $null } if ($null -eq $cur) { if ($WhatIf) { "WhatIf: would set existing $nm = 0 at $dp" | Tee-Object -FilePath $log -Append $changedCount++ } else { try { New-ItemProperty -Path $dp -Name $nm -PropertyType DWord -Value 0 -Force -ErrorAction Stop | Out-Null "Set $nm = 0" | Tee-Object -FilePath $log -Append $changedCount++ } catch { "ERROR writing $nm at $dp: $($_.Exception.Message)" | Tee-Object -FilePath $log -Append } } } else { "$nm exists with value $cur — not overwriting" | Tee-Object -FilePath $log -Append } } } break
} # Test-Path
} # candidates
if (-not $dpFound) { "No Device Parameters key found for $inst" | Tee-Object -FilePath $log -Append }
} # foreach ports
"Created/updated properties count: $changedCount" | Tee-Object -FilePath $log -Append
if (($changedCount -gt 0) -and (-not $WhatIf) -and (-not $NoReboot) {
"Rebooting in 15s..." | Tee-Object -FilePath $log -Append
Start-Process -FilePath 'shutdown.exe' -ArgumentList @('/r','/t','15','/c','Applying FTDI Device Parameter changes') -NoNewWindow
} else {
"No reboot scheduled." | Tee-Object -FilePath $log -Append
}
"Done" | Tee-Object -FilePath $log -Append
C — One‑line to create missing selective‑suspend properties (no PortName) and reboot if anything created
Run elevated. This is equivalent to the script but inline:
$made=0; Get-PnpDevice -Class Ports -PresentOnly | Where-Object { ($
.Manufacturer -like 'FTDI') -or ($.InstanceId -match 'VID
0403') } |
ForEach-Object {
$inst=$.InstanceId; $dp1="HKLM:\SYSTEM\CurrentControlSet\Enum\$inst\Device Parameters"; $dp2="HKLM:\SYSTEM\CurrentControlSet\Enum\$inst\0000\Device Parameters";
foreach($dp in @($dp1,$dp2){ if(Test-Path $dp) {
foreach($kv in @('DeviceIdleEnabled','DefaultIdleState','UserSetDeviceIdleEnabled','SSIdleTimeout'){
if(-not (Get-ItemProperty -Path $dp -Name $kv -ErrorAction SilentlyContinue) {
New-Item -Path $dp -Force | Out-Null; New-ItemProperty -Path $dp -Name $kv -PropertyType DWord -Value 0 -Force | Out-Null; $made++;
}
}
break
} }
}; if($made -gt 0){ Start-Process -FilePath 'shutdown.exe' -ArgumentList @('/r','/t','15','/c','Applying FTDI Device Parameter changes') -NoNewWindow } else { Write-Output "No changes were necessary." }
D — Abort countdown
If you see the 15s reboot countdown and change your mind, run (elevated):
shutdown /a
Tell me which you want to do now:
- I’ll inspect the log for you (paste the log summary or run the log command and paste output), or
- You want me to run (i.e., you want the exact command) the idempotent one‑liner above to create any missing properties (it does not touch PortName) and then reboot, or
- You want the saved script file pasted for copying (I included it above).
If you paste the last ~40 lines of your log I’ll confirm why no reboot happened and recommend the safest action.