代码之家  ›  专栏  ›  技术社区  ›  UnDiUdin

有没有一种方法可以从一个大的exe放在共享驱动器上的单元中只执行代码?

  •  4
  • UnDiUdin  · 技术社区  · 6 年前

    我承认在这个问题上我是在耍花招。

    问题:exe部署在共享文件夹上(从现在起我称之为ShaExe),没有更改部署规则,我想在本地缓存文件(从现在起我称之为LocExe),在启动ShaExe时,我最终运行LocExe。每次修改ShaExe(=更新)都必须更新LocExe(从ShaExe复制)。

    不知何故,我研究的是建立这样的东西:

    1. 启动ShaExe

    2. ShaExe将其大小与LocExe的大小进行比较,如果不同,则将ShaExe复制到LocExe上

    3. ShaExe使用 -skiplauncher

    4. ShaExe自动终止

    什么时候 -滑雪者

    现在这种方法可行,但瓶颈是(1),因为ShaExe的大小是110MB,所以从共享路径启动exe需要时间(即使我不使用这个标志) {$SetPEFlags IMAGE_FILE_NET_RUN_FROM_SWAP} ).

    我希望(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;
    

    这段代码使用了其他单元的一些函数,但是如果这有助于加快exe的执行速度,我可以将所有函数都移动到execache单元中。

    不知何故,我只想运行一个初始化部分,包含这里描述的逻辑,然后终止应用程序(当ShaExe就位时,基本上意味着 -skipLauncher

    那么,有没有可能只运行一个大exe文件的初始化逻辑?

    我希望我表达了我自己,谢谢。

    1 回复  |  直到 6 年前
        1
  •  5
  •   Sertac Akyuz    6 年前

    不管你有什么样的代码,你基本上要问的是,是否可以部分加载一个可执行文件,让它有条件地只执行它包含的代码的一部分。或者流式可执行文件?这些都是不可能的,操作系统将不得不从远程位置获取整个运行时,连同任何静态依赖项,到本地计算机。即使可执行文件要立即退出。

    推荐文章