Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2018年07月16日] [更新 2019年12月25日] Delphi 一般・その他
   
BDE ( Borland Database Engine ) の設定等
動作確認等 Windows Vista 以降
Windows 7 U64(SP1) + Delphi XE5(UP2) Pro VCL-32
[整理番号 - 0560]







Windows Vista 以降における BDE の使用


本ページは,Windows Vista 以降に関するページから BDE 関係だけを 2018年07月16日 に移動したものですが,BDE の設定関係のコード類を追加しています.

新規にデータベースアプリを構築するのに BDE (ビーディーイー,Borland Database Engine) を使用することは考えられませんが.BDE と SQL Link は,各種データベースへの接続を仲介するためのソフトウェアです.
Paradox, dBASE, Oracle, INFORMIX, SYBASE, IBM DB2, MS SQL Server, InterBase Server 等との接続を可能します.このような,データベースとの接続を仲介するソフトウェアはミドルウェアと呼ばれています.BDE は汎用的なミドルウェアということになります.
Delphi XE6 までは,この BDE と,Paradox, dBASE のサンプルデータが付属していて,Delphi をインストールすると自動的にセットされていました (Paradox, dBASE というデータベースのソフトが付属していたわけではありません).

サードパーティが提供しているデータベースには,多くの場合,そのデータベース専用のミドルウェアが付属しています.BDE を使用する必然性はありません.それらの専用のミドルウェアは,一般的に,そのデータベースの機能を十分に引き出すことが可能です.一方,BDE を使用する場合,機能的な制限があります.



[備考 1]
Delphi 6 が BDE のサポート最終版です.BDE は 2002年以降メンテナンスされていません.Paradox も,Borland 社でのサポートが 1997年10月21日で終了しています.
現在は,昔の Delphi 5 / 6 の時代とはかなり状況が違います.隔世の感があります.しかし,BDE が 1 つの役割を担ってきたのは間違いなく事実です.

[備考 2]
BDE の設定関係の処理コードは管理者権限での実行が必要です.そのためには,アプリにアプリケーションマニフェストを組み込みます.基本的に,配布用のアプリにはアプリケーションマニフェスト-の組み込みが必要です.

[備考 3]
記事本文,あるいは図中に,フォルダ (ディレクトリ) として Program Files がありますが,64 ビットの Windows では Program Files (x86) となります.




01_BDE の設定と制限


Windows Vista 以降で Paradox を利用するには,Paradox の NET DIR の値を設定する必要があります.その設定を行わないと,下図のように「ネットワークの初期化に失敗しました.」という内容のダイアログが現れてアプリが実行できません.
Windows Vista 以降では,たとえ管理者権限を持つユーザーであっても,システムドライブのルート直下のファイルは操作できません



図1
C:\ ルートへのアクセス拒否

図2
一般的なルート直下の操作
  • ルート直下のファイル操作は特権が必要

PDOXUSRS.NET ファイルは,Paradox に接続するユーザを管理するために BDE が使用します.
PDOXUSRS.NET ファイルにアクセス可能にするには,別の場所に作成します.PDOXUSRS.NET ファイルを別の場所に作成するには,BDEAdmmin.exe を起動し,PARADOX の NET DIR の値を変更します.

もちろん,システムドライブのルートディレクトリ以外の場所にします.また,Program Files (あるいは Program Files (x86)) やシステム関係のディレクトリは指定しないようにします.
BDEAdmin.exe は管理者権限で起動します.ネット上には,UAC を無効にしないと更新できないという記事もあるようですが,筆者の環境ではそのような現象は確
認できていません.

下図は BDEAdmin.exe がある場所です.この BDEAdmin.exe を [管理者として実行] で起動します.



[備考]
BDEAdmin.exe, データベースデスクトップ共に,[スタート] メニューから起動できます.メニューの項目は [BDE Administrator], [Database Desktop] です.これらの項目がメニューにない場合は以下の図を参考にしてください.
BDEAdmmin.exe も dbd32.exe (データベース・デスクトップ) も BDE 用のツールです.これらが添付されているのは Delphi XE6 までです.



図3

PARADOX の NET DIR の値を例えば,C:\Users\Public\Documents に変更します.この NET DIR の値は,実際に存在するディレクリ名にします.変更したら BDEAdmmin.exe を閉じます.閉じる時に現れるダイアログで変更内容を保存できます.
BDE を使用して PARADOX に接続するアプリを実行すると,この場所に新しい PDOXUSRS.NET ファイルが作成されます.前の場所にあった PDOXUSRS.NET ファイルは削除して構いません.

LAN 上で複数のコンピュータから (複数のユーザが) Paradox データベースを共有して使用する場合には,PDOXUSRS.NET ファイルを LAN 上の共有ディレクトリに作成します.そのためには,NET DIR の値をその共有ディレクトリ名にします.ディレクトリ名には UNC を使用します.
BDE は各コンピュータにインストールする必要があります.



図4

NET DIR の値を設定するコード例です.このコードは,BDE のインストール先にある IDAPI32.CFG ファイルの内容を書き換えます.

グローバルな設定を変更することなく,自アプリのプロセスだけで NET DIR の設定を有効する方法が「今更ながら BDE ... 」の「トラブルシューティング」にあります.わずか 2 行のコードだけで設定できます.
「今更ながら BDE ... 」の記事では SysUtils.GetHomePath に設定しています.この値は,ユーザの操作に伴い変更されるアプリのカスタマイズ情報の置き場所として,マイクロソフトが推奨している場所となっています.

BDE 関係の関数類のヘルプファイルは BDE32.HLP です.オンラインヘルプには BDE 関数類の説明記事はありません.



implementation

uses
  BDE,
  Winapi.ShlObj,
  System.IOUtils;

{$R *.dfm}

//-----------------------------------------------------------------------------
//  BDE の 環境の設定を変更する関数
//  戻り値は変更前の値   
//
//  AConfigPath  : 環境の項目名
//  AConfigName  : その項目内の定義名
//  AConfigValue : その定義名の設定値

//  管理者権限で実行しないと変更できない
//  変更できない場合でもエラーは発生しない
//
//  uses に BDE が必要
//-----------------------------------------------------------------------------
function ConfigBDE(AConfigPath, AConfigName, AConfigValue: string): string;
var
  LhDBICur : hDBICur;
  LConfig  : CFGDesc;
  LszPath  : DBIPATH;
