<# .SYNOPSIS Export ODBC DSNs, registry keys, and driver inventory. Generate migration package + report with vendor download links. .DESCRIPTION This script: - Exports ODBC System/User DSNs - Exports registry keys for ODBC.INI - Lists all installed ODBC drivers and Add/Remove Program entries - Matches known ODBC drivers to official vendor download URLs - Searches for local EXE/MSI installers - Generates CSV + Markdown reports - Compresses all output into a single ZIP archive Run as Administrator on the source PC. #> # =========================== # CONFIGURATION # =========================== $BaseDir = "C:\ODBC_Migration" $ExportDir = Join-Path $BaseDir "export" $ZipFile = Join-Path $BaseDir "ODBC_Backup.zip" $LogFile = Join-Path $BaseDir "export_log.txt" # Optional: Add local folders to search for installers $InstallerHuntPaths = @( "$env:USERPROFILE\Downloads", "C:\Installers", "C:\Drivers", "$env:PUBLIC\Downloads" ) | Where-Object { Test-Path $_ } # =========================== # PREP # =========================== New-Item -ItemType Directory -Path $ExportDir -Force | Out-Null Start-Transcript -Path $LogFile -Append Write-Host "Starting ODBC migration export..." -ForegroundColor Cyan # =========================== # STEP 1: EXPORT BASELINE DATA # =========================== Write-Host "Exporting ODBC driver list..." $drivers = Get-OdbcDriver | Select-Object Name, Platform, Version, Attribute $driversCsv = Join-Path $ExportDir "odbc_drivers.csv" $drivers | Export-Csv -Path $driversCsv -NoTypeInformation -Encoding UTF8 Write-Host "Exporting DSNs..." $dsnsXml = Join-Path $ExportDir "odbc_dsns.xml" Get-OdbcDsn | Export-Clixml $dsnsXml Write-Host "Exporting registry keys..." reg export "HKLM\SOFTWARE\ODBC\ODBC.INI" (Join-Path $ExportDir "ODBC_System.reg") /y | Out-Null reg export "HKCU\Software\ODBC\ODBC.INI" (Join-Path $ExportDir "ODBC_User.reg") /y | Out-Null $WowKey = "HKLM\SOFTWARE\WOW6432Node\ODBC\ODBC.INI" if (Test-Path "Registry::$WowKey") { reg export $WowKey (Join-Path $ExportDir "ODBC_System32.reg") /y | Out-Null Write-Host "Exported 32-bit ODBC keys." } # =========================== # STEP 2: ENUMERATE INSTALLED PRODUCTS # =========================== Write-Host "Enumerating Add/Remove Programs entries..." function Get-UninstallEntries { $roots = @( "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall", "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" ) foreach ($r in $roots) { if (Test-Path $r) { Get-ChildItem $r | ForEach-Object { Get-ItemProperty $_.PsPath } } } } $uninst = Get-UninstallEntries | Select-Object ` DisplayName, DisplayVersion, Publisher, InstallLocation, UninstallString, ModifyPath, QuietUninstallString # Tokenizer helper function Normalize([string]$s) { if (-not $s) { return "" } return (($s -replace '[^a-zA-Z0-9]+', ' ') -as [string]).Trim().ToLowerInvariant() } # Map ODBC drivers -> installed programs Write-Host "Mapping ODBC drivers to installed programs..." $map = foreach ($d in $drivers) { $nameNorm = Normalize $d.Name $candidates = $uninst | Where-Object { $_.DisplayName -and (Normalize $_.DisplayName) -match ($nameNorm -replace '\s+','.*') } if (-not $candidates -and $d.Name -match 'oracle|mysql|postgres|sql\s*server|mariadb|sqlite|snowflake|teradata|ibm|db2|progress|sybase|firebird|hana|vertica|redshift') { $kw = ($matches[0]) $candidates = $uninst | Where-Object { $_.DisplayName -match $kw } } [PSCustomObject]@{ OdbcDriverName = $d.Name Platform = $d.Platform DriverVersion = $d.Version ProductName = ($candidates | Select-Object -First 1 -ExpandProperty DisplayName) ProductVersion = ($candidates | Select-Object -First 1 -ExpandProperty DisplayVersion) Publisher = ($candidates | Select-Object -First 1 -ExpandProperty Publisher) InstallLocation = ($candidates | Select-Object -First 1 -ExpandProperty InstallLocation) UninstallString = ($candidates | Select-Object -First 1 -ExpandProperty UninstallString) } } # =========================== # STEP 3: ADD KNOWN VENDOR LINKS # =========================== Write-Host "Attaching known vendor download links..." $vendorLinks = @{ # --- Microsoft --- 'odbc driver 18 for sql server' = 'https://learn.microsoft.com/sql/connect/odbc/download-odbc-driver-for-sql-server' 'odbc driver 17 for sql server' = 'https://learn.microsoft.com/sql/connect/odbc/download-odbc-driver-for-sql-server' 'sql server native client' = 'https://learn.microsoft.com/sql/relational-databases/native-client/applications/installing-sql-server-native-client' 'microsoft access driver' = 'https://www.microsoft.com/download/details.aspx?id=54920' 'microsoft excel driver' = 'https://www.microsoft.com/download/details.aspx?id=54920' 'microsoft text driver' = 'https://www.microsoft.com/download/details.aspx?id=54920' 'microsoft dbase driver' = 'https://www.microsoft.com/download/details.aspx?id=54920' 'microsoft odbc for oracle' = 'https://learn.microsoft.com/sql/odbc/microsoft/odbc-driver-for-oracle' # --- Oracle --- 'oracle odbc driver' = 'https://www.oracle.com/database/technologies/releasenote-odbc-ic.html' 'oracle in oraclient' = 'https://www.oracle.com/database/technologies/releasenote-odbc-ic.html' # --- MySQL / MariaDB --- 'mysql odbc' = 'https://dev.mysql.com/downloads/connector/odbc/' 'mariadb odbc' = 'https://mariadb.com/products/connectors/odbc/' # --- PostgreSQL --- 'postgresql odbc' = 'https://odbc.postgresql.org/' 'psqlodbc' = 'https://odbc.postgresql.org/' # --- SQLite --- 'sqlite odbc' = 'https://www.ch-werner.de/sqliteodbc/' # --- IBM / Informix --- 'ibm db2 odbc' = 'https://www.ibm.com/support/pages/db2-clients' 'informix odbc' = 'https://www.ibm.com/support/pages/informix-odbc-driver' # --- Snowflake --- 'snowflake odbc' = 'https://developers.snowflake.com/odbc/' # --- Teradata --- 'teradata odbc' = 'https://downloads.teradata.com/connectivity/odbc-driver' # --- Progress / OpenEdge --- 'progress openedge odbc' = 'https://www.progress.com/odbc/openedge' 'openedge odbc' = 'https://www.progress.com/odbc/openedge' # --- SAP HANA --- 'sap hana odbc' = 'https://tools.hana.ondemand.com/#hanatools' # --- Amazon Redshift --- 'redshift odbc' = 'https://docs.aws.amazon.com/redshift/latest/mgmt/configure-odbc-connection.html' # --- Vertica --- 'vertica odbc' = 'https://www.vertica.com/download/vertica/client-drivers/' # --- Firebird --- 'firebird odbc' = 'https://firebirdsql.org/en/odbc-driver/' # --- Generic fallback --- 'generic odbc driver' = 'https://www.microsoft.com/en-us/sql/connect/odbc/' } foreach ($item in $map) { $norm = Normalize $item.OdbcDriverName $found = $false foreach ($key in $vendorLinks.Keys) { if ($norm -like "*$key*") { $item | Add-Member -NotePropertyName "DownloadURL" -NotePropertyValue $vendorLinks[$key] $found = $true break } } if (-not $found) { $item | Add-Member -NotePropertyName "DownloadURL" -NotePropertyValue "Search manually" } } # =========================== # STEP 4: FIND LOCAL INSTALLER FILES # =========================== Write-Host "Scanning for local installers..." $searchTerms = ($map.OdbcDriverName | Sort-Object -Unique) $installerHits = @() foreach ($p in $InstallerHuntPaths) { Get-ChildItem -Path $p -Recurse -ErrorAction SilentlyContinue -Include *.msi,*.exe | ForEach-Object { $fileNorm = Normalize $_.Name foreach ($term in $searchTerms) { $t = Normalize $term if ($fileNorm -match ($t -replace '\s+','.*')) { $installerHits += [PSCustomObject]@{ Term = $term FileName = $_.Name FullPath = $_.FullName SizeMB = [math]::Round($_.Length/1MB,2) LastWrite = $_.LastWriteTime SearchRoot = $p } break } } } } # =========================== # STEP 5: REPORT OUTPUT # =========================== $mapCsv = Join-Path $ExportDir "odbc_driver_product_map.csv" $map | Export-Csv -Path $mapCsv -NoTypeInformation -Encoding UTF8 $hitsCsv = Join-Path $ExportDir "odbc_installer_hits.csv" $installerHits | Export-Csv -Path $hitsCsv -NoTypeInformation -Encoding UTF8 $reportMd = Join-Path $ExportDir "ODBC_Migration_Report.md" @" # ODBC Migration Report **Generated:** $(Get-Date -Format "yyyy-MM-dd HH:mm:ss") **Machine:** $env:COMPUTERNAME ## Summary - Drivers detected: $($drivers.Count) - DSNs exported: $((Get-OdbcDsn).Count) - Installer hits: $($installerHits.Count) ## Drivers & Product Mapping | ODBC Driver | Platform | Version | Product | Publisher | Download Link | |---|---:|---|---|---|---| $( ($map | ForEach-Object { $dn = if ($_.OdbcDriverName) { $_.OdbcDriverName.Replace('|','-') } else { '' } $pf = $_.Platform $dv = $_.DriverVersion $pn = ($_.ProductName -replace '\|','-') $pu = ($_.Publisher -replace '\|','-') $dl = if ($_.DownloadURL -match '^https?') { "[Download]($($_.DownloadURL))" } else { $_.DownloadURL } "| $dn | $pf | $dv | $pn | $pu | $dl |" }) -join "`r`n" ) ## Likely Local Installer Files | Matches Term | File | Size (MB) | Modified | Path | |---|---|---:|---|---| $( ($installerHits | Sort-Object Term,FileName | ForEach-Object { "| $($_.Term) | $($_.FileName) | $($_.SizeMB) | $($_.LastWrite.ToString('yyyy-MM-dd')) | $($_.FullPath) |" }) -join "`r`n" ) ## Next Steps 1. On the **target PC**, install matching ODBC driver packages using the links above or your local installers. 2. Then run **Restore-ODBC.ps1** to import DSNs and registry settings. 3. Verify DSNs in *ODBC Data Source Administrator* (both 32-bit and 64-bit). "@ | Out-File -FilePath $reportMd -Encoding UTF8 # =========================== # STEP 6: ZIP PACKAGE # =========================== if (Test-Path $ZipFile) { Remove-Item $ZipFile -Force } Compress-Archive -Path "$ExportDir\*" -DestinationPath $ZipFile -Force Write-Host "Export complete. ZIP created at: $ZipFile" -ForegroundColor Green Stop-Transcript