Q&A

  • DLL 호출시 ERROR가 나는데.....
동적DLL로 Child Form 호출시 에러가 납니다.

도대체 원인을 모르겠군요.

소스와 에러 메세지를 올립니다. 도움좀 주세요.

저는 처음에 SPLASH 화면을 뛰우고 그다음 사용자 ID와 PASSWORD를 받고

맞으면 MENU폼을 뛰웁니다.

여기까지는 이상 없이 되는데 여기서(MENU화면)CODE를 Click하면 아래와 같은

ERROR가 나옵니다.

도와주십시요.

---------------------------------------------------------------------------------------

Project log_on.exe raised exception calss EExternalException with message ;external

exception c000001D'.Process stopped Use Step or Run to continue.

---------------------------------------------------------------------------------------



//메인에서 코드 Click시 dll을 호출하는데 자꾸 에러가 발생

{*----------------------------------------------*

*program_id : u_main

*Dscription : Mainmenu

*----------------------------------------------*}

unit u_menu;



interface



uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

Menus, Buttons, ToolWin, ComCtrls,DB,BDE,DBTables,ExtCTRLS;



//Dll에서 사용할 내용 정의

type

//기초코드

Tcodedll = Procedure(App : TApplication);StdCall;

Tcodedll_1 = Function(AOWNER: TCOMPONENT ):TFORM;StdCall;



EDllLoadError = Class(Exception);



type

TF_main = class(TForm)

Menu: TMainMenu;

Code: TMenuItem;

C_Insert: TMenuItem;

E_Insert: TMenuItem;

E_h1: TMenuItem;

E_List: TMenuItem;

E_h2: TMenuItem;

E_See: TMenuItem;

E_h3: TMenuItem;

E_Term: TMenuItem;

User: TMenuItem;

U_chg: TMenuItem;

U_h1: TMenuItem;

U_Insert: TMenuItem;

Config: TMenuItem;

C_Printer: TMenuItem;

Exit: TMenuItem;

Error: TMenuItem;

PrinterSetupDialog1: TPrinterSetupDialog;

ToolBar1: TToolBar;

Sbtn_code: TSpeedButton;

Sbtn_error: TSpeedButton;

Sbtn_User: TSpeedButton;

procedure FormCreate(Sender: TObject);

procedure ExitClick(Sender: TObject);

procedure C_PrinterClick(Sender: TObject);

procedure FormHide(Sender: TObject);

procedure C_InsertClick(Sender: TObject);



private

{ Private declarations }



//Dll에서 사용할 내용 추가

DllHandle:THandle;

//기초코드

CodeDll : TCodeDll;

CodeDll_1 : TCodeDll_1;



public

{ Public declarations }



end;



var

F_main: TF_main;



implementation



uses u_log;



{$R *.DFM}



procedure TF_main.FormCreate(Sender: TObject);

var

WindowRgn: HRgn; // 윈도우 영역을 얻어 오는 자료형 선언 Hrgn

begin



WindowRgn := 0; // 현재 윈도우 영역을 지운다.

GetWindowRgn(Handle,WindowRgn); //현재 윈도우 영역을 얻어 옴

DeleteObject(WindowRgn); // 얻어온 윈도우 영역의 객체를 지움

WindowRgn := CreateRectRgn(0,0,Width,78); // 사각형 생성 (Left,Top,Right,Bottom)

SetWindowRgn(Handle,WindowRgn,True); // 실제 그려지고 사용될 영역 선언

DeleteObject(WindowRgn);



end;



//작업종료시 Check

procedure TF_main.ExitClick(Sender: TObject);

begin

if MessageDlg('작업을 종료 하시겠습니까?',mtConfirmation,[mbYes, mbNo],0) = mrYes then

Close;

Form_Log.Close;

end;





procedure TF_main.C_PrinterClick(Sender: TObject);

begin

PrinterSetupDialog1.ExeCute;

end;









procedure TF_main.FormHide(Sender: TObject);

begin

Close;

Form_Log.Close;



end;





//기초코드 등록을 선택하면

procedure TF_main.C_InsertClick(Sender: TObject);

begin



// 기초코드 동적 호출

DllHandle := LoadLibrary('CallCode.Dll');



try

//에러가발생하면

if DllHandle = HINSTANCE_ERROR then

raise EDLLLoadError.Create('CallCode.Dll을 Load 할 수 없습니다.');



@CodeDll := GetProcaddress(DLLHANDLE,'CodeDll');



//메인에서 코드 Click시 dll을 호출하는데 자꾸 에러가 발생되는 위치

CodeDll(Application);

@CodeDll := GetProcaddress(DLLHANDLE,'CodeDll_1');

if ASSIGNED(APPLICATION) then

