Я признаю, что нахожусь в области грязных хитростей в этом вопросе.
ПРОБЛЕМА: exe развернут в общей папке (с этого момента я называю ее ShaExe), без изменения правил развертывания каким-либо образом я хочу кэшироватьфайл локально (я называю это LocExe с этого момента) и при запуске ShaExe я, наконец, в конечном итоге запустить LocExe.LocExe должен обновляться (копироваться из ShaExe) каждый раз при изменении ShaExe (= обновляется).
Каким-то образом то, что я исследую, настраивает что-то вроде этого:
Предварительное условие: путь LocExe - это пользователь \AppData \ Local \ MyApp - зашифрованный путь, поэтому ShaExe знает, где находится LocExe.
ShaExe запускается
ShaExe сравнивает свой размер с размером LocExeесли он отличается, он копирует ShaExe в LocExe
ShaExe выполняет LocExe с параметром командной строки -skiplauncher
ShaExe завершается
при использовании -skiplauncher
точки 2 3 4 из приведенного выше списка не выполняются (это позволяет избежать бесконечного цикла выполнения LocExe и завершения приложения)
Теперь этот подходработает, но узким местом является (1), потому что размер ShaExe составляет 110 МБ, поэтому запуск файла exe из общего пути занимает некоторое время (даже если я не использую флаг {$SetPEFlags IMAGE_FILE_NET_RUN_FROM_SWAP}
).
Я пытался подготовить оченьмаленькая версия ShaExe (в основном построенный без юнитов, но только с логикой запуска в нем, заканчивающийся в 6 МБ exe).
С этим "легким, но бесполезным ShaExe" весь процесс быстрее.
Я бынапример, (2) (3) и (4) выполняются немедленно, возможно ли это в Windows или нет?
Я прекрасно знаю, что лучше всего будет либо вручную скопировать файл локально и запустить его, либосоздать простой запускаемый exe-файл, который выполняет работу по запуску LocExe и делать кеш-память, когда это необходимо, но у меня есть очень крупный клиент, который требует от меня сделать это без изменения процедуры развертывания.
Именно поэтому я и прошу экспертасовет здесь.
Это мой код (конечно, упрощенный, вместо Unit1 представьте 100 единиц):
//this is the dpr
program MYProgram;
uses
Vcl.Forms,
execache in 'execache.pas',
Unit1 in 'Unit1.pas' {Form1};
{$R *.res}
begin
RunCachedExe;
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.
//this is the execache unit
unit execache;
interface
uses
Vcl.Forms,
Windows,
ShellAPi,
sysutils,
dialogs,
system.IOUtils;
procedure RunCachedExe;
implementation
procedure RunCachedExe;
function GetFileSize(const aFilename: String): Int64;
var
info: TWin32FileAttributeData;
begin
result := -1;
if NOT GetFileAttributesEx(PWideChar(aFileName), GetFileExInfoStandard, @info) then
EXIT;
result := Int64(info.nFileSizeLow) or Int64(info.nFileSizeHigh shl 32);
end;
var
CurrentInstanceSize, CachedFileSize, i: integer;
CachedFilePath, Outs: string;
SkipLauncher: Boolean;
begin
SkipLauncher := False;
for i := 0 to paramcount -1 do
begin
if Paramstr(i) = '-SkipLauncher' then
SkipLauncher := True;
end;
if not SkipLauncher then
begin
// in this code path is hardcoded, in real life I use a function that calls:
// SHGetSpecialFolderPath with CSIDL_LOCAL_APPDATA
CachedFilePath := 'C:\Users\myuser\AppData\Local\MyProject\bincache\MyProject.exe';
CurrentInstanceSize := GetFileSize(Application.ExeName);
// this will return -1 if file not found
CachedFileSize := GetFileSize (CachedFilePath);
if CachedFileSize <> CurrentInstanceSize then
begin
ForceDirectories('C:\Users\myuser\AppData\Local\MyProject\bincache\');
CopyFile(PChar(Application.ExeName), PCHar(CachedFilePath), False);
end;
// launch local exe and close this one
ShellExecute (0, 'open', PWideChar( CachedFilePath ), PWideChar('-SkipLauncher'), nil, SW_SHOWNORMAL);
Application.Terminate;
end;
end;
Этот код использует некоторые функции из других модулей, но я мог бы переместить все вмодуль execache, если это может помочь ускорить выполнение exe.
Каким-то образом я хотел бы запустить только часть инициализации, содержащую логику deздесь, а затем завершить работу приложения (когда ShaExe на месте, это в основном означает, что -skipLauncher
не используется).
Итак, возможно ли запустить только логику инициализации большого exe-файла?
Надеюсь, я высказался, спасибо.