begin
  Result := '';

  // BDE がインストールされていなければ (使用不可ならば) 終了
  if DbiInit(nil) <> DBIERR_NONE then Exit;
  try
    LhDBICur := nil;
    StrPCopy(LszPath, AConfigPath);
    if DbiOpenCfgInfoList(nil,
                          dbiREADWRITE,
                          cfgPersistent,
                          @LszPath,
                          LhDBICur) = DBIERR_NONE then begin
      if DbiSetToBegin(LhDBICur) <> DBIERR_NONE then Exit;

      while True do begin
        if (DbiGetNextRecord(LhDBICur,
                             dbiWRITELOCK,
                             @LConfig,
                             nil) <> DBIERR_NONE) then Break;

        if Trim(string(LConfig.szNodeName)) = AConfigName then begin
          Result := LConfig.szValue;
          StrPCopy(LConfig.szValue, AConfigValue);
          DbiModifyRecord(LhDBICur, @LConfig, True);
          Break;
        end;
      end;
    end;
  finally
    DbiExit;
  end;
end;

//=============================================================================
//  BDE の PARADOX の NET DIR の設定を変更
//
//  管理者権限で実行しないと変更できない.エラーは発生しない
//  結果の表示は変更結果の値になるが実際は変更されていない
//  再度実行すれば変更されたかの確認が可能
//
//  uses に Winapi.ShlObj. System.IOUtils が必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LText     : string;
  LOldValue : string;
  LNewValue : string;
begin
  Memo1.Lines.Clear;

  if not IsUserAnAdmin then begin
    LText := '管理者権限で実行してください';
    MessageBox(Handle, PChar(LText), 'BDE の環境設定', MB_ICONWARNING);
    Exit;
  end;


  // Delphi XE5 以降用 = C:\Users\Public\Documents
  LNewValue := TPath.GetSharedDocumentsPath;
  LOldValue := ConfigBDE('\DRIVERS\PARADOX\INIT', 'NET DIR', LNewValue);

  Memo1.Lines.Add('変更前 : ' + LOldValue);
  Memo1.Lines.Add('変更後 : ' + LNewValue);

    // 前の場所の PDOXUSRS.NET ファイルは削除
    if LOldValue <> LNewValue then begin
    DeleteFile(IncludeTrailingPathDelimiter(LOldValue) + 'PDOXUSRS.NET');
  end;
end;


Paradox の [データベース・デスクトップ] (database desktop) も下図の場所にあります.Delphi 5 / 6 / 7  等では [Program Files] フォルダ直下の [Borland] フォルダにあります.

この [データベース・デスクトップ] は BDE 用のツールです.当然ですが,BDE 関係の設定をしておかないと正常に動作しません.この図では,dbd32.exe は [Program Files] フォルダの階層下にあります.したがって,Windows Vista 以降の環境では当然ながら,管理者権限で起動しないと正常に機能しないことになります.




図5

下図は [データベース・デスクトップ] のテーブルの新規作成の画面です.





図6

BDE は,32 ビットの Windowsアプリケーション用です.64 ビット版の Windows でも,BDE を使用したアプリの開発はできますが,作成できるのは,32 ビットのアプリケーションだけです. また,4G を超えるファイルは扱えません.BDE はマルチプロセッサ環境では正常動作しない場合があります.詳細については以下を参考にしてください.
BDE で Paradox のデータベースを扱う場合,サブクエリーは使用できません.SQL 文をディスクに保存して読み出すことは可能ですが,その SQL 文に変数は使用できません.






02_BDE の初期化中にエラーが発生


BDE を使用するアプリの実行時に,下図のような初期化のエラーが発生することがあるようです.


Borland Database Engine の初期化中にエラーが発生しました (エラー $210D)
Borland Database Engine の初期化中にエラーが発生しました (エラー $2501)
Borland Database Engine の初期化中にエラーが発生しました (エラー $2A06)

初期化中のエラーが $2108 の場合は,BDE がインストールされていないか,使用できない状態の時に発生する現象です.このエラーの場合は BDE のインストールが必要です.

BDE を使用するアプリケーションの実行中に BDEAdmin.exe を起動すると,$210C の同様のエラーが発生します.また,BDEAdmin.exe を起動中に BDE を使用したアプリを起動する時も,$210C のエラーが発生します.




図7
初期化中にエラー

この現象は,SHAREDMEMLOCATION の値を範囲内の値に修正して,SHREDMEMSIZE の値を適切に設定すれば回避できるという記事があります.
以下のリンクの記事を参考にしてください.
下図では BDEAdmmin.exe を管理者権限で起動して,[System] [INIT] の SHAREDMEMLOCATION の値を $3BDE という値にしています.



図8


上の図の SHAREDMEMLOCATION と SHAREDMEMSIZE の値をコードで設定する例です.
NEt DIR の設定コードで使用している関数 ConfigBDE を使用しています.


//=============================================================================
//  BDE の System の Init の以下の設定を変更するプログラム
//  SHAREDMEMLOCATION
//  SHAREDMEMSIZE
//
//  管理者権限で実行しないと変更できない.エラーは発生しない
//  結果の表示は変更結果の値になるが実際は変更されていない
//  再度実行すれば変更されたかの確認が可能
//
//  uses に Winapi.ShlObj が必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LText     : string;
  LOldValue : string;
  LNewValue : string;
begin
  Memo1.Lines.Clear;

  if not IsUserAnAdmin then begin
    LText := '管理者権限で実行してください';
    MessageBox(Handle, PChar(LText), 'BDE の環境設定', MB_ICONWARNING);
    Exit;
  end;


  LNewValue := '3BDE';
  LOldValue := ConfigBDE('\SYSTEM\INIT', 'SHAREDMEMLOCATION', LNewValue);

  Memo1.Lines.Add('SHAREDMEMLOCATION');
  Memo1.Lines.Add('変更前 : ' + LOldValue);
  Memo1.Lines.Add('変更後 : ' + LNewValue);


  LNewValue := '2048';
  LOldValue := ConfigBDE('\SYSTEM\INIT', 'SHAREDMEMSIZE', LNewValue);

  Memo1.Lines.Add('');
  Memo1.Lines.Add('SHAREDMEMSIZE');
  Memo1.Lines.Add('変更前 : ' + LOldValue);
  Memo1.Lines.Add('変更後 : ' + LNewValue);
end;


NET DIR の値はレジストリには書き込まれませんが,上の図の設定内容は,レジストリの以下の場所にあります.
32 ビットの EXE は特に指定しない限り 32 ビット用のレジストリにアクセスしますから,32 ビットのプログラムから操作する場合は,32 ビットのレジストリのキー名でアクセスできます.


// 32 ビット Windows のレジストリ
// 64 ビット Windows の 32 ビット用レジストリ (C:\Windows\SysWOW64\Regedit で起動可能)
HKEY_LOCAL_MACHINE\SOFTWARE\Borland\Database Engine\Settings\SYSTEM\INIT

// 64 ビット Windows のレジストリ (RegEdit だけで起動可能)
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Borland\Database Engine\Settings\SYSTEM\INIT




03_Delphi XE7 以降で BDE を使用する


