none
ドライブの名前(ex.Hitachi HDT21010SLA360 ATA Device)を取得する方法は? RRS feed

  • 質問

  • こんにちは。

    USB接続されたリムーバブルディスクを操作するプログラムを作ろうとしています。
    対象のディスクを判定するために、ドライブの名前(ex.Hitachi HDT21010SLA3
    60 ATA Device)を取得したいのですが、方法がわかりません。

     DriveInfoクラスを用いた方法では取得できず、WMI("Win32_LogicalDisk")の
    プロパティにも該当するものがありませんでした。
     ご存知の方、教えていただけますようお願いいたします。

    よろしくお願いします。
    2010年2月8日 13:37

回答

  • ドライブ(ボリューム)は論理的なものであり、物理的なディスクドライブとは切り離されてます。
    具体的に言うと、パーティションなどによって一つの HDD を複数のボリュームに分けることができますし、RAID やスパンボリュームなどによって複数の HDD を一つのボリュームにすることもできます。これらを組み合わせることも。
    なので、「ドライブから HDD の名前」は難しい話です。一つに絞ることができないので。

    さて、.NET Framework の標準ライブラリでは論理レベルのものまでしか扱えません。そのため、Win32API なり WMI なりの利用が必要になります。
    Win32API の場合 DeviceIoControl 関数であれこれできるようですが、この辺を使うのには管理者権限が必要なため扱いづらいものになっています。
    そこで WMI を使って調べる方法を考えました。
    Win32_LogicalDiskToPartition クラスを使えば、論理ドライブとパーティションの組み合わせを取得することができます。ディスクのパーティションの示すクラス Win32_DiskPartition には DiskIndex プロパティがあり、これは物理ドライブのドライブ番号を指します。そこでドライブ番号を元に Win32_DiskDrive を取得し、目的のプロパティを取得します(多分 Model プロパティです)。
    // RAID やスパンボリュームでどうなるかは検証していませんが。

    葛藤プログラマの一日 - USBメモリのドライブの確認方法

    ここが参考になると思います。最終的な目的は異なりますが、大筋は同じです。
    2010年2月8日 17:24

