چطور میتونم در فایل odbcad32 یک اتصال جدید اضافه کنم؟
نویسنده: هادی مزارعی
تاریخ: ۱۴۰۵/۰۵/۱۶ ۱۷:۴۲
آدرس: www.dntips.ir
odbcad32.exe که در مسیر C:\Windows\System32 قرار دارد یک اتصال اضافه کنم (برای SQL) و چنانچه اتصالی از قبل وجود داشت (برحسب نام تعریف شده) آن را اصلاح کنم. یک برنامه کوچک ساختم که وقتی کاربر آن را اجرا میکند، برنامه فایل MS-Access (در نقش Front-End) موجود در شبکه را (آخرین نسخه) را از شبکه دریافت و در کامپیوتر کاربر کپی میکند و سپس اجرا خواهد کرد. فایل MS-Access از طریق Connection تعریف شده در odbcad32.exe با بانک اطلاعاتی ارتباط برقرار خواهد کرد. در حال حاضر Connection بصورت دستی در سیستم کاربر تعریف میشود و سپس برنامه به کاربر تحویل میشود اما چالش آنجاست که رمز اتصال به SQL را هر چند وقت یکبار تغییر میدم و قصد ندارم مجددا دستی در تمام سیستمها Connection را اصلاح کنم بلکه میخوام توسط همان برنامهای که فایل MS-Access را اجرا میکند، ابتدا اتصال را ایجاد/اصلاح کنم و سپس فایل را به سیستم کاربر انتقال بدم.internal static class OdbcInstaller
{
[DllImport("ODBCCP32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool SQLConfigDataSource(
IntPtr hwndParent,
int fRequest,
string lpszDriver,
string lpszAttributes);
private const int ODBC_ADD_SYS_DSN = 4;
private const int ODBC_CONFIG_SYS_DSN = 5;
public static bool CreateOrUpdateSqlServerDsn(
string dsn,
string server,
string database,
string user,
string password)
{
string attributes =
$"DSN={dsn}\0" +
$"SERVER={server}\0" +
$"DATABASE={database}\0" +
$"UID={user}\0" +
$"PWD={password}\0" +
"Trusted_Connection=No\0" +
"\0";
// ابتدا تلاش برای ویرایش
if (SQLConfigDataSource(
IntPtr.Zero,
ODBC_CONFIG_SYS_DSN,
"ODBC Driver 18 for SQL Server",
attributes))
{
return true;
}
// اگر وجود نداشت ایجاد شود
return SQLConfigDataSource(
IntPtr.Zero,
ODBC_ADD_SYS_DSN,
"ODBC Driver 18 for SQL Server",
attributes);
}
}OdbcInstaller.CreateOrUpdateSqlServerDsn(
"Accounting",
"SQLSERVER01",
"AccountingDB",
"sa",
"123456");ODBC Driver 18 for SQL Server ODBC Driver 17 for SQL Server SQL Server SQL Server Native Client 11.0
Connection ایجاد نشد از GPT کمک گرفتم و جهت دریافت خطای برنامه کد را بصورت زیر اصلاح کرد:using System;
using System.Runtime.InteropServices;
using System.Text;
public static class OdbcInstaller
{
#region Win32 API
[DllImport("ODBCCP32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern bool SQLConfigDataSource(
IntPtr hwndParent,
int fRequest,
string lpszDriver,
string lpszAttributes);
[DllImport("ODBCCP32.dll", CharSet = CharSet.Unicode)]
private static extern uint SQLInstallerError(
uint iError,
out uint pfErrorCode,
StringBuilder lpszErrorMsg,
ushort cbErrorMsgMax,
out ushort pcbErrorMsg);
#endregion
#region Constants
private const int ODBC_ADD_DSN = 1;
private const int ODBC_CONFIG_DSN = 2;
private const int ODBC_REMOVE_DSN = 3;
private const int ODBC_ADD_SYS_DSN = 4;
private const int ODBC_CONFIG_SYS_DSN = 5;
private const int ODBC_REMOVE_SYS_DSN = 6;
#endregion
/// <summary>
/// Creates or updates a SQL Server DSN.
/// </summary>
/// <param name="dsn">DSN name.</param>
/// <param name="server">SQL Server.</param>
/// <param name="database">Database.</param>
/// <param name="user">Login.</param>
/// <param name="password">Password.</param>
/// <param name="driver">
/// Installed ODBC driver name.
/// Example:
/// "ODBC Driver 18 for SQL Server"
/// "ODBC Driver 17 for SQL Server"
/// "SQL Server"
/// </param>
/// <param name="systemDsn">True = System DSN.</param>
public static void CreateOrUpdateSqlServerDsn(
string dsn,
string server,
string database,
string user,
string password,
string driver = "ODBC Driver 18 for SQL Server",
bool systemDsn = false)
{
string attributes =
$"DSN={dsn}\0" +
$"SERVER={server}\0" +
$"DATABASE={database}\0" +
$"UID={user}\0" +
$"PWD={password}\0" +
$"Trusted_Connection=No\0" +
$"Encrypt=No\0" +
$"TrustServerCertificate=Yes\0\0";
int config = systemDsn ? ODBC_CONFIG_SYS_DSN : ODBC_CONFIG_DSN;
int add = systemDsn ? ODBC_ADD_SYS_DSN : ODBC_ADD_DSN;
if (SQLConfigDataSource(IntPtr.Zero, config, driver, attributes))
return;
if (SQLConfigDataSource(IntPtr.Zero, add, driver, attributes))
return;
throw new Exception(GetInstallerErrors());
}
public static void RemoveDsn(
string dsn,
string driver = "ODBC Driver 18 for SQL Server",
bool systemDsn = false)
{
int remove = systemDsn ? ODBC_REMOVE_SYS_DSN : ODBC_REMOVE_DSN;
string attributes =
$"DSN={dsn}\0\0";
if (!SQLConfigDataSource(IntPtr.Zero, remove, driver, attributes))
throw new Exception(GetInstallerErrors());
}
private static string GetInstallerErrors()
{
StringBuilder sb = new();
uint i = 1;
while (true)
{
StringBuilder msg = new(1024);
uint errorCode;
ushort length;
uint result = SQLInstallerError(
i,
out errorCode,
msg,
(ushort)msg.Capacity,
out length);
if (result != 0)
break;
sb.AppendLine($"[{errorCode}] {msg}");
i++;
}
if (sb.Length == 0)
{
int err = Marshal.GetLastWin32Error();
sb.AppendLine($"Win32 Error: {err}");
}
return sb.ToString();
}
}try
{
OdbcInstaller.CreateOrUpdateSqlServerDsn(
dsn: "Accounting",
server: @"DESKTOP-321584",
database: "MyDatabase",
user: "Newuser",
password: "123",
driver: "SQL Server", // Change if necessary
systemDsn: false);
MessageBox.Show("DSN created successfully.");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}[8] Invalid keyword-value pairs [11] Driver's ConfigDSN, ConfigDriver, or ConfigTranslator failed
UID و PWD بود که بصورت زیر و جداگانه در رجیستری ثبت شدند:using Microsoft.Win32;
using var key = Registry.CurrentUser.CreateSubKey(
@"Software\ODBC\ODBC.INI\Accounting");
key.SetValue("UID", "NewUser");
key.SetValue("PWD", "123");odbcca32.exe اتصال Accounting را باز میکنم، گزینه SQL Authentication غیرفعال و Windows Authentication فعال هستش و ورودیهای username و password غیرفعال هستند. که ادامه بررسی بدین صورت شد:تنظیمات احراز هویت توسط خود Driver مدیریت میشه (msodbcsql17S.dll, msodbcsql18S.dll, etc.) و روشی برای انتخاب گزینه احراز هویت توسط SQL از طریق SQLConfigDataSource برای این Driver وجود ندارد.