Delphi XE7 では BDE は添付されなくなりました.Delphi XE7 以降で BDE (と BDE 関係コンポーネント類) を使用するには,以下のリンクから別途ダウンロードしてインストールする必要があります.
インストール用のプログラムは,Delphi のバージョンによって異なります.[Download ...] のボタンをクリックしてダウンロードします.

[Network License Users] というのがありますが,これは,ネットワーク経由で製品のライセンスを取得したという意味ではありません.[ネットワークコンカレントライセンス] の契約者用です .
[Download ...] と [Network License Users] の違いは,ライセンスの取得方法ではなく,ライセンスの内容の違いです.



BDE のインストーラをダウンロードするには EDN (Embarcadero Developer Network) のアカウントが必要です.まだ取得していない場合は [Download ...] ボタンをクリックして表示される,下図の画面の右側の赤枠部分の [Join Today!] をクリックして登録します.
ただし英語のページです.英語の登録ページでは,漢字が文字化けする可能性があります.日本語の登録ページへのリンクは以下の記事にあります.



[備考 1]
Rad Studio には無料トライアル版 (試用版・評価版) があります.Rad Studio 10 Seatle までのトライアル版にも BDE がインストールできましたが,Rad Studio 10.1 Berlin 以降のトライアル版には BDE はインストールできなくなっているようです.ダウンロードの段階で Not Authorized の表示が現れてダウンロードが拒否されます.


[備考 2]
上記のリンクからダウンロードした Delphi XE7 以降の BDE 関係ファイルには,SQL Link 関係ファイル,[データベース・デスクトップ] はありません.



図9

BDE をインストールすると,下図のような BDE 関係のコンポーネントが利用できるようになります.




図10
Delphi XE7 の BDE 関係コンポーネント類




04_BDE の単体インストールまたは BDE の単体配布
plBDEInstaller.zip [839 KB] 2021年07月19日版 (EXEのみ.説明なし.BDE 関係ファイルなし)
BDE インストール用プログラム.掲載コードの動作確認用


BDE を使用するアプリを配布する際は,BDE のインストールの機能を実装することになりす. BDE の単体インストールおよび配布に関する内容は以下の記事を参考にしてください.
Embarcadero ては (Borland 時代も含めて) BDE の単体配布はしていません.

BDE は必ず,BDE を使用するアプリと共にインストール可能にする必要があります.BDE を別途入手してインストールするようにしたアプリを見たことがあります.そのような仕様は避けるべきです.BDE の単体配布はありませんがら,そのユーザは,そのアプリを使用できないことになります.



自アプリに BDE のインストールの機能を実装する際の参考コードです.
このコードは,「今更ながら BDE ... 」の regsvr32 (BdeInst.dll) を使用する手順の 2. ~ 5. を自動的に処理するようにしたものです.手順 1. だけは手作業になります.本サンプルでは,BDE_Temp というフォルダに BDE 関係のファイルをコピーすることが手順 1 に相当します.IDAPI.CFG は,実行時に自動削除するようにしています.
製品版の Delphi 6 の場合,BDE 関係ファイルは,インストール用 CD の [Install] [Common] ... [BDE] フォルダにあります.

この方法は,インストールに使用する元の BDE 関係のファイルに bdeinst.cab ファイルがないと利用できません.
最後にインストールしたのが Delphi XE6 以前の製品版であれば,bdeInst.cab ファイルは BDE のインストール先のフォルダにあります.Delphi XE7 以降の BDE 関係ファイルには bdeInst.cab ファイルはありません.

regsvr32.exe'BdeInst.dll を実行するとインストール先のディレクトリの確認ダイアログが現れます.ダイアログの起動をフックして,そのダイアログをすぐ閉じるようにしています.「十分な残り容量がありません」のダイアログもすぐ閉じるようにしていますから,ダイアログの表示によるインストールの中断はありません.
「十分な残り容量がありません」のダイアログは,おそらく整数計算のオーバフローの発生が原因と思われます.




図11
BDE のインストール完了
  • BDE を使用するアプリ内で NET DIR やエイリアス等の設定をする場合は環境設定は不要

このサンプルには上書きインストール用としての処理コードはありません.インストール先を決め打ちににしているので新規インストール用です.
現実問題として,最終バージョンの BDE を新規でインストールすれば,上書きインストールの必要性はないことになります.Delphi 6 以降の Delphi であれば,BDE は全て最終バージョンです.32 ビットの Windows にも 64 ビットの Windows にもインストール可能です.




図12
BDE がインストール済みの場合
  • 上書きインストールはしない

下に示すコードを実行すると,ディレクトリ %CommonProgramFiles% の階層下に Borland Shared といディレクトリを作成し,更にその階層下に BDE というディレクトリを作成します.この BDE 内に関係ファイルをコピーします.その後に BDE のインストールのコマンドを実行します.




図13
BDE をインストールした後の Common Files ディレクトリの構成
  • Borland Shared ディレクトリを作成する
  • この直下にディレクトリ BDE を作成し,そこに関係ファイルをコピーする

BDE のインストールを実行すると,レジストリの [HKEY_LOCAL_MACHINE\SOFTWARE] に [Borland] というキー項目が作成され,その階層下に関係するキーが作成されます.
下図は 32 ビット版のレジストリの場合です.64 ビット版のレジストリでは SOFTWARE\Wow6432Node の階層下となります.




図14
BDE をインストールした後の レジストリの構成
  • Borland というキー項目が作成されいる
  • この階層下に関係するキーが作成される

[備考 1]
Delphi 製品版の登録ユーザは,Delphi 7 と Delphi 2007 と 1 つ前までのバージョンの Delphi の ISO イメージファイルを入手してインストールできます (前項の BDE のダウンロードのリンクを参照).Delphi 7 / 7.1 / 2007 の日本語版だけでしか確認していませんが,それらの ISO イメージファイルには bdeInst.cab ファイルがないようです.製品版には bdeInst.cab があります.

[備考 2]
インストールに regsvr32 を使用していますが DLL の登録 (COM の登録) ではありません.
BDE を ActiveX で (COM として) 使用するには,INF ファイルを作成して,Bdeinst.dll の clsid (GUID) 関係の設定をします.



unit plBDEInstallerUnit;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
    function DialogHook(var Message: TMessage): Boolean;
  end;

function InstallBDE(ASrcDir: string): Boolean;
function RunExeFile(hWnd: HWND; AFile: string; AParameters: string;
   Verb: string; nShow: Cardinal): Cardinal;
function ExpandEnvironmentString(AEnvName: String): String;
function ConfigBDE(AConfigPath, AConfigName, AConfigValue: string): string;
function GetBDEVersion: string;
function GetFileVersionString(FileName: string): string;

var
  Form1: TForm1;

implementation

uses
  BDE,
  System.Types,
  System.IOUtils,
  Winapi.ShlObj,
  Winapi.ShellAPI,
  System.Win.Registry;

