C++拡張ストアドプロシージャを含むレガシーアプリケーションに取り組んでいます。このxsprocは、ODBC=を使用してデータベースに接続します。つまり、DSNを構成する必要があります。
インストーラー(Visual Studio 2008セットアッププロジェクトを使用して作成された)を更新しています。ODBC DSNエントリを作成できるカスタムアクションが必要ですが、Googleで役立つ情報を見つけるのに苦労しています。
誰か助けてもらえますか?
私は実際にレジストリを操作することで、最終的にこれを自分で解決しました。機能を含むクラスを作成しました。その内容をここに含めました。
///<summary>
/// Class to assist with creation and removal of ODBC DSN entries
///</summary>
public static class ODBCManager
{
private const string ODBC_INI_REG_PATH = "SOFTWARE\\ODBC\\ODBC.INI\\";
private const string ODBCINST_INI_REG_PATH = "SOFTWARE\\ODBC\\ODBCINST.INI\\";
/// <summary>
/// Creates a new DSN entry with the specified values. If the DSN exists, the values are updated.
/// </summary>
/// <param name="dsnName">Name of the DSN for use by client applications</param>
/// <param name="description">Description of the DSN that appears in the ODBC control panel applet</param>
/// <param name="server">Network name or IP address of database server</param>
/// <param name="driverName">Name of the driver to use</param>
/// <param name="trustedConnection">True to use NT authentication, false to require applications to supply username/password in the connection string</param>
/// <param name="database">Name of the datbase to connect to</param>
public static void CreateDSN(string dsnName, string description, string server, string driverName, bool trustedConnection, string database)
{
// Lookup driver path from driver name
var driverKey = Registry.LocalMachine.CreateSubKey(ODBCINST_INI_REG_PATH + driverName);
if (driverKey == null) throw new Exception(string.Format("ODBC Registry key for driver '{0}' does not exist", driverName));
string driverPath = driverKey.GetValue("Driver").ToString();
// Add value to odbc data sources
var datasourcesKey = Registry.LocalMachine.CreateSubKey(ODBC_INI_REG_PATH + "ODBC Data Sources");
if (datasourcesKey == null) throw new Exception("ODBC Registry key for datasources does not exist");
datasourcesKey.SetValue(dsnName, driverName);
// Create new key in odbc.ini with dsn name and add values
var dsnKey = Registry.LocalMachine.CreateSubKey(ODBC_INI_REG_PATH + dsnName);
if (dsnKey == null) throw new Exception("ODBC Registry key for DSN was not created");
dsnKey.SetValue("Database", database);
dsnKey.SetValue("Description", description);
dsnKey.SetValue("Driver", driverPath);
dsnKey.SetValue("LastUser", Environment.UserName);
dsnKey.SetValue("Server", server);
dsnKey.SetValue("Database", database);
dsnKey.SetValue("Trusted_Connection", trustedConnection ? "Yes" : "No");
}
/// <summary>
/// Removes a DSN entry
/// </summary>
/// <param name="dsnName">Name of the DSN to remove.</param>
public static void RemoveDSN(string dsnName)
{
// Remove DSN key
Registry.LocalMachine.DeleteSubKeyTree(ODBC_INI_REG_PATH + dsnName);
// Remove DSN name from values list in ODBC Data Sources key
var datasourcesKey = Registry.LocalMachine.CreateSubKey(ODBC_INI_REG_PATH + "ODBC Data Sources");
if (datasourcesKey == null) throw new Exception("ODBC Registry key for datasources does not exist");
datasourcesKey.DeleteValue(dsnName);
}
///<summary>
/// Checks the registry to see if a DSN exists with the specified name
///</summary>
///<param name="dsnName"></param>
///<returns></returns>
public static bool DSNExists(string dsnName)
{
var driversKey = Registry.LocalMachine.CreateSubKey(ODBCINST_INI_REG_PATH + "ODBC Drivers");
if (driversKey == null) throw new Exception("ODBC Registry key for drivers does not exist");
return driversKey.GetValue(dsnName) != null;
}
///<summary>
/// Returns an array of driver names installed on the system
///</summary>
///<returns></returns>
public static string[] GetInstalledDrivers()
{
var driversKey = Registry.LocalMachine.CreateSubKey(ODBCINST_INI_REG_PATH + "ODBC Drivers");
if (driversKey == null) throw new Exception("ODBC Registry key for drivers does not exist");
var driverNames = driversKey.GetValueNames();
var ret = new List<string>();
foreach (var driverName in driverNames)
{
if (driverName != "(Default)")
{
ret.Add(driverName);
}
}
return ret.ToArray();
}
}
chrfalchの投稿 に加えて、API呼び出しではなく、DSNを更新するためのサンプルコードを以下に示します(OPは作成を求めていますが、このコードは必要なものに簡単に変換できます)。レジストリダイレクト経由( pinvoke.netページ からの情報を使用):-
[DllImport("ODBCCP32.DLL", CharSet = CharSet.Unicode, SetLastError = true)]
static extern bool SQLConfigDataSourceW(UInt32 hwndParent, RequestFlags fRequest, string lpszDriver, string lpszAttributes);
enum RequestFlags : int
{
ODBC_ADD_DSN = 1,
ODBC_CONFIG_DSN = 2,
ODBC_REMOVE_DSN = 3,
ODBC_ADD_SYS_DSN = 4,
ODBC_CONFIG_SYS_DSN = 5,
ODBC_REMOVE_SYS_DSN = 6,
ODBC_REMOVE_DEFAULT_DSN = 7
}
bool UpdateDsnServer(string name, string server)
{
var flag = RequestFlags.ODBC_CONFIG_SYS_DSN;
string dsnNameLine = "DSN=" + name;
string serverLine = "Server=" + server;
string configString = new[] { dsnNameLine, serverLine }.Aggregate("", (str, line) => str + line + "\0");
return SQLConfigDataSourceW(0, flag, "SQL Server", configString);
}
このようなことを行うためのAPIがあります。 APIを使用すると、アプリケーションが新しいバージョンのWindowsとの互換性を維持することも保証されます。 APIはここにあります:
http://msdn.Microsoft.com/en-us/library/ms716476(VS.85).aspx
P#でこの関数を呼び出すことは、PInvoke.netにあります。
ODBC情報の読み取り時に CodeProjectページがあります 。
必要なレジストリエントリをリバースエンジニアリングして書き込むために必要な情報が得られるはずです。
そのコードから;
private const string ODBC_LOC_IN_REGISTRY = "SOFTWARE\\ODBC\\";
private const string ODBC_INI_LOC_IN_REGISTRY =
ODBC_LOC_IN_REGISTRY + "ODBC.INI\\";
private const string DSN_LOC_IN_REGISTRY =
ODBC_INI_LOC_IN_REGISTRY + "ODBC Data Sources\\";
private const string ODBCINST_INI_LOC_IN_REGISTRY =
ODBC_LOC_IN_REGISTRY + "ODBCINST.INI\\";
private const string ODBC_DRIVERS_LOC_IN_REGISTRY =
ODBCINST_INI_LOC_IN_REGISTRY + "ODBC Drivers\\";
バーンウェルのコードの+1!
ただし、私はthink彼のDSNExists()が間違ったキーをクエリしています。 I thinkこれは次のようになるはずです:
public static bool DSNExists(string dsnName)
{
var sourcesKey = Registry.LocalMachine.CreateSubKey(ODBC_INI_REG_PATH + "ODBC Data Sources");
if (sourcesKey == null) throw new Exception("ODBC Registry key for sources does not exist");
return sourcesKey.GetValue(dsnName) != null;
}
このコードを提供してくれてありがとう、私は自分で使用しました。私は2つの難しいことを変えなければなりませんでした:
driverName
を取得するには、OpenSubKey
の代わりにCreateSubKey
を使用して値を取得する必要がありました。
// Lookup driver path from driver name
var driverKey = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(
ODBCINST_INI_REG_PATH + driverName);
Vistaを実行しているので、アプリケーションマニフェストを使用し、requestedPrivileges
を次のように設定する必要がありました。
<requestedExecutionLevel level="requireAdministrator" uiAccess="false"/>
次の記事は、OpenSubKey
の問題を見つけるのに役立ちました: http://www.daveoncsharp.com/2009/08/read-write-delete-from-windows-registry-with-csharp/
excelにDSNを作成する場合は、このようなものを追加する必要があるかもしれません。
var dsnKeyEng = Microsoft.Win32.Registry.LocalMachine.CreateSubKey(ODBC_INI_REG_PATH + dsnName + "\\Engines");
var dsnKeyExl = Microsoft.Win32.Registry.LocalMachine.CreateSubKey(ODBC_INI_REG_PATH + dsnName + "\\Engines\\Excel");
dsnKeyExl.SetValue("FirstRowHasNames", 01);
dsnKeyExl.SetValue("MaxScanRows", 8);
dsnKeyExl.SetValue("Threads",3);
dsnKeyExl.SetValue("UserCommitSync", "Yes")