AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Packages in anderem Verzeichnis

Ein Thema von hschmid67 · begonnen am 22. Sep 2024 · letzter Beitrag vom 24. Sep 2024
Antwort Antwort
Seite 1 von 2  1 2      
hschmid67

Registriert seit: 2. Jul 2012
Ort: Weilheim i. Obb.
71 Beiträge
 
Delphi 12 Athens
 
#1

Packages in anderem Verzeichnis

  Alt 22. Sep 2024, 07:08
Hallo zusammen,

ich habe eine „einfache“ Frage und komme nicht so recht weiter mit all dem, was ich bisher dazu gefunden habe:

Mein Programm verwendet Packages, eingebunden über die Programmoptionen. Gibt es eine Möglichkeit, beim Programmstart Code auszuführen - vermutlich in der dpr-Datei - bevor versucht wird, diese Packages (bpl) zu laden? Wo muss der Code dann hin?

Hintergrund meiner Frage:
Ich möchte mein Programmverzeichnis gerne „sauber“ halten, also nicht viele libraries/packages dort unterbringen. dort sollten sich nur die paar Dateien befinden, die ausschließlich zum Progamm gehören (also .exe, .ini, .db zum Beispiel). Dazu möchte ich gerne die bpl-Dateien in ein Unterverzeichnis packen und vor deren Laden den Windows-Pfad entsprechend anpassen - und beim Entladen wieder zuück. Habe dazu eine interessante dll gefunden https://github.com/Bill-Stewart/PathMgr.

Wo packe ich also den Code zum Anpassen der Path-Variablen hin?

Delphi-Quellcode:
 begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TformMain, formMain);
  Application.Run;
end.
hier irgendwo?

Oder in das initialization einer eigenen unit, die ich dann als erstes einbinde?

Leider weiß ich zu wenig, wie ein Programmstart intern abläuft, um das richtig zu verstehen.

Für jeden Hinweis dankbar
Harald
Harald Schmid
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
347 Beiträge
 
#2

AW: Packages in anderem Verzeichnis

  Alt 22. Sep 2024, 10:26
Hi, very interesting problem !

I spent almost two hours testing different approaches and ...

Delphi-Quellcode:
 begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.CreateForm(TformMain, formMain);
  Application.Run;
end.
hier irgendwo?
Alas, this is not possible !
One approach i tested is to add a DLL that will change set the PATH variable with SetEnvironmentVariable, the DLL worked fine right after loading by the OS, but ... it seems the OS loads few DLLs in bulk then after that start to call them, if it hit missed one it will stop and unload the loaded ones, so that DLL was loaded but no called, i mean DllMain not called.
Also patched the binary to make sure it is the first to be in the Import Table, and yes the OS tried and loaded it first but didn't call DllMain, even it loaded few more DLL, non being executed, so this was not a solution.

Zitat:
Oder in das initialization einer eigenen unit, die ich dann als erstes einbinde?
Same as above, this will not help at all, as Runtime packages imported by the Import Table as declared in the PE header, meaning, nothing will execute from the EXE Project, before all the imported libraries loaded (attached) and then all the thunk table resolved.

There is few ways to do this, but all are ugly !!
1) Use batch file to execute your EXE, with :
Zitat:
set PATH=YOUR_PACKAGE_PATH;%PATH%
//like
set PATH=D:\Program Files (x86)\Embarcadero\Studio\16.0\bin;%PATH%
2) Add another small, minimum (bare exe) to load your application but before calling CreateProcess do the same with PATH variable in the environment, in this case use SetEnvironmentVariable
https://learn.microsoft.com/en-us/wi...onmentvariable
Also here i am not sure if the the same PATH value will work, i mean passing this "YOUR_PACKAGE_PATH;%PATH%" to SetEnvironmentVariable, so to be on the safe side i would read PATH value first with GetEnvironmentVariable, then append the path then call SetEnvironmentVariable, this before CreateProcess (or any other executing calls that works)
3) Move your EXE to the same package directory, and leave a shortcut !!

Hope that helps, or may be someone else might have ideas to entertain.
Kas
  Mit Zitat antworten Zitat
Benutzerbild von dummzeuch
dummzeuch

Registriert seit: 11. Aug 2012
Ort: Essen
1.604 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#3

AW: Packages in anderem Verzeichnis

  Alt 22. Sep 2024, 11:14
Eine weitere Möglichkeit wäre kleines Vorschalt-Programm, das das eigentliche Programm aufruft. Dieses eigentliche Programm liegt dann im gleichen Ordner wie die BPLs. Also quasi dasselbe wie eine Verknüpfung, wie Kas Ob es vorgeschlagen hat, aber flexibler.

Wir benutzen sowas intern, um aus Unterordnern jeweils die neueste Version eines Programms aufzurufen:

Code:
Pfad\zum\Programm\
                  Version_1.0.0\
                  Version_1.0.1\
                  Version_1.2.0\
                  Version_1.3.5\
                  Vorschaltprogramm.exe
Hintergrund: So kann man eine neue Programmversion releasen, wenn die alte noch irgendwo in Benutzung ist und deshalb nicht ersetzt werden kann.
Thomas Mueller

