如何修复CopyFile()错误5 - 访问被拒绝错误

时间:2017-07-14 14:15:33

标签: c++ windows winapi copy

我正在尝试编写可在Linux和Windows上使用的复制文件功能。它适用于Linux,但在Windows上,我在尝试使用WinApi函数CopyFile()时收到错误代码5。

在标题File.h中

这是我应该可以在Linux和Windows上使用的File命名空间中的自定义函数。

class File
{
public:
    static bool copyFile(std::string source, std::string destination);
private:
}

在File.cpp中

对于Linux来说很简单:

#ifdef __unix__
  #include "File.h"
  bool File::copyFile(std::string source, std::string destination)
  {
      std::string arg = source + " " + destination;
      return launchProcess("cp", arg);
  }
#endif

在Windows特定的代码块中,我使用WinAPI(#include< windows.h>)函数CopyFile()。这接受LPCWSTR数据类型而不是字符串。为了解决这个问题,我创建了一个将字符串转换为LPCWSTR类型的函数。

#ifdef _WIN32    
  #include "File.h"
  #include <Windows.h>
  std::wstring strtowstr(const std::string &str)
  {
      // Convert an ASCII string to a Unicode String
      std::wstring wstrTo;
      wchar_t *wszTo = new wchar_t[str.length() + 1];
      wszTo[str.size()] = L'\0';
      MultiByteToWideChar(CP_ACP, 0, str.c_str(), -1, wszTo,(int)str.length());
      wstrTo = wszTo;
      delete[] wszTo;
      return wstrTo;
  }


  bool File::copyFile(std::string source, std::string destination)
  {
      std::wstring wsource = strtowstr(source);
      std::wstring wdestination = strtowstr(destination);

      int result = CopyFileW(wsource.c_str(), wdestination.c_str(), TRUE);

          //for debugging...
          std::wcout << "The error is " << GetLastError() <<std::endl;
          std::wcout  << wsource.c_str() << std::endl;
          std::wcout << wdestination.c_str() << std::endl;              

      if (result == 0)
      {
          return false;
      }
      return true;
  }
#endif

在我的测试计划中

TEST(all,main_copy_file)
{
    std::cout << "Testing copyFile() function..." << std::endl;

    std::string srcDir = File::currentWorkingDirectory() + "srcDir";
    File::makeDirectory(srcDir);

    std::string destDir = File::currentWorkingDirectory() + "destDir/";
    File::makeDirectory(destDir);

    File::makeFile(srcDir, "testFile", ".txt");

    ASSERT_TRUE(File::fileExists(srcDir + "/testFile.txt")) << "Error: Test file has not been generated" << std::endl;
    ASSERT_TRUE(File::directoryExists(destDir)) << "Error: Destination directory does not exist" <<std::endl;

    ASSERT_TRUE(File::copyFile(srcDir + "/testFile.txt", destDir)) << "Error: Coppy unsucsessfull" << std::endl;
    ASSERT_TRUE(File::fileExists(destDir + "/testFile.txt")) << "Error: CoppyFile() flagged as sucsessfull but file does not exist" << std::endl;

}

在应用程序输出(在Windows上)

/*
Testing copyFile() function...
The error is 5    
C:\GIT\CorteX\Externals\OSAL\build\Debug/srcDir/testFile.txt
C:\GIT\CorteX\Externals\OSAL\build\Debug/destDir/

error: Value of: File::copyFile(srcDir + "/testFile.txt", destDir)
Actual: false
Expected: true
Error: Coppy unsucsessfull
*/

错误代码5是拒绝访问错误。我认为当目录不存在,目录在其他地方打开,或者我没有权限时,它会出现此错误。

由于我测试过该目录确实存在,我认为它必须是后两者之一。我可能只限制了管理员权限(我不知道),但我可以粘贴到&#34; destDir&#34;没有管理员权限。那么也许它认为该目录是开放的?是否存在确保目录已关闭的命令?

在Linux上运行时测试成功。

2 个答案:

答案 0 :(得分:1)

CopyFile API需要源文件和目标文件的文件名。您的代码传递目标的目录名称。这会导致API失败。您还需要为目标附加文件名。

除此之外,您的代码还有其他几个问题:

  • Windows上的路径分隔符是反斜杠(\)。你正在混合正斜杠(/)和反斜杠。根据传递的参数,系统不会将正斜杠转换为反斜杠,然后再将它们传递给较低级别​​的文件I / O API。
  • 你打电话给GetLastError太晚了。只要记录下来,您需要立即将其称为 以返回有意义的值。不要在任何其他代码中散布它,不管它看起来多么微不足道。该代码可以修改和使调用线程的最后一个错误代码无效。
  • 您的代码采用ASCII编码的字符串。处理包含非ASCII字符的文件时,这将停止工作。这很常见。
  • new wchar_t[...]只会在std::vector<wchar_t>上购买任何东西,除了可能会引入错误。
  • 基于MultiByteToWideChar的字符串转换实现会对不同字符编码的代码单元要求做出(过度)假设。这些假设可能不正确。通过传递 cchWideChar 0,让API计算并告诉您目标缓冲区大小。
  • 您的字符串转换例程会忽略所有返回值,使错误变得非常可能,并且不必要地进行诊断。

答案 1 :(得分:0)

我知道这是一篇过时的文章,但是对于那些偶然发现这里需要更多帮助的人来说

CopyFile具有以下约束,如果不满足,则会给出拒绝访问错误:

  1. 当前用户权限不足
  2. 文件正在使用中
  3. 文件路径是目录,而不是文件
  4. 文件为只读

就我而言,以上所有条件均得到满足,但我仍然遇到相同的错误。帮助我的是一个简单的 SetFileAttributes(filePath,FILE_ATTRIBUTE_NORMAL)

Retrieving and Changing File Attributes

SetFileAttributes