较大的.exe文件无法自行删除,而较小的.exe文件可以使用相同的代码(Delphi)

时间:2016-02-03 07:24:41

标签: file delphi version exe shellexecute

我想在Delphi中编写一个程序,它删除自己并复制另一个版本而不是它,另一个.exe文件来自另一个文件夹。我在测试项目上尝试了这个代码,但它确实有效。但是当我为我的大项目复制它时,它无法删除自己。 大项目的大小是68 413 KB(如果它与问题有任何关联..)

有什么建议吗?

AppName:= ExtractFileName(ParamStr(0));
myBatFile:= 'copy.bat';
AssignFile(myText, myBatFile);
Rewrite(myText);
Writeln(myText, 'del ' + AppName);
Writeln(myText, 'copy whateverPath\myProgram.exe whateverPath\destination\myProgram.exe');
Writeln(myText, 'del ' + myBatFile);
CloseFile(myText);
ShellExecute(Application.Handle,'open','copy.bat',nil,nil,SW_ShowNormal);
Halt;

3 个答案:

答案 0 :(得分:3)

当您调用create view DemoView as select name=SUBSTRING(name,1,50)+'...' from tableName; 时,会创建一个新的命令解释程序进程,然后进程B.然后ShellExecute返回,您的进程A继续执行。

你现在拥有所谓的种族。这两个过程都处于竞争中。进程B正在尝试删除用于创建进程A的可删除文件。因此进程A需要在进程B完成之前终止,以便成功完成。但是你没有做任何事情来实现这一目标。

实现这一目标的正确方法如下:

  1. 拥有第二个可执行复制和删除的可执行文件。这将是流程B.
  2. 让进程A创建新进程B,将文件名作为命令行参数传递。并且还为进程A传递了重复的可继承进程句柄。
  3. 一旦进程A完成第2步,它就会终止。
  4. 进程B现在等待步骤2中提供的进程句柄。当发出该句柄信号时,进程B知道进程A已终止并且可执行文件可被删除。

答案 1 :(得分:3)

您可以使用http://www.catch22.net/tuts/self-deleting-executables中的自删除批处理文件方法在退出后删除可执行文件,然后复制新的可执行文件并删除批处理文件。

procedure UpdateMeAfterClose(const NewFilename: string);
var
  batch: TStrings;
  appName, newApp, batchName: string;
begin
  batch := TStringList.Create;
  try
    //** Get batch filename in temp
    batchName := TPath.GetTempPath;
    if GetTempFileName(PChar(batchName), 'bat', 0, PChar(batchName)) = 0 then
      RaiseLastOSError;
    batchName := ChangeFileExt(batchName, '.bat');
    newApp := AnsiQuotedStr(NewFilename, '"');
    appName := AnsiQuotedStr(Application.ExeName, '"');

    batch.Add(':Repeat');
    batch.Add('del ' + appName); // try to delete current exe
    batch.Add('if exist ' + appName + ' goto Repeat');
    batch.Add('copy ' + newApp + ' ' + appName); // copy new exe
    batch.Add(appName); // start new app
    batch.Add('del "' + batchName + '"'); // delete this batch file
    batch.SaveToFile(batchName);
  finally
    batch.Free;
  end;
  ShellExecute(0, 'open', PChar(batchName), nil, nil, SW_HIDE);
end;

答案 2 :(得分:3)

您无法删除正在运行的进程的文件。但你可以重命名它! 所以你可以:

  1. 将新的可执行文件下载到* .tmp文件
  2. 将* .exe重命名为* .exe.tmp
  3. 将下载的文件从* .tmp重命名为* .exe
  4. 重新启动应用程序
  5. 删除* .exe.tmp