Geändert von dummzeuch (22. Sep 2024 um 11:18 Uhr)
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
347 Beiträge
 
#4

AW: Packages in anderem Verzeichnis

  Alt 22. Sep 2024, 11:17
Still lingering in my head and i think i found more elegant solution

This involve utilizing Windows Application Registration
https://learn.microsoft.com/en-us/wi...p-registration

In short the steps are:
1) add a key in the registry with your EXE name to this path
Zitat:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Curr entVersion\App Paths\DelphiRuntimeTest.exe
then make sure the default (entry without name) in that key has the Application name and path like this
Code:
(default) REG_SZ D:\Projects Delphi\DelphiRuntime\Win32\Debug\DelphiRuntimeTest.exe
and at last add the PATH value
Code:
PATH REG_SZ D:\Projects Delphi\DelphiRuntime\Win32\Debug;D:\Program Files (x86)\Embarcadero\Studio\16.0\bin
and that is it !!


I tested it and it worked perfectly, thoughts on this:
1) For some reason, yet i don't understand it works fine with HKEY_LOCAL_MACHINE but didn't work with HKEY_CURRENT_USER on my OS, yet again my OS is %$#%$ the least, i heavily tweaked many things about paths and users, specially my user, so it might work for you with HKEY_CURRENT_USER.
2) Here how the registry entries look like
registry.png
3) Not sure about adding the current directory in my case above "D:\Projects Delphi\DelphiRuntime\Win32\Debug", most likely it is not needed.

Hope that helps.
Kas
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
347 Beiträge
 
#5

AW: Packages in anderem Verzeichnis

  Alt 22. Sep 2024, 11:34
OK, with the registry trick above, it works only with ShellExecute, with the debugger executing the application with CreateProcess will not work.
If you run the exe using Windows Explorer then it is fine and the DLL will be found and loaded, but other executing method might not work !
Kas
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.063 Beiträge
 
Delphi 12 Athens
 
#6

AW: Packages in anderem Verzeichnis

  Alt 22. Sep 2024, 13:02
Delphi-Referenz durchsuchenLoadPackage, aber das geht natürlich nicht bei statisch eingebundenen Packagages. (genauso, wie LoadLibrary bei DLLs)


Side-by-Side Manifest (SxS) : <PackageDependency> in <Dependencies>
bekannte Libraries : HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs
oder, was eben über die Standard-Suchpfade zu finden ist, welches diese Unterverzeichnisse nunmal nicht beinhaltet.

und
MSDN-Library durchsuchenSetDllDirectory
MSDN-Library durchsuchenLoadLibraryEx + LOAD_WITH_ALTERED_SEARCH_PATH
gehen halt erst zur Laufzeit und demnach nur beim dynamischen Laden
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
hschmid67

Registriert seit: 2. Jul 2012
Ort: Weilheim i. Obb.
71 Beiträge
 
Delphi 12 Athens
 
#7

AW: Packages in anderem Verzeichnis

  Alt 22. Sep 2024, 20:49
erst einmal Euch allen ein dickes Danke! Es ist wirklich großartig, hier solche engagierte und kompetente Hilfe zu erhalten

Nun, die Überlegungen von Kas Ob. sind sehr interessant und haben mir ein wenig Einblick in die Funktionsweise einer exe und Windows gegeben. Ich fürchte, dass ich das aber nicht tun kann, weil ich die Zielsysteme nicht so weit manipulieren möchte. Mein Programm soll eigentlich kaum einen Hinweis auf sich im System, in der Registry hinterlassen - und da ist das Ändern der Path-Variablen schon mehr als eigentlich gewollt. Danke dennoch für die interessanten Ideen, die ich sicherlich für mich weiterverfolgen werde.

Spannend finde ich den Vorschlag von Herrn Müller (dummzeuch), der auch noch andere Vorteile hätte, wie er schreibt. Das werde ich mir genauer ansehen. Einziger Wermutstropfen ist, dass meine Programmstruktur noch komplizierter wird. Aber da das mit den bpl-Dateien und manchen eigenen dll-Dateien eh schon nicht einfach ist, macht das wohl auch nicht mehr viel aus.

Rein verständnishalber würde mich noch die Idee mit dem
Code:
LoadPackage
interessieren. Wenn ich über die Programmoptionen ein Package einbinde, dann ist das wohl statisch. Das Programm wird mit diesem Package kompiliert und alles aus dem Package ist dann statisch eingebunden. Die Exe-Datei wird kleiner und ich muss nichts irgendwo extra deklarieren. Wenn ich ein Package mit LoadPackage einbinde, wie funktioniert das dann mit dem Verwenden der Routinen und Classen des Packages? Muss ich dann ähnlich wie bei LoadLibrary erstmal alle Routinen und Klassen extra deklarieren, oder kann ich die Unit aus dem Package einfach so wie beim statischen Einbinden nutzen. Damit hab ich mich bisher überhaupt nicht beschäftigt und verstehe das mit den Packages gar nicht.

Also nochmal vielen Dank Euch allen und viele Grüße
Harald
Harald Schmid
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.582 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: Packages in anderem Verzeichnis

  Alt 23. Sep 2024, 08:37
