【问题标题】:Inno Setup FileCopy failingInno 设置文件复制失败
【发布时间】:2017-01-24 22:41:52
【问题描述】:

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

但是,我收到一个提示,指示 file copy failed,但我就是不明白为什么它不起作用。我的错误消息打印了正确的目录\文件名,我可以验证它们存在并且没有在任何外部程序中打开。

以下是代码,取自(并稍作修改):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;

【问题讨论】:

  • 给我们一个复制失败的SourceFilePathDestFilePath的实际值的例子。
  • FileCopy 失败时,DLLGetLastError 会返回什么?
  • 您对 DestPath 有写入权限吗?确实 DestPath 有效吗?
  • 可能有点跑题了,但是为了创建文件的备份副本,您将覆盖它可能会更好地在复制新文件之前简单地将这些旧文件移动/重命名为新位置/名称。这样,您可以避免从旧文件中实际复制数据,这可能需要一些时间,并且还可以避免在此复制过程中发生数据损坏的可能性,因为通过移动/重命名,仅修改文件表中的数据条目以表示现有文件的新位置/名称这要快得多。 ...
  • ... 这种方法的缺点是,如果您不替换所有文件并且某些文件必须保持原样,您就不能对该目录中的每个文件都执行此操作。但是话又说回来,如果不是所有文件都被新文件替换,我也不明白为什么要复制所有文件。您可能考虑的另一种方法实际上是将这些旧文件存档到 ZIP 存档中。这样可以节省一些硬盘空间。如果您的程序会不必要地占用空间,尤其是使用 SSD 驱动器的人,那么没有多少用户会很高兴。 ...

标签: delphi inno-setup pascal


【解决方案1】:

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

Martin 的DirectoryCopy 函数的原始链接位于here

【讨论】:

  • FileCopy 不创建目标文件夹是很自然的。没有任何迹象表明它确实如此。这是一个具有单一目的的微不足道的功能。你不能指望它做更多的事情。无需记录。无论如何 +1。
  • 由于在目录名称中使用了非法字符,CreateDir 函数失败。为 Windows 开发时,作为本地 Mac 用户的缺点之一!
【解决方案2】:

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

要找出任何(文件)系统函数失败的原因,请使用GetLastError WinAPI function。您还可以使用SysErrorMessage support function 将错误代码转换为消息。该函数是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);

作为@RobertWigley already posted in his answer,确保目标文件夹存在。如果没有,你会得到错误代码3(系统找不到指定的路径)。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多