写入 VirtualBox 重定向的 USB 闪存驱动器时出现“WriteFile”错误 1006

`WriteFile` error 1006 when writing to VirtualBox-redirected USB flash drive

提问人:voidboy 提问时间:3/3/2023 最后编辑:Ben Voigtvoidboy 更新时间:3/3/2023 访问量:125

问:

我需要将存档 () 文件解压缩到 U 盘上,但是在成功多次 / 调用后,我收到各种错误,大多数情况下第一个错误是(给出错误代码 1006)。.zipCreateFile()WriteFile()WriteFile()FILE INVALIDGetLastError()

请注意,当启动计算机(我正在使用虚拟化的 Windows 11)并首次启动该程序时,它可以工作并完全解压缩存档。任何其他尝试都将失败。

下面是伪代码:


// *dst is my usb stick mounpoint, most of the time its "E:"

static int decompress_file(const char * zip,
    const char * dst) {
    struct zip_stat sb;
    struct zip * za = zip_open(zip, ZIP_RDONLY, NULL);
    size_t readLen, totalLen = 0;
    char buffer[4096];

    for (long int i = 0; i < zip_get_num_entries(za, 0); i++) {
        zip_stat_index(za, i, 0, & sb);
        const std::string file = std::string(dst) + sb.name;
        struct zip_file * zf = zip_fopen_index(za, i, 0);
        HANDLE fd = CreateFile(
            file.c_str(),
            GENERIC_WRITE,
            0,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL
        );

        totalLen = 0;
        while (totalLen != sb.size) {
            readLen = zip_fread(zf, buffer, 4096);
            WriteFile(fd, buffer, readLen, NULL, NULL);
            totalLen += readLen;
        }

        CloseHandle(fd);
        zip_fclose(zf);
    }
    zip_close(za);
    return 0;
}

我试图简化代码,请注意它不会按原样编译。我正在使用 libzip

在 Linux/macOS 上使用 / 运行良好的相同代码。open()write()

此代码在单独的线程中执行,主线程显示 GUI (wxWidget) 并等待此任务完成。

我试图根据页面大小调整缓冲区的大小,我想对于我们大多数人来说,4096 字节?我还尝试将缓冲区大小设置为 512 和 8192,但它没有改变任何内容。

错误总是发生在程序执行的中间/结束时,在成功调用 / 之后。CreateFile()WriteFile()

我尝试使用进程监视器和进程资源管理器监视我的程序。我正确地关闭了文件描述符,除了我向您描述的那个之外,进程监视器上没有危险信号。

以下是 Proc Monitor 输出的捕获:

Procmon 输出

我还收到一个错误,根据 MSDN 的说法,该错误与常量有关:0x80000016STATUS_VERIFY_REQUIRED

介质已更改,并且正在进行验证操作,因此无法对设备执行读取或写入操作,但验证操作中使用的读取或写入操作除外。

https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-FSCC/%5BMS-FSCC%5D-130808.pdf

我看到直接写入外部驱动器(当使用语法作为物理驱动器打开时)必须与扇区对齐,但这不是我的情况吗?我也尝试切换到 /,但遇到了完全相同的问题。\\\\.\_open()_write()

谁能帮我?

C++ Windows IO USB 驱动器

评论

1赞 Some programmer dude 3/3/2023
为了使代码更简单,请尝试将不同操作系统之间的差异抽象为类。或者使用已经为您完成此操作的标准库文件流。代码越简单,就越容易维护、调试和修复问题。
0赞 user253751 3/3/2023
您的 U 盘有可能是假冒的吗?
0赞 voidboy 3/3/2023
我根据您的建议编辑了我的帖子,谢谢。
1赞 user253751 3/3/2023
你说它是虚拟化的,它是如何虚拟化的?虚拟机如何访问 U 盘?
1赞 Ben Voigt 3/3/2023
您是否正在检查来自 ?CreateFile

答:

0赞 Ben Voigt 3/3/2023 #1

1006 是

ERROR_FILE_INVALID

1006 (0x3EE)

文件的卷已从外部更改,因此打开的文件不再有效。

在使用映射驱动器时,“外部更改”似乎是一个明确的可能性(从虚拟机主机或网络服务器映射都可能合理地产生该错误)。似乎实际控制的文件系统(在主机上运行)已经删除了该文件,使打开的句柄过时且无法使用。

如果提取到虚拟磁盘 (VMDK) 而不是映射驱动器,是否会获得更好的结果?

或者,如果让 VM 控制整个 USB 卷,而不将其装载到主机中?

评论

0赞 voidboy 3/3/2023
VM 托管在 VirtualBox 上,我安装了来宾添加并启用了 USB 3.0 控制器 (xHCI)。USB 闪存驱动器仅在 VM 运行时可见。
0赞 Ben Voigt 3/3/2023
@voidboy:您至少可以尝试使用 VDI 文件(第二个文件,与客户机引导的文件分开)吗?如果它在那里工作,但不适用于 VirtualBox USB 重定向,则这是重定向中的错误。
1赞 Ben Voigt 3/3/2023
@voidboy:还要检查来宾的 Windows 事件日志中是否有来自存储子系统的条目
0赞 voidboy 3/3/2023
我从头开始重新安装了 VM,我将尝试使用 VDI 模拟 USB 闪存驱动器,谢谢 Ben Voigt。
0赞 voidboy 3/3/2023 #2

按照 Ben 的建议,我用 VDI(虚拟磁盘映像)替换了 USB 闪存驱动器。它连续 3 次成功解压缩存档。正如我之前所说,相同的代码在 Linux 和 macOS 上运行良好,但我没有说的是 Windows 是我在虚拟机中使用的唯一操作系统,我在本机主机上测试了 Linux 和 macOS。open()write()

为了确认这是一个“虚拟化问题”,我将安装 Windows 11 在笔记本电脑上并确认这一假设。谢谢你的帮助。

编辑:我在原生 Windows 11 上测试了我的程序,它有效,我不会深入探讨为什么它在虚拟机中失败,这解决了我的问题。再次感谢您的帮助。

评论

0赞 Ben Voigt 3/3/2023
我很高兴您能够确认问题仅限于 VirtualBox 的 USB 重定向。我已经更新了您的问题标题以包含这个重要的上下文。