Delphi Programming / Object Pascal
サイトのトップページへ リンクのページへ ロゴマーク
[掲載 2007年04月01日] [更新 2016年05月05日] Delphi サンプルプログラム集
   
827_デバッグ中の実行か EXE 実行かを判定
動作確認等 Windows 7 U64(SP1) + Delphi XE(UP1) Pro
827_IDEorEXE.zip [2,215 KB] 2016年05月05日版(EXE同梱)



  • 2010年11月27日
  • ページの URL を [820_XXX] から [827_XXX] に変更.ダウンロードファイル名も変更
  • 2013年06月11日
  • コードの整備.Delphi XE Pro で動作確認
  • 環境変数を実パスに変換するサンプルを追加




01_デバッグ中の実行か,作成した EXE ファイルの実行かを知る


例えばデータベースのアプリケーションの開発などで,開発中はログインダイアログを表示せず,作成した EXE ファイルを直接実行した時は表示したい場合があります.そのような時にデバッグ (開発) 中での実行かを判定できると便利です.
このサンプルプログラムのコードは,その方法の一つです.

本サンプルで使用しているログインダイアログは,Delphi XE(UP1) Pro の場合,デフォルトでは英語表記になるようです.ライブラリパスに以下を追加すると日本語表記になります.

$(BDS)\source\db\ja


図1
設計時画面
図2
実行結果
  • 作成した EXE ファイルを起動した場合
  • IDE でコンパイルして実行した場合は,このダイアログは表示されない

リスト1
開発中と単独 EXE 実行で実行内容を変える
unit IDEorEXEUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;

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

var
  Form1: TForm1;

implementation

uses 
  DBLogDlg;

{$R *.dfm}

//=============================================================================
//  DebugHook関数を使用してデバッグ時とEXE実行時を判定
//  LoginDilaogEx関数の使用にはusesにDBLogDlgが必要
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
var
  LUser : String;
  LPass : String;
begin
  if DebugHook <> 0 then begin
    //デバッグ中はログインダイアログ表示なし
  end else begin
    LoginDialogEx('接続テスト', LUser, LPass, False);
  end;
end;

end.


IsDebuggerPresent 関数も,IDE での実行か,EXE を実行したかの判定に利用できます.


//=============================================================================
//  IsDebuggerPresent関数を使用してIDEでの実行時とEXE実行時を判定
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
  if IsDebuggerPresent then begin
    MessageBox(Handle, 'デバッグ中です', '結果', MB_ICONINFORMATION);
  end else begin
    MessageBox(Handle, 'EXE 実行です', '結果', MB_ICONINFORMATION);
  end;
end;


デバッグ時ということは,Delphi の IDE から実行していることになります.
つまり,本項のサンプルは,デバック環境での実行か,そうでない環境での実行なのかの判定方法ということになります.

Delphi の IDE は管理者権限で実行しなけれぱ,正常に機能しません.以下のコードは,自分自身が管理者権限で実行しているかを調べる 1 つの方法です.
実際には,上のコードと組み合せて使用することになるでしょう.この関数は,IDE 自身が管理者権限で起動しているかの判定には利用できませ.




  //IsUserAnAdminの使用には,usesにShlObjが必要
  if IsUserAnAdmin then begin
    //管理者権限で実行中
  end else begin
    //管理者権限以外で実行中
  end;




02_デバッグ版とリリース版の判定


前項のサンプルは,デバッグ時と EXE の直接実行時の判定でした.
以下のサンプルは,Debug  版か Release 版かの判定用のコード例です.デバッグ版とリリース版の切り換えは,プロジェクトマネージャのビルド構成で行いますが,切り換えたら,プロジェクトの再構築あるいはビルドをしないと,正しく判定できないことがあります.

Delphi で新規にプロジェクトを作成した場合は,Debug 版がデフォルトのビルド構成です.



図3
デバッグ版
図4
リリース版

リスト2
デバッグ版かリリース版かの判定
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;

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

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  デバッグ版かリリース版かの判定の方法
//  ビルド構成(デバッグかリリース版)を変更したらプロジェクトを再構築(ビルド)する
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
  {$IFDEF DEBUG}
  MessageBox(Handle, 'デバッグ版です', '結果', MB_ICONINFORMATION);
  {$ENDIF}
  {$IFDEF RELEASE}
  MessageBox(Handle, 'リリース版です', '結果', MB_ICONINFORMATION);
  {$ENDIF}
end;

end.




03_環境変数 $(DELPHI) または $(BDS) を取得 - デバッグ時のみ有効


デバッグ時と EXE の直接実行時の違いと言えば.例えば Delphi の環境変数,$(DELPHI) とか $(BDS) があります.これらの値は Delphi のインストール先のディレクトリを意味していますが,デバッグ時にのみに取得可能な値です.デバッグ時というのは IDE からの実行という意味です.
下のリストはその取得例です.


図5
デバッグ時の実行画面
図6
作成した EXE を直接実行した結果

リスト3
環境変数 $(DELPHI) または $(BDS) を取得 - デバッグ時のみ有効
unit GetDelphiPathUnit;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
  private
    { Private 宣言 }
    function GetDelphiPath(APath : string): string;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//=============================================================================
//  Delphiの環境変数($(DELPHI)または$(BDS)のフルパスを取得
//  デバッグ時のみ有効
//=============================================================================
procedure TForm1.Button2Click(Sender: TObject);
var
  LText : string;
begin
  //IDE実行時のみ実行
  if DebugHook <> 0 then begin
    LText := GetDelphiPath('$(DELPHI)\Lib');
    Application.MessageBox(PChar(LText), 'デバッグ');
  end else begin
    Application.MessageBox('EXE を直接実行しても取得できません', 'EXE 実行');
  end;
end;

//-----------------------------------------------------------------------------
//  Delphiの環境変数($(DELPHI)または$(BDS))のフルパスを取得する関数
//  ただしこの関数は,どのDelphiで実行しているかという情報なのでデバッグ時(IDE
//  で操作時)のみ有効(EXEの直接実行ではDelphiのバージョンは無関係)
//-----------------------------------------------------------------------------
function TForm1.GetDelphiPath(APath: string): string;
var
  LText : string;
begin
  Result := APath;

  if Pos('DELPHI', APath) > 0 then begin
    LText := SysUtils.GetEnvironmentVariable('DELPHI');
    if Trim(LText) <> '' then
      Result := StringReplace(APath, '$(DELPHI)', LText, [rfIgnoreCase,rfReplaceAll]);
  end else
  if Pos('BDS', APath) > 0 then begin
    LText := SysUtils.GetEnvironmentVariable('BDS');
    if Trim(LText) <> '' then
      Result := StringReplace(APath, '$(BDS)', LText, [rfIgnoreCase,rfReplaceAll]);
  end;
end;

end.




04_環境変数のパスを実パス名に変換 - デバッグ時のみ有効


上のサンプルでは,1 つの環境変数の実パスを取得しました.
このサンプルは,複数の環境変数を含む文字列を,実際のフルパスに変換します.デバッグ時というのは IDE からの実行という意味です.


図7
設計時画面
図8
Edit1 の値を変換する
図9
実行結果例

リスト4
環境変数のパスを実パス名に変換 - デバッグ時のみ有効
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private 宣言 }
    function GetDelphiPath(APath : string): string;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

uses 
  HTTPApp;

{$R *.dfm}

//=============================================================================
//  テスト用の値をセット
//=============================================================================
procedure TForm1.FormCreate(Sender: TObject);
begin
  Edit1.Text := '$(BDSLIB)\$(Platform)\debug';
end;

//=============================================================================
//  Delphiの環境変数を含むフルパスを取得
//  デバッグ時のみ有効
//=============================================================================
procedure TForm1.Button1Click(Sender: TObject);
begin
  //IDE実行時のみ実行
  if DebugHook <> 0 then begin
    Application.MessageBox(PChar(GetDelphiPath(Edit1.Text)), '結果');
  end else begin
    Application.MessageBox('EXE を直接実行しても取得できません', '結果');
  end;
end;

//-----------------------------------------------------------------------------
//  Delphiの環境変数のパスをフルパスに変換
//  どのDelphiで実行しているかという情報なのでデバッグ時のみ有効
//-----------------------------------------------------------------------------
function TForm1.GetDelphiPath(APath: String): string;
const
  LDelimiters : TSysCharSet = [')'];
  LWhiteSape  : TSysCharSet = ['$', '(', '\', '/'];
var
  LStrList : TStringList;
  LText    : string;
  i        : Integer;
begin
  Result := '';

  LStrList := TStringList.Create;
  try
    HTTPApp.ExtractHTTPFields(LDelimiters, LWhiteSape, PChar(Trim(APath)), LStrList);
    for i := 0 to LStrList.Count - 1 do begin
      if Trim(LStrList[i]) <> '' then begin
        LText := SysUtils.GetEnvironmentVariable(LStrList[i]);
        if LText <> '' then begin
          if i = 0 then begin
            Result := Result + LText;
          end else begin
            Result := IncludeTrailingPathDelimiter(Result) + LText;
          end;
        end else begin
          if Result <> '' then begin
            Result := IncludeTrailingPathDelimiter(Result) + LStrList[i];
          end else begin
            Result := Result + LStrList[i];
          end;
        end;
      end;
    end;
  finally
    FreeAndNil(LStrList);
  end;
end;

end.