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

Delphi 有没有一种方法可以只从共享驱动器上的大型exe执行单元中的代码?,delphi,exe,delphi-10-seattle,Delphi,Exe,Delphi 10 Seattle,我承认在这个问题上我是在耍花招 问题:exe部署在共享文件夹上(从现在起我称之为ShaExe),在不更改部署规则的情况下,我希望本地缓存文件(从现在起我称之为LocExe),在启动ShaExe时,我最终运行LocExe。每次修改SHAXE(=更新)时,必须更新LocExe(从SHAXE复制) 不知何故,我正在研究的是建立这样的东西: 前提条件:LocExe路径是用户\AppData\Local\MyApp的加密路径,因此SHAXE知道LocExe在哪里 ShaExe已启动 SHAXE将其大小与L

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

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

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

前提条件:LocExe路径是用户\AppData\Local\MyApp的加密路径,因此SHAXE知道LocExe在哪里

  • ShaExe已启动

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

  • SHAXE使用
    -skiplauncher
    命令行参数执行LocExe

  • ShaExe会自动终止

  • 使用
    -skiplauncher
    时,不会执行上述列表中的点2 3 4(这是为了避免执行LocExe和终止应用程序的无休止循环)

    现在这种方法可行了,但瓶颈是(1),因为ShaExe大小是110MB,所以从共享路径启动exe需要时间(即使我不使用标志
    {$SetPEFlags IMAGE\u FILE\u NET\u RUN\u from\u SWAP}

    我试着准备一个非常小版本的ShaExe(基本上没有单元,但只有启动程序逻辑在里面,最后才有6MB的exe)

    有了这个“轻而无用的ShaExe”,整个过程会更快

    我希望(2)(3)和(4)立即执行,这在Windows中是否可行

    我非常清楚,最佳做法是在本地手动复制文件并运行它,或者创建一个简单的launcher exe,在必要时运行LocExe进行缓存,但我有一个非常大的客户,要求我在不更改部署过程的情况下执行此操作

    这就是我在这里征求专家意见的原因

    这是我的代码(当然是简化的,而不是单元1想象100个单元):

    //这是dpr
    计划我的计划;
    使用
    Vcl.表格,
    “execache.pas”中的execache,
    ‘Unit1.pas’{Form1}中的Unit1;
    {$R*.res}
    开始
    RunCachedExe;
    应用程序初始化;
    Application.MainFormOnTaskbar:=True;
    Application.CreateForm(TForm1,Form1);
    应用程序。运行;
    结束。
    //这是execache单元
    单位execache;
    接口
    使用
    Vcl.表格,
    窗户,
    谢拉皮,
    sysutils,
    对话,
    system.IOUtils;
    程序RunCachedExe;
    实施
    程序RunCachedExe;
    函数GetFileSize(const aFilename:String):Int64;
    变量
    信息:TWin32FileAttributeData;
    开始
    结果:=-1;
    如果不是GetFileAttributesEx(PWideChar(aFileName)、GetFileExInfo标准、@info),那么
    出口
    结果:=Int64(info.nFileSizeLow)或Int64(info.nFileSizeHigh shl 32);
    结束;
    变量
    CurrentInstanceSize,CachedFileSize,i:整数;
    CachedFilePath,Outs:字符串;
    SkipLauncher:布尔值;
    开始
    SkipLauncher:=假;
    对于i:=0到paramcount-1 do
    开始
    如果Paramstr(i)='-skipluncher',则
    SkipLauncher:=真;
    结束;
    如果不是SkipLauncher那么
    开始
    //在此代码中,路径是硬编码的,在现实生活中,我使用一个函数调用:
    //带有CSIDL\u LOCAL\u APPDATA的SHGetSpecialFolderPath
    CachedFilePath:=“C:\Users\myuser\AppData\Local\MyProject\bincache\MyProject.exe”;
    CurrentInstanceSize:=GetFileSize(Application.ExeName);
    //如果找不到文件,则返回-1
    CachedFileSize:=GetFileSize(CachedFilePath);
    如果CachedFileSize CurrentInstanceSize,则
    开始
    强制目录('C:\Users\myuser\AppData\Local\MyProject\bincache\');
    CopyFile(PChar(Application.ExeName)、PChar(CachedFilePath)、False);
    结束;
    //启动本地exe并关闭此文件
    ShellExecute(0,'open',PWideChar(CachedFilePath),PWideChar('-SkipLauncher'),nil,SW_SHOWNORMAL);
    申请。终止;
    结束;
    结束;
    
    这段代码使用了其他单元中的一些函数,但是如果这有助于加快exe的执行速度,我可以在execache单元中移动所有函数

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

    那么,是否可以只运行大型exe文件的初始化逻辑


    我希望我能表达我自己的想法,谢谢。

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


    您可以通过将条件部分分离到不同的可执行文件(启动器)来实现所需的行为。没有任何VCL依赖,您可以拥有非常小的VCL。即使如此,更好的选择是在本地运行可执行文件,让它检查远程位置是否包含更新的版本,因为网络访问更容易出现性能和安全问题

    不要让你的客户这样推你。“所有这一切都将发生,你最终将陷入比你现在更大的混乱。”大卫·费弗南感谢你的评论。我完全同意你的看法,但就我而言,我只是复杂机器中的一个齿轮,我执行命令。当然,我可以说出我的想法并影响决策,但不管怎样,有没有办法实现我想要实现的目标?你似乎很困惑。远程位置上的可执行文件将加载到本地计算机的内存空间。即使第一条指令是Halt,也将获取整个运行时。是否可以只运行ini并不重要
    //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;