すべての返信

  • ドライブ(ボリューム)は論理的なものであり、物理的なディスクドライブとは切り離されてます。
    具体的に言うと、パーティションなどによって一つの HDD を複数のボリュームに分けることができますし、RAID やスパンボリュームなどによって複数の HDD を一つのボリュームにすることもできます。これらを組み合わせることも。
    なので、「ドライブから HDD の名前」は難しい話です。一つに絞ることができないので。

    さて、.NET Framework の標準ライブラリでは論理レベルのものまでしか扱えません。そのため、Win32API なり WMI なりの利用が必要になります。
    Win32API の場合 DeviceIoControl 関数であれこれできるようですが、この辺を使うのには管理者権限が必要なため扱いづらいものになっています。
    そこで WMI を使って調べる方法を考えました。
    Win32_LogicalDiskToPartition クラスを使えば、論理ドライブとパーティションの組み合わせを取得することができます。ディスクのパーティションの示すクラス Win32_DiskPartition には DiskIndex プロパティがあり、これは物理ドライブのドライブ番号を指します。そこでドライブ番号を元に Win32_DiskDrive を取得し、目的のプロパティを取得します(多分 Model プロパティです)。
    // RAID やスパンボリュームでどうなるかは検証していませんが。

    葛藤プログラマの一日 - USBメモリのドライブの確認方法

    ここが参考になると思います。最終的な目的は異なりますが、大筋は同じです。
    2010年2月8日 17:24
  • HongLiangさん、ご回答ありがとうございます。

    知識がなくて、ご回答を把握するところまでいっていません。すみません。
    理解・検証後、改めてお返事させていただきます。

    2010年2月9日 11:05
  • HongLiangさん、改めまして回答ありがとうございました。
    呈示いただいたサイトをよみつつ、当初の目的は果たすコードとなったようです。

    >ディスクのパーティションの示すクラス Win32_DiskPartition には DiskIndex プロパティがあり、これは物理ドライブのドライブ番号を指します。
    >そこでドライブ番号を元に Win32_DiskDrive を取得し、

     ここのところが少し難解で自信がないのですが...

    Win32_DiskDriveのName

    Win32_DiskPartitionのDiskIndexに"PHYSICALDRIVE"を付加した物

    が一致していれば対象の物理ドライブの論理ドライブだと判定しています。

    //1論理ドライブに対して、二つ以上のハードウェアが対応することは気がついていませんでした。残念ながらハードがないので実験できません。


                //
                // ポメラドライブの検索
                //
                //Win32_DiskDriveオブジェクトの取得 
                ManagementObjectSearcher disks = new ManagementObjectSearcher("SELECT * FROM Win32_DiskDrive");
                
                foreach (ManagementObject disk in disks.Get()){         //全ての物理ドライブに対して
                    string diskName = disk["Name"].ToString();          //物理ドライブ名 ex."\\\\.\\PHYSICALDRIVE1"
                    string diskModel = disk["Model"].ToString();        //ハードウェア名 ex."Hitachi HDT721010SLA360 ATA Device"
    
                    if ((diskModel == "DM10 USB Device")            //ポメラDM10 未デバッグ
                        || (diskModel == "DM20 USB Device")         //ポメラDM20
                        || (diskModel == "DM30 USB Device"))        //ポメラDM30 未デバッグ
                    {
                        //
                        //  ポメラの接続されている論理ドライブを検索する。
                        //
    
                        //LogicalDiskToPartitionオブジェクトの取得
                        ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT * FROM Win32_LogicalDiskToPartition");
    
                        foreach (ManagementObject mo in searcher.Get())  //LogicalDiskToPartitionオブジェクト全て
                        {
                            //論理ドライブを取得
                            string logicakDiskPartitionInfo = mo["Dependent"].ToString();
                            ManagementObject dm = new ManagementObject(logicakDiskPartitionInfo);
                            string driveLetter = dm["DeviceID"].ToString(); //論理ドライブ名 ex."C:"
    
                            //物理ドライブを取得
                            string physicalDiskPartitionInfo = mo["Antecedent"].ToString();
    
                            // Win32_DiskPartitionオブジェクトの取得
                            ManagementObject pd = new ManagementObject(physicalDiskPartitionInfo);
                            string driveNumber = pd["DiskIndex"].ToString();        //物理ドライブ番号 ex."0"
    
                            //ポメラのドライブか?
                            if (diskName == "\\\\.\\PHYSICALDRIVE" + driveNumber)   //ポメラの論理ドライブであれば
                            {
                                //Console.WriteLine("{0}", driveLetter);              //コンソールにドライブ名を出力する。
                            }
    
    
                        }
    
                    }//ポメラのドライブでなければ
                    else
                    {
                        continue;   //次の物理ドライブにいく。
                    }
    
    2010年2月9日 14:30
  • System.IOによるドライブ検査

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.IO;

    private void button1_Click(object sender, EventArgs e)
            {
                string DName = "";
                string Drive = textBox1.Text;
                DriveInfo DRInfo = new DriveInfo(Drive);
                textBox2.Clear();
                textBox3.Clear();
                textBox4.Clear();
                textBox5.Clear();
                textBox6.Clear();

                DName = (DRInfo.Name).ToString();
                textBox3.Text = DName;

                string TypeD = "";

                switch (DRInfo.DriveType)
                {
                    case DriveType.CDRom:
                        TypeD = "CD-ROM,DVD-ROM,CD-RAM,DVD-RAM"; //RAMかROMの判別はできない
                        break;
                    case DriveType.Fixed:
                        TypeD = "HDD";
                        break;
                    case DriveType.Network:
                        TypeD = "NetWorkDisk";
                        break;
                    case DriveType.NoRootDirectory:
                        TypeD = "Diskが存在しない";
                        break;
                    case DriveType.Ram:
                        TypeD = "RAMDisk";
                        break;
                    case DriveType.Removable:
                        TypeD = "FDやRemovable";
                        break;
                    case DriveType.Unknown:
                        TypeD = "不明";
                        break;
                    default:
                        break;
                }
                textBox2.Text = TypeD;
                string VolLabel = "";
                //ドライブの準備ができているかどうかの検査
                if (DRInfo.IsReady)
                {
                    textBox7.Text = "使用中";
                    VolLabel = (DRInfo.VolumeLabel).ToString();
                    if (string.IsNullOrEmpty(VolLabel))
                    {
                        textBox4.Text = "VolimeLabel無し";
                    }
                    else
                    {
                        textBox4.Text = VolLabel;
                    }
                    textBox5.Text = (DRInfo.DriveFormat).ToString();
                    textBox6.Text = (DRInfo.RootDirectory).ToString();
                }
                else
                {
                    textBox7.Text = "未使用状態";
                    textBox4.Text = "未使用状態";
                    textBox5.Text = "未使用状態";
                    textBox6.Text = "未使用状態";
                }
                
            }

    --------------------------------------------------------------------------------
    WMIのLogicalDiskToPartitionクラスによるドライブ検査

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Management;

    namespace LogiDiskTest
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }

            private void button1_Click(object sender, EventArgs e)
            {
                //WMIのWin32_LogicalDiskToPartitionクラスによるドライブ検査
                
                bool Ans = true;
                string Drive = textBox1.Text;
                Ans = CheckDriveUSBOrRemovable(Drive);
                textBox2.Clear();
                textBox2.Text = Ans.ToString();
            }

            public bool CheckDriveUSBOrRemovable(string drive)
            {
                //driveを検査してUSB接続ならばTrueを返すルーチン
               
                bool Ans = false;
                string[] PInfo = new string[0];
                string DLetter = "";
                string LogiDPInfo = "";
                ManagementObjectSearcher Search = new ManagementObjectSearcher("SELECT * FROM Win32_LogicalDiskToPartition");

                foreach (ManagementObject Mo in Search.Get())
                {
                    LogiDPInfo = Mo["Dependent"].ToString();
                    ManagementObject Dm = new ManagementObject(LogiDPInfo);
                    DLetter = Dm["DeviceID"].ToString();
                    UInt32 DriveType = (UInt32)Dm["DriveType"];
                    //string caption = Dm["Caption"].ToString();
                    //string description = Dm["Description"].ToString();

                    if (DLetter != drive)
                    {
                        continue;
                    }
                    else
                    {
                        ;
                    }
                    if (DriveType == 3) //固定ドライブかどうかの確認(5=CDやDVD 3=HDD 4=ネットワークDrive 1=存在しない 6=RAMディスク 2=リムーバブルディスクFDやUSBメモリー 0=不明)
                    {
                        Ans = true; //外付け内臓の区別が付けられない、全て、HDDだと言う検査結果になる
                        break;
                    }
                    else
                    {
                        Ans = false;
                        break;
                    }
                }
                return Ans;
            }
        }
    }

    ----------------------------------------------------------------------------------------------
    以上の様に、USB接続かどうかは、System.IOでもWMIのLogicalDiskToPartitionクラス検査できません。
    https://dobon.net/vb/dotnet/file/driveinfo.html←参考になると思います。

    http://dev-hijiki.blogspot.com/2007/12/private-bool-checkdriveletterusbandremo.html
    ↑このサイトのは、動いていません。C:がfalseになりますし、USB接続のHDDがtrueになりますが、ループを途中で抜けてごまかしているだけです。

    USB接続のHDDであるかどうかを検査する方法は、二つあります。
    一つ目は、LogicalDiskToPartitionクラスの上位にある、WMIそのもので、USB接続かどうかを検査す事でUSB接続HDDであるかどうかを検査する方法。
    二つ目は、System.IOか、WMIのLogicalDiskToPartitionクラス検査で、HDDかどうかを検査して、WMIそのもので、USB接続かどうかを検査し、両方が真の場合、USB接続のHDDであると言う検査を行う方法です。
    • 編集済み Wupu One 2019年4月19日 20:52
    2019年4月19日 16:34