01f78466df
- Aggiunta persistenza campi ODBC (OdbcDsnName, OdbcMode) in CredentialEntity - Creata migration EF Core per nuovi campi database - Aggiornato mapping credenziali per caricare/salvare dati ODBC - Creato OdbcDatabaseManager dedicato (bypass EF Core che non supporta ODBC) - Aggiornato DataConnectionFactory per usare OdbcDatabaseManager con connessioni ODBC - Fix auto-load DSN: sostituito @onchange con @bind-Value:after in dropdown tipo database - Fix test connessione SAP HANA: rimossa query SELECT 1 che causava errori sintassi - Implementati tutti i metodi IDatabaseManager in OdbcDatabaseManager - Supporto completo per discovery schema, tabelle e query ODBC Risolve problema DbContext non configurato per ODBC e abilita connessioni ODBC complete.
183 lines
5.9 KiB
C#
183 lines
5.9 KiB
C#
using Microsoft.Win32;
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
namespace CredentialManager.Services;
|
|
|
|
/// <summary>
|
|
/// Informazioni su un DSN ODBC
|
|
/// </summary>
|
|
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<string, string> Properties { get; set; } = new();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Interfaccia per il servizio di discovery DSN ODBC
|
|
/// </summary>
|
|
public interface IOdbcDsnDiscoveryService
|
|
{
|
|
/// <summary>
|
|
/// Ottiene tutti i DSN ODBC configurati (sia User che System)
|
|
/// </summary>
|
|
List<OdbcDsnInfo> GetAllDsn();
|
|
|
|
/// <summary>
|
|
/// Ottiene solo i DSN utente
|
|
/// </summary>
|
|
List<OdbcDsnInfo> GetUserDsn();
|
|
|
|
/// <summary>
|
|
/// Ottiene solo i DSN di sistema
|
|
/// </summary>
|
|
List<OdbcDsnInfo> GetSystemDsn();
|
|
|
|
/// <summary>
|
|
/// Ottiene i dettagli di un DSN specifico
|
|
/// </summary>
|
|
OdbcDsnInfo? GetDsnDetails(string dsnName, bool isUserDsn = true);
|
|
|
|
/// <summary>
|
|
/// Ottiene la lista dei driver ODBC installati
|
|
/// </summary>
|
|
List<string> GetInstalledDrivers();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Servizio per la scoperta e lettura dei DSN ODBC configurati sul sistema
|
|
/// </summary>
|
|
public class OdbcDsnDiscoveryService : IOdbcDsnDiscoveryService
|
|
{
|
|
private readonly ILogger<OdbcDsnDiscoveryService> _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<OdbcDsnDiscoveryService> logger)
|
|
{
|
|
_logger = logger;
|
|
}
|
|
|
|
public List<OdbcDsnInfo> GetAllDsn()
|
|
{
|
|
var allDsn = new List<OdbcDsnInfo>();
|
|
allDsn.AddRange(GetUserDsn());
|
|
allDsn.AddRange(GetSystemDsn());
|
|
return allDsn;
|
|
}
|
|
|
|
public List<OdbcDsnInfo> GetUserDsn()
|
|
{
|
|
return GetDsnFromRegistry(Registry.CurrentUser, USER_DSN_PATH, USER_DSN_DETAILS_PATH, true);
|
|
}
|
|
|
|
public List<OdbcDsnInfo> 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<string> GetInstalledDrivers()
|
|
{
|
|
var drivers = new List<string>();
|
|
|
|
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<OdbcDsnInfo> GetDsnFromRegistry(RegistryKey rootKey, string dsnPath, string detailsPath, bool isUserDsn)
|
|
{
|
|
var dsnList = new List<OdbcDsnInfo>();
|
|
|
|
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;
|
|
}
|
|
}
|