c++ - 当文件路径名超过 255 个字符时,如何在 Windows 中使用 MFC 创建文件?

标签 c++ windows winapi mfc

我在 Windows 中工作,使用 vc++2010 和 MFC。

以下是我的代码:

CFile File;
TCHAR lpCause[1024];
CFileException eException;
CString strErrorMessage;
//  a very long file path name means a file name over 255 characters
if (!File.Open(_T("a very long file path name"), CFile::modeCreate, &eException))
{
    eException.GetErrorMessage(lpCause, 1024);
    strErrorMessage = lpCause;
}
else
    File.Close();

当我运行代码时,我收到错误消息:“一个很长的文件路径名包含一个不正确的路径”。

我的问题是:

  1. 如何修改我的代码以使其工作?
  2. 我了解到 CreateFile() 函数可以在文件路径的开头添加 "\\\\?\",然后它将此限制扩展到 32767 宽字符。如何在 MFC 中做同样的事情?

最佳答案

原因

CFile::Open() 的源代码中,有一个明确的检查路径长度是否超过 _MAX_PATH:

if (lpszFileName != NULL && SUCCEEDED(StringCchLength(lpszFileName, _MAX_PATH, NULL)) )

如果超过 _MAX_PATH,函数设置 pException->m_cause = CFileException::badPath 并返回 FALSE

即使是VS2017自带的MFC版本也是如此。

因此,绕过 _MAX_PATH 限制的标准技术,即在路径前加上 \\?\ 将不起作用。

可能的解决方案

直接调用 CreateFileW() 以向其传递一个带有 \\?\ 前缀的路径。使用接受HANDLECFile 构造函数通过CFile 对象管理文件。 CFile 对象将取得句柄的所有权,因此您不得在句柄上调用 CloseHandle()

HANDLE hFile = CreateFileW( L"\\\\?\\a very long file path name", GENERIC_WRITE, 0, nullptr, CREATE_ALWAYS, 0, NULL );
if( hFile != INVALID_HANDLE_VALUE )
{
    // Manage the handle using CFile
    CFile file( hFile );
    // Use the file...

    // The CFile destructor closes the handle here. 
}
else
{
    DWORD err = GetLastError();
    // TODO: do your error handling...
}

另一种可能性是从 CFile 派生一个类来覆盖 CFile::Open()(它是虚拟的)。对于实现,复制/粘贴 MFC 源代码,但省略 _MAX_PATH 检查。对于大型项目,此类可以直接替代 CFile 以启用长路径。如果 \\?\ 前缀不存在,您甚至可以在前面添加前缀(但这涉及更多,因为前缀还禁用从 Win32 路径到 NT- 的常规转换样式路径,如将 / 转换为 \,解析点等)。

关于c++ - 当文件路径名超过 255 个字符时,如何在 Windows 中使用 MFC 创建文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49272809/

相关文章:

c++ - 在静态库和 DLL 中使用静态成员 - 成员值正在重置

delphi - Winmm.dll无法播放某些WAV声音吗?

c++ - 在初始化期间将成员地址发送给父类安全吗?

c++ - __cxa_pure_virtual 的目的是什么?

python - Popen Windows 中的“^' is ignored by Python - how to escape ' ^”字符?

Python:导航到便携设备目录 (Windows 7)

iphone - Windows 上的 DragonFireSDK 和 iPhone 开发

c++ - 如何退出阻塞的 recv() 调用?

qt - 在 Qt 应用程序中使用 WinAPI 提取图标

c++ - 命名空间中的类前向声明