C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[4]: 内蔵か外付けを判別する方法


(過去ログ 168 を表示中)

[トピック内 5 記事 (1 - 5 表示)]  << 0 >>

■97332 / inTopicNo.1)  内蔵か外付けを判別する方法
  
□投稿者/ 常磐 (1回)-(2021/04/26(Mon) 19:36:06)

分類:[.NET 全般] 


C#あるいはVB.NETを使って、

あるドライブレターのドライブが
内蔵ストレージか外付けストレージかどうかを
調べたいのですが、
どのようなコードでできますでしょうか?

試してはいないですが
https://oshiete.goo.ne.jp/qa/2988779.html

ここのコードを使えば、
全てのストレージの列挙はできると思うのですが
指定したドライブレターに関して調べるにはどのようにしたら良いですか?




引用返信 編集キー/
■97335 / inTopicNo.2)  Re[1]: 内蔵か外付けを判別する方法
□投稿者/ 魔界の仮面弁士 (3086回)-(2021/04/26(Mon) 23:07:25)
No97332 (常磐 さん) に返信
コマンドラインから、
「wmic diskdrive list brief」
を実行したときのような結果を求めているのでしょうか。


> 試してはいないですが
> https://oshiete.goo.ne.jp/qa/2988779.html
> ここのコードを使えば、

これは WMI ですね。

自身の環境で列挙可能な内容を知りたければ、PowerShell で
「Get-WmiObject Win32_DiskDrive」
「Get-WmiObject Win32_LogicalDisk」
「Get-WmiObject Win32_DiskPartition」
「Get-WmiObject Win32_LogicalDiskToPartition」
「Get-WmiObject Win32_DiskDriveToDiskPartition」
「Get-WmiObject Win32_Volume」
などを実行してみてください。

それらで得られる情報で足りるようであれば、C# や VB から
System.Management 名前空間のクラスを使って調べられるかと思います。


> 全てのストレージの列挙はできると思うのですが
> 指定したドライブレターに関して調べるにはどのようにしたら良いですか?

物理ディスクと論理ドライブは、多対多の関係になりまえますよね。

たとえば物理 Disk #0 と 物理 Disk #1 が RAID 構成になっていて、
その論理ディスクにパーティションを切って 3 つに分割したとしましょう。
それぞれのパーティションに、D: と E: と F: のドライブレターを割り当てていた場合、
どのような結果を得たいですか?


> あるドライブレターのドライブが
> 内蔵ストレージか外付けストレージかどうかを
> 調べたいのですが、

まず、論理ドライブのマウントに関する問題があります。

RAID 構成の場合、複数の物理ドライブが一つのドライブレターを構成することがあります。
極端な例では、VHD を介して、外付けの HDD と内蔵の HDD で RAID を組むこともできます。
http://mtkdt.blog.fc2.com/blog-entry-66.html

あるいはストレージが、ドライブではなくフォルダーにマウントされるケースもありえますので、
D:\ と D:\Example が別のストレージというケースをどう考えるのかという問題もあります。
https://www.atmarkit.co.jp/ait/articles/0002/05/news001.html



そもそも、何をもってして「内蔵」か「外付け」かを判断するのかという話も出てきます。
https://www.dospara.co.jp/5shopping/detail_parts.php?bg=7&br=221&sbr=1071&mkr=2523&ic=437733&lf=0
https://my-best.com/6906

内蔵/外付けというのは、PC に対する物理的な配置を指すものであるため、OS からでは必ずしも区別できないため、
プログラムだけで判断するのではなく、ユーザー判断を伴わせるのが良いかも知れません。


たとえば SD カードの場合。
複数枚を RAID で束ねて 1 台のドライブとして扱える製品がありますが、
下記は PC 内部に装着するので、内蔵扱いと考えられます。
https://news.mynavi.jp/article/20140127-55kbdssd/

では、デスクトップ PC のシャドウベイに搭載されたカードリーダーはどうでしょうか。
リムーバブルメディアという点で見れば外付けという見方もできますし、
リーダーそのものは内蔵であるともいえるので、定義としては曖昧になります。

また、PC に内蔵されたリーダーであっても、その接続インターフェイスが USB であった場合には、
OS 側から見た場合には、外付けの USB カードリーダーと見分けがつかない可能性があります。