Wenn ich über die Programmoptionen ein Package einbinde, dann ist das wohl statisch. Das Programm wird mit diesem Package kompiliert und alles aus dem Package ist dann statisch eingebunden. Die Exe-Datei wird kleiner und ich muss nichts irgendwo extra deklarieren. Wenn ich ein Package mit LoadPackage einbinde
Dann funktioniert das nicht. Denn der Compiler benötigt zum Kompilieren die Information, woher die Typen kommen usw., was nur mit Laufzeitpackages extern funktioniert. Später geladene Packages kann der Compiler nicht berücksichtigen. Denn nur bei Laufzeitpackages ist sichergestellt, dass diese bei Verwendung eines Typs auch geladen sind.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Benutzerbild von dummzeuch
dummzeuch

Registriert seit: 11. Aug 2012
Ort: Essen
1.604 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#9

AW: Packages in anderem Verzeichnis

  Alt 23. Sep 2024, 08:44
Mit LoadPackage kann man zur Laufzeit weitere Packages einbinden, die für die Funktion optional sind. So, wie die IDE das für Package-basierte Plugins und auch mit den Designtime-Packages der Komponenten macht.

Ich habe mal eine Zeit lang damit geliebäugelt, das für unsere internen Programme zur Modularisierung zu verwenden, aber da die Voraussetzung ist, dass man die Delphi RTL und VCL ebenfalls als Packages einbinden muss, habe ich wieder davon abgesehen. Da Du aber sowieso mit Runtime-Packages arbeitest, wäre das eine Option.
Thomas Mueller
  Mit Zitat antworten Zitat
Kas Ob.

Registriert seit: 3. Sep 2023
347 Beiträge
 
#10

AW: Packages in anderem Verzeichnis

  Alt 23. Sep 2024, 11:05
LoadPackage will not be much of a help here, as itself (LoadPackage) does exist within RTLxxx.BPL, so even if you managed to change you application and remove all the designtime packages from the IDE designer for all the auto-created forms/frames/modules you still will have trouble to handle RTLxxx.BPL and most likely VCLxxx.BPL with fewer others.

There is other solution i didn't mention before, but because you are interested i will explain it, but before that i will include this small loader, that works perfectly everywhere (i hope) with any adjustment to OS settings, namely the path in environment:
Delphi-Quellcode:
program Loader;
// This application is VCL application and not console/cmd, we don't need the console window to pop every time and scare everyone!!
uses
  Windows;

{$R *.res}

const
  APPLICATION_EXE_NAME = 'DelphiRuntimeTest.exe';
  APPLICATION_EXTRA_COMMANDLINE = '';
  APPLICATION_PATH_TO_ADD ='D:\Program Files (x86)\Embarcadero\Studio\16.0\bin';

procedure SetPathAndRun;
var
  si: TStartupInfo;
  pi: TProcessInformation;
  Path:string;
  PathLen:Integer; // length in characters
begin
  // adjust the path
  PathLen := GetEnvironmentVariable('PATH',nil,0);
  SetLength(Path,PathLen);
  GetEnvironmentVariable('PATH',@Path[1],PathLen);
  Path := APPLICATION_PATH_TO_ADD +';'+Path; // we add out path first to skip handling the null terminator
  SetEnvironmentVariable(PChar('PATH'), PChar(Path));
  //SetEnvironmentVariable(PChar('PATH'), PChar(APPLICATION_PATH_TO_ADD+';%PATH%')); // this might be enough though, instead of all above

  // run and don't wait
  ZeroMemory(@si,SizeOf(si)); //si := Default(TStartupInfo); // ZeroMem for old Delphi versions
  si.cb := sizeof(si);
  CreateProcess(PChar(APPLICATION_EXE_NAME), // EXE Name with or without path
    PChar(GetCommandLine + APPLICATION_EXTRA_COMMANDLINE), // this will pass the same command line to the exe with the extra
    nil, nil, False, 0, nil, nil, si, pi);
end;

begin
  SetPathAndRun; // will run the exe and exit without waiting
end.
The other solution is to look and understand how packers works, namely UPX for the easy understanding.
UPX is executable packer, that strip and compress sections ... bla bla, we care about one thing here, how it does handle the import table, UPX strip/remove the functions leaving only one from each statically loaded/imported DLL, then when it is unpacking the exe it does resolve the rest, from its own stored and compressed table.
The reason to strip them all, because that table is not optimized on byte level, and might be big, but that is irrelevant as UPX tries to squeeze space every where it can, the question is why it does leave one ?
The answer is: for two reasons first security, it doesn't want to irritate AV(security analyzing software) more than needed, and secondly to keep the OS behavior consistent when loading and handling DLL, so it doesn't go to full length and loaded the libraries on its own and resolve the import addresses, this for compatibility and also will keep the unpacker code as small as it could be.

What can be done here is:
UPX is on GitHub with license GPL-2, but it does some changes, we need to remove the one imported function and replace them with your slightly adjusted table.
This solution should work, but the work and changes could be not-so-practical.

Anyway, wrote this as food for thought.
Kas
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:14 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz