using Microsoft.Win32;
using Microsoft.Extensions.Logging;
namespace CredentialManager.Services;
///
/// Informazioni su un DSN ODBC
///
public class OdbcDsnInfo
{
public string Name { get; set; } = string.Empty;
public string Driver { get; set; } = string.Empty;
public string? Description { get; set; }
public bool IsUserDsn { get; set; } // true = User DSN, false = System DSN
public Dictionary Properties { get; set; } = new();
}
///
/// Interfaccia per il servizio di discovery DSN ODBC
///
public interface IOdbcDsnDiscoveryService
{
///
/// Ottiene tutti i DSN ODBC configurati (sia User che System)
///
List GetAllDsn();
///
/// Ottiene solo i DSN utente
///
List GetUserDsn();
///
/// Ottiene solo i DSN di sistema
///
List GetSystemDsn();
///
/// Ottiene i dettagli di un DSN specifico
///
OdbcDsnInfo? GetDsnDetails(string dsnName, bool isUserDsn = true);
///
/// Ottiene la lista dei driver ODBC installati
///
List GetInstalledDrivers();
}
///
/// Servizio per la scoperta e lettura dei DSN ODBC configurati sul sistema
///
public class OdbcDsnDiscoveryService : IOdbcDsnDiscoveryService
{
private readonly ILogger _logger;
// Percorsi del registro di Windows per ODBC
private const string USER_DSN_PATH = @"SOFTWARE\ODBC\ODBC.INI\ODBC Data Sources";
private const string SYSTEM_DSN_PATH = @"SOFTWARE\ODBC\ODBC.INI\ODBC Data Sources";
private const string USER_DSN_DETAILS_PATH = @"SOFTWARE\ODBC\ODBC.INI\";
private const string SYSTEM_DSN_DETAILS_PATH = @"SOFTWARE\ODBC\ODBC.INI\";
private const string DRIVERS_PATH = @"SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers";
public OdbcDsnDiscoveryService(ILogger logger)
{
_logger = logger;
}
public List GetAllDsn()
{
var allDsn = new List();
allDsn.AddRange(GetUserDsn());
allDsn.AddRange(GetSystemDsn());
return allDsn;
}
public List GetUserDsn()
{
return GetDsnFromRegistry(Registry.CurrentUser, USER_DSN_PATH, USER_DSN_DETAILS_PATH, true);
}
public List GetSystemDsn()
{
return GetDsnFromRegistry(Registry.LocalMachine, SYSTEM_DSN_PATH, SYSTEM_DSN_DETAILS_PATH, false);
}
public OdbcDsnInfo? GetDsnDetails(string dsnName, bool isUserDsn = true)
{
var allDsn = isUserDsn ? GetUserDsn() : GetSystemDsn();
return allDsn.FirstOrDefault(d => d.Name.Equals(dsnName, StringComparison.OrdinalIgnoreCase));
}
public List GetInstalledDrivers()
{
var drivers = new List();
try
{
using var key = Registry.LocalMachine.OpenSubKey(DRIVERS_PATH);
if (key != null)
{
foreach (var driverName in key.GetValueNames())
{
var value = key.GetValue(driverName)?.ToString();
if (value == "Installed")
{
drivers.Add(driverName);
}
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Errore nella lettura dei driver ODBC dal registro");
}
return drivers.OrderBy(d => d).ToList();
}
private List GetDsnFromRegistry(RegistryKey rootKey, string dsnPath, string detailsPath, bool isUserDsn)
{
var dsnList = new List();
try
{
using var dsnKey = rootKey.OpenSubKey(dsnPath);
if (dsnKey == null)
{
_logger.LogWarning("Chiave registro ODBC non trovata: {Path}", dsnPath);
return dsnList;
}
foreach (var dsnName in dsnKey.GetValueNames())
{
try
{
var driver = dsnKey.GetValue(dsnName)?.ToString();
if (string.IsNullOrEmpty(driver))
continue;
var dsnInfo = new OdbcDsnInfo
{
Name = dsnName,
Driver = driver,
IsUserDsn = isUserDsn
};
// Leggi i dettagli del DSN
using var detailKey = rootKey.OpenSubKey(detailsPath + dsnName);
if (detailKey != null)
{
foreach (var valueName in detailKey.GetValueNames())
{
var value = detailKey.GetValue(valueName)?.ToString();
if (!string.IsNullOrEmpty(value))
{
dsnInfo.Properties[valueName] = value;
// Popola proprietà comuni
if (valueName.Equals("Description", StringComparison.OrdinalIgnoreCase))
dsnInfo.Description = value;
}
}
}
dsnList.Add(dsnInfo);
_logger.LogDebug("DSN trovato: {Name} ({Driver}) - Type: {Type}",
dsnName, driver, isUserDsn ? "User" : "System");
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Errore nella lettura del DSN: {DsnName}", dsnName);
}
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Errore nella lettura dei DSN ODBC dal registro");
}
return dsnList;
}
}