{$R *.dfm}

//=============================================================================
//  フォーム生成時の処理
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  Button2.Enabled := DbiInit(nil) = DBIERR_NONE;
  DbiExit;
end;

//=============================================================================
//  BDE のインストールを実行
//
//  この EXE のフォルダ内に BDE_Timp の名前のフォルダを作成
//  既存の BDE フォルダ内のフォルダとファイルを BDE_Temp 内にコピーしておく
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LBDE_TempDir : string;
  LNetDirPath  : string;
  LText        : string;
begin
  if not IsUserAnAdmin then begin
    LText := '管理者権限で実行してください';
    MessageBox(Handle, PChar(LText), 'BDE インストール', MB_ICONWARNING);
    Exit;
  end;

  LBDE_TempDir := ExtractFilePath(Application.ExeName) + 'BDE_Temp';

  if not FileExists(IncludeTrailingPathDelimiter(LBDE_TempDir) + 'bdeinst.cab') then begin
    LText := 'bdeinst.cab ファイルがありません';
    MessageBox(Handle, PChar(LText), 'BDE インストール', MB_ICONWARNING);
    Exit;
  end;


  Button1.Enabled := False;

  // ダイアログのフック開始
  Application.HookMainWindow(DialogHook);

  if InstallBDE(LBDE_TempDir) then begin
    // NET DIR の設定
    // Delphi XE5 以降用 = C:\Users\Public\Documents
    LNetDirPath := TPath.GetSharedDocumentsPath;
    ConfigBDE('\DRIVERS\PARADOX\INIT', 'NET DIR', LNetDirPath);

    // その他の設定
    // 必要に応じてエイリアス等,他の設定をする
    ConfigBDE('\SYSTEM\INIT', 'SHAREDMEMLOCATION', '3BDE');
    ConfigBDE('\SYSTEM\INIT', 'SHAREDMEMSIZE',     '2048');

    LText := 'BDE のインストールが完了しました' + sLineBreak
           + 'BDE Version : ' + GetBDEVersion;
    MessageBox(Handle, PChar(LText), 'BDE インストール', MB_ICONINFORMATION);

    Button2.Enabled := True;
  end else begin
    LText := 'BDE はインストールされています ' + sLineBreak
           + 'BDE Version : ' + GetBDEVersion;
    MessageBox(Handle, PChar(LText), 'BDE インストール', MB_ICONINFORMATION);
  end;

  // ダイアログのフック終了
  Application.UnhookMainWindow(DialogHook);

  Button1.Enabled := True;
  Close;
end;

//=============================================================================
//  BDE Administrator の起動
//  エンドユーザにエクスプローラで bdeadmin.exe を探すような操作はさせない
//  
//  64 ビット Windows の場合はコントロールパネルから起動できない
//  32 ビット Windows はコントロールパネルから起動可能だが管理者権限では起動不可
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
begin
  ShellExecute(0, 'runas', 'bdeadmin.cpl', nil, nil, SW_SHOW);
end;

//-----------------------------------------------------------------------------
//  DBE のインストール用関数
//  アプリに BDE のインストール機能を組み込む際の参考コード
//  インストール先は %CommonProgramFiles%\Borland Shared\BDE 固定
//  管理者権限で実行しないと失敗する
//  失敗してもエラーは発生しない
//
//  ASrcDir   : BDE 関係のファイルがあるディレクトリ
//
//  uses に BDE 等が必要
//-----------------------------------------------------------------------------
function InstallBDE(ASrcDir: string): Boolean;
var
  LInstDir : string;
  LCabPath : string;
  LDllPath : string;
begin
  Result := False;

  // BDE がインストール済みの場合は終了
  try
    if (DbiInit(nil) = DBIERR_NONE) then Exit;
  finally
    DbiDLLExit;
    DbiExit;
  end;

  // インストール先のディレクトリ
  LInstDir := ExpandEnvironmentString('%CommonProgramFiles%\Borland Shared\BDE');

  // ディレクトリを作成してファイルをコピー
  ForceDirectories(LInstDir);
  Sleep(10);
  TDirectory.Copy(ASrcDir, LInstDir);
  Sleep(10);

  LInstDir := IncludeTrailingPathDelimiter(LInstDir);
  LCabPath := AnsiQuotedStr(LInstDir + 'bdeinst.cab', '"');
  LDllPath := AnsiQuotedStr(LInstDir + 'BdeInst.dll', '"');

  // 環境設定ファイルは削除
  DeleteFile(LInstDir + 'IDAPI32.CFG' );

  // CAB 書庫からインストール用の DLL を取り出す
  RunExeFile(0, 'Expand', LCabPath + ' ' + LDllPath, '', SW_HIDE);

  // BDE のインストール
  // regsvr32 を使用しているが DLL の登録 (COM の登録) ではない
  RunExeFile(0, 'regsvr32.exe', '/s ' + LDllPath, '', SW_SHOW);

  Result := True;
end;

//-----------------------------------------------------------------------------
//  ShellExecuteEx関数を使用して,指定したファイルを実行する
//  起動したアプリが終了するまで待つ
//  この関数の戻り値は TShellExecuteInfo.hInstApp の値
//
//  uses に Winapi.ShellAPI が必要
//-----------------------------------------------------------------------------
function RunExeFile(hWnd: HWND; AFile: string; AParameters: string;
   Verb: string; nShow: Cardinal): Cardinal;
var
  LInfo : TShellExecuteInfo;
  LRet  : Cardinal;
begin
  FillChar(LInfo, SizeOf(LInfo), 0);
  LInfo.cbSize := SizeOf(LInfo);
  LInfo.fMask  := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_FLAG_NO_UI;

  LInfo.lpFile       := PChar(AFile);
  LInfo.lpParameters := PChar(AParameters);
  LInfo.Wnd    := hWnd;
  LInfo.lpVerb := PChar(Verb);
  LInfo.nShow  := nShow;

  ShellExecuteEx(@LInfo);

  //ShellExecuteExは成功するとhInstAppに33以上の値を返す
  Result := LInfo.hInstApp;
  if Result >= 33 then begin
    //プロセス生成完了まで待つ
    repeat
      LRet := WaitForInputIdle(LInfo.hProcess, 50);
      Application.ProcessMessages;
    until LRet <> WAIT_TIMEOUT;

    // プロセスが起動したらプロセス ID の値をグローバル変数に代入
//      FProcessID := GetProcessId(LInfo.hProcess);

   //起動したプロセス(アプリ)の終了を待つ処理
    while WaitForSingleObject(LInfo.hProcess, 100) = WAIT_TIMEOUT do begin
      Application.ProcessMessages;
    end;

    CloseHandle(LInfo.hProcess);
  end;
end;

