【问题标题】:Failed to Create File. Second time it succeeds无法创建文件。第二次成功了
【发布时间】:2018-05-09 12:21:22
【问题描述】:

首先很抱歉 - 对于这个问题,完全不可能创建一个最小的示例,因为涉及到一些专门的硬件。

所以.. 我们已经构建了一个记录设备,它通过 USB 连接到 PC 并在其中模拟 SD 卡(显示为驱动器)。驱动器最初是只读的 但可以通过写入特殊扇区(MBR 和 FAT 之间)切换为读/写操作,以便在该驱动器上创建文件。

到目前为止一切顺利。现在,当创建一个抱怨媒体是只读的文件时,Windows 似乎会产生一些问题。第二次尝试创建文件实际上成功了。

这里是es执行的代码:

 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;

所以问题是:为什么第二次尝试成功而第一次文件流没有?

如何让 Windows 相信驱动器实际上没有写保护? 我尝试了一些 IO 控制代码: IOCTLCheckVerify IOCTLUpdateProperties

但没有成功。

我不希望有任何代码,但有些想法会受到高度重视。

一点说明: fMK5UsbComm 拥有 2 个句柄:一个用于卷,一个用于与卷关联的物理设备。物理设备句柄首先以只读方式打开,发生特殊的读取操作,该操作撤消设备中的只读标志,然后以读/写方式重新打开句柄(以允许与设备进行特殊通信)。

【问题讨论】:

  • 这肯定是题外话,因为它不能被复制。而且我们看不到相关代码。这很可能在硬件或设备驱动程序中。
  • 问题实际上还在于,在删除只读标志后,实际上可以在资源管理器中复制文件......但它在程序中失败。是的,大卫,我知道你总是想要一个最小的例子,但这是不可能的......所以我恳请一些可能有帮助的提示
  • 这不是我想要的。这是网站政策。这是一个错误的地方。向 G+ delphi 开发人员提问。

标签: delphi delphi-2010


【解决方案1】:

好吧,我想我现在明白了 - 所以这只是针对可能最终落入同一陷阱的任何人:

  1. 驱动器句柄是通过发出 SYNCHRONIZED 访问标志而不是 GENERIC_READ 或 GENERIC_WRITE 获得的。这加快了设备的检测速度,因为当时它还没有完全安装(例如,读取该设备上的 FAT 很慢),但可以进行较低级别的调用。
  2. 我需要关闭驱动器句柄,使用 GENERIC_READ 或 GENERIC_WRITE 重新打开它,发出 FSCTL_DISMOUNT_VOLUME 命令,然后再次重新打开驱动器句柄以安装驱动器并让 Windows 更新内部卷信息。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-16
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多