Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

creating a new ODBC user DSN with Delphi

AI am trying to make a new entry in User DSN, in ODBC Data Source Administrator with the following code:

procedure TForm1.FormCreate(Sender: TObject);
var strAttributes: string;
    wideChars   : array[0..1000] of WideChar;
     pfErrorCode: DWORD;
     errMsg: PChar;

begin
 strAttributes := 'DSN=' + 'example_DSN' + Chr(0);
    strAttributes := strAttributes + 'DESCRIPTION=' + 'description' + Chr(0);
    strAttributes := strAttributes + 'SERVER=' + 'testserver' + Chr(0);
    strAttributes := strAttributes + 'DATABASE=' + 'somedatabase' + Chr(0);

  StringToWideChar(strAttributes, wideChars, 12);
  if not SqlConfigDataSource(0, ODBC_ADD_DSN, 'SQL Server', wideChars) then
  begin
    errMsg := AllocMem(SQL_MAX_MESSAGE_LENGTH);
    SQLInstallerError(1, @pfErrorCode, errMsg, SQL_MAX_MESSAGE_LENGTH, nil);
    MessageBox(0, errMsg, PChar('Add System DSN Error #' + IntToStr(pfErrorCode)), 0);
    FreeMem(errMsg);
  end;
end;

but the SqlConfigDataSource part does not do the job, and also the error that is returned is not undarstandable at all. It is not a number, nor description for the error. Can anyone help me where i make the mistake? Thanks

like image 740
dzibul Avatar asked Mar 04 '12 15:03

dzibul


People also ask

How do I create a System DSN in ODBC 32-bit and 64 bit?

If you build and then run an application as a 32-bit application on a 64-bit operating system, you must create the ODBC data source by using the ODBC Administrator tool in %windir%\SysWOW64\odbcad32 .exe. To indicate the type of DSN, you can add '_32' to the 32-bit user DSNs and '_64' to the 64-bit user DSNs.

What is User DSN in ODBC?

It is the name that applications use to request a connection to an ODBC Data Source. In other words, it is a symbolic name that represents the ODBC connection. It stores the connection details like database name, directory, database driver, UserID, password, etc.


2 Answers

Probably your error or even set of errors is in incorrect translation of ODBC headers, which then may be used for non-Unicode or Unicode Delphi version. For example:

  • for Unicode Delphi you rather need to use XxxW (UTF16) functions from ODBCCP32.DLL, than Xxx (ANSI) functions;
  • for non-Unicode Delphi rather Xxx functions. And then wideChars should be defined as array[..] of Char;
  • SqlConfigDataSource may be defined as XxxW with PAnsiChar;
  • etc.

I wanted to show you the idea, because without full sources I can only speculate. Then you have suspicious call StringToWideChar(strAttributes, wideChars, 12);. strAttributes value is much more long than 12 characters.

The following code works well in Delphi XE2:

type
  SQLHWnd = LongWord;
  SQLChar = Char;
  PSQLChar = ^SQLChar;
  SQLBOOL = WordBool;
  UDword = LongInt;
  PUDword = ^UDword;
  SQLSmallint = Smallint;
  SQLReturn = SQLSmallint;

const
  SQL_MAX_MESSAGE_LENGTH = 4096;

  ODBC_ADD_DSN     = 1;         // Add data source
  ODBC_CONFIG_DSN  = 2;         // Configure (edit) data source
  ODBC_REMOVE_DSN  = 3;         // Remove data source

  ODBC_ADD_SYS_DSN    = 4;          // add a system DSN
  ODBC_CONFIG_SYS_DSN   = 5;        // Configure a system DSN
  ODBC_REMOVE_SYS_DSN   = 6;        // remove a system DSN
  ODBC_REMOVE_DEFAULT_DSN   = 7;    // remove the default DSN

function SQLConfigDataSource (
    hwndParent:     SQLHWnd;
    fRequest:       WORD;
    lpszDriver:     PChar;
    lpszAttributes: PChar
  ): SQLBOOL; {$IFDEF MSWINDOWS} stdcall {$ELSE} cdecl {$ENDIF};
  external 'odbccp32.dll' name 'SQLConfigDataSourceW';

function SQLInstallerError (
    iError:           WORD;
    pfErrorCode:      PUDword;
    lpszErrorMsg:     PChar;
    cbErrorMsgMax:    WORD;
    pcbErrorMsg:      PWORD
  ): SQLReturn; {$IFDEF MSWINDOWS} stdcall {$ELSE} cdecl {$ENDIF};
  external 'odbccp32.dll' name 'SQLInstallerErrorW';

procedure TForm616.Button1Click(Sender: TObject);
var
  strAttributes: string;
  pfErrorCode: UDword;
  errMsg: PChar;
begin
  strAttributes := 'DSN=' + 'example_DSN' + Chr(0);
  strAttributes := strAttributes + 'DESCRIPTION=' + 'description' + Chr(0);
  strAttributes := strAttributes + 'SERVER=' + 'testserver' + Chr(0);
  strAttributes := strAttributes + 'DATABASE=' + 'somedatabase' + Chr(0);
  if not SqlConfigDataSource(0, ODBC_ADD_DSN, 'SQL Server', PChar(strAttributes)) then begin
    errMsg := AllocMem(SQL_MAX_MESSAGE_LENGTH);
    SQLInstallerError(1, @pfErrorCode, errMsg, SQL_MAX_MESSAGE_LENGTH, nil);
    MessageBox(0, errMsg, PChar('Add System DSN Error #' + IntToStr(pfErrorCode)), 0);
    FreeMem(errMsg);
  end;
end;
like image 130
da-soft Avatar answered Sep 27 '22 21:09

da-soft


The answer is right but i have to make a note.

If you don't set the testserver with the port, windows marks "ODBC SQL SERVER DRIVER DBNETLIB 'Invalid Connection'" It creates the driver and in connects but everytime it sends this error if you don't set the test server like:

'testserver,port'

strAttributes := strAttributes + 'SERVER=' + 'testserver,port' + Chr(0);

That would make a better answer because it would avoid sendidng this error.

like image 30
Supergomes Avatar answered Sep 27 '22 20:09

Supergomes