//-----------------------------------------------------------------------------
//  環境変数(%で囲まれた文字列)から実際のパス名を取得する関数
//-----------------------------------------------------------------------------
function ExpandEnvironmentString(AEnvName: String): String;
var
  LDstPath : array [0..MAX_PATH - 1] of Char;
begin
  ExpandEnvironmentStrings(PChar(AEnvName), LDstPath, Length(LDstpath));
  Result := LDstPath;
end;

//-----------------------------------------------------------------------------
//  TApplication.HookMainWindowの処理関数 (ダイアログのフック)
//  BDE のインストール時に現れる以下のダイアログで処理を継続
//  進捗ダイアログは表示
//
//  (1) インストール先のディレクトリの確認ダイアログ (TOKBottomDlg)
//  (2) 『ドライブ C: に十分な残り容量がありません.インストールを継続しますか』
//     整数値のオーバーフローによって発生するものと思われる (TOKBottomDlg)
//
//  注意 : この処理は常に正常に動作するとは限らない
//-----------------------------------------------------------------------------
function TForm1.DialogHook(var Message: TMessage): Boolean;

  Procedure PressEnterKey(AhWindow: HWND);
  begin
    SetForegroundWindow(AhWindow);
    Sleep(30);
    keybd_event(VK_RETURN, MapVirtualKey(VK_RETURN, 0), 0, 0);
    keybd_event(VK_RETURN, MapVirtualKey(VK_RETURN, 0), KEYEVENTF_KEYUP, 0);
  end;
var
  LDlgWindow : HWND;
begin
  Result := False;

  LDlgWindow := FindWindow('TOKBottomDlg', nil);
  if (LDlgWindow <> 0) and IsWindowVisible(LDlgWindow) then begin
    PressEnterKey(LDlgWindow);
  end;

  LDlgWindow := FindWindow('TMessageForm', nil);
  if (LDlgWindow <> 0) and IsWindowVisible(LDlgWindow) then begin
    PressEnterKey(LDlgWindow);
  end;
end;

//-----------------------------------------------------------------------------
//  BDE の 環境の設定を変更する関数
//  戻り値は変更前の値
//
//  AConfigPath  : 環境の項目名
//  AConfigName  : その項目内の定義名
//  AConfigValue : その定義名の設定値

//  管理者権限で実行しないと変更できない
//  変更できない場合でもエラーは発生しない
//
//  uses に BDE が必要
//-----------------------------------------------------------------------------
function ConfigBDE(AConfigPath, AConfigName, AConfigValue: string): string;
var
  LhDBICur : hDBICur;
  LConfig  : CFGDesc;
  LszPath  : DBIPATH;
begin
  Result := '';

  // BDE がインストールされていなければ (使用不可ならば) 終了
  if DbiInit(nil) <> DBIERR_NONE then Exit;
  try
    LhDBICur := nil;
    StrPCopy(LszPath, AConfigPath);
    if DbiOpenCfgInfoList(nil,
                          dbiREADWRITE,
                          cfgPersistent,
                          @LszPath,
                          LhDBICur) = DBIERR_NONE then begin
      if DbiSetToBegin(LhDBICur) <> DBIERR_NONE then Exit;

      while True do begin
        if (DbiGetNextRecord(LhDBICur,
                             dbiWRITELOCK,
                             @LConfig,
                             nil) <> DBIERR_NONE) then Break;

        if Trim(string(LConfig.szNodeName)) = AConfigName then begin
          Result := LConfig.szValue;
          StrPCopy(LConfig.szValue, AConfigValue);
          DbiModifyRecord(LhDBICur, @LConfig, True);
          Break;
        end;
      end;
    end;
  finally
    DbiDLLExit;
    DbiExit;
  end;
end;

//-----------------------------------------------------------------------------
//  BDE のバージョンを取得する関数
//  uses に BDE, System.Win.Registry, Scripting_TLB が必要
//-----------------------------------------------------------------------------
function GetBDEVersion: string;
var
  LRegistry  : TRegistry;
  LRegistKey : string;
  LDllPath   : string;
begin
  Result := '';

  // BDE のインストール先のディレクトリを取得
  LRegistry := TRegistry.Create(KEY_READ);
  try
    LRegistry.RootKey := HKEY_LOCAL_MACHINE;
    LRegistKey := 'SOFTWARE\Borland\Database Engine';

    if LRegistry.OpenKey(LRegistKey, False) then begin
      LDllPath := LRegistry.ReadString('DLLPATH');
      LRegistry.CloseKey;
    end;
  finally
    FreeAndNil(LRegistry);
  end;
  if LDllPath = '' then Exit;

  LDllPath := LDllPath + '\idapi32.dll';
  if not FileExists(LDllPath) then Exit;

  Result := GetFileVersionString(LDllPath);
end;

//-----------------------------------------------------------------------------
//  [ファイルのバージョン]の文字列を取得する関数
//  [ファイルのバージョン]は,ファイルのプロパティダイアログで表示される値
//  引数はファイルのフルパス名
//-----------------------------------------------------------------------------
function GetFileVersionString(FileName: string): string;
var
  LdwHandle  : Cardinal;
  LpInfo     : Pointer;
  LInfoSize  : DWORD;
  LpFileInfo : PVSFixedFileInfo;
  LiVer      : array[0..3] of Cardinal;
begin
  Result := '';

  LInfoSize := GetFileVersionInfoSize(PChar(FileName), LdwHandle);
  if LInfoSize = 0 then exit;

  GetMem(LpInfo, LInfoSize);
  try
    GetFileVersionInfo(PChar(FileName), 0, LInfoSize, LpInfo);
    VerQueryValue(LpInfo, PathDelim, Pointer(LpFileInfo), LInfoSize);

    LiVer[0] := LpFileInfo.dwFileVersionMS shr 16;
    LiVer[1] := LpFileInfo.dwFileVersionMS and $FFFF;
    LiVer[2] := LpFileInfo.dwFileVersionLS shr 16;
    LiVer[3] := LpFileInfo.dwFileVersionLS and $FFFF;
    Result := Format('%d.%d.%d.%d', [LiVer[0], LiVer[1], LiVer[2], LiVer[3]]);
  finally
    FreeMem(LpInfo, LInfoSize);
  end;
end;

end.


BDE がアンインストールされてしまったとか,自アプリの起動時に BDE が検出てきない場合,BDE をインストールし直さなければなりません.BDE のインストールには管理者権限が必要です.
上のサンプルコードで使用している RunExeFile 関数の第 4 引数を runas にすると,EXE を管理者権限で起動できます.以下のコードはその例です.
Delphi 10.2 では,この機能を使用しなくても,プロジェクトのオプションで,作成した EXE を管理者権限で起動するように設定できます.


