UpFileCopyExW在现有文件上报告0且带有ERROR_FILE_NOT_FOUND

问题描述

上下文:

我有一个应用程序,可以使用QDirIterator在目录中搜索文件,过滤并复制特定文件

问题:

使用QDirIterator::next()的结果,我使用有效的QFile::exists(QString)确保文件存在(作为不必要的安全措施)。

GetLastError()报告ERROR_FILE_NOT_FOUND错误

ERROR_FILE_NOT_FOUND

2(0x2)

系统找不到指定的文件

核心代码:(有关详细信息,请参见底部

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

     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);

     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)) {
                    // =================================================
                    // < ------------------------------------- This is gets triggered
                    // =================================================

                    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
    }

问题:

对我来说没有意义的是,为什么QFile::exists(String)报告FilecopyExW找到的文件说系统找不到指定的文件。我想念什么?


调试器图片

enter image description here

完整代码实现:

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("/","\\");
     const wchar_t* localC_src = toLPCWSTR(src);
     const wchar_t* localC_dst = toLPCWSTR(dst);

// c-style casts
//     LPCWSTR localC_src = (LPCWSTR) src.utf16();
//     LPCWSTR localC_dst = (LPCWSTR) dst.utf16();
//     LPCWSTR dirC = (LPCWSTR) dir.utf16();

     auto rc = copyFileExW(localC_src,0);
     if (rc == 0) {

          DWORD lastError = GetLastError(); // Error = 0x2 (2)
          bool dirExist = DirExists(dirC); // false
          bool fileExists = FileExists(localC_src); // false

          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;
}

更新

如@john的评论中所述,目标文件指向源文件时出现了一个问题,该文件显然无法正常工作。

解决此问题,这突出显示了另一个错误ERROR_INVALID_NAME

ERROR_INVALID_NAME

123(0x7B)

文件名,目录名或卷标语法不正确。

我通过发布的解决方解决了这个问题。

解决方法

此功能有问题:

// 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;
}

您将返回已被解构的字符串的原始指针。

因此,这两行:

 const wchar_t* localC_src = toLPCWSTR(src);
 const wchar_t* localC_dst = toLPCWSTR(dst);

是不确定的行为,但最可能的结果是localC_srclocalC_dst指向已释放的内存。

最好在您的内部指针仍被引用的同时保持std::wstring随处可见

std::wstring strSrc = src.toStdWString();
std::wstring strDst = dst.toStdWString();

const wchar_t* localC_src = strSrc.c_str();
const wchar_t* localC_dst = strDst.c_str();