【问题标题】:Take disks online/offline使磁盘联机/脱机
【发布时间】:2011-11-23 19:27:20
【问题描述】:

我有一个程序在 Windows 中对磁盘进行原始 IO。

如果目标磁盘在线,一切正常。但是,某些 Windows 操作系统中的默认行为是让新磁盘最初处于脱机状态。

我很难在 Windows 上找到正确的 API 来执行此操作。等效的命令行类似于:

"select disk 2", "online disk" | diskpart

但是我需要能够在代码中执行此操作。我查看了 DeviceIoControl Win32 API(我认为这是正确的),但无法确定要使用哪个控制代码。我找不到它的事实让我觉得我可能缺少更好的 API 来使用。

【问题讨论】:

  • 为什么不直接从 C# shell 执行命令行?
  • 出于多种原因,但足以说明这不是一种选择。如果 diskmgmt 和 diskpart 可以做到,那就有办法了。我想知道那是什么。
  • @joe - diskmgmt 和 diskpart 是 Windows 内置命令的 gui,它们可能使用 Win32 API。考虑到他们已经存在了一段时间,那不太可能。您可以通过这些 gui 执行的所有操作都可以通过命令行执行。
  • @Ramhound:我明白:有一个 Win32 API somewhere 可以让你做到这一点。我找不到它,所以我的问题。
  • 找不到怎么知道它存在?

标签: c# winapi deviceiocontrol


【解决方案1】:

This question 有几个有用的 Windows API 链接,包括 DeviceIOControl 方法。

查看所有枚举后,我找不到任何与使磁盘联机相关的内容,或对磁盘进行格式化/分区之外的任何有趣更改。这可能是因为此功能仅支持热插拔硬盘驱动器。热插拔硬盘的市场非常小,绝大多数情况下都有驱动程序来支持任何需要的操作。最后,其余的应该能够使用 diskpart 工具进行任何必要的操作。

我认为您需要再次查看您的要求。您正在运行具有联机硬盘所需权限的进程,但无法访问命令行程序?以下是一些不使用命令行程序的常见原因的建议:

  • 无法弹出黑屏 - 网上有大量针对此问题的解决方案
  • 安全团队不允许 - 您已经以管理员身份运行该进程,因此您信任它,为什么不信任 Windows 内置功能
  • 技术问题无法调用其他进程 - 鉴于该进程以管理员身份运行,我会对如何管理此问题感兴趣
  • 诸如“始终使用 API”之类的编码指南 - 由于缺乏需求,因此没有此指南

【讨论】:

  • 除了热插拔之外,动态磁盘实际上还有很多用途。感谢您的链接,我看到了,尽管您注意到那里没有真正的解决方案。
  • @Joe:我指的是驱动器的物理性能而不是动作
【解决方案2】:

对于后代,答案(在 Win 2k3/Vista 及更高版本上)是虚拟磁盘服务 (VDS)。有一些工作可以将它们整合在一起,特别是如果您在 .NET 中不使用 COM 对象。

磁盘在线/离线使用IVdsDrive::SetStatus 完成。至少它应该;我发现我可以通过简单地禁用磁盘上的只读状态来解决我的问题。我可以使用带有适当标志值的IVdsDisk::SetFlags 来做到这一点。

【讨论】:

  • 这个api是一个大地狱,我该如何使用它?文档真的不清楚。
【解决方案3】:

不确定 C#,但我在 C++ 中使用它: 尝试用IOCTL_DISK_SET_DISK_ATTRIBUTES 调用DeviceIoControl()。文件句柄必须具有读写权限。我认为它至少需要 Windows 7。它不适用于 Windows 2003 x64。 Windows 8 成功使磁盘脱机,然后您可以从备份中重写它。

BOOL disk_offline(HANDLE h_file, bool enable){
DWORD bytes_returned = 0;
BOOL b_offline = 0;
if(get_size_volume_disk(h_file)){
    SET_DISK_ATTRIBUTES disk_attr;
    ZeroMemory(&disk_attr, sizeof(disk_attr));
    disk_attr.Version = sizeof(SET_DISK_ATTRIBUTES);
    disk_attr.Attributes = enable? DISK_ATTRIBUTE_OFFLINE: 0;
    disk_attr.AttributesMask = DISK_ATTRIBUTE_OFFLINE;
    b_offline = DeviceIoControl(h_file, IOCTL_DISK_SET_DISK_ATTRIBUTES, &disk_attr, disk_attr.Version, NULL, 0, &bytes_returned, NULL);
    // Invalidates the cached partition table and re-enumerates the device.
    if(!enable) BOOL b_update = DeviceIoControl(h_file, IOCTL_DISK_UPDATE_PROPERTIES, NULL, 0, NULL, 0, &bytes_returned, NULL);
}
return b_offline;
}

【讨论】:

    【解决方案4】:

    使用 DeviceIoControl 和 IOCTL_DISK_IS_WRITABLE 控制代码,可以检查磁盘是否可写。如果磁盘处于脱机状态,则返回 false。这意味着可以确定磁盘是否处于脱机状态,并且可以在 Windows 2003 及更高版本中正常工作。但是,我找不到任何有用的 IOCTL 来使磁盘在 Windows 2003 上联机。IOCTL_DISK_SET_DISK_ATTRIBUTES 仅适用于 Windows 2008 及更高版本。

    【讨论】:

      猜你喜欢
      • 2022-09-24
      • 2011-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-21
      • 2017-03-04
      • 1970-01-01
      相关资源
      最近更新 更多