あるいは Wi-Fi 接続型の SD カードリーダーもありますが、これは外付けですかね。
引用返信 編集キー/
■97337 / inTopicNo.3)  Re[2]: 内蔵か外付けを判別する方法
□投稿者/ 常磐 (3回)-(2021/04/27(Tue) 14:05:57)
> 自身の環境で列挙可能な内容を知りたければ、PowerShell で

列挙はできるのですが、
ある程度ドライブレターがどのドライブに属しているかは
どのように調べれば良いですか?




> 物理ディスクと論理ドライブは、多対多の関係になりまえますよね。

すいません、
RAIDとかWi-Fi は無しで

SATA接続のHDDあるいはSSDか
USB接続のHDDあるいはSSDかだけを認識できれば十分です。
それ以外はその他あるいはunknownとして認識できれば良いです。








引用返信 編集キー/
■97345 / inTopicNo.4)  Re[3]: 内蔵か外付けを判別する方法
□投稿者/ 魔界の仮面弁士 (3089回)-(2021/04/28(Wed) 02:58:11)
No97337 (常磐 さん) に返信
> ある程度ドライブレターがどのドライブに属しているかは
> どのように調べれば良いですか?

目視確認なら
 diskmgmt.msc
で行えますね。

物理ドライブとして、ディスク 0、ディスク 1、ディスク 2 …という情報があり、
それぞれに対して、パーティションが切られています。RAID のケースもあるため、これらは多対多の関係になりえます。

そして、そのパーティション領域に対してドライブレターやフォルダーが割り当てられることになりますね。
これらの情報は、 No97335 で列挙した WMI のクラスを使って取得できます。


> ある程度ドライブレターがどのドライブに属しているかは

「物理ディスクのパーティション領域」を表すのが【Win32_DiskPartition クラス】、
「ハードディスクの記憶域」を表すのが【Win32_Volume クラス】、
「物理ディスク ドライブ」を表すのが【Win32_DiskDrive クラス】、
「論理ディスク(および、マップ)」が【Win32_LogicalDisk クラス】


「論理ディスクがあるディスク パーティション」(Win32_DiskPartition) と、
「物理ディスクのパーティションにある論理ディスク」(Win32_LogicalDisk) の関連付けを表すのが
【Win32_LogicalDiskToPartition クラス】

「パーティションが存在するディスク ドライブ」(Win32_DiskDrive) と、
「ディスク ドライブにあるディスク パーティション」(Win32_DiskPartition) の関連付けを表すのが
【Win32_DiskDriveToDiskPartition クラス】です。


ドライブレターから、物理ディスク装置を辿るには、
 Win32_LogicalDisk
→ (Win32_LogicalDiskToPartition)
→ Win32_DiskPartition
→ (Win32_DiskDriveToDiskPartition)
→ Win32_DiskDrive
のように辿っていけば、目的を果たせるかと思います。

ただし、それらの装置が外付けか内蔵かは、PC に対する物理的な搭載位置でしか分かりません。
WMI で得られるインターフェイス情報などから推測することはできそうですが、最終的には人力判定ですね。


そして WMI を扱うには、最初に御提示頂いた 教えて!goo の回答にもあったように、
System.Management を参照設定して、ManagementObjectSearcher などからアクセスすることができます。

また、WMI のクラスをプログラムから扱いやすくするため、MgmtClassGen.exe という
クラス ジェネレーターを使えます。これは、WMI 操作のためにカプセル化されたクラスを生成するツールです。
https://docs.microsoft.com/ja-jp/dotnet/framework/tools/mgmtclassgen-exe

上記ツールは、Visual Studio コマンド プロンプトから、「MgmtClassGen Win32_DiskDrive」などとすることで
Win32_DiskDrive.cs ファイルが生成されます。パラメーターを指定すれば VB 版も作れます。

こうして生成した .cs ファイル群をプロジェクトに加えてやれば、
IntelliSense が使えますし、列挙情報も enum 化されるので、コーディングも容易です。


参考までに、この *.cs ファイルを使って、ディスク情報を単純列挙するコードを書いてみます。
(参照設定に System.Management も必要です)
Win32_DiskDrive の情報に、内蔵/外付けの判定に使えそうな内容が含まれているか確認してみてください。



