使用Delphi7做的程序,DLL里做了个Form,然后把DLL注入到目标进程内使用。使用SQLConnection连接的mysql服务器,KeepConnection设为True。这样如果mysql的网线掉了或者系统崩了,那么客户端就会假死,很有可能崩溃
所以写了1个检测数据库服务器的在线状态的函数,2个用来切换KeepConnection状态的函数,放在线程内执行,结果客户端经常崩溃
是在添加了这部分后程序经常崩溃,所以问题应该出现在这里吧
客户端也不是马上就崩,有的客户端运行了半个小时就崩溃,有的运行了1天也没事function CheckOnline(destip:string): Integer;
var
  hICMPDll, hICMP  : THandle;
  wsaData          : TWSADATA;
  ICMPCreateFile   : TICMPCreateFile;
  IcmpCloseHandle  : TIcmpCloseHandle;
  IcmpSendEcho     : TIcmpSendEcho;
  IPOpt            : TIPOptionInfo;
  IPAddr           : DWORD;
  pReqData,pRevData: PChar;
  pIPE             : PIcmpEchoReply;
  FSize            : DWORD;
  MyString         : string;
  FTimeOut         : DWORD;
  BufferSize       : DWORD;
  HostEnt          : PHostEnt;
  sIP              : String;
begin
  Result := 0;
  hICMPdll := LoadLibrary('icmp.dll');
 Try
  if hICMPDll <> NULL then
  begin
    WSAStartup($101,wsaData);
    @ICMPCreateFile := GetProcAddress(hICMPdll, 'IcmpCreateFile'); 
    @IcmpCloseHandle := GetProcAddress(hICMPdll, 'IcmpCloseHandle');
    @IcmpSendEcho := GetProcAddress(hICMPdll, 'IcmpSendEcho');
    hICMP := IcmpCreateFile; 
    IPAddr:= inet_addr(PChar(destip));
    if IPAddr = $FFFFFFFF then
    begin
      HostEnt := gethostbyname(PChar(destip));
      if HostEnt <> nil then
        sIP := Format('%d.%d.%d.%d', [Byte(HostEnt^.h_addr^[0]), Byte(HostEnt^.h_addr^[1]),
                  Byte(HostEnt^.h_addr^[2]), Byte(HostEnt^.h_addr^[3])])
      else
        sIP := '';
      IPAddr:= inet_addr(PChar(sIP));
    end;    FSize := 40;
    BufferSize := SizeOf(TICMPEchoReply) + FSize;
    GetMem(pRevData,FSize);
    GetMem(pIPE,BufferSize);
    FillChar(pIPE^, SizeOf(pIPE^), 0);
    pIPE^.Data := pRevData;
    MyString := 'Hi, OnLine?';
    pReqData := PChar(MyString);
    FillChar(IPOpt, Sizeof(IPOpt), 0);
    IPOpt.TTL := 64;
    FTimeOut := 30;
    Result:=IcmpSendEcho(hICMP, IPAddr, pReqData, Length(MyString), @IPOpt, pIPE, BufferSize, FTimeOut);
    ReNum:=Result;          //ReNum是一个全局变量
    //如果有返回,返回值表示收到的回复的个数。如果为0表示没有回复,主机无法到达
    FreeMem(pRevData);
    FreeMem(pIPE);
    IcmpCloseHandle(hicmp);
    FreeLibrary(hICMPdll);
    WSAcleanup();
  end;
 except      //Try
 Result:=0;
 ReNum:=0;
 end;
end;Function SqlOnlineCheck():integer;          //检测与mysql服务器的连接是否正常,是个死循环,伴随程序启动就开始检测
begin
 Try
SafeStat:=True;         //线程处于启用状态
    while True do begin
      if CheckOnline('192.168.0.10')=0 then begin       //与数据库的连接中断
      Inc(SqlNum);   //与服务器连接中断时间+1,连续4次中断则取消与Sql的连接,SqlNum也是全局变量
          if (SqlNum>4)and(Form1.SQLConnection1.KeepConnection=True) then begin
          //与Sql服务器间连接中断
          Form1.SQLConnection1.KeepConnection :=False;
          Form1.SQLConnection1.Connected:=False;   //目标数据库不在,取消连接
          Form1.sqldataset1.Close;
          SqlNum:=0;
          end;
      end else begin
      Sqlnum:=0;
      end;
      MyWait(500);                 //每0.5秒循环一次
    end;
    //EndThread(0);
    SafeStat:=False;    //线程结束
 except
 //EndThread(0);
 SafeStat:=False;    //线程结束
 end;
end;Function SqlOnlineCheckTrue():integer;          //通过SqlOnlineCheck所获得的SqlNum断开连接的时间,确定是断开连接还是重新连接
begin
 Try
    if ReNum=0  then begin     //ReNum=Sql在线检测的返回值
      if (SqlNum>4)and(Form1.SQLConnection1.KeepConnection=True) then begin
      Form1.SQLConnection1.KeepConnection :=False;
      Form1.SQLConnection1.Connected:=False;   //目标数据库不在,取消连接
      Form1.sqldataset1.Close;
      SqlNum:=0;
      end;
    end else begin
      if (Form1.SQLConnection1.Connected=False)or(Form1.SQLConnection1.KeepConnection=False) then begin
      Form1.SQLConnection1.KeepConnection :=True;
      Form1.SQLConnection1.Connected:=True;   //MySql没有连接则连接上
      end;
    end;
  except
  end;
end;//线程启动部分:
if (SafeStat=False) then Safehthread:=BeginThread(nil,0,@SqlOnLineCheck,nil,0,SafeThreadID);  //与sql服务器的连接测试没有启动,则启动,每1秒检查一次
Safe2hthread:=BeginThread(nil,0,@SqlOnLineCheckTrue,nil,0,Safe2ThreadID);  //每次与sql服务器的连接前测试,大约10秒一次

解决方案 »

  1.   

    忘了说了,那个MyWait(500)相当与Sleep(500)
      

  2.   

    在MyWait(500)下加  Application.ProcessMessages;试试
      

  3.   

    MyWait(500)里面已经包含Application.ProcessMessages;了
    之所以用线程来执行也就是为了不让检测过程卡客户端的Form
      

  4.   

    使用Delphi7做的程序,DLL里做了个Form,然后把DLL注入到目标进程内使用
    楼主能不能把这个dll代码和注入代码发一下,我正在学这个?
      

  5.   

    通常情况,是你的那段"ping"程序中有内存尺寸计算错误,实在没功夫细看了,现在才发现,搞了那么久的.net,被矮化了,现在看这些代码竟然有些吃力了。