我用delphi写了一个带dll的窗体,
在主程序中通过动态调用DLL。
在先关闭DLL窗体再关闭主程序没什么问题,不会报错。
如果在打开DLL窗体的情况下,直接关闭主程序就会报错runtime error 216 ...
请问各位高手如何解决???

解决方案 »

  1.   

    關閉之前把DLL釋 放掉 
      

  2.   

    比较大的可能是在DLL中开辟的存储空间,而在退出时是由EXE程序来清理DLL开辟的内存所导致的内存错误!
      

  3.   

    我的dll窗体的函如下:
    procedure Newwgrk(H: THandle; AConn: Widestring; S: string; N: Integer);
    begin
      Application.Handle := H; 
      NewRk:=TNewRk.Create(Application);
      with NewRk do
          try{ 创建窗体 }
          con1.ConnectionString:=aconn;
          stat1.Panels[1].Text:=S;
          if not showing then
          Show; { 模式化显示窗体 }
          except
           con1.connected:=False;
           free;
        end;
    end;主程序中是这样调用的:
    type
        TDll=procedure(H:THandle;AConn:WideString;S:string;N:Integer);register;{ 指定调用协议 }Procedure tmainfrm.shownewwgrk(sender:tobject);
    var
      Dll:TDllwg;
      DllName:THandle;
    begin
      DllName:=LoadLibrary('jxwgrk.dll');// Dll的路径
      try
        if DllName<32 then
        begin
          messagebox(handle,'没有找到附带DLL文件,请确认程序是否完整!','加载DLL失败',MB_OK+MB_ICONEXCLAMATION);
          exit;
        end;
        @Dll:=GetProcAddress(DllName,'Newwgrk');
        if @dll <> nil then
        try
          Dll(Application.Handle,frmlog.Drugconn.ConnectionString,statusbar2.Panels[0].Text,256);
        except
          raise Exception.Create('不存在!');
        end;
      except
        FreeLibrary(DllName);//
      end;
    end;
    各位看看需要如何改进,才能避打开Dll的同时,直接关闭主程序后报错的问题???
      

  4.   


    procedure TfrmMain.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      rslt := spiMain.UnloadAllPlugins(FALSE);//那就在退出主程序前先Unload一下主程序中包含的所有DLL呗
    end;
      

  5.   

    在mainform的关闭事件中,先把所有dll释放掉~~
      

  6.   


    Undeclared identifier: 'unloadallplugins'
    UnloadAllPlugIns(False)如何加,加在哪个地方??
      

  7.   

    晕,Liangpei2008用的可能是人家项目中卸载DLL的自定义函数,你可以自己编写一个'unloadallplugins' 函数来实现把主程序中加载的所有DLL窗体全部Unload啊
      

  8.   

    建议你不要向DLL传递句柄,而是传递主程序指针
      

  9.   

    我以前也写过类似的,出现错误原因基本上,DLL里自己分配的资源没有释放的原因!建议在DLL里检查下!
      

  10.   

    Show; { 模式化显示窗体 } 
    改为ShowModal才是模态显示窗体如果不是模态显示,则关闭主程序前必须释放到DLL中的窗体资源.不然肯定报错.
      

  11.   

    DLL的Project单元, 你必须写成这样
    var
      DllApp : TApplication;
      DLLScr: TScreen;procedure ExitDLL(Reason: Integer);
    begin
      if Reason = DLL_PROCESS_DETACH then
      begin
        Application := DLLApp;
        Screen := DLLScr;
      end;
    end;begin
      DLLApp := Application;
      DLLScr := Screen;
      DLLProc := @ExitDLL; // DLLProc 在SysInit单元中
    end.
    然后把你的DLL函数改成
    procedure Newwgrk(H: TApplication; HS: TScreen; AConn: Widestring; S: string; N: Integer); 
    begin 
      Application := H;
      Screen := HS; 
      ........
    end; 
    最后把你的调用函数改成:
    type 
        TDll=procedure Newwgrk(H: TApplication; HS: TScreen; AConn: Widestring; S: string; N: Integer); 
    var
      DllName:THandle; // 要么单元全局, 要么放在MainForm成员里面 采用ShowModal则不用
    Procedure tmainfrm.shownewwgrk(sender:tobject); 
    var 
      Dll:TDllwg; 
      
    begin 
      if DllName = 0 then
        DllName:=LoadLibrary('jxwgrk.dll');// Dll的路径 
      try 
        if DllName <32 then 
        begin 
          messagebox(handle,'没有找到附带DLL文件,请确认程序是否完整!','加载DLL失败',MB_OK+MB_ICONEXCLAMATION); 
          exit; 
        end; 
        Dll:=GetProcAddress(DllName,'Newwgrk'); 
        if Dll <> nil then 
        try 
          Dll(Application.Handle,frmlog.Drugconn.ConnectionString,statusbar2.Panels[0].Text,256); 
        except 
          raise Exception.Create('不存在!'); 
        end; 
      except 
        // 这句不放这儿   FreeLibrary(DllName);
      end; 
    end; finalization
      FreeLibrary(DllName);  // 改放这儿
      

  12.   

    内存未释放.释放所有全局变量,数据库控件链接和DLL中的窗体
      

  13.   

    今天碰到这个问题,发现Themes.pas的问题。dll关闭的主题句柄已经在exe里关闭了,造成关闭无效句柄。
    procedure TThemeServices.UnloadThemeData;
    var
      Entry: TThemedElement;
    begin
      if not IsLibrary then//添加这句就好,但是这样dll是否使用主题就只能由exe决定了,对于全部窗口
                           //封装在dll的可能要再修改一点,例如为这个类加一个属性来控制开关就好了。
      for Entry := Low(TThemeData) to High(TThemeData) do
        if FThemeData[Entry] <> 0 then
        begin
          try
            CloseThemeData(FThemeData[Entry]);
            FThemeData[Entry] := 0;
          except
          end; 
        end;
    end;