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.