//=============================================================================
//  管理者権限で eXE を起動
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LExePath : string;
begin
  // BDE のインストール用プログラムのフルパス
  LExePath := 'BDEInstaller.exe';

  Form1.Enabled := False;

  RunExeFile(Handle, LExePath, '', 'runas', SW_Show);

  SetForegroundWindow(Handle);
  Form1.Enabled := True;
end;


BDE を使用するアプリの開発を,BDE が使用できない環境で開発することは考えられません.当然,BDE のインストーラの機能も自アプリに組み込めるわけです.

自分で BDE のインストール用プログラムを作成するのが面倒な方は,英語版で古いバージョンの BDE 5.1.1.1 ですが,BDE のインストーラが以下の最初のリンクのページからダウンロードできます.このインストーラは管理者権限で実行するようになっています.改めて [管理者としして実行] する必要はありません.

ダウンロードするには EDN (Embarcadero Developer Network) のアカウントが必要です.EDN のアカウントの取得方法については前述の説明で確認してください.
2 番目のリンクのページの [Baixe agora] をクリックすると CarsyBde.exe を直接ダウンロードできます.3 番目のウェブページにそのファイルに関する説明があります.

CarsyBde.exe でインストールするファイルには SQL Link 関係のドライバは含まれていません.純粋に BDE だけのインストールとなっています.SQL Link が必要なデータベースについては,[今更ながら BDE ... ] の記事で確認してください.






05_BDE のアンインストール
plBDEUnInstaller.zip [829 KB] 2021年07月19日版 (EXEのみ.説明なし)
BDE アンインストール用プログラム


BDE のアンインストールの参考コードです.
BDEを使用するアプリケーションをアンインストール時は,コンピュータに BDE を使用する他のアプリがない場合は,BDE をアンインストールすることにななります.以下のコードでは,レジストリ情報ででインストール先を調べて,そのディレクトリを削除します.インストールの際に生成されたレジストリのキーも削除します.

開発環境でも BDE のインストールや設定のテストができるように,インストール先のディレクトリ内に BDE 関係以外のファイルやディレクトリがある場合は,それらを残して,BDE のディレクトリだけを削除します.
レジストリも,Borland キーの階層下に BDE 以外のキーが存在する場合は,BDE 関係のキーだけを削除するようにしています.



[備考]
BdeAdmin.cpl ファイルは必ず削除するようにします.このファイルを削除しないと,BDE が使用できないのに,コントロールパネルに BDE Administrator のアイコンが表示されることになります.
BDE のアイコンは,以下のコマンドを,コマンドプロンプト,または [ファイル名を指定して実行] のダイアログで実行すれば確認できます.この BDE のアイコンをクリックしても,BDE Administrator は正常に動作しません.BDE Administrator の動作には,管理者権限が必要です.

  • explorer ::{26EE0668-A00A-44D7-9371-BEB064C98683}\0



図15
BDE のアンインストール

BDE を使用するプログラムの起動中に BDE のアンインストールを実行すると正常に処理できません.
そこで,このサンプルでは,BDE を使用するコードが実行されている場合,下図のようなダイアログを表示するようにしていす.




図16
BDE を使用するアプリで BDE を使用するコードが実行中の場合

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

function UnInstallBDE(ANetDir: string; var AIsRunBDE: Boolean): Boolean;
function ExpandEnvironmentString(AEnvName: String): string;
function Is64bitWindows: Boolean;

var
  Form1: TForm1;

implementation

uses
  System.Win.Registry,
  System.IOUtils,
  Winapi.ShlObj,
  System.Types;

{$R *.dfm}

// -----------------------------------------------------------------------------
// BDE のアンインストール用関数
// 管理者権限で実行しないと失敗する
// 失敗してもエラーは発生しない
//
//  BDE 関係の機能を使用しないコードにしている
//  BDE 関係の機能を使用するとインストール先のディレクトリが削除できない
//
//  uses に System.Win.Registry 等が必要
// -----------------------------------------------------------------------------
function UnInstallBDE(ANetDir: string; var AIsRunBDE: Boolean): Boolean;
var
  LInstDir   : string;
  LBdeDir    : string;
  LIdAPI32   : string;
  LRegistry  : TRegistry;
  LRegistKey : string;
  LKeyList   : TStringList;
  LAdminPath : string;
begin
  Result := False;
  AIsRunBDE := False;

  // BDE のインストール先のディレクトリを調べる
  LRegistry := TRegistry.Create(KEY_READ);
  try
    LRegistry.RootKey := HKEY_LOCAL_MACHINE;
    LRegistKey := 'SOFTWARE\Borland\Database Engine';

    if LRegistry.OpenKey(LRegistKey, False) then begin
      LBdeDir := LRegistry.ReadString('DLLPATH');
      LRegistry.CloseKey;
    end;
  finally
    FreeAndNil(LRegistry);
  end;
  if LBdeDir = '' then Exit;


  // 親ディレクトリとidapi32.dll のパス
  LInstDir := ExtractFileDir(LBdeDir);
  LIdAPI32 := IncludeTrailingPathDelimiter(LBdeDir) + 'idapi32.dll';

  // この DLL が削除できない時は BDE を使用するコードが実行されている
  // 単に BDE を使用するアプリが起動しているだけであれば削除可能
  // その場合,このディレクトリは操作不可状態となり,そのアプリ終了後に削除される
  if not DeleteFile(LIdAPI32) then begin
    AIsRunBDE := True;
    Exit;
  end;

  // インストール先ディレクトリを削除
  if DirectoryExists(LBdeDir) then begin
    TDirectory.Delete(LBdeDir, True);
  end;
  if DirectoryExists(LInstDir) then begin
    if TDirectory.IsEmpty(LInstDir) then begin
      TDirectory.Delete(LInstDir, True);
    end;
  end;

  // 関係レジストリキーを削除
  LKeyList := TStringList.Create;
  LRegistry := TRegistry.Create;
  try
    LRegistry.RootKey := HKEY_LOCAL_MACHINE;
    LRegistry.DeleteKey('SOFTWARE\Borland\BLW32');
    LRegistry.DeleteKey('SOFTWARE\Borland\Database Engine');

    if LRegistry.OpenKey('SOFTWARE\Borland', False) then begin
      LRegistry.GetKeyNames(LKeyList);
      LRegistry.CloseKey;
      if LKeyList.Count = 0 then begin
        LRegistry.DeleteKey('SOFTWARE\Borland');
      end;
    end;

    LRegistry.RootKey := HKEY_CURRENT_USER;
    LRegistry.DeleteKey('SOFTWARE\Borland\BLW32');
    LRegistry.DeleteKey('SOFTWARE\Borland\Database Engine');

    if LRegistry.OpenKey('SOFTWARE\Borland', False) then begin
      LRegistry.GetKeyNames(LKeyList);
      LRegistry.CloseKey;
      if LKeyList.Count = 0 then begin
        LRegistry.DeleteKey('SOFTWARE\Borland');
      end;
    end;
  finally
    FreeAndNil(LRegistry);
    FreeAndNil(LKeyList);
  end;

  // BdeAdmin.cpl の削除
  if Is64bitWindows then begin
    LAdminPath := ExpandEnvironmentString('%SystemRoot%\SysWOW64\BDEADMIN.CPL');
  end else begin
    LAdminPath := ExpandEnvironmentString('%SystemRoot%\System32\BDEADMIN.CPL');
  end;
  DeleteFile(LAdminPath);

  // PDOXUSRS.NET ファイルの削除
  if ANetDir <> '' then begin
    ANetDir := IncludeTrailingPathDelimiter(ANetDir) + 'PDOXUSRS.NET';
    DeleteFile(ANetDir);
  end;

  Result := True;
end;

//=============================================================================
//  BDE のアンインストールを実行
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LResBool : Boolean;
  LRunBDE  : Boolean;
  LText   : string;
begin
  if not IsUserAnAdmin then begin
    LText := '管理者権限で実行してください';
    MessageBox(Handle, PChar(LText), 'BDE アンインストール', MB_ICONWARNING);
    Exit;
  end;

  Button1.Enabled := False;

  LResBool := UnInstallBDE('', LRunBDE);

  if LResBool then begin
    LText := 'BDE をシステムから削除しました';
    MessageBox(Handle, PChar(LText), 'BDE アンインストール ( 削除 )', MB_ICONINFORMATION);
  end else begin
    if not LRunBDE then begin
      LText := 'BDE はインストールされていません';
      MessageBox(Handle, PChar(LText), 'BDE アンインストール ( 削除 )', MB_ICONINFORMATION);
    end else begin
      // この場合はアンインストールの中止も可能
      LText := 'BDE をアンインストールできません' + sLineBreak
             + 'BDE を使用したアプリを終了して再度実行してください' + sLineBreak
             + 'またはアンインストールを中止してください';
      MessageBox(Handle, PChar(LText), 'BDE アンインストール ( 削除 )', MB_ICONWARNING);
    end;
  end;

  Button1.Enabled := True;
  Close;
end;

//-----------------------------------------------------------------------------
//  環境変数(%で囲まれた文字列)から実際のパス名を取得する関数
//-----------------------------------------------------------------------------
function ExpandEnvironmentString(AEnvName: String): String;
var
  LDstPath : array [0..MAX_PATH - 1] of Char;
begin
  ExpandEnvironmentStrings(PChar(AEnvName), LDstPath, Length(LDstpath));
  Result := LDstPath;
end;

//-----------------------------------------------------------------------------
//  32ビットのWindowsか64ビットのWindowsかを調べる関数
//  64ビット版のWindowsの場合はTrueを返す
//-----------------------------------------------------------------------------
function Is64bitWindows: Boolean;
var
  Wow64Proc : function(hProcess: THandle; var Wow64: BOOL): BOOL stdcall;
  LRetFlag  : LongBool;
begin
  @Wow64Proc := GetProcAddress(GetModuleHandle('Kernel32.dll'), 'IsWow64Process');
  if @Wow64Proc <> nil then begin
    Wow64Proc(GetCurrentProcess, LRetFlag);

    if SizeOf(THandle) = 4 then begin
      Result := LRetFlag;
    end else
    if SizeOf(THandle) = 8 then begin
      Result := True;
    end;
  end else begin
    //Windows XPの64ビット版か
    Result := CheckWin32Version(5, 2);
  end;
end;

end.




06_BDEのバージョンを取得


インストールされている BDE のバージョンを取得する関数の例です.
BDE のインストール用のサンプルでは GetFileVersionInfo 関数を使用していますが,IFileSystem 関係の関数も使用でききます.
このサンプルでは,システムに BDE がインストールされている時は,BDE のバージョン番号の文字列を取得しますが,インストールされいない場合は空文字を返します.
コード中で使用しているユニット Scripting_TLB は,以下のページから ZIP 書庫ファイルをダウンロードするとその中に含まれています.

このサンプルではフォームの OnCreate イベントで判定していますが,場合によってはプロジェクトのソースコード内で判定することも考えられます.



[備考]
BDE のバージョン情報は DbiGetSysVersion 関数を使用すると,SysVesion レコード型の値として取得することができます.ただし,このレコード型からはメジャーなバージョンの値しか取得できません.また,szVersion メンバの値は空文字です.




図17
BDE がインストールされていない場合

図18
BDE がインストールされている場合は,BDE のバージョンを取得
  • 5.2.0.2 は BDE の最終バージョン

implementation

uses
  BDE,
  System.Win.Registry,
  Scripting_TLB;

{$R *.dfm}

//-----------------------------------------------------------------------------
//  BDE のバージョンを取得する関数
//
//  [戻り値]
//  BDE がインストール済みで使用可能であればそのバージョン文字列
//  BDE がインストールしていないか使用不可の時は空文字
//
//  uses に BDE, System.Win.Registry, Scripting_TLB が必要
//-----------------------------------------------------------------------------
function GetBDEVersion: string;
var
  LRegistry     : TRegistry;
  LRegistKey    : string;
  LDllPath      : string;
  LIFileSystem3 : Scripting_TLB.IFileSystem3;
begin
  Result := '';

  // BDE がインストールされていなければ (使用不可ならば) 終了
  if DbiInit(nil) <> DBIERR_NONE then Exit;
  DbiExit;


  // BDE のインストール先のディレクトリを取得
  LRegistry := TRegistry.Create(KEY_READ);
  try
    LRegistry.RootKey := HKEY_LOCAL_MACHINE;
    LRegistKey := 'SOFTWARE\Borland\Database Engine';

    if LRegistry.OpenKey(LRegistKey, False) then begin
      LDllPath := LRegistry.ReadString('DLLPATH');
      LRegistry.CloseKey;
    end;
  finally
    FreeAndNil(LRegistry);
  end;
  if LDllPath = '' then Exit;


  LDllPath := LDllPath + '\idapi32.dll';
  if not FileExists(LDllPath) then Exit;

  // DLL のファイルバージョン文字列を取得
  LIFileSystem3 := CoFileSystemObject.Create;
  try
    Result := LIFileSystem3.GetFileVersion(LDllPath);
  finally
    LIFileSystem3 := nil;
  end;
end;

//=============================================================================
//  フォーム生成時の処理
//  BDE のインストールの有無と BDE のバージョン取得
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
var
  LValue : string;
begin
  LValue := GetBDEVersion;

  if LValue = '' then begin
    MessageBox(Handle, 'BDE はインストールされていません.', 'BDE', MB_ICONWARNING);
    PostMessage(Handle, WM_CLOSE, 0, 0);
    Exit;
  end;

  LValue := 'BDE Version' + sLineBreak + LValue;
  MessageBox(Handle, PChar(LValue), 'BDE', MB_ICONINFORMATION);
end;




07_データベースのテスト用データファイル


データベースのテスト用のデータファイルが,各バージョンの Delphi のデモ (サンプル) プログラムのフォルダ内の [Data] フォルダにあります.
Samples (サンプル) フォルダがない場合は,以下の最初のリンクの記事を参考にしてダウンロードして,デフォルトの場所である下図の場所に保存してください.



[Data] の部分だけ必要なのであれば,以下のページで [Download Snapshot] をクリックすると,[Data] フォルダ内のファイルだけを ZIP 書庫ファイルとしてダウンロードできます.



[備考]
Delphi XE6 以前のデータファイルは [Program Files] [Common Files] [CodeGear Shared] フォルダ階層下の [Data] フォルダにもあります.ただし,Delphi 7 以前では [Program Files] フォルダ直下の [Borland Shared] の [Data] フォルダにあります.

アプリケーシヨン側でそれらのデータに接続しても,管理者権限でないと編集や更新の操作はできません.Windows Vista 以降では,Program Files フォルダ階層下のファイルの変更操作には管理者権限が必要です.




図19
テスト用のデータベースファイルの場所
  • [%PUBLIC%\DOCUMENTS\Embarcadero] の階層下のフォルダ
  • この図は Delphi XE5 の場合
  • .db, .px は Paradox のデータベース関係のファイル
  • .mdb は JET テータベースのファイル




08_Paradox データベースのエイリアス DBDEMOS の設定
BDESetDBDEMOS.zip [1,101 KB] 2020年03月16日版 (EXE 同梱)
NET DIR とエイリアス DBDEMOS 設定用


当サイトで提供しているコンポーネントのテストプログラムに BDE + Paradox を使用するサンプルがあります.それらのサンプルでは DBDEMOS という Paradox データベースのエイリアス (別名) を使用しています.
以下のコードを実行すると,このエイリアスを設定できます.Button1 をクリックすると,フォルダの選択ダイアログが表示されます.そのダイアログで,例えば,前項で説明したデータファイルが置いてあるフォルダを選択します.

このコードで設定するのは下図の値です.設定した内容は,BDE のスンストール先の IDAPI32.CFG ファイルに保存されます.

BDESetDBDEMOS.zip 書庫内のプロジェクトは,NET DIR と エイリアス DBDEMOS の設定用です.
BDE がインストールされている環境でこのプログラムで NET DIR と DBDEMOS を設定すると,当サイトで提供している BDE を使用したサンプルプログラムが利用できます.テスト用のデータについては,前項の記事で確認してください.



図20

[備考]
DBDEMOS という名前を使用しているのは歴史的な経過があります.
Delphi XE6 以前のバージョンの Delphi をインストールすると,この名前のエイリアスが自動で設定されて,Windows XP 以前ではテスト用のデータが利用可能になっていました.



implementation

uses
  BDE,
  Bde.DBTables,
  Winapi.ShlObj,
  System.IOUtils;

{$R *.dfm}

//-----------------------------------------------------------------------------
//  BDE 使用データベースのエイリアスを設定する手続き
//---------------------------------------------------------------------------
procedure AddStdAlias(Alias, Driver, Path: String);
begin
  if Session.IsAlias(Alias) then begin
    Session.DeleteAlias(Alias);
  end;

  Session.AddStandardAlias(Alias, Path, Driver);
  Session.SaveConfigFile;
end;

//=============================================================================
//  Paradox のデータベースのエイリアスの設定
//
//  フォームに TFileOpenDialog (Vista Dialogs) コンポーネントを配置
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LDefaultFolder : string;
  LDataFileDir   : string;
  LText          : string;
begin
  if not IsUserAnAdmin then begin
    LText := '管理者権限で実行してください';
    MessageBox(Handle, PChar(LText), 'BDE の設定', MB_ICONWARNING);
    Exit;
  end;

  if DbiInit(nil) <> DBIERR_NONE then begin
    MessageBox(Handle, 'BDE がインストールされていません.', 'BDE の設定', MB_ICONWARNING);
    Exit;
  end;
  DbiExit;


  FileOpenDialog1.Options := [fdoPickFolders, fdoPathMustExist, fdoForceFileSystem];
  LDefaultFolder := TPath.GetSharedDocumentsPath + '\ParadoxData';
  FileOpenDialog1.DefaultFolder := LDefaultFolder;

  // フォルダの選択ダイアログを表示
  if FileOpenDialog1.Execute then begin
    LDataFileDir :=  FileOpenDialog1.FileName;
    AddStdAlias('DBDEMOS', 'PARADOX', LDataFileDir);
  end;
end;


BDE の API 関数を使用する例です.文字列は AnsiString 型を使用しないと設定できません.上のコードのように Session 変数を使用した方が便利です.「今更ながら BDE ... 」に uBDE_CONFIG というユニット名で,エイリアス操作用のコードが掲載されています.


//-----------------------------------------------------------------------------
//  BDE 使用データベースのエイリアスを設定する手続き
//---------------------------------------------------------------------------
procedure AddStdAlias(Alias, Driver, Path: String);
var
  LAlias  : AnsiString;
  LDriver : AnsiString;
  LPath   : AnsiString;
  LParams : AnsiString;
begin
  LAlias  := Alias;
  LDriver := Driver;
  LPath   := Path;

  if DbiInit(nil) <> DBIERR_NONE then Exit;
  try
    DbiDeleteAlias(nil, PAnsiChar(LAlias));

    LParams := 'PATH:' + LPath + ';ENABLE BCD:TRUE';

    DbiAddAlias(nil, PAnsiChar(LAlias), PAnsiChar(LDriver), PAnsiChar(LParams), True);
    DbiCfgSave(nil, nil, True);
  finally
    DbiExit;
  end;
end;




09_BDE を使用しないデータベースアプリの構築


BDE を使用しなくてもデータベースのアプリケーションは開発できます.

Delphi XE5 以降の Pro 版以上であれば BDE の代わりに FireDAC が使用できます.FireDAC には データベースとして広く普及している SQLite の機能も組み込まれています.FireDAC は BDE とは違い,実行環境にドライバ等をインストールする必要はありません.

Delphi XE4 以前の場合は ZeosLib をインストールすれば SQLite 等の各種のデータベースへの接続が可能となります.ZeosLib は Starter エディションにもインストールできます.ZeosLib も BDE とは違い,実行環境にドライバ等をインストールする必要がありません.ZeosLib が持つ機能は EXE に組み込まれます.

可搬型のデータベースとして Absolute Database, ElevateDB, DBISAM, あるいは TurboDB 等もあります.これらも BDE を必要としません.