Inno Setup FileCopy 失败

Inno Setup FileCopy failing

我正在开发一个需要在安装前创建目录备份的安装程序。我实现的方法纯粹是将当前目录的所有文件复制到新目录,然后我可以随意覆盖旧目录中的文件(我的安装程序)。

然而,我收到提示file copy failed,但我不明白为什么它不起作用。我的错误消息打印出正确的 directory\filename,我可以验证它们是否存在并且未在任何外部程序中打开。

下面是代码,取自(并稍作修改):http://blogs.candoerz.com/question/139833/inno-setup-copy-folder-subfolders-and-files-recursively-in-code-section.aspx

function DirectoryCopy(SourcePath, DestPath: string): boolean;
var
  FindRec: TFindRec;
  SourceFilePath: string;
  DestFilePath: string;
begin
  if FindFirst(SourcePath + '\*', FindRec) then begin
    try
      repeat
        if (FindRec.Name <> '.') and (FindRec.Name <> '..') then begin
          SourceFilePath := SourcePath + '\' + FindRec.Name;
          DestFilePath := DestPath + '\' + FindRec.Name;
          if FindRec.Attributes and FILE_ATTRIBUTE_DIRECTORY = 0 then begin
            if FileCopy(SourceFilePath, DestFilePath, False) then begin
              Result := True;
              MsgBox('Copy Worked!', mbInformation, MB_OK);
            end else begin
              Result := False;
              MsgBox('Copy Failed!'+SourceFilePath, mbInformation, MB_OK);
            end;
          end else begin
            if CreateDir(DestFilePath) then begin
              Result := True;
              MsgBox('Created Dir!', mbInformation, MB_OK);
              DirectoryCopy(SourceFilePath, DestFilePath);
            end else begin
              Result := False;
              MsgBox('Failed to create Dir!', mbInformation, MB_OK);
            end;
          end;
        end;
      until not FindNext(FindRec);
    finally
      FindClose(FindRec);
    end;
  end else begin
    Result := False;
    MsgBox('Failed to List!', mbInformation, MB_OK);
  end;
end;

我怀疑您要复制到的目录不存在。您需要先使用 CreateDirForceDirectories 创建目录。文件函数(包括 Martin 的 DirectoryCopy 函数,它使用这些内部函数)要求目录存在,否则它们将失败。他们不会自动为您创建路径。遗憾的是,这在任何地方都没有记录(我能找到,尽管有人可能会纠正我)因为它也让我困惑了一段时间。

原来link到Martin的DirectoryCopy函数可用

由于我们没有收到任何可用于调试您的实际问题的信息,我发布了用于调试文件问题的通用说明。

要找出任何(文件)系统功能失败的原因,请使用 GetLastError WinAPI function. You can also use the SysErrorMessage support function to convert an error code to a message. The function is a wrapper for the FormatMessage WinAPI function

function GetLastError: Cardinal;
  external 'GetLastError@kernel32.dll stdcall';

function FileCopyLogged(
  ExistingFile, NewFile: String; FailIfExists: Boolean): Boolean;
var
  Error: Cardinal;
begin
  Result := FileCopy(ExistingFile, NewFile, FailIfExists);

  if not Result then
  begin
    Error := GetLastError;
    Log(
      Format(
        'Copying "%s" to "%s" failed with code %d (0x%x) - %s', [
        ExistingFile, NewFile, Error, Error, SysErrorMessage(Error)]));
  end
    else
  begin
    Log(Format('Copying "%s" to "%s" succeeded', [ExistingFile, NewFile]));
  end;
end;

FileCopy(或 FileCopyLogged)的正确调用如下:

FileCopyLogged(
  ExpandConstant('{app}\MyProg.exe'), 
  ExpandConstant('{app}\archive\MyProg.exe'),
  False);

,确保目标文件夹存在。如果没有,您将收到错误代码 3 (系统找不到指定的路径).

还要确保在 NewFile 参数 (C:\folder\file) 中使用目标文件的完整路径。不仅仅是目标文件夹的路径(C:\folderC:\folder\)。如果您只使用目标文件夹的路径,您将收到错误代码 5 (访问被拒绝).

当然这两个代码也可以指示其他问题。