using System;
using ROOT.CIMV2.Win32; // この名前空間は、MgmtClassGen.exe で生成されたクラスに含まれています。

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("★★Win32_LogicalDisk (論理ディスク)");
        Console.WriteLine("☆☆ドライブレターを持つ論理ディスクの情報です。ネットワークドライブや DVD ドライブも含みます。");
        foreach (LogicalDisk item in LogicalDisk.GetInstances())
        {
            Console.WriteLine("DeviceID={0}", item.DeviceID);               // 識別子(ドライブレター)
            Console.WriteLine(" FileSystem={0}", item.FileSystem);         // 論理ディスクのファイル システム
            Console.WriteLine(" DriveType={0}", item.DriveType);           // 論理ディスク ドライブの種類
            Console.WriteLine(" MediaType={0}", item.MediaType);           // 論理ドライブに現在あるメディアの種類
            Console.WriteLine(" VolumeName={0}", item.VolumeName);         // 論理ドライブのボリューム名
        }
        Console.WriteLine();
        Console.WriteLine("★★Win32_DiskDrive (物理ドライブ)");
        Console.WriteLine("☆☆HDDやSSDの物理ドライブの情報です。論理ディスクに割り当てられていないドライブも含みます。");
        foreach (DiskDrive item in DiskDrive.GetInstances())
        {
            Console.WriteLine("Index={0}", item.Index);                     // 物理ドライブ番号
            Console.WriteLine("DeviceID={0}", item.DeviceID);               // 識別子
            Console.WriteLine(" Partitions={0}", item.Partitions);         // 物理ドライブのパーティション数
            Console.WriteLine(" InterfaceType={0}", item.InterfaceType);   // 物理ディスク ドライブのインターフェイスの種類
            Console.WriteLine(" MediaType={0}", item.MediaType);           // メディアの種類
            Console.WriteLine(" Model={0}", item.Model);                   // ディスク ドライブ製造元のモデル番号
            Console.WriteLine(" SerialNumber={0}", item.SerialNumber);     // 製造元が割り当てた物理メディアの識別番号
            Console.WriteLine(" Manufacturer={0}", item.Manufacturer);     // ディスク ドライブ製造元名
        }
        Console.WriteLine();
        Console.WriteLine("★★Win32_Volume (ハードディスクの記憶域の領域)");
        Console.WriteLine("☆☆HDDやSSDの記憶域の領域です。未フォーマットや非マウント状態のパーティション領域も含みます。");
        foreach (Volume item in Volume.GetInstances())
        {
            Console.WriteLine("DeviceID={0}", item.DeviceID);               // 識別子
            Console.WriteLine("DriveLetter={0}", item.DriveLetter);         // ドライブレター
            Console.WriteLine(" DriveType={0}", item.DriveType);           // 論理ディスクが表すディスク ドライブの種類
            Console.WriteLine(" FileSystem={0}", item.FileSystem);         // 論理ディスクのファイル システム
            Console.WriteLine(" Label={0}", item.Label);                   // 論理ディスクのボリューム名
            Console.WriteLine(" SerialNumber={0}", item.SerialNumber);      // ボリュームのシリアル番号
        }
        Console.WriteLine();
        Console.WriteLine("-- Push Enter Key --");
        Console.ReadLine();
    }
}


上記では単純に全列挙としていますが、たとえば C: ドライブの Win32_LogicalDisk だけを得たいような場合には、
 foreach (LogicalDisk logical in LogicalDisk.GetInstances(@"DeviceID='C:'"))
のように、条件を指定して問い合わせることもできます。


また、今回のケースでは Win32_LogicalDiskToPartition と Win32_DiskDriveToDiskPartition を使って、
該当ドライブレターのパーティションを持つ物理ドライブ(RAID の場合は複数になりえる)を探ることになります。

パーティションを辿って取得する方法は、過去ログ No82538 で述べているので、そちらも参照してみてください。
http://bbs.wankuma.com/index.cgi?mode=red&namber=82538&KLOG=141

引用返信 編集キー/
■97352 / inTopicNo.5)  Re[4]: 内蔵か外付けを判別する方法
□投稿者/ 常磐 (4回)-(2021/04/28(Wed) 20:59:54)
ありがとうございます。

試してみたのですが、
Win32_DiskDriveのInterfaceTypeで認識できるような気がします。

しかし、返り値が変です。

内蔵のSATAだとIDE
外付けのSATAだとSCSI
外付けのUSBメモリーだとUSB

を返します。

IDEとかSCSIって昔の規格だと思うのですが
なぜこのような値を返すのでしょうか???

引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -