You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

USB模拟SD卡设备首次创建文件失败、二次成功的原因及解决咨询

先跟大伙道个歉——因为涉及专用硬件,没法做最小复现示例。

我们团队开发了一款USB录制设备,它会模拟成SD卡(在Windows里显示为一个驱动器)。这个驱动器默认是只读状态,但可以通过写入MBR和FAT之间的特殊扇区切换成读写模式,之后就能在上面创建文件了。

遇到的诡异问题

现在碰到个搞不懂的情况:第一次尝试在这个驱动器上创建文件时,Windows会报错提示介质只读,但第二次再试就完全正常了。

我目前用的代码逻辑是这样的:

if not (fMK5UsbComm as TMK5USBComm).IsWritable then raise Exception.Create('WTF');
try
  fs:=TFileStream.Create(fMK5UsbComm.DriveLetter + ':\Tom24.ini', fmCreate or fmOpenReadWrite);
  try
    fs.WriteBuffer(ss[1], length(ss));
  finally
    fs.Free;
  end;
except
  fs:=TFileStream.Create(fMK5UsbComm.DriveLetter + ':\Tom24.ini', fmCreate or fmOpenReadWrite);
  try
    fs.WriteBuffer(ss[1], length(ss));
  finally
    fs.Free;
  end;
end;

其中判断是否可写的IsWritable方法实现是:

function TVolume.IsWritable: boolean;
var
  numBytesReturned : DWORD;
begin
  numBytesReturned := 0;
  Result := DeviceIoControl(
    fHandle,
    IOCTLDiskIsWritable,
    nil, 0,
    nil, 0,
    numBytesReturned,
    nil);
  if not Result then begin
    if GetLastError <> ERROR_WRITE_PROTECT then
      RaiseLastOSError;
  end;
end;

想请教的两个核心问题

  1. 为什么第一次创建文件流会失败,第二次却能成功?
  2. 有没有办法让Windows立刻识别到驱动器已经解除只读状态?我试过IOCTLCheckVerify、IOCTLUpdateProperties这些IO控制指令,但都没起作用。

不需要给具体代码,只要相关的思路建议就好。

补充说明一下:fMK5UsbComm里持有两个句柄,一个对应卷,一个对应关联的物理设备。物理设备句柄最初是只读模式打开的,执行特殊读取操作取消设备的只读标记后,会重新以读写模式打开(这样才能和设备进行特殊通信)。


内容的提问来源于stack exchange,提问作者mrabat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:03:44