Bug Report B133886
Visible to All Users

Encounter "Cannot load a RichEdit library" in application using dynamic load packages

created 16 years ago

I have an VCL Win32 application design using dynamic load packages (.bpl). I encounter "Cannot load a RichEdit library" in a sequence of operations:

  1. Load cxExtEditorsD12.bpl statically (e.g.: Add cxExtEditorsD12.bpl in runtime packages)
  2. use LoadPackage to load cxExtEditorsD12.bpl, then unload it
  3. use LoadPackage to load cxExtEditorsD12.bpl again and you will be prompted "Cannot load a RichEdit library".
    After trace into the cxRichEdit.pas source, I found out something in the following method:
    procedure TcxRichInnerEdit.RichCreateParams(var Params: TCreateParams;
      out ARichVersion: Integer);
    var
      ARichClassName: string;
      AWndClass: TWndClass;
      I: Integer;
      ARichClass: TcxRichEditClass;
    begin
      if FRichEditLibrary = 0 then
        for I := High(cxRichEditDLLNames) downto Low(cxRichEditDLLNames) do
        begin
          FRichEditLibrary := LoadLibrary(PChar(cxRichEditDLLNames[I]));
          if FRichEditLibrary <> 0 then
            Break;
        end;
      if FRichEditLibrary = 0 then
        raise EcxEditError.Create(cxGetResourceString(@cxSEditRichEditLibraryError));
      for ARichClass := RichEditClass downto cxMinVersionRichEditClass do
      begin
        ARichClassName := cxRichEditClassNames[ARichClass];
        if GetClassInfo(HInstance, PChar(ARichClassName), AWndClass) then
          Break;
      end;
      if GetClassInfo(HInstance, PChar(ARichClassName), AWndClass) then
        ARichVersion := cxRichEditVersions[ARichClass]
      else
        raise EcxEditError.Create(cxGetResourceString(@cxSEditRichEditLibraryError));
      CreateSubClass(Params, PChar(ARichClassName));
    end;
    When an error is about to occurs in step 5 below, cxRichEditClassNames (a constant array) always contain 2 empty strings that doesn't make sense at all.
    Steps to Reproduce:
  4. Extract zp file in the attachment
  5. Use Delphi 2009 to build and run the application
  6. Click "Load" button (a dynamic created child form will show from package PkgChild.bpl)
  7. Click "Unload" button to close and PkgChild.bpl will be unloaded
  8. Click "Load" button again and you will be prompted "Cannot load a RichEdit library"
    Actual Results:
    Prompt error
    Expected Results:
    No error prompted even pressing many times of "Load" and "Unload"
Show previous comments (4)
DevExpress Support Team 16 years ago

    Hello,
    Thank you for the message.
    We're investigating this workaround, but this may take us some extra time. I will get back to you once we have any results.
    Thanks,
    Valdemar

    DevExpress Support Team 16 years ago

      Hello,
      Our developers have investigated this issue.
      When you are using a runtime package, some units that are included in this package should be used in our program, some may not. When you call the LoadPackage / UnloadPackage methods, only units that are not added are initialized/finalized.
      Your suggestion works correctly. However, we've decided not to implement this in the near future, because you can avoid this problem if you use the following approaches:

      1. you shouldn't use the LoadPackage / UnloadPackage methods. You can use the followings code to get a package handle:
      Delphi
      FPackage := GetModuleHandle('PkgChild.bpl'); @Proc := GetProcAddress(FPackage, 'NewForm'); FForm := Proc;
      1. you shouldn't link your package to the project statically.
        Thanks,
        Valdemar

        Even the Delphi XE2 has released, this problem still happen (QC#71565).
        I found a construct in cxRichEdit.pas:
          procedure InitRichEditDLLNames;
          const
            cxRichEditDLLNamesCount = 3;
          begin
            SetLength(FRichEditDLLNames, cxRichEditDLLNamesCount);
            FRichEditDLLNames[0] := 'Riched32.dll';
            FRichEditDLLNames[1] := 'Riched20.dll';
            FRichEditDLLNames[2] := 'Msftedit.dll';
          end;
        I hope DevExpress team may do the same for
          cxRichEditClassNames: array [TcxRichEditClass] of string =
            ('RICHEDIT',
            {$IFDEF DELPHI12}'RICHEDIT20W'{$ELSE}'RICHEDIT20A'{$ENDIF}{,
            'RICHEDIT30',
            'RICHEDIT41',
            'RICHEDIT50'});
        to avoid the bug happens in dynamic package loading.

        Answers approved by DevExpress Support

        created 14 years ago (modified 13 years ago)

        Hello Chee,
        Our developers have investigated your suggestion. We appreciate your input. However, we have decided not to implement this in the near future. We believe that it is not correct to fix this issue at the level of our components. This issue should be fixed centrally at the IDE level.
        Also, there is a workaround for this problem - do not use the LoadPackage / UnloadPackage methods. Can you use it in your applications?
        Thanks,
        Valdemar

          Show previous comments (4)
          DevExpress Support Team 12 years ago

            Thank you for your comment. I see that QC#71565 still has the "Open" status. So, it is not fixed yet.

              QC#71565 should have fixed if WRITEABLECONST is OFF but the status isn't updated accordingly. Please consider to set WRITEABLECONST to OFF when compile cxRichEdit.pas in the distribution.

              DevExpress Support Team 12 years ago

                Thank you for your idea. However, we widely use writable constants in our sources and tend not to exclude them to overcome the QC#71565 issue. I see that Valdemar suggested avoiding mixing static and dynamic linking in your project. It looks like a good solution to this issue.

                Disclaimer: The information provided on DevExpress.com and affiliated web properties (including the DevExpress Support Center) is provided "as is" without warranty of any kind. Developer Express Inc disclaims all warranties, either express or implied, including the warranties of merchantability and fitness for a particular purpose. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.

                Confidential Information: Developer Express Inc does not wish to receive, will not act to procure, nor will it solicit, confidential or proprietary materials and information from you through the DevExpress Support Center or its web properties. Any and all materials or information divulged during chats, email communications, online discussions, Support Center tickets, or made available to Developer Express Inc in any manner will be deemed NOT to be confidential by Developer Express Inc. Please refer to the DevExpress.com Website Terms of Use for more information in this regard.