打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
C#调用DELPHI webservice 的DLL 在退出程序是出现异常处理 runtime error 216

C#调用DELPHI webservice 的DLL 在退出程序是出现异常处理 runtime error 216 


1.修改注册表:

开始菜单-运行-输入regedit-点确定-进入注册表, 在:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\ShellExecuteHooks 下,应该只有一个正常的键值"{AEB6717E-7E19-11d0-97EE-00C04FD91972}, 将其他的删除。
2.Delphi中利用SEH屏蔽退出时的Runtime ErrorDelphi

写的程序,如果在单元的finalization里出现了一些异常操作会导致退出时抛出Runtime Error ,规范的处理办法当然是解决这些异常,但是有些特殊的情况下,比如用了很多的第三方控件,实在没办法解决问题时,只有把他屏蔽掉,这样给客户的时候就不至于看到满天的Runtime Error 了。前些日子同事正好碰到了这个问题,他写的一个ACTIVEX控件,在客户的IE里关闭的时候就会抛出很多错误导致IE死掉,但是在本机又模拟不出来,问题不能解决,又得应付客户。找我讨论解决方案,我提议可以用SEH解决,于是写了一段代码,效果不错,不敢独享,贴出来希望能够帮大家应付遇到的问题。我的做法其实很简单,就是在 END.之前手工调用Halt释放,并且将Halt抛出的错误屏蔽掉,这样做和正常的DELPHI释放过程没有任何区别,因为End.编译后其实就是一句话 Call Halt0,只是VCL自己没有屏蔽Halt0里抛出的错误,而是跳出个Runtime Error 来;首先就是位置的问题,如果是EXE的话,直接在END.之前就行了,如果是Dll的话就麻烦点,需要挂上DllProc,当wReason = DLL_PROCESS_DETACH时处理。然后就是如何屏蔽错误的问题了,第一个最容易想到的做法就是直接Tryhaltexceptend;

新窗口查看复制到剪贴板打印?
Try 
  halt 
except 
end; 

Try  haltexceptend;但是这样是不行的,因为try…except end捕获的错误都会放到System单元的_HandleOnException中处理,函数检查错误类型是否是DelphiException,如果不是就不处理,这个时候就会被DELPHI的顶层异常机制捕获,并抛出Runtime error,halt里抛出来的错误恰恰就是非DelphiException,代码如下:

新窗口查看复制到剪贴板打印?
procedure _HandleOnException; 
… 
CMP [EAX].TExceptionRecord.ExceptionCode,cDelphiException 
JE @@DelphiException 
CLD 
CALL _FpuInit 
MOV EDX,ExceptClsProc 
TEST EDX,EDX 
JE @@exit 
CALL EDX 
TEST EAX,EAX 
JNE @@common 
JMP @@exit 
… 
End; 

procedure _HandleOnException;…CMP [EAX].TExceptionRecord.ExceptionCode,cDelphiExceptionJE @@DelphiExceptionCLDCALL _FpuInitMOV EDX,ExceptClsProcTEST EDX,EDXJE @@exitCALL EDXTEST EAX,EAXJNE @@commonJMP @@exit…End;所以,需要借助SHE机制来处理这个问题(哈哈,不然就得改标题了),代码如下(关于如何挂SHE我就不介绍了,我在另外一篇文章《Delphi异常机制与SEH》详细介绍了):
新窗口查看复制到剪贴板打印?
asm 
//挂上SEH 
xor edx, edx 
push ebp 
push OFFSET @@safecode 
push dword ptr fs:[edx] 
mov fs:[edx],esp 
//调用Halt0 
call Halt0 
jmp @@exit; 
@@safecode: 
//如果出现异常继续调用Halt0退出 
call Halt0; 
@@exit: 
end; 

asm//挂上SEHxor edx, edxpush ebppush OFFSET @@safecodepush dword ptr fs:[edx]mov fs:[edx],esp//调用Halt0call Halt0jmp @@exit;@@safecode://如果出现异常继续调用Halt0退出call Halt0;@@exit:end;这个做法的好处就是,不会对DELPHI正常释放过程产生影响,所有的释放操作都是和VCL一致的,只是不会把错误显示出来。

以下是完整代码:

一、EXE的情况,把代码放在工程文件

二、DLL的情况,把代码放在工程文件里

明生注:Exe的 在工程文件PER里面写入此过程

新窗口查看复制到剪贴板打印?
procedure Halt0; 
begin 
  Halt; 
end; 

procedure Halt0;begin  Halt;end;

然后在BEGIN和END.之间写上此汇编

 

新窗口查看复制到剪贴板打印?
asm 
    xor edx, edx 
    push ebp 
    push OFFSET @@safecode 
    push dword ptr fs:[edx] 
    mov fs:[edx],esp 
 
    call Halt0 
    jmp @@exit; 
 
    @@safecode: 
    call Halt0; 
 
    @@exit: 
  end; 

asm    xor edx, edx    push ebp    push OFFSET @@safecode    push dword ptr fs:[edx]    mov fs:[edx],esp    call Halt0    jmp @@exit;    @@safecode:    call Halt0;    @@exit:  end;DLL处写入:

新窗口查看复制到剪贴板打印?
procedure Halt0; 
begin 
   Halt; 
end; 
 
var 
  OldProc: Pointer; 
procedure DLLEntryPoint(dwReason: DWord); 
begin 
  if (dwReason = DLL_PROCESS_DETACH) Then 
  Begin 
    asm 
      xor edx, edx 
      push ebp 
      push OFFSET @@safecode 
      push dword ptr fs:[edx] 
      mov fs:[edx],esp 
      call Halt0 
      jmp @@exit; 
      @@safecode: 
      call Halt0; 
      @@exit: 
    end; 
  end; 
end; 
 
begin 
  DllProc := @DLLEntryPoint; 
  DllProcEX := @DLLEntryPoint; 
end. 


例子

library HouseAgent;

{ 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,
  Forms,
  Windows,
  Messages,
  Classes,
    Dialogs,
  cell in 'cell.pas' {cellfrm},
  ManageUser in 'ManageUser.pas' {ManageUserfrm};

{$R *.res}
procedure  showBook(hdc:Thandle);    stdcall ;    {接口函数}
var frm :Tcellfrm;
begin
  frm := Tcellfrm.Create(Application);
  frm.ParentWindow  := hdc;
  frm.Show;
end;

procedure showManagerUser(hdc:Thandle;UserId:integer;Soap_Mode:integer);    stdcall ;     {接口函数  UserId:登录店ID Soap_Mode是否SOAP模式}
 var frm :TManageUserfrm;
 begin
frm := TManageUserfrm.Create(Application);
frm.ParentWindow := hdc;
frm.UserId:=UserId;
frm.Soap_Mode:=Soap_Mode;
frm.Show;
end;

//异常处理
procedure Halt0; 
begin
   Halt;
end;

procedure DLLEntryPoint(dwReason: DWord);
begin
  if (dwReason = DLL_PROCESS_DETACH) Then
  Begin
    asm
      xor edx, edx
      push ebp
      push OFFSET @@safecode
      push dword ptr fs:[edx]
      mov fs:[edx],esp
      call Halt0
      jmp @@exit;
      @@safecode:
      call Halt0;
      @@exit:
    end;
  end;
end;

本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
android退出
Delphi
Delphi捕捉DLL执行所抛出的异常。
Delphi调用C#类库 - chenghm2003 - 博客园
DELPHI的BPL使用(收藏)
无痛使用Delphi Package
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服