limelect 48 Posted November 1, 2020 (edited) I have an expert that gets all the classes from the IDE. var xx: TPersistentClass; xx := GetClass(PackageServices.ComponentNames[PackageCounter, ComponentCounter]); some components show xx as nil although they are on the pallet and can be used i cannot read xx.ClassName for that Any idea why? P.S It seems that components from ToolPalette do not have that problem I just checked it on ToolPalette it has the same problem xx := GetClass on some names are nil Edited November 1, 2020 by limelect Share this post Link to post
Mahdi Safsafi 225 Posted November 1, 2020 GetClass requires a class to be priory registered using RegisterClass function otherwise it will fail. Below, a sample that uses some undocumented functions to get all classes: type TDesignPackages = TObject; TDesignPackage = TObject; TIDEDesignPackage = TObject; TRegModule = TObject; TRegClass = TObject; TDesignPackagesGetPackages = function(Obj: TDesignPackages; PackageIndex: Integer): TObject; TIDEDesignPackageGetCount = function(Obj: TIDEDesignPackage): Integer; TRegModuleGetCount = function(Obj: TRegModule): Integer; TIDEDesignPackageGetModules = function(Obj: TIDEDesignPackage; Index: Integer): TRegModule; TRegModuleGetClasses = function(Obj: TRegModule; Index: Integer): TRegClass; var DesignPackagesGetPackages: TDesignPackagesGetPackages; IDEDesignPackageGetCount: TIDEDesignPackageGetCount; IDEDesignPackageGetModules: TIDEDesignPackageGetModules; RegModuleGetCount: TRegModuleGetCount; RegModuleGetClasses: TRegModuleGetClasses; function GetClass2(PackageIndex, ComponentIndex: Integer): TClass; var Coreide: THandle; Delphicoreide: THandle; LGlobalPackagesPtr: Pointer; LDesignPackages: TDesignPackages; LIDEDesignPackage: TIDEDesignPackage; LRegModule: TRegModule; LRegClass: TRegClass; LIDEDesignPackageCount: Integer; LRegModuleCount: Integer; LIndex: Integer; I: Integer; J: Integer; begin Result := nil; { --- Move me outside --- } // adapt 260 suffix according to your Delphi version. Coreide := GetModuleHandle('coreide260.bpl'); Delphicoreide := GetModuleHandle('delphicoreide260.bpl'); LGlobalPackagesPtr := GetProcAddress(Coreide, '@Pakmgr@Packages'); DesignPackagesGetPackages := GetProcAddress(Coreide, '@Pakmgr@TDesignPackages@GetPackages$qqri'); IDEDesignPackageGetCount := GetProcAddress(Delphicoreide, '@Pascpppakmgr@TIDEDesignPackage@GetCount$qqrv'); IDEDesignPackageGetModules := GetProcAddress(Delphicoreide, '@Pascpppakmgr@TIDEDesignPackage@GetModules$qqri'); RegModuleGetCount := GetProcAddress(Coreide, '@Pakmgr@TRegModule@GetCount$qqrv'); RegModuleGetClasses := GetProcAddress(Coreide, '@Pakmgr@TRegModule@GetClasses$qqri'); Assert(Assigned(LGlobalPackagesPtr), 'LGlobalPackagesPtr not assigned'); Assert(Assigned(DesignPackagesGetPackages), 'DesignPackagesGetPackages not assigned'); Assert(Assigned(IDEDesignPackageGetCount), 'IDEDesignPackageGetCount not assigned'); Assert(Assigned(IDEDesignPackageGetModules), 'IDEDesignPackageGetModules not assigned'); Assert(Assigned(RegModuleGetCount), 'RegModuleGetCount not assigned'); Assert(Assigned(RegModuleGetClasses), 'RegModuleGetClasses not assigned'); { --- End Move outside --- } if Assigned(LGlobalPackagesPtr) then begin LDesignPackages := TObject(PPointer(LGlobalPackagesPtr)^); LIDEDesignPackage := DesignPackagesGetPackages(LDesignPackages, PackageIndex); LIDEDesignPackageCount := IDEDesignPackageGetCount(LIDEDesignPackage); LIndex := 0; // Component Index. for I := 0 to LIDEDesignPackageCount - 1 do begin LRegModule := IDEDesignPackageGetModules(LIDEDesignPackage, I); LRegModuleCount := RegModuleGetCount(LRegModule); for J := 0 to LRegModuleCount - 1 do begin if LIndex = ComponentIndex then begin LRegClass := RegModuleGetClasses(LRegModule, J); Result := TClass(PPointer(PByte(LRegClass) + 4)^); exit; end; Inc(LIndex); end; end; end; end; procedure Test(Sender: TObject); var PackageServices: IOTAPAckageServices; I: Integer; J: Integer; LClass: TClass; s: string; begin if Supports(BorlandIDEServices, IOTAPAckageServices, PackageServices) then begin for I := 0 to PackageServices.PackageCount - 1 do begin for J := 0 to PackageServices.GetComponentCount(I) - 1 do begin s := PackageServices.ComponentNames[I, J]; LClass := GetClass2(I, J); if Assigned(LClass) then begin Assert(LClass.ClassName = s); end; end; end; end; end; 1 Share this post Link to post
limelect 48 Posted November 2, 2020 (edited) @Mahdi Safsafi Well, not good news. I have used your suggestion it does not work in my case. Well, let me explain. I am using this guy component. https://github.com/digao-dalpiaz/Dam It worked great and I have no complaint BUT it represents a section of components that reading them from the IDE get nil for classes. They seem to register OK and show on the pallet and are usable. So that is the problem. in your case, I used TPersistentClass(LClass); like that. Maybe this is the problem.? Since I have to use TPersistentClass as I am taking an old program and making it an EXPERT. So the question is if TPersistentClass is the problem as I am using GetClass or your Lclass. Any idea? Maybe I can tackle my problem differently. at the end I use this RegisterClasses(MyArray); where MyArray is TPersistentClass. This is why the above Hold my question something fishy Ok I return to my basic question 1. Reading from component toolbar NO DAM 2. Reading from tool pallet YES DAM in this case still DAM shows nil !!! DAM can be used from both Crazy IDE ???? Edited November 2, 2020 by limelect Share this post Link to post
Mahdi Safsafi 225 Posted November 2, 2020 The code I provided is working perfectly for me ... In fact I'm able to access all components (fmx, vcl, indy, ...). Here is some contracts I made : // all true: Assert(Assigned(LClass)); Assert(LClass.ClassName = s); Assert(LClass.InheritsFrom(TPersistent)); So what exactly is not working ? Share this post Link to post
limelect 48 Posted November 2, 2020 (edited) First I am using D10.2.3. All "Normal components are read" But try to install the above component and am i wrong? Further more try to do if xx<>nil then qqqqq.... else <<<< catch here and see I did catch by InstalledComponentName := PackageServices.ComponentNames[PackageCounter, ComponentCounter]; and lastly I xx := GetClass(InstalledComponentName); where xx: TPersistentClass; The class name is not the problem Edited November 2, 2020 by limelect Share this post Link to post
Mahdi Safsafi 225 Posted November 2, 2020 Quote Further more try to do if xx<>nil then qqqqq.... else <<<< catch here and see Sorry man ! I tried to assist you but definitely I'm not in a position to understand your words. Share this post Link to post
limelect 48 Posted November 2, 2020 (edited) I have made a very simple DEMO reading from the component bar (it does not have to show) In the end, it saves components to a txt file. Very simple. See how many components are NIL !!!!! DockingForm (2).zip And that is my problem The same problem with Tool Pallet although there is a discrepancy between the two Edited November 2, 2020 by limelect Share this post Link to post
Mahdi Safsafi 225 Posted November 2, 2020 @limelect Yes that's the way you should go for when language fails ... thanks ! I tested with my code and it works perfectly ... all components (tst.txt) are assigned (no nil): // procedure TExampleDockableForm.Initilize; // ... for PackageCounter := 0 to PackageServices.PackageCount - 1 do begin for ComponentCounter := 0 to PackageServices.GetComponentCount(PackageCounter) - 1 do begin InstalledComponentName := PackageServices.ComponentNames[PackageCounter, ComponentCounter]; // xx := GetClass(InstalledComponentName); remove this line xx := TPersistentClass(GetClass2(PackageCounter, ComponentCounter)); // <-- use GetClass2 if not(xx = nil) then begin s.Add(xx.ClassName); end else s.Add('nil- ' + InstalledComponentName); end; end; Share this post Link to post
limelect 48 Posted November 2, 2020 (edited) Thank i will try yours again Edited November 2, 2020 by limelect Share this post Link to post
limelect 48 Posted November 2, 2020 (edited) @Mahdi Safsafi Just for general knowledge why there is a difference between the getting of the component from the toolbar and from the package. Since every component is going from a search through the bpl again and again which is time-consuming. I guess I can leave most of the initialization outside of GetClass2 but still a lot of iterations. So again why the difference? in nil In the package the class is different? Edited November 2, 2020 by limelect Share this post Link to post
Mahdi Safsafi 225 Posted November 2, 2020 29 minutes ago, limelect said: @Mahdi Safsafi Just for general knowledge why there is a difference between the getting of the component from the toolbar and from the package. Since every component is going from a search through the bpl again and again which is time-consuming.but still a lot of iterations. So again why the difference? in nil In the package the class is different? Don't worry about that ... all what you need to know is that this line (assumed that initialization of GetClass2 moved outside) xx := TPersistentClass(GetClass2(PackageCounter, ComponentCounter)); runs faster than this : InstalledComponentName := PackageServices.ComponentNames[PackageCounter, ComponentCounter]; xx := GetClass(InstalledComponentName); Quote I guess I can leave most of the initialization outside of GetClass2 Yes that's what you should do. Share this post Link to post
limelect 48 Posted November 2, 2020 I hop i do not bother someone but this buffels me https://github.com/digao-dalpiaz/Dam this is not on the list although it is on the pallet And if this is the case may be some other components too. procedure GetAllClass; // var Coreide: THandle; Delphicoreide: THandle; LGlobalPackagesPtr: Pointer; LDesignPackages: TDesignPackages; LIDEDesignPackage: TIDEDesignPackage; LRegModule: TRegModule; LRegClass: TRegClass; LIDEDesignPackageCount: Integer; LRegModuleCount: Integer; LIndex: Integer; I: Integer; J: Integer; PackageServices: IOTAPackageServices; PackageCounter: Integer; s: TStringList; begin s := TStringList.Create; // Result.Clear; PackageServices := BorlandIDEServices as IOTAPackageServices; Assert(Assigned(PackageServices)); { --- Move me outside --- } // adapt 260 suffix according to your Delphi version. Coreide := GetModuleHandle('coreide250.bpl'); Delphicoreide := GetModuleHandle('delphicoreide250.bpl'); LGlobalPackagesPtr := GetProcAddress(Coreide, '@Pakmgr@Packages'); DesignPackagesGetPackages := GetProcAddress(Coreide, '@Pakmgr@TDesignPackages@GetPackages$qqri'); IDEDesignPackageGetCount := GetProcAddress(Delphicoreide, '@Pascpppakmgr@TIDEDesignPackage@GetCount$qqrv'); IDEDesignPackageGetModules := GetProcAddress(Delphicoreide, '@Pascpppakmgr@TIDEDesignPackage@GetModules$qqri'); RegModuleGetCount := GetProcAddress(Coreide, '@Pakmgr@TRegModule@GetCount$qqrv'); RegModuleGetClasses := GetProcAddress(Coreide, '@Pakmgr@TRegModule@GetClasses$qqri'); Assert(Assigned(LGlobalPackagesPtr), 'LGlobalPackagesPtr not assigned'); Assert(Assigned(DesignPackagesGetPackages), 'DesignPackagesGetPackages not assigned'); Assert(Assigned(IDEDesignPackageGetCount), 'IDEDesignPackageGetCount not assigned'); Assert(Assigned(IDEDesignPackageGetModules), 'IDEDesignPackageGetModules not assigned'); Assert(Assigned(RegModuleGetCount), 'RegModuleGetCount not assigned'); Assert(Assigned(RegModuleGetClasses), 'RegModuleGetClasses not assigned'); { --- End Move outside --- } if Assigned(LGlobalPackagesPtr) then begin for PackageCounter := 0 to PackageServices.PackageCount - 1 do begin if PackageServices.GetComponentCount(PackageCounter) > 0 then begin LDesignPackages := TObject(PPointer(LGlobalPackagesPtr)^); LIDEDesignPackage := DesignPackagesGetPackages(LDesignPackages, PackageCounter); LIDEDesignPackageCount := IDEDesignPackageGetCount(LIDEDesignPackage); LIndex := 0; // Compeginonent Index. for I := 0 to LIDEDesignPackageCount - 1 do begin LRegModule := IDEDesignPackageGetModules(LIDEDesignPackage, I); LRegModuleCount := RegModuleGetCount(LRegModule); for J := 0 to LRegModuleCount - 1 do begin // if LIndex = ComponentIndex then begin LRegClass := RegModuleGetClasses(LRegModule, J); s.Add(TClass(PPointer(PByte(LRegClass) + 4)^).ClassName); // exit; end; Inc(LIndex); end; end; end; end; end; s.SaveToFile('c:\tst.txt'); s.Free; end; can some one install and help ? just add above to my test package and in Initilize just call GetAllClass; Share this post Link to post
limelect 48 Posted November 2, 2020 Sorry for the bother but it mite be me Thanks for any help Share this post Link to post
limelect 48 Posted November 3, 2020 OK to sum it . I do not understand the IDE. I recompiled and reinstaled the component and now it shows on the list. Even it was on the pallet it did not show. Not my fault. As for my first problem the @Mahdi Safsafi solution helped a lot. Thanks Share this post Link to post
limelect 48 Posted November 3, 2020 Oh no not again . Restart Delphi stop showing in the list the component. I will manege. Share this post Link to post
limelect 48 Posted November 3, 2020 (edited) @Mahdi Safsafi and others Well, I just installed a new component on my D10.2.3, and after closing the Delphi program and reopening it does not show on my list !!. Although it is on the pallet. So it is the Delphi program. !!!! So now for the questions 1. is there another way to get the component list? beside PackageServices := BorlandIDEServices as IOTAPackageServices; and for PackageCounter := 0 to PackageServices.PackageCount - 1 do 2. is there a max quantity for components? I have many. P.S @Mahdi Safsafi I just installed your ZControl and it too disappeared Edited November 3, 2020 by limelect Share this post Link to post
Guest Posted November 3, 2020 @limelect It took me while to understand what is going on based on your description, and had to try it is. I tried your example and it work just perfect, the problem is you are populating the package using Initialize, means this package will see only the initialized packages before it, an when you install new package then most likely (if not always) will be initialized and registered after this package, so the populating will not see them, just recompile/install your demo and it will start to see them, but that is not a solution, just a confirmation of expected behavior. You have to find a work around for that like use TPackageNotifier or something, also might be interesting to test if it is possible to uninstall self and reinstall, this might be ugly, dangerous and definitely not recommend as easily can lead to endless loop then crash the IDE, but interesting non the less. Share this post Link to post
limelect 48 Posted November 3, 2020 I have created a text file of the components and there packeges. Where there is no component in the package see ---------zcontrols_d.bpl and more. if PackageServices.GetComponentCount(PackageCounter) = 0 then s.Add('---------'+PackageServices.PackageNames[PackageCounter]); But one can see in the component tab the components and also on the pallet So i am trying to investigate but i am almost at the end. tst.txt Share this post Link to post
limelect 48 Posted November 3, 2020 (edited) @Kas Ob. I am too professional to leave this point. After installing and seeing the component I close the Delphi program and reopen. This is when the package is empty. P.S I have a new demo with a button to initialize. The problem is that restart Delphi the packages are empty. !!! If you want I can put here the source it is 2 more lines. See my last comment Edited November 3, 2020 by limelect Share this post Link to post
limelect 48 Posted November 3, 2020 Here it is my last demo to see how many packages are empty DockingForm (2).zip Share this post Link to post
Guest Posted November 3, 2020 7 minutes ago, limelect said: Here it is my last demo to see how many packages are empty Are referring to a package with no class's reported ? is this what did you mean with empty packages ? Share this post Link to post
limelect 48 Posted November 3, 2020 (edited) Use my last demo because the old one are not perfect You will get a list of similar txt This is an empty package ---------xxxxxx.bpl Edited November 3, 2020 by limelect Share this post Link to post
Guest Posted November 3, 2020 2 minutes ago, limelect said: You will get a list of similar txt I did, but still confused as you did not answer if you referring to these packages with no components. Take an example you package itself "DockingFormPackage.bpl", what should it show ? ( away from its name ) Share this post Link to post