CodeDll_1(SELF).Show

else

ShowMessage(IntToStr(GetLastError));





finally



// DLL를 해제한다.

FreeLibrary(DLLHandle);



end;

end;







end.











{*----------------------------------------------*

*program_id : CallCode.Dll

*Dscription : 기초코드

*DLL : callcode.dll 사용

*----------------------------------------------*}







library CallCode;



{ Important note about DLL memory management: ShareMem must be the

first unit in your library's USES clause AND your project's (select

Project-View Source) USES clause if your DLL exports any procedures or

functions that pass strings as parameters or function results. This

applies to all strings passed to and from your DLL--even those that

are nested in records and classes. ShareMem is the interface unit to

the BORLNDMM.DLL shared memory manager, which must be deployed along

with your DLL. To avoid using BORLNDMM.DLL, pass string information

using PChar or ShortString parameters. }



uses

SysUtils,

Classes,

Forms,

Windows,

u_code in 'u_code.pas' {F_Code};



{$R *.RES}

exports // 추가

codedll Name 'codedll',

codedll_1 Name codedll_1';



procedure CallDllProc(Reason : Integer);

begin

if Reason = DLL_Process_Detach then

if Assigned(DllApp) then

Application := DllApp;

end;



begin

DllApp := nil;

DllProc := @CallDllProc;



end.



















{*----------------------------------------------*

*program_id : u_Code

*Dscription : 기초코드 입력 및 조회 및 출력

*DLL : callcode.dll 사용

*관계 DB : Code.DB

*----------------------------------------------*}



unit u_code;



interface



uses

Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

Db, DBTables, StdCtrls, Grids, DBGrids, ExtCtrls, Buttons, ToolWin,

ComCtrls,BDE;



type

TF_Code = class(TForm)

Panel1: TPanel;

Bvl_cdgu: TBevel;

Lbl_cdgu: TLabel;

Lbl_cd: TLabel;

Bvl_cd: TBevel;

Lbl_Etc: TLabel;

Bvl_etc: TBevel;

Lbl_nm: TLabel;

Bvl_nm: TBevel;

Tbar_cd: TToolBar;

Btn_Que: TBitBtn;

Splitter1: TSplitter;

Btn_Save: TBitBtn;

Btn_Cancel: TBitBtn;

Btn_Del: TBitBtn;

Btn_Esc: TBitBtn;

DBGrid1: TDBGrid;

Cbox_cdgu: TComboBox;

Edt_cd: TEdit;

Edt_Etc: TEdit;

Edt_nm: TEdit;

DataSource1: TDataSource;

Tbl_Code: TTable;

private

{ Private declarations }

public

{ Public declarations }

end;





//기초코드 DLL호출

procedure CodeDll(MainApp : TApplication);Export;StdCall;

Function CodeDll_1(Aowner : TComponent):TF_Code;Export;StdCall;



var

F_Code: TF_Code;

DllApp : TApplication; //Dll 호출시 추가

implementation



uses U_menu;

{$R *.DFM}



procedure DLLEntryPoint(Reason: integer);

begin

if Reason = DLL_Process_DETACH then

if Assigned(DllAPP) Then

Application := DllAPP;

end;





procedure CodeDll(MainApp : TApplication);

begin

if not Assigned(DllApp) then

begin

DllApp := Application;

Application := MainApp;

end;

// DBH:=SDB;

end;



Function CodeDll_1(Aowner : Tcomponent):TF_Code;

begin

Result := TF_Code.Create(Aowner);

end;



end.











1  COMMENTS
  • Profile
    이태수 2000.07.31 23:18
    그냥, 일반적인 방법을 사용하여 보시는 것은 어떨런지요.

    저는 child Form을 호출하지는 않고,

    하나의 Exe에서 DLL 서브 프로그램을 호출하는 형식을 취하고 있는데,

    가장 일반적인 방법으로 처리하고 있습니다.







    CodeDll := GetProcaddress( DLLHANDLE, 'CodeDll' );



    if ( NOT ASSIGNED( CodeDll ) ) then

    begin

    end

    else

    try

    CodeDll();

    finally

    end;



    FreeLibrary( DLLHANDLE );



    end;





    ...end of mail......











    김인 wrote:

    > 동적DLL로 Child Form 호출시 에러가 납니다.

    > 도대체 원인을 모르겠군요.

    > 소스와 에러 메세지를 올립니다. 도움좀 주세요.

    > 저는 처음에 SPLASH 화면을 뛰우고 그다음 사용자 ID와 PASSWORD를 받고

    > 맞으면 MENU폼을 뛰웁니다.

    > 여기까지는 이상 없이 되는데 여기서(MENU화면)CODE를 Click하면 아래와 같은

    > ERROR가 나옵니다.

    > 도와주십시요.

    > ---------------------------------------------------------------------------------------

    > Project log_on.exe raised exception calss EExternalException with message ;external

    > exception c000001D'.Process stopped Use Step or Run to continue.

    > ---------------------------------------------------------------------------------------

    >

    > //메인에서 코드 Click시 dll을 호출하는데 자꾸 에러가 발생

    > {*----------------------------------------------*

    > *program_id : u_main

    > *Dscription : Mainmenu

    > *----------------------------------------------*}

    > unit u_menu;

    >

    > interface

    >

    > uses

    > Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

    > Menus, Buttons, ToolWin, ComCtrls,DB,BDE,DBTables,ExtCTRLS;

    >

    > //Dll에서 사용할 내용 정의

    > type

    > //기초코드

    > Tcodedll = Procedure(App : TApplication);StdCall;

    > Tcodedll_1 = Function(AOWNER: TCOMPONENT ):TFORM;StdCall;

    >

    > EDllLoadError = Class(Exception);

    >

    > type

    > TF_main = class(TForm)

    > Menu: TMainMenu;

    > Code: TMenuItem;

    > C_Insert: TMenuItem;

    > E_Insert: TMenuItem;

    > E_h1: TMenuItem;

    > E_List: TMenuItem;

    > E_h2: TMenuItem;

    > E_See: TMenuItem;

    > E_h3: TMenuItem;

    > E_Term: TMenuItem;

    > User: TMenuItem;

    > U_chg: TMenuItem;

    > U_h1: TMenuItem;

    > U_Insert: TMenuItem;

    > Config: TMenuItem;

    > C_Printer: TMenuItem;

    > Exit: TMenuItem;

    > Error: TMenuItem;

    > PrinterSetupDialog1: TPrinterSetupDialog;

    > ToolBar1: TToolBar;

    > Sbtn_code: TSpeedButton;

    > Sbtn_error: TSpeedButton;

    > Sbtn_User: TSpeedButton;

    > procedure FormCreate(Sender: TObject);

    > procedure ExitClick(Sender: TObject);

    > procedure C_PrinterClick(Sender: TObject);

    > procedure FormHide(Sender: TObject);

    > procedure C_InsertClick(Sender: TObject);

    >

    > private

    > { Private declarations }

    >

    > //Dll에서 사용할 내용 추가

    > DllHandle:THandle;

    > //기초코드

    > CodeDll : TCodeDll;

    > CodeDll_1 : TCodeDll_1;

    >

    > public

    > { Public declarations }

    >

    > end;

    >

    > var

    > F_main: TF_main;

    >

    > implementation

    >

    > uses u_log;

    >

    > {$R *.DFM}

    >

    > procedure TF_main.FormCreate(Sender: TObject);

    > var

    > WindowRgn: HRgn; // 윈도우 영역을 얻어 오는 자료형 선언 Hrgn

    > begin

    >

    > WindowRgn := 0; // 현재 윈도우 영역을 지운다.

    > GetWindowRgn(Handle,WindowRgn); //현재 윈도우 영역을 얻어 옴

    > DeleteObject(WindowRgn); // 얻어온 윈도우 영역의 객체를 지움

    > WindowRgn := CreateRectRgn(0,0,Width,78); // 사각형 생성 (Left,Top,Right,Bottom)

    > SetWindowRgn(Handle,WindowRgn,True); // 실제 그려지고 사용될 영역 선언

    > DeleteObject(WindowRgn);

    >

    > end;

    >

    > //작업종료시 Check

    > procedure TF_main.ExitClick(Sender: TObject);

    > begin

    > if MessageDlg('작업을 종료 하시겠습니까?',mtConfirmation,[mbYes, mbNo],0) = mrYes then

    > Close;

    > Form_Log.Close;

    > end;

    >

    >

    > procedure TF_main.C_PrinterClick(Sender: TObject);

    > begin

    > PrinterSetupDialog1.ExeCute;

    > end;

    >

    >

    >

    >

    > procedure TF_main.FormHide(Sender: TObject);

    > begin

    > Close;

    > Form_Log.Close;

    >

    > end;

    >

    >

    > //기초코드 등록을 선택하면

    > procedure TF_main.C_InsertClick(Sender: TObject);

    > begin

    >

    > // 기초코드 동적 호출

    > DllHandle := LoadLibrary('CallCode.Dll');

    >

    > try

    > //에러가발생하면

    > if DllHandle = HINSTANCE_ERROR then

    > raise EDLLLoadError.Create('CallCode.Dll을 Load 할 수 없습니다.');

    >

    > @CodeDll := GetProcaddress(DLLHANDLE,'CodeDll');

    >

    > //메인에서 코드 Click시 dll을 호출하는데 자꾸 에러가 발생되는 위치

    > CodeDll(Application);

    > @CodeDll := GetProcaddress(DLLHANDLE,'CodeDll_1');

    > if ASSIGNED(APPLICATION) then

    > CodeDll_1(SELF).Show

    > else

    > ShowMessage(IntToStr(GetLastError));

    >

    >

    > finally

    >

    > // DLL를 해제한다.

    > FreeLibrary(DLLHandle);

    >

    > end;

    > end;

    >

    >

    >

    > end.

    >

    >

    >

    >

    >

    > {*----------------------------------------------*

    > *program_id : CallCode.Dll

    > *Dscription : 기초코드

    > *DLL : callcode.dll 사용

    > *----------------------------------------------*}

    >

    >

    >

    > library CallCode;

    >

    > { Important note about DLL memory management: ShareMem must be the

    > first unit in your library's USES clause AND your project's (select

    > Project-View Source) USES clause if your DLL exports any procedures or

    > functions that pass strings as parameters or function results. This

    > applies to all strings passed to and from your DLL--even those that

    > are nested in records and classes. ShareMem is the interface unit to

    > the BORLNDMM.DLL shared memory manager, which must be deployed along

    > with your DLL. To avoid using BORLNDMM.DLL, pass string information

    > using PChar or ShortString parameters. }

    >

    > uses

    > SysUtils,

    > Classes,

    > Forms,

    > Windows,

    > u_code in 'u_code.pas' {F_Code};

    >

    > {$R *.RES}

    > exports // 추가

    > codedll Name 'codedll',

    > codedll_1 Name codedll_1';

    >

    > procedure CallDllProc(Reason : Integer);

    > begin

    > if Reason = DLL_Process_Detach then

    > if Assigned(DllApp) then

    > Application := DllApp;

    > end;

    >

    > begin

    > DllApp := nil;

    > DllProc := @CallDllProc;

    >

    > end.

    >

    >

    >

    >

    >

    >

    >

    >

    >

    > {*----------------------------------------------*

    > *program_id : u_Code

    > *Dscription : 기초코드 입력 및 조회 및 출력

    > *DLL : callcode.dll 사용

    > *관계 DB : Code.DB

    > *----------------------------------------------*}

    >

    > unit u_code;

    >

    > interface

    >

    > uses

    > Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,

    > Db, DBTables, StdCtrls, Grids, DBGrids, ExtCtrls, Buttons, ToolWin,

    > ComCtrls,BDE;

    >

    > type

    > TF_Code = class(TForm)

    > Panel1: TPanel;

    > Bvl_cdgu: TBevel;

    > Lbl_cdgu: TLabel;

    > Lbl_cd: TLabel;

    > Bvl_cd: TBevel;

    > Lbl_Etc: TLabel;

    > Bvl_etc: TBevel;

    > Lbl_nm: TLabel;

    > Bvl_nm: TBevel;

    > Tbar_cd: TToolBar;

    > Btn_Que: TBitBtn;

    > Splitter1: TSplitter;

    > Btn_Save: TBitBtn;

    > Btn_Cancel: TBitBtn;

    > Btn_Del: TBitBtn;

    > Btn_Esc: TBitBtn;

    > DBGrid1: TDBGrid;

    > Cbox_cdgu: TComboBox;

    > Edt_cd: TEdit;

    > Edt_Etc: TEdit;

    > Edt_nm: TEdit;

    > DataSource1: TDataSource;

    > Tbl_Code: TTable;

    > private

    > { Private declarations }

    > public

    > { Public declarations }

    > end;

    >

    >

    > //기초코드 DLL호출

    > procedure CodeDll(MainApp : TApplication);Export;StdCall;

    > Function CodeDll_1(Aowner : TComponent):TF_Code;Export;StdCall;

    >

    > var

    > F_Code: TF_Code;

    > DllApp : TApplication; //Dll 호출시 추가

    > implementation

    >

    > uses U_menu;

    > {$R *.DFM}

    >

    > procedure DLLEntryPoint(Reason: integer);

    > begin

    > if Reason = DLL_Process_DETACH then

    > if Assigned(DllAPP) Then

    > Application := DllAPP;

    > end;

    >

    >

    > procedure CodeDll(MainApp : TApplication);

    > begin

    > if not Assigned(DllApp) then

    > begin

    > DllApp := Application;

    > Application := MainApp;

    > end;

    > // DBH:=SDB;

    > end;

    >

    > Function CodeDll_1(Aowner : Tcomponent):TF_Code;

    > begin

    > Result := TF_Code.Create(Aowner);

    > end;

    >

    > end.

    >

    >

    >

    >

    >