こんにちは、はじめまして。
指定された二つのパーテーション(例えばC:とD:)が物理的に同じハードディスク内
にあるパーテーションなのか
それぞれ別のハードディスクにあるパーテーションなのかを判断する必要があるのですが
実現方法が分からず困っています。
方針として、ドライブレター又は「\Device\HarddiskVolume2」などの情報から「\Device
\Harddisk2」のような情報を取得するか
もしくはシリアルナンバーのようなドライブ固有の情報を取得できれば良いと思ったので
すが、どちらも詰まってしまいました。
ドライブの情報の取得という点でもう少し深く調査してみようとは思っていますが、もっ
とスマートな方法があるのではないかと質問致しました。
何か良い方法はありませんでしょうか?
実行環境はWindows2000,XP,Vista以降に限定しています。
開発環境はVisualC++2005です。
GetVolumeInformation
で取得できるシリアルNoでは判断できませんか?
char volumeName[512], fileSystem[512];
unsigned long SirialNo;
GetVolumeInformation(d:\\, volumeName, 512, &SirialNo, 0, 0,
fileSystem, 512);
TRACE(SirialNo = %x\n, SirialNo);
配列のサイズ(512)は適当です。
な さん、御回答ありがとうございます。
GetVolumeInformation()でシリアル番号を取得してみたのですが、論理ドライブのシリア
ル番号が返ってきているような気がします。
(すいません間違っていたらご指摘願います)
手元でやってみたところ同じドライブ上のパーテーションでも違う値が返ってきます。
物理ドライブ固有の情報を取得する方法はありませんでしょうか?
面倒ですが方法のうちの1つとして。
WMIのWin32_DiskDriveToDiskPartitionを使えば、物理ディスク中に含まれる
パーティションが取得できるはずです。
但し、パーティションが必ずしもドライブレターが割りあたっているとは限らない
ためにWin32_DiskPartition→ドライブレターが取得できなかったと思います。
この点については「Win32_DiskPartition Drive Letter」辺りのキーワードで
ググると変換方法が見つかると思います。
(結局、ローレベルなネイティブプログラムになったかと。)
# 管理ツールの「ディスクの管理」は物理デバイスに対して直接IOCTLを飛ばしてる
# 気がします。
RAIDとかどうするんだろ。
追加です。
一応、WMIのみで「ドライブレター → 論理ディスク番号」の取得は可能な
ようです。方法は以下のとおり。(@ VB6.0から確認, VC++でも可能かと。)
1. Win32_LogicalDiskを取得 (DriveTypeが0x03のみ)
2. インスタンスから連想クラスであるCIM_StorageExtentを取得
3. Win32_LogicalDisk.Captionがドライブレター
CIM_StorageExtent.DiskIndexが論理ディスク番号
自環境では、1論理ディスクを3パーティションで使用しているので以下のような結果。
PhysicalDisk -> C: -> 0
PhysicalDisk -> D: -> 0
PhysicalDisk -> E: -> 0
但し、方法的に2点ほど問題がありまして
・Win2000上ではエラーが発生 (開発環境が入ってないので特定できず)
・フロッピーシークが発生する
Win32_LogicalDiskの取得時にシークが入るのはわかりますが、CIM_StorageExtentを
取得時にシークが入るのは謎です。(MS仕様?)
Win32_DiskDriveToDiskPartitionからも同様に取得できると思われますが、この点は
未確認です。(クラス派生確認上は問題なさ気です)
結局は、無理してWMIのみで取得するかどうか、に尽きてしまいそうな方法ですが。
# いい加減、VC++からのWMI操作を覚えないといけないですね。
> RAIDとかどうするんだろ。
以前にBelutionでも別の方からJBODの時にどのようになるか、という指摘が
ありましたね。
結局、自前環境では不可能なので空中に浮いたままです。orz
僕の知っている限りだと、WMIは結構複雑です。
SDKが対応しているみたいですね。
じじゃんぬねっとさんが回答してます。
> http://dobon.net/vb/bbs/log3-17/10246.html
修正です(^^;
じゃんぬねっとさんですね。
玲音さん、シャノンさん、ITOさん、ご回答ありがとうございます。
玲音さんに教えて頂いた情報を元に調べたところ以下のようなページを発見しWMIで欲し
い情報が取得できそうなことがわかりました。
[論理ドライブと物理ディスクを相互に関連付ける方法はありますか]
http://www.microsoft.com/japan/technet/scriptcenter/resources/qanda/may05/hey0523.mspx
管理者権限がないと実行できなさそうなことが難点ですが、それは仕方ないんでしょうね。
VCでのWMIは使ったことがないのですが、この方向で実装をしてみようと思います。
ありがとうございました。
URL案内ありがとうございます。
先に自分が行った方法はWQLではなく、WMIライブラリのSWbemServices.InstanceOf()や
SWbemObject.Associators_()を直接使っていたため複雑になったようです。
参考にさせていただきたいと思います。m(__)m
玲音さん、ありがとうございます。
前回書いたURLのスクリプトと同じ処理をVCで書いて無事情報の取得ができましたの
で一応報告いたします。
ソースはいい加減に書いたためか長くなりすぎて貼り付けられませんでした。
スクリプトの順番どおりにExecQueryを3回行っただけです。
このままだとHDD以外もシークしてしてしまい処理が返ってくるまで結構時間がかかっ
てしまうので改造が必要そうですが・・・。
あまり理解できずに書いてしまったので苦戦しそうですが、これを機会に勉強してみます。
ありがとうございました。
このままだとHDD以外もシークしてしてしまい処理が返ってくるまで結構時間がかか
っ
てしまうので改造が必要そうですが・・・
引用で誤送信してしまった orz
> このままだとHDD以外もシークしてしてしまい処理が返ってくるまで
> 結構時間がかかってしまうので改造が必要そうですが・・・
WQLを色々考察しましたが、恐らくは不可能です。
ポイントとなるのはやはり、「ASSOCIATORS OF」であり、これによって
{ }にあるキーとなるクラスを持つ全てのクラスを引き当てます。
この時点で、Win32_LogicalDiskクラスに対して検索が入り、シークが
発生するのだと予測されます。
だからといって、「ASSOCIATORS OF」無しに論理ディスクからドライブレターを
引き当てる(or その逆)方法がないのですよね・・・。
これ以上の改善となると、WMIではない手段になるような気がします。
HDD以外をスキップしてみましたが、玲音さんのおっしゃるとおり、ドライブレターを
探すところで時間がかかってしまいますね・・・。
調べたい二つのボリュームのシリアル番号と前回のボリュームと物理ディスクの対応付け
結果を記憶しておき、シリアル番号が変わっていたときのみもう一度処理を行うようにし
て回避したいと思います。
そうそう頻繁にドライブレターが割り当てられたディスクが変更されることもないでしょ
うから実用上は問題なさそうです。
ちなみに私の環境でWMIによる処理にかかる時間は1000ms程度のようです。
物理ディスク1
-C:
-D:
物理ディスク2
-E:
物理ディスク3 USBカードリーダ
物理ディスク4 USB接続
-F:
色々と試していただきましてありがとうございました。