1

语境:

我需要扫描、收集信息并从特定目录复制一些媒体文件。

我在某些文件未被检测到等方面遇到了很多麻烦

问题:

在下面的代码中,我使用 c 样式转换将我QString的转换LPCWSTRCopyFileExW我在这篇SO 帖子中找到的 for。我尝试了许多不同的转换,但它们似乎都不能正常工作——现在这不是重点

这种“转换”技术给出的问题是错误ERROR_NOT_SUPPORTED

ERROR_NOT_SUPPORTED

50 (0x32)

不支持该请求。

坦率地说,在这种情况下,这对我来说完全没有意义。我正在从 NTFS -> NTFS(用于测试的同一硬盘驱动器)复制,目标文件长度 < 200 个字符(参见图片,确切地说是 192 个字符)。

核心代码:(详见底部)

     // QString src (src file location), dst (destination file location)

     LPCWSTR localC_src = (LPCWSTR) src.utf16();
     LPCWSTR localC_dst = (LPCWSTR) dst.utf16();
     LPCWSTR dirC = (LPCWSTR) dir.utf16();

     auto rc = CopyFileExW(localC_src, localC_dst, &BackupManager::copyProgress, this, &bStopBackup, 0);
     if (rc == 0) {

          DWORD lastError = GetLastError(); // Error = 0x32
          bool dirExist = DirExists(dirC); // true
          bool fileExists = FileExists(localC_src); // true

          printWarning(TAG, QString("File Copy Error: %1").arg(getLastErrorMsg()));
#ifdef QT_DEBUG
          if (FileExists(localC_src)) {
               qDebug() << "#FailedCopy: Windows file exists but copy failed" << src;  // this gets hit using the implemented c-style cast 
          }
          else {
               if (QFile::exists(src)) {
                    qDebug() << "#FailedCopy: Windows is really being full of shit! " << src;   // this always gets triggered when using QString::toStdWString.c_str()
               }
               else {
                    qDebug() << "#FailedCopy: Windows file copy failed outright" << src; 
               }
          }
          // ...
    } else {
          // success
    }

这个错误在FileCopyExW上下文中意味着什么?

(另外,如果有人有 windows.h 实现的源代码以允许我进一步跟踪错误,请将其作为评论发布)

调试器的图像等 在此处输入图像描述

完整代码实现:

static QString toString(HRESULT hr)
{
     _com_error err{hr};
     const TCHAR* lastError = err.ErrorMessage();
     return QStringLiteral("Error 0x%1: %2").arg((quint32)hr, 8, 16, QLatin1Char('0'))
            .arg(lastError);
}

static QString getLastErrorMsg()
{
     DWORD lastError = GetLastError();
     QString s = toString(HRESULT_FROM_WIN32(lastError));
     return s;
}

BOOL FileExists(LPCWSTR szPath)
{
     DWORD dwAttrib = GetFileAttributes(szPath);

     return (dwAttrib != INVALID_FILE_ATTRIBUTES &&
             !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY));
}

// not used
static const wchar_t* toLPCWSTR(QString s)
{
     std::wstring dstWString = s.toStdWString();
     const wchar_t* localC_src = dstWString.c_str();
     return localC_src;
}

static bool DirExists(LPCWSTR szPath)
{
     DWORD ftyp = GetFileAttributes(szPath);
     if (ftyp == INVALID_FILE_ATTRIBUTES)
          return false;  //something is wrong with your path!

     if (ftyp & FILE_ATTRIBUTE_DIRECTORY)
          return true;   // this is a directory!

     return false;    // this is not a directory!
}

BackupResult BackupManager::copyFile(QString m_src, QString m_dst)
{
     QFileInfo fi(m_src);
     QString dir = fi.dir().path();
//     const wchar_t* dirC = toLPCWSTR(dir);
     QString src = QString(m_src).replace("/", "\\");
     QString dst = QString(m_src).replace("/", "\\");
//     const wchar_t* localC_src = toLPCWSTR(src);
//     const wchar_t* localC_dst = toLPCWSTR(dst);
     LPCWSTR localC_src = (LPCWSTR) src.utf16();
     LPCWSTR localC_dst = (LPCWSTR) dst.utf16();
     LPCWSTR dirC = (LPCWSTR) dir.utf16();

     auto rc = CopyFileExW(localC_src, localC_dst, &BackupManager::copyProgress, this, &bStopBackup, 0);
     if (rc == 0) {

          DWORD lastError = GetLastError(); // Error = 0x32
          bool dirExist = DirExists(dirC); // true
          bool fileExists = FileExists(localC_src); // true

          printWarning(TAG, QString("File Copy Error: %1").arg(getLastErrorMsg()));
#ifdef QT_DEBUG
          if (FileExists(localC_src)) {
               qDebug() << "#FailedCopy: Windows file exists but copy failed" << src; // this gets hit using the implemented c-style cast 
          }
          else {
               if (QFile::exists(src)) {
                    qDebug() << "#FailedCopy: Windows is really being full of shit! " << src;   // this always gets triggered when using QString::toStdWString.c_str()
               }
               else {
                    qDebug() << "#FailedCopy: Windows file copy failed outright" << src;
               }
          }
#endif
          // copy failed
          return BackupResult::IOError;
     }

     // copy success
     return BackupResult::Success;
}
4

1 回答 1

1

我建议您检查复制的文件句柄是否在另一个进程中打开。

我创建了一个简单的示例,代码如下:

#include <iostream>
#include <Windows.h>
using namespace std;

int main(int argc, const char* argv[])
{
    CopyFileEx(L"D:\\test\\test.txt", L"D:\\test\\test2.txt", NULL, NULL, 0, 0);
    int e = GetLastError();
    cout << "error code is :" << e << endl;
    return 0;
}

这个示例当然成功复制了文件。但是如果我添加代码来打开这个文件的句柄,它会返回错误代码 32。

#include <iostream>
#include <Windows.h>
using namespace std;

int main(int argc, const char* argv[])
{
    CreateFileW(L"D:\\test\\test.txt", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
    CopyFileEx(L"D:\\test\\test.txt", L"D:\\test\\test2.txt", NULL, NULL, 0, 0);
    int e = GetLastError();
    cout << "error code is :" << e << endl;
    return 0;
}

输出: 在此处输入图像描述

所以我认为您在其他位置打开手柄后没有正确关闭它。如果您需要在句柄打开时复制文件,您可以将dwShareMode参数修改为FILE_SHARE_READ. 这样就可以在句柄打开时进行文件复制操作。

这是示例:

#include <iostream>
#include <Windows.h>
using namespace std;

int main(int argc, const char* argv[])
{
    CreateFileW(L"D:\\test\\test.txt", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
    CopyFileEx(L"D:\\test\\test.txt", L"D:\\test\\test2.txt", NULL, NULL, 0, 0);
    int e = GetLastError();
    cout << "error code is :" << e << endl;
    return 0;
}

输出:

在此处输入图像描述

更多参考:CreateFileWCopyFileExA

于 2020-08-12T06:19:29.737 回答