C#/Native:使用 SCSI PassThrough 读取 HDD 串行

2023-12-08

我编写了三种利用本机的不同方法CreateFile and DeviceIoControl调用以检索 HDD 序列号(而不是型号)。第一个使用S.M.A.R.T.,第二个使用Storage Query第三个使用SCSI PassThrough。我的大部分代码都是基于的内容这个线程(有一些修复和改进)。

这是我使用得到的结果diskid32 实用程序:

Trying to read the drive IDs using physical access with admin rights

Drive Model Number________________: [ST975XXXXX]
Drive Serial Number_______________: [            6WS2XXXX]

Trying to read the drive IDs using physical access with zero rights

Product Id = [ST975XXXXX]
Serial Number = [6WS2XXXX]

Trying to read the drive IDs using Smart

Drive Model Number________________: [ST975XXXXX]
Drive Serial Number_______________: [            6WS2XXXX]

现在,这是使用我的方法的结果:

S.M.A.R.T. = 6WS2XXXX
Storage Query = 6WS2XXXX
SCSI PassThrough = ST975XXXXX

嗯……休斯顿,我们这里有问题。通过前两种方法,我得到了正确的序列号。最后一个我得到的型号非常糟糕。现在,这是我的代码:

--- METHOD ---

internal static String GetHardDiskSerialSCSIPassthrough(SafeFileHandle deviceHandle)
{
    IntPtr bufferPointer = IntPtr.Zero;
    String serial = String.Empty;
    UInt32 bytesReturned;

    SCSIPassthroughBuffered bspt = new SCSIPassthroughBuffered();
    bspt.SPT.Length = (UInt16)Marshal.SizeOf(bspt.SPT);
    bspt.SPT.CommandDescriptorBlockLength = 16;
    bspt.SPT.DataIn = 0x1;
    bspt.SPT.DataTransferLength = 64;
    bspt.SPT.DataBufferOffset = new IntPtr(Marshal.SizeOf(bspt) - 64);
    bspt.SPT.TimeOutValue = 60;
    bspt.SPT.CommandDescriptorBlock = new Byte[] { 0x12, 0x1, 0x80, 0x0, 64, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 };

    Int32 bufferSize = Marshal.SizeOf(bspt);

    try
    {
        bufferPointer = Marshal.AllocHGlobal(bufferSize);

        Marshal.StructureToPtr(bspt, bufferPointer, true);

        if (DeviceIoControl(deviceHandle, 0x4D004, bufferPointer, (UInt32)bufferSize, bufferPointer, (UInt32)bufferSize, out bytesReturned, IntPtr.Zero) && (bytesReturned > 0))
        {
            SCSIPassthroughBuffered result = (SCSIPassthroughBuffered)Marshal.PtrToStructure(bufferPointer, typeof(SCSIPassthroughBuffered));
            serial = Encoding.ASCII.GetString(result.Buffer, 0, result.Buffer.Length).Replace("\0", String.Empty).Trim();
        }
    }
    finally
    {
        Marshal.FreeHGlobal(bufferPointer);
    }

    return serial;
}

--- STRUCTURES ---

[StructLayout(LayoutKind.Sequential)]
private struct SCSIPassthrough
{
    public UInt16 Length;
    public Byte SCSIStatus;
    public Byte PathID;
    public Byte TargetID;
    public Byte LogicalUnitNumber;
    public Byte CommandDescriptorBlockLength;
    public Byte SenseInfoLength;
    public Byte DataIn;
    public UInt32 DataTransferLength;
    public UInt32 TimeOutValue;
    public IntPtr DataBufferOffset;
    public UInt32 SenseInfoOffset;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
    public Byte[] CommandDescriptorBlock;
}

[StructLayout(LayoutKind.Sequential)]
private struct SCSIPassthroughBuffered
{
    public SCSIPassthrough SPT;
    public UInt32 Filler;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)]
    public Byte[] Buffer;
}

我究竟做错了什么?也许使用了错误的 CDB?


您的代码实际上对我来说运行正常,即它返回与引用线程中描述的其他方法相同的数据。我必须做的唯一改变是:

serial = Encoding.ASCII.GetString(result.Buffer, 0, result.Buffer.Length)
                       .Replace("\0", String.Empty)
                       .Trim();

To:

serial = Encoding.ASCII.GetString(result.Buffer, 0, result.Buffer.Length)
                       .Substring(IntPtr.Size)
                       .Replace("\0", String.Empty)
                       .Trim();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C#/Native:使用 SCSI PassThrough 读取 HDD 串行 的相关文章

