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

问题描述 投票:0回答:2

我需要将存档 (

.zip
) 文件解压到 USB 记忆棒上,但是在成功调用
CreateFile()
/
WriteFile()
之后,我从
WriteFile()
收到各种错误,大多数时候第一个是
FILE INVALID
GetLastError()
给出错误代码 1006)。

请注意,当启动计算机(我正在使用虚拟化 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.

使用

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

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

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

错误总是发生在程序执行的中间/结束时,在大量成功调用

CreateFile()
/
WriteFile()
之后。

我尝试使用 Process MonitorProcess Explorer 来监控我的程序。我正确地关闭了文件描述符,Process Monitor 上没有任何危险信号,除了我向您描述的那个。

这是 Proc Monitor 输出的截图:

procmon output

我也得到一个

0x80000016
错误,根据MSDN,它与常量
STATUS_VERIFY_REQUIRED
有关:

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

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

我看到直接写入外部驱动器(当使用

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

有人能帮帮我吗?

c++ windows io usb-drive
2个回答
0
投票

1006是

ERROR_FILE_INVALID

1006 (0x3EE)

文件的体积已被外部更改,因此打开的文件不再有效。

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

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

或者如果您让 VM 控制整个 USB 卷而无需将其安装在主机中?


0
投票

按照 Ben 的建议,我用 VDI(虚拟磁盘映像)替换了 USB 闪存驱动器。它连续 3 次成功解压存档。正如我之前所说,相同的代码在 Linux 和 macOS 上运行良好,带有

open()
write()
,但我没有说的是 Windows 是我在虚拟机中使用的唯一操作系统,我测试了 Linux 和 macOS本地主机。

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

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

© www.soinside.com 2019 - 2024. All rights reserved.