.NET 4.7.2下VB.NET超长路径文件移动失败问题求助
解决方案
核心问题:MoveFileW的路径格式要求
MoveFileW 对长路径的处理要求源路径和目标路径必须统一使用 \\?\ 前缀,不能混合带前缀和无前缀的路径,也不能随意移除目标路径的前缀——你之前移除目标路径前缀的操作是错误的,这会导致系统无法识别长路径。
修正步骤与代码
- 编写路径转换辅助函数:将普通Windows路径转为
\\?\格式,确保Win32 API能识别长路径 - 统一源/目标路径格式:临时文件夹路径虽短,但统一格式可避免兼容性问题
- 保留目标路径的前缀,同时添加错误排查逻辑定位问题
Imports System.Runtime.InteropServices ' 声明MoveFileW API <DllImport("kernel32.dll", SetLastError:=True, CharSet:=CharSet.Unicode)> Private Shared Function MoveFileW(lpExistingFileName As String, lpNewFileName As String) As Boolean End Function ' 辅助函数:将普通路径转换为\\?\格式的长路径 Private Function GetLongPath(path As String) As String ' 已带前缀则直接返回 If path.StartsWith("\\?\") Then Return path End If ' 先转绝对路径避免相对路径问题 Dim absolutePath = IO.Path.GetFullPath(path) ' 添加长路径前缀 Return $"\\?\{absolutePath}" End Function ' 修正后的文件移动逻辑 Sub MoveFileToLongPath(filename As String) ' 构建源文件路径(临时文件夹) Dim sourcePath = My.Computer.FileSystem.CombinePath(My.Computer.FileSystem.SpecialDirectories.Temp, $"{filename}.ddb") Dim longSourcePath = GetLongPath(sourcePath) ' 构建目标文件路径(你的长路径) Dim baseLongPath = "\\?\C:\Basedir\Long-path-base" Dim destinationPath = My.Computer.FileSystem.CombinePath(baseLongPath, $"{filename}.ddb") Dim longDestinationPath = GetLongPath(destinationPath) ' 执行移动 Dim success As Boolean = MoveFileW(longSourcePath, longDestinationPath) If Not success Then ' 获取Win32错误码排查问题 Dim errorCode = Marshal.GetLastWin32Error() Throw New System.ComponentModel.Win32Exception(errorCode) End If End Sub
额外优化:启用.NET 4.7.2原生长路径支持
.NET 4.7.2已原生支持长路径,无需依赖Win32 API,只需在app.config中添加配置:
<configuration> <runtime> <AppContextSwitchOverrides value="Switch.System.IO.UseLegacyPathHandling=false;Switch.System.IO.BlockLongPaths=false" /> </runtime> </configuration>
配置后直接使用System.IO.File.Move即可处理长路径,无需手动添加前缀:
Dim sourcePath = My.Computer.FileSystem.CombinePath(My.Computer.FileSystem.SpecialDirectories.Temp, $"{filename}.ddb") Dim destinationPath = My.Computer.FileSystem.CombinePath("C:\Basedir\Long-path-base", $"{filename}.ddb") System.IO.File.Move(sourcePath, destinationPath)
常见排查点
如果移动仍失败,通过Marshal.GetLastWin32Error()获取错误码定位:
- 错误码
3:路径不存在(检查目标文件夹是否真的创建成功) - 错误码
5:权限不足(确保程序有目标文件夹的写入权限) - 错误码
87:参数错误(路径格式错误,检查前缀是否正确添加)
内容的提问来源于stack exchange,提问作者Tobbe
相关产品推荐
相关产品推荐

