4

i am developing a a component in delphi 7 and delphi 2006,component uses a .pas (Not mine )file which requires a DLL file to be present in the application directory.

It is possible to embed the DLL file into the component, so that when the user drops it on the form or create it at run time the DLL will be placed in the application directory?

currently

1) i am telling the user to place DLL file in the application directory.

2) Add the DLL file in the Resources , so that on create, i can drop the DLL into the application directory? from delphidabbler_embed_resource. This i have done using

   {Drop the Resource..!!!}

     procedure DropDllToApplicationDirectOry(applicationPath : string);
     var
           RS: TResourceStream;
     begin
           // Create resource stream
          RS := TResourceStream.CreateFromID(HInstance, 100, RT_RCDATA);
     try
         //  applicationPath : example  c:\MyTestProject Lee\
        if DirectoryExists(applicationPath) then         RS.SaveToFile(applicationPath+'myDllFileWhichIsNeeded.dll')
     finally
     // Free the stream
     RS.Free;
    end;
  end;

this DropDllToApplicationDirectOry take the resource from the {$RmyDllFileWhichIsNeeded.dll.RES} and drope to the location but

how do i call DropDllToApplicationDirectOry this when i drop the component on the Form?

i tried initialization of the component but DLL is not copied so i get the error enter image description here

EDIT For RXControls's TRxClock when we drop the clock runs on this form, the clock begins to run(show the curent time)... so i tried this

 constructor Tmycomponeny.Create(AOwner: TComponent);
   begin
      inherited Create(AOwner);
      {add dll}
      DropDllToApplicationDirectOry(ExtractFilePath(Application.ExeName));
  end;

But this doesnt work..

The code OF RXControls

  constructor TRxClock.Create(AOwner: TComponent);
  begin
    inherited Create(AOwner);
    if not Registered then begin
     ClockInit;
    Registered := True;
  end;
   Caption := TimeToStr(Time);
   ControlStyle := ControlStyle - [csSetCaption] 
   {$IFDEF WIN32} - [csReplicatable] {$ENDIF};
   BevelInner := bvLowered;
   BevelOuter := bvRaised;
   FTimer := TRxTimer.Create(Self);
   FTimer.Interval := 450; { every second }
   FTimer.OnTimer := TimerExpired;
   FDotsColor := clTeal;
   FShowSeconds := True;
   FLeadingZero := True;
   GetTime(FDisplayTime);
   if FDisplayTime.Hour >= 12 then Dec(FDisplayTime.Hour, 12);
   FAlarmWait := True;
  FAlarm := EncodeTime(0, 0, 0, 0);
 end;

enter image description here

PresleyDias
  • 3,657
  • 6
  • 36
  • 62
  • 2
    You don't know the application directory when the user drops the component onto a form, so that's not gonna work. The only option left is to drop the dll at runtime. That also won't work if the dll is statically linked because the OS will throw an exception for the missing library before any user code runs. – Sertac Akyuz May 05 '12 at 09:28
  • @SertacAkyuz : in short in stuck on a wild goose chase other than using @ david simple and effective idea – PresleyDias May 05 '12 at 10:27
  • Yes, there's nothing wrong with what you're doing already. Re: your edit - At design time the 'Application' refers to the TApplication object of the IDE itself, you're trying to drop the library near 'delphi32.exe'. – Sertac Akyuz May 05 '12 at 11:21
  • `Application.ExeName` means `'delphi32.exe'` at design time? oops i dint think of that – PresleyDias May 05 '12 at 11:26
  • @PresleyDias: Is loading the DLL (embedded in resource) from memory an option (no more need to write it back to the disk)? – menjaraz May 07 '12 at 06:20

4 Answers4

6

This idea is not going to work, in general. You are assuming that the developer will always drop your component onto a form. But they could just as well check an existing project out from revision control and then the DLL would not be created.

In my opinion you should simply document the dependency and let the developer ensure that the dependency is met. Suggest that they add the DLL to their revision control system so that it is checked out into the application directory.

The developer is going to need to be aware of this dependency when it comes to deployment. That has to be the developer's responsibility. So it is just cleaner and easier to let the developer manage this full stop.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • +1,i think `simply document the dependency and let the developer ensure that the dependency is met` is quick n simple idea. – PresleyDias May 05 '12 at 10:24
3

Although David is correct that documenting is probably the only reliable approach, your question is an interesting one.

You seem to have written the code to write the dll to a file so the problem is responding to an event that will be fired when the component is created?

If I was to do this I think I would check on component creation that the dll exists and if not create it at this stage if not. Is it possible for you to load the dll dynamically? If you can only use the dll linked statically, then David's way is really the only reliable way.

Toby Allen
  • 10,997
  • 11
  • 73
  • 124
  • +1,`Is it possible for you to load the dll dynamically?`...na not possible....and i took your idea `will be fired when the component is created?` in my new edit but it doesnt work – PresleyDias May 05 '12 at 10:26
  • 1
    If the dll has to be linked statically, by definition, the dll needs to exist before any of the component code is executed. You will only be able to achieve what you want if you have a helper component that is put on the form first that doesnt actually use the dll just ensurees it exists! – Toby Allen May 06 '12 at 08:33
2

What you are asking for is technically doable, but ONLY if the DLL is dynamically loaded at runtime using LoadLibrary(). The "Unable to Locate Component" error is a result of statically linking to the DLL at compile-time instead, which makes it impossible to extract the DLL at runtime (unless the static linked DLL is delay-loaded, which utilizes LoadLibrary() internally).

If, and only if, the DLL is dynamically/delay loaded, then you can extract it from your component's resources at runtime before the DLL is used. When calling TResourceStream.CreateFromID(), do not use the global HInstance variable, use the FindClassHInstance() function instead. The global HInstance variable will not point to the component's module if the component is used in a project with Runtime Packages enabled, but FindClassHInstance() can find the correct module no matter how the component is linked in to the project.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
2

Try putting the dll file in the Contains folder of the Package you're creating, using the Project Manager from Delphi.

enter image description here

NaN
  • 8,596
  • 20
  • 79
  • 153