Delphi 10 cannot find unit in a package - delphi

I created a design-time package, placed it on disk C:, compiled, installed and added to Library path and Search path.
Now I create new project using a component from this package. Component is added to form, name of unit where the component resides is automatically added to uses, but then Delphi's editor complains that it cannot find the unit where my component is defined and also I am unable to compile.
I never had such a problem in Delphi 6.
What's wrong?

Design time packages cannot be used in your programs.
Usually, you have (or should have) a designtime package, which is only used for installation in the IDE, and a runtime package with the actual component code. The designtime package should have the runtime package in its requires section and register the components in the runtime package.
Your app should only use the runtime package. And that runtime package (or its units or .dcl file) should be in the Library or Search Path.
This separation of designtime and runtime was not enforced in Delphi 6 yet (IIRC), but in more current versions it is, by making some of the units in e.g. the designide package unavailable outside the IDE.
Update
If I remember correctly, the packages to be included in a designtime package for Delphi 6 are not the exact same packages a designtime package for the latest Delphis requires. Ensure that your requires section contains the correct packages for your version.

Ok, now I have untangled this puzzle.
There were multiple superposed Delphi issues:
If Delphi's IDE encounters an unhandled exception when loading DFM it doesn't go further and pretends that it didn't find the faulty unit and units that are listed after it. My problem was that the faulty unit was the last in uses clause, therefore only its name was underlined.
If Delphi's IDE encounters an exception in component's constructor, it makes an automatic "shutdown" for the faulty component by calling Free. Then it tries to use an already freed component and of course encounters Access Violation which affects the number 1.
Sometimes exception messages in component's constructor are suppressed, but IDE still makes a component's emergency "shutdown" which affects the number 2. To find out the exception messages an explicit try-except block is needed.
TChart cannot be created in component's constructor and raises an exception which affects the number 3. When TChart is created it requires a presence of an already created component's window, therefore it should be created in CreateWnd method.

Related

Can I make the `requires` clause in a package conditional?

I'm using Anders Melander's DragDrop package.
It works fine in Win32 mode, but needs adjustment for 64 bit.
I do this by adding {$IFNDEF CPUX64} to comment out the references to the designIDE.
However when I change the package source from
requires
rtl,
DesignIDE;
to
requires
rtl
{$IFNDEF CPUX64} ,DesignIDE{$ENDIF};
The compiler simply throws away the DesignIDE line in the package source, leaving only:
requires
rtl;
Which works fine for X64, but breaks as soon as I rebuilt for 32-bit.
Is there a way to have one package including design-time items for win32 with the conflicting items IFDEF'ed out for X64? Or am I forced to create a separate Runtime package for X64?
No, you cannot use conditionals in any project main file. The IDE owns and controls it, and is subject to discarding (and even destroying) any customization you do with conditionals. You will need to create a second package for this, which is normal practice for using DesignIDE anyway. Even if it weren't for supporting 64bit, you're not permitted to deploy DesignIDE with any application. It is for the sole purpose of integrating with the IDE, which for legal reasons, must only reside in a Design-Time package.
Bear in mind also that the Design-Time package must only be Win32, as the Delphi IDE is only 32bit. Then, the Run-Time package can be any supported platform you wish (i.e. Win64), of course as long as it's supported by any framework it might be using.

Recompile modified VCL unit

I have to compile my project with a changed VCL unit. I use Delphi XE8. I copied Vcl.StdCtrls.pas from D:\Program Files (x86)\Embarcadero\Studio\16.0\source\vcl to my project folder where my .dpr file is localed, then I changed my copy of Vcl.StdCtrls.pas. I also added this unit to project tree. The problem is that with Delphi XE8 such method of recompiling VCL units no longer works. I put an obvious syntax error in my modified Vcl.StdCtrls.pas unit. Compiler does not report the error which means it does no even check the file. I always do a full build Shift+F9. I found a similar question How to recompile a specific unit from the VCL? but like I said, it no longer works, not for Delphi XE8.
Also, the modified unit is on my uses list in .dpr file:
uses
Vcl.StdCtrls in 'D:\Dev\MYPROJECT\Vcl.StdCtrls.pas',
...
// it does not help
This seems to be a bug. I guess you're using runtime packages. In XE7 such project will not compile - which is the correct behavior. In XE8 it compiles, apparently using the VCL runtime package and ignoring your modified unit.
Edit:
Note that even in previous Delphi versions, modifying a VCL unit while using runtime packages would still require you to repackage the modified packages and their dependencies (in this case, vcl and rtl).
In other words, you cannot simply use a modified unit while linking against a runtime package which contains another copy of that unit. Unit names must be unique within the full scope of the project, including the main executable and all linked runtime packages.
So the solution for you is to either:
not use runtime packages, or
repackage all required units into your own runtime packages, and link against them instead of Embarcadero-supplied rtl, vcl etc.

How to build delphi projects for WIN64 when units inside it uses DesignEditors DesignIntf?