随机推荐

  • 新添加的元素 $.each 和 events

    我已经阅读了很多帖子 each并新增了元素 事件附件 StackOverflow 上当前有关此主题的许多问题似乎对我不起作用 on 通常推荐 因为它允许我们附加新元素并且仍然维护单个事件侦听器 处理程序 在我当前的代码中 1 input t
  • 检测可穿戴设备何时与 Android 手机连接/断开连接

    Pebble 手表有一个 Intent 当 Pebble 连接 断开连接时会全局发送 这允许手机应用程序知道手表是否已连接 我已进行搜索 但无法找到有关 Android Wear 类似功能的信息 如何知道可穿戴设备是否已连接到手机 是否可以
  • 生成 Linkedin 访问令牌

    我一直在尝试使用简单的 REST 客户端以及 Mozilla 的 REST 插件 我正进入 状态 HTTP 1 1 401 未经授权 响应 正文中的 error unauthorized client error description 客
  • .NET,每分钟都有事件(每分钟)。计时器是最好的选择吗?

    我想使用 C 在 Windows 窗体应用程序中每分钟 按时钟 做一些事情 我只是想知道最好的方法是什么 我可以使用计时器并将其间隔设置为 60000 但要让它按分钟运行 我必须精确地按分钟启用它 这不太可行 我可以使用计时器并将其间隔设置
  • java.lang.SecurityException:权限拒绝:实现内容提供程序时打开提供程序

    我有问题 我尝试在我的消费者应用程序中实现内容提供程序 这是我来自应用程序 A 提供商 的 Android 清单
  • 以相反顺序打印 bash 参数

    我必须编写一个脚本 它将接受所有参数并反向打印它们 我已经提出了解决方案 但发现它非常糟糕 你有更聪明的主意吗 bin sh gt tekst txt for i in do echo i cat tekst txt gt temp mv
  • spring 3.0 MVC 似乎忽略 messages.properties

    Spring 3 0 MVC 首先 我没有找到任何有关 messages properties 的文档泉源我在各种论坛上发现了有关覆盖错误消息的所有内容 如果有人能参考 messages properties 的记录位置 那就太棒了 也许
  • MVC 3 和 DRY 自定义验证

    除非我遗漏了一些东西 这很有可能 否则在我看来 自定义验证总是违反 DRY 的 在我见过的所有示例中 即使使用 MVC 3 引入的全新非侵入式客户端验证 我们也必须为服务器端验证创建 NET 代码 并为客户端验证创建 jQuery 或 Ja
  • 我应该使用 HTML5 和 CSS3 吗?

    我是一个想要了解最新网络技术的人 但也很感激很多人仍然使用 IE6 7 8 如果一半内容在大多数浏览器上都无法显示 这是浪费代码 时间吗 这只是使用不同样式表的情况 还是只使用一个样式表 如果浏览器不支持文本阴影 那就搞砸了 他们可以看到它
  • 左填充猪中的一根绳子

    我想用 0 s 填充字符串数据类型字段 有什么办法可以做到这一点吗 我需要有固定长度 40 值 提前致谢 千里眼 零的数量需要根据剩余字符串的长度动态生成 所以我认为这在本地猪中是不可能的 这在 UDF 中是很有可能的 输入 txt 111
  • 在 Angular 2 中使用 Typescript 选择输入中的文本

    我正在尝试准确地执行中所描述的操作这个帖子 但是在 Angular2 中 基本上都是使用javascript函数 setSelectionRange start end 在用户单击触发器后的输入中 我找不到任何方法来使用 Typescrip
  • 如何将图片绘制到闭合曲线区域

    你好 我想在 onDraw Canvas canvas 中将图像的一部分绘制到闭合曲线上 我已经使用以下代码绘制了一条闭合曲线 油漆 setColor 颜色 红色 油漆 setAlpha 80 canvas drawPath turnpag
  • C++ #include 未找到

    当我在 Visual Studio Express 中编译 C 程序时 它说找不到atlbase h 我是否缺少一些 SDK 或者其他东西 视觉工作室 2017 When running the Visual Studio Installe
  • 基于表单的网站身份验证的权威指南[关闭]

    Closed 这个问题需要多问focused 目前不接受答案 这个问题的答案是社区努力 编辑现有答案以改进这篇文章 目前不接受新的答案或互动 版主注 这个问题不太适合我们的问答格式话题性规则目前适用于 Stack Overflow 对于内容
  • 如何访问FlipView内DataTemplate内的xaml控件

    我想访问 C 代码中的 图像 元素 我知道我无法直接访问它 因为它位于数据模板中 我已经尝试过视觉树 但仍然无法在代码中获取 图像 控制元素
  • 如何在 VS 负载测试之前设置 JWT 令牌

    我正在尝试运行 Visual Studio 负载测试 但在运行之前 我必须调用登录 webAPI 来生成 JWT 令牌 然后在所有 webAPI Web 测试中使用此令牌 我只需要调用一次登录即可生成令牌 我的所有其他 webAPI 调用中
  • 如何在.NET中不使用乘法运算符来实现乘法[关闭]

    很难说出这里问的是什么 这个问题模棱两可 含糊不清 不完整 过于宽泛或言辞激烈 无法以目前的形式合理回答 如需帮助澄清此问题以便重新打开 访问帮助中心 我想在 NET中实现两个整数的乘法而不使用乘法运算符 public uint Multi
  • 写入我的临时文件的权限被拒绝

    我正在尝试使用 Python 在 Windows 操作系统上创建并写入临时文件 我已经使用了Python模块tempfile创建一个临时文件 但是当我去写入临时文件时出现错误Permission Denied 我不允许写入临时文件吗 难道我
  • android.database.sqlite.SQLiteException:靠近“Group”:语法错误(代码1):

    Error Caused by android database sqlite SQLiteException near Group syntax error code 1 while compiling create table Grou
  • C#/Native:使用 SCSI PassThrough 读取 HDD 串行

    我编写了三种利用本机的不同方法CreateFile and DeviceIoControl调用以检索 HDD 序列号 而不是型号 第一个使用S M A R T 第二个使用Storage Query第三个使用SCSI PassThrough