동적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.
저는 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.
>
>
>
>
>