I am trying to migrate some code from Delphi 5 to Delphi XE7-WIN64. The scenario is DesignEditors is 32bit only since the IDE is 32 bit application. And the project I am migrating has units which have uses clause containing DesignEditors or DesignIntf or both.
Putting -LUDesignIDE in Build Configurations>Edit>Delphi Compiler>Compiling>Additional options to pass to compiler>-LUDesignIDE
Gives the following as first error on build
[dcc64 Fatal Error] E2202 Required package 'DesignIDE' not found
I am using Delphi XE7 trial version.
It sounds like you have a package which is both design-time and run-time combined into one. In most scenarios however, you must split your package into two different packages. One package is run-time (where you implement all of your actual library), and the other is design-time (which exposes your library to the IDE).
That being said, the design-time packages must work directly with the Delphi IDE. The Delphi IDE is 32bit, so the design-time package must also be 32bit. Whereas, your run-time package will support whatever platforms are needed. Your design-time package is only responsible for registering your components, property editors, etc. to the IDE.
Anything which has anything to do with the IDE (such as registering components, registering property editors, etc.) Must be in your design-time package which is only 32bit. Because of legal copyright issues, all design-time implementation must be in a design-time package, separate from your run-time package.
Start by creating a new design-time only package, same name but prefixed with DCL. Then, change your original package to run-time only. Create a new unit now in your new design-time only package. This unit will be dedicated to registering all IDE design-time interaction. Everything in your run-time package which relies on these design-time units must be converted over to this design-time package. These units which you cannot find are only compatible with the 32bit Delphi IDE.
The new design-time only package will then have to require your run-time package. You'll have to compile the run-time package first before you can compile the design-time package. Any time, you make changes to your library, you need to 1) re-compile the run-time package, 2) re-compile the design-time package, and 3) re-install the design-time package.
The ToolsAPI units can be included in Win32 designtime packages, and nowhere else. You are trying to include them in a Win64 executable project. That is not allowed.
The solution is that you remove all the ToolsAPI units from your project.

How to use the range selector component unit in Delphi [duplicate]

I have a pas unit defining a component.
How can I add it to the palette? the only way I know is to include it in a package, is tehre a direct way to do it?
In a package, have a unit that has a procedure named Register — the capitalization is important. In that procedure, call RegisterComponents on the component you'd like to appear on the Tool Palette.
You must use packages. That's the only way the IDE will load the executable code; it cannot execute DCU files directly. If you don't already have some other package to use, you can add your component to the DclUsr package.
With component libraries of any appreciable complexity, there will usually be at least two packages. There will be a run-time package that contains all the components, and then there will be a design-time package that contains the Register procedures.

List of loaded BPL plugins pretends empty, despite the package been actually loadeed

I have project group in Delphi XE2 which function is to load plugins from packages. I created these projects:
PluginInterface.bpl – package with interfaces to plugins and to MainForm
UClassManager.pas – plugins manager
UPlugin.pas – plugins interface
MultiPlug2.exe – Main Form with configurable menu
MainUnit.pas (*.dfm) – MainForm (MDI Owner)
etc... – some forms (e.g. Splash, Database Login)
TestPlugin.bpl – Test plugin
UTestPlugin.pas – Test Plugin Interface
TestForm.pas (*.dfm) – Test Form (MDI Child).
Here are some listings.
I have problem with
procedure TMainForm.RefreshPluginsList;
var
Pair: TPair<string, TMenuItem>;
I: integer;
begin
for I := 0 to ClassManager.Count - 1 do
RegisterPlugin(ClassManager[i]);
for Pair in MenuDict do
Pair.Value.Visible := Pair.Value.Count > 0;
end;
where ClassManager.Count is always zero, so RegisterPlugin is never called. What should I do to make it 1 and to register my plugin properly?
EDIT: I removed Handles.Add(LoadPackage('PluginInterface.bpl')) as suggested. This didn't help. I see 2 instances of Manager when tracing program.
Looks like you made your EXE without using BPLs - either "Use Runtime Packages" is off, or common shared PluginInterface package is not in "Required" list.
Another possible (but less probable) reason is using weak packaging -
which also mean that UClassManager unit (including extra instances of
ClassManager function and variable) would be copied into every binary.
http://docwiki.embarcadero.com/RADStudio/XE5/en/Using_the_Weak_Packaging_Directive
You can not and should not load that package dynamically - because the link to UClassManager should be made in compile-time already. Hence LoadPackage('PluginInterface.bpl') is redundant at best and breaking at worst and should be removed.
I think you did not do it, so now you have TWO instances of ClassManager - one in EXE and another in DLL. You can check for it issuing commands like
ShowMessage(IntToHex(Integer(Pointer(ClassManager()))))
in EXE and both BPLs and seeing what those instances really were.
Read manual or some Delphi textbook about using Runtime Packages. Few examples:
http://www.obsof.com/delphi_tips/DL613.html
http://pluginmgr.dennislandi.com/
Build with runtime packages on Delphi XE2
How to divide a Delphi project into BPLs properly?
How do I call Delphi functions in a bpl from an executable?
How to program a plugin in Windows/Delphi?
http://delphi.about.com/od/objectpascalide/l/aa012301a.htm
https://groups.google.com/forum/#!topic/borland.public.delphi.vcl.components.writing/E_HyoAiai28
After properly bulding your project you can check whether your EXE actually make use of unit UClassManager from the BPL rather than making its own independent clone of it.
You can look into imported functions table and DLL dependency tree of the EXE, so to see whether EXE really does call UClassManager initialization function from the proper BPL. Some programs allowing doing this:
http://wincmd.ru/plugring/fileinfo.html (and http://www.totalcmd.net/plugring/fileinfo.html)
http://ntcore.com/exsuite.php
http://ru.wikipedia.org/wiki/Dependency_Walker
One more option is to use "Project / Analyze" command from Delphi IDE menu and check "show packages" option to see which binary file contains which unit. You can find this command after installing Project Analyzer package which is part of Jedi CodeLib as http://jcl.sf.net
PS. Since you use XE2, i suggest you to avoid using TList with binary pointers and dangerous unchecked typecasts. You better base your TClassManager upon good old TClassList (already existed in Delphi 5 and maybe even earlier) or upon TList<TPlugin>
PPS. Since you're using XE2 and dynamically loading/unloading BPLs, avoid in your packages constants (or pre-initialized variables) of array [...] of string type. They are being destroyed. I have some ideas why that might happen and how it was fixed in XE3/4 but am somewhat lazy to implement a patch. I just switched to array [....] of PChar constants for that matter.

Resources