Orphaned DSNs and the Ticket That Started It All
The ticket read: “Application can’t connect to the database.” After remoting into the server, I ran Get-OdbcDsn and found seventeen ODBC data source names — eight of which pointed to decommissioned SQL instances. A client with twelve application servers had been through three database migrations over two years. Nobody cleaned up the old DSNs. The application was grabbing a stale System DSN instead of the current one, and connections were timing out against a server that no longer existed.
That’s when I scripted the cleanup with PowerShell Remove-OdbcDsn. Manual removal through the ODBC Data Source Administrator GUI works fine for one machine. It does not scale to a dozen servers with mixed 32-bit and 64-bit DSNs, each carrying years of configuration drift.
What Remove-OdbcDsn Actually Does
The Remove-OdbcDsn cmdlet belongs to the Wdac module — Windows Data Access Components. It removes ODBC data source names from the local machine’s registry. User DSNs live under HKCU. System DSNs live under HKLM. The cmdlet handles both, plus the 32-bit and 64-bit registry hives.
Two parameter sets exist. The Name set lets you specify DSNs by name, type, driver, and platform. The InputObject set accepts pipeline input from Get-OdbcDsn. Both support -WhatIf and -Confirm, which matters when you’re running this in production at 2 AM during a maintenance window.
Core Syntax and Parameter Breakdown
Removing by Name
Remove-OdbcDsn -Name "MyPayroll" -DsnType "System"
This removes the System DSN named “MyPayroll” from the native platform — 64-bit on a 64-bit OS, 32-bit on a 32-bit OS. The -DsnType parameter is mandatory when using the Name set. Accepted values: User, System, or All.
Targeting a Specific Platform
Remove-OdbcDsn -Name "*Payroll*" -DsnType "User" -Platform "32-bit"
The wildcard catches every User DSN with “Payroll” in the name, but only in the 32-bit hive. This distinction matters. I’ve seen environments where a legacy 32-bit application had its own DSN alongside a 64-bit version of the same connection. Remove the wrong one and the app breaks silently — it falls back to a different DSN or throws a generic ODBC error that tells you nothing useful.
Filtering by Driver
Remove-OdbcDsn -Name "*Payroll*" -DsnType "System" -Platform "32-bit" -DriverName "SQL Server*"
The -DriverName parameter accepts wildcards. This targets only DSNs using a driver whose name starts with “SQL Server” — useful when you’re decommissioning a specific database backend but need to keep DSNs that point to other systems through different drivers.
Pipeline Input from Get-OdbcDsn
Get-OdbcDsn -Name "MyPayroll" -DsnType "System" | Remove-OdbcDsn
Pipe the output of Get-OdbcDsn directly into Remove-OdbcDsn. This pattern is powerful for conditional logic. Query first, filter with Where-Object, then remove only what matches your criteria.
Capturing What You Removed
By default, Remove-OdbcDsn produces no output. Use -PassThru to get the deleted DSN object back:
$Removed = Remove-OdbcDsn -Name "MyPayroll" -DsnType "User" -Platform "32-bit" -PassThru
The $Removed variable now holds a CimInstance representing the DSN that was deleted. This is essential for audit logging. We pipe that object into Export-Csv or write it to a centralized log during client engagements where change management requires documented evidence of every modification.
Scaling Across Multiple Servers
Single-server removal is straightforward. The real value shows up when you need to clean DSNs across an entire fleet. Remove-OdbcDsn supports -CimSession, which means you can target remote machines without PSRemoting workarounds.
# Build CIM sessions to target servers
$Sessions = New-CimSession -ComputerName "APP01","APP02","APP03"
# Remove all System DSNs matching the old payroll driver
Remove-OdbcDsn -Name "*OldPayroll*" -DsnType "System" -CimSession $Sessions -PassThru |
Export-Csv -Path "C:\Logs\RemovedDSNs.csv" -NoTypeInformation
The -ThrottleLimit parameter controls how many CIM operations run concurrently. Default is fine for a handful of servers. For larger rollouts, adjust it to avoid saturating your management network.
During a database migration project for a client running a multi-site ERP system, we used this exact pattern to strip 32-bit DSNs from forty-six servers in one pass. The alternative — opening the ODBC administrator on each box, clicking through the GUI — would have taken an entire afternoon. The script ran in under three minutes and produced a CSV audit trail we attached to the change request.
Dry Runs with -WhatIf
Here’s my opinionated take: never run Remove-OdbcDsn in production without -WhatIf first. Every time. No exceptions.
Remove-OdbcDsn -Name "*" -DsnType "All" -Platform "All" -WhatIf
That command previews what would be removed without touching anything. The output shows each DSN that matches your criteria. Review it. Confirm it matches your expectations. Then run again without -WhatIf. This two-pass approach has saved us from accidental deletions more than once. A wildcard pattern that looks right on paper can match DSNs you didn’t expect — especially in environments where naming conventions drifted over time.
Building a Reusable Cleanup Script
Here’s a pattern we use across managed environments. It queries, logs, and removes stale DSNs in one pass:
# Define targets
$StaleDrivers = @("SQL Server", "SQL Server Native Client 10.0")
$LogPath = "C:\Logs\DSN_Cleanup_$(Get-Date -Format 'yyyyMMdd_HHmmss').csv"
# Gather all System DSNs using outdated drivers
$StaleDsns = Get-OdbcDsn -DsnType "System" | Where-Object {
$driver = $_.DriverName
$StaleDrivers -contains $driver
}
if ($StaleDsns) {
# Log before removal
$StaleDsns | Select-Object Name, DsnType, DriverName, Platform |
Export-Csv -Path $LogPath -NoTypeInformation
# Remove with PassThru for confirmation
$StaleDsns | Remove-OdbcDsn -PassThru | ForEach-Object {
Write-Output "Removed: $($_.Name) [$($_.DriverName)] ($($_.Platform))"
}
} else {
Write-Output "No stale DSNs found."
}
This script identifies DSNs tied to deprecated drivers — the old “SQL Server” driver or “SQL Server Native Client 10.0” — logs them to a timestamped CSV, then removes them. If you’re building PowerShell loop structures for fleet-wide automation, this pattern slots right into a ForEach loop over your server inventory.
Caveats and Limitations
A few things the documentation won’t emphasize enough.
Platform defaults are context-dependent. On a 64-bit OS, the default platform is 64-bit. If your legacy app uses 32-bit DSNs and you forget to specify -Platform "32-bit", you’ll be removing from the wrong hive. I’ve seen this cause a thirty-minute outage during what should have been a routine cleanup.
No built-in backup. Remove-OdbcDsn deletes registry keys. There’s no undo. Before any bulk removal, export your DSN configuration with Get-OdbcDsn | Export-Clixml. If something goes wrong, you can reconstruct the DSNs from that export using Add-OdbcDsn.
CIM session requirements. Remote removal via -CimSession requires WMI/WinRM access. If your firewall rules or WinRM configuration aren’t set up, the command fails silently or throws a generic CIM error. Verify connectivity with Test-WSMan before running removal scripts across a fleet. For servers you manage directly, having proper root access to the infrastructure simplifies this significantly.
Driver name matching. The -DriverName parameter supports wildcards on the Name parameter set but the documentation lists Supports wildcards: False for the DriverName parameter itself. In practice, wildcard patterns like "SQL Server*" work in the Name parameter set. Test your patterns with Get-OdbcDsn first to confirm what matches before piping into removal.
Integrating with Configuration Management
For environments managed with tools like Ansible or DSC, Remove-OdbcDsn fits into your desired-state workflow. Define which DSNs should exist. Query the current state with Get-OdbcDsn. Remove anything that doesn’t match the definition. Add anything that’s missing with Add-OdbcDsn.
We built this into a quarterly compliance check for a client in financial services. Their NIST framework alignment required documented evidence that no unauthorized database connections existed on application servers. The script runs as a scheduled task, exports findings, and flags any DSN that doesn’t match the approved list. It turned a manual audit into a two-minute automated report.
If you’re also auditing what runs at startup on those same servers, pairing this with a tool like Autoruns for autostart location auditing gives you a fuller picture of the machine’s configuration state.
The Practical Takeaway
Stale ODBC DSNs are technical debt that accumulates silently. Applications grab the wrong connection string. Security audits flag unauthorized database paths. Migration rollbacks fail because old DSNs conflict with new ones. Remove-OdbcDsn with -WhatIf, -PassThru, and -CimSession gives you a repeatable, auditable way to keep DSN configurations clean across your fleet.
Start with Get-OdbcDsn -DsnType All | Format-Table on your servers. If you find DSNs pointing to hosts that no longer exist, you’ve got cleanup to do. Script it, log it, and schedule it.
If your environment has years of accumulated DSN sprawl and you need help building the automation to clean it up, get in touch with us. We’ve done this across environments ranging from five servers to five hundred.

