アプリ版:「スタンプのみでお礼する」機能のリリースについて

ハードディスクやリムーバブルディスクなどストレージデバイスの容量を取得したいのですが
どうやって調べたらよいのでしょうか?

C言語、WindowsXP環境での方法を教えてください。
ちなみに、ディスクは未フォーマットで
全部0でクリアされている場合でも可能な方法が好みです。

A 回答 (6件)

参考までに、途中まで成功するコードを記述してみました。


#include<windows.h>
const GUID CLSID_Locator =
{0x76A64158,0xCB41,0x11D1,{0x8B,0x02,0x00,0x60,0x08,0x06,0xD9,0xB6}};
const GUID IID_Locator =
{0x76A6415B,0xCB41,0x11D1,{0x8B,0x02,0x00,0x60,0x08,0x06,0xD9,0xB6}};
LCID id;
//メソッドを実行する
HRESULT exec(IDispatch *p,OLECHAR *m,DISPPARAMS *s,VARIANT *r) {
  HRESULT retc = 0;
  DISPID disp = 0;
  retc = p->GetIDsOfNames(IID_NULL,&m,1,id,&disp);
  if( ! SUCCEEDED( retc ) ) return retc;
  VariantInit(r);
  retc = p->Invoke(disp,IID_NULL,id,DISPATCH_METHOD,s,r,NULL,NULL);
  return retc;
}
//プロパティを取得する
HRESULT getp(IDispatch *p,OLECHAR *m,VARIANT *r) {
  HRESULT retc = 0;
  DISPID disp = 0;
  retc = p->GetIDsOfNames(IID_NULL,&m,1,id,&disp);
  if( ! SUCCEEDED( retc ) ) return retc;
  VariantInit(r);
  DISPPARAMS s = {NULL,NULL,0,0};
  retc = p->Invoke(disp,IID_NULL,id,DISPATCH_PROPERTYGET,&s,r,NULL,NULL);
  return retc;
}
//中核処理
HRESULT sub(IDispatch *p) {
  HRESULT retc = 0;
  VARIANT rval;
  {
    DISPPARAMS param = {NULL, NULL, 0, 0};
    retc = exec(p,L"ConnectServer",&param,&rval);
  }
  if( ! SUCCEEDED( retc ) ) return retc;
  p = (IDispatch *)rval.ulVal;
  {
    VARIANT sql;
    sql.vt = VT_BSTR;
    sql.bstrVal = SysAllocString(L"SELECT * FROM Win32_DiskPartition");
    DISPPARAMS param = {&sql, NULL, 1, 0};
    retc = exec(p,L"ExecQuery",&param,&rval);
    SysFreeString(sql.bstrVal);
  }
  if( ! SUCCEEDED( retc ) ) return retc;
  p = (IDispatch *)rval.ulVal;
  retc = getp(p,L"Count",&rval);
  if( ! SUCCEEDED( retc ) ) return retc;
  int cnt = rval.ulVal;
  IDispatch *obj;
  for( int i = 0 ; i < cnt ; i++ ) {
    VARIANT pos;
    pos.vt = VT_I4;
    pos.uintVal = i;
    DISPPARAMS param = {&pos, NULL, 1, 0};
    retc = exec(p,L"Item",&param,&rval);//★ここで失敗する
    if( ! SUCCEEDED( retc ) ) return retc;
    obj = (IDispatch *)rval.ulVal;
  }
  return retc;
}
int WINAPI WinMain(HINSTANCE hi,HINSTANCE pi,LPSTR cp,int sw) {
  id = GetUserDefaultLCID();
  IDispatch *p = NULL;
  HRESULT retc;
  CoInitialize(0);//★必須
  retc = CoCreateInstance(CLSID_Locator,0, CLSCTX_INPROC_SERVER,
              IID_Locator, (void **)&p);
  if( SUCCEEDED( retc ) ) retc = sub(p);
  if( ! SUCCEEDED( retc ) ) {
    char msg[128];
    wsprintf(msg,"ERROR occured = %08x\n",retc);
    MessageBox(NULL,msg,"Error",0);
  }
  CoUninitialize();
  return 0;
}
ExecQueryに成功し、結果のオブジェクト数(Countプロパティ)を取得
するところまでは出来るんですが、やはり、For Each に相当する処理
が分かりません。オブジェクトには他にItemメソッド、Securityプロパティが
あります。後出しですが、Itemメソッドのパラメータに下記文字列を
指定すると、オブジェクトが取得でき、CaptionやSizeが取れます。
\\.\root\cimv2:Win32_DiskPartition.DeviceID="Disk #0, Partition #0"
でも、Diskが2個あるとか、パーティションがn個あるとどうなるか、
実際の環境が無いので、分かりません。上記文字列も結果を知ってから
コーディングしました。(だから後出しジャンケンなんですが・・・)
    • good
    • 0
この回答へのお礼

回答ありがとう御座います。

わざわざコードまで頂き大変有り難く思います。
なにやら、随分と難しそうですが、やはりディスクの情報なんかはディスクパラメータがない場合、
結構深いところまで探る必要があるわけですね。
OSがサービスを提供してくれるのはうれしいですが、
C言語でサクッと弄れるほど甘くはないですね。
知的好奇心はワクワクなのですが、
あまりに複雑怪奇だと結構時間が必要に思います。

スクリプトでサクッとファイルに出力してから
C言語側でファイルから情報を頂く感じで妥協するしかないですかね。

いやはや、ここまでしていただき感謝、感謝です。
本当にありがとう御座いました。

お礼日時:2009/01/23 03:47

思い出したんですが、以前にCOMコンポーネントをCからイジろうとして


挫折したことがあります。その時に参照したページを紹介します。
http://www.asahi-net.or.jp/~kv8s-yjm/another/yja …

WBemScripting.SWBemLocator のIDを載せておきます。
CLSID:76A64158-CB41-11D1-8B02-00600806D9B6
TYPELIB:565783C6-CB41-11D1-8B02-00600806D9B6
    • good
    • 0
この回答へのお礼

回答ありがとう御座います。

中々、興味深いですね。
COMの知識は殆ど無いので一朝一夕で出来るとは思いませんが、
じっくりと調べて後試してみたいと思います。

貴重な情報ありがとうございました。

お礼日時:2009/01/15 18:10

こんにちは。



物理ドライブのジオメトリ情報を取得することでも取得できますね。
CreateFileで "\\\\.\\PHYSICALDRIVEn"をファイルパスに指定することで、物理ドライブをオープンすることができます。

オープンできたらDeviceIoControlでIOCTL_DISK_GET_DRIVE_GEOMETRY_EXまたはIOCTL_DISK_GET_DRIVE_GEOMETRYを使って、希望の情報を取得できます。

開発環境によっては、Microsoft Windows SDKが必要かもしれません。
    • good
    • 0
この回答へのお礼

回答ありがとう御座います。

フォーマットされている場合には、ジオメトリ情報を読み込めますが
未フォーマットの状態では無理ですね。
ディスクパラメータも0で埋めてありますので、ディスクから情報を取り出すといった手法は取れません。

特に公開する訳でも無いので少々トリッキーな方法であっても
Win32APIを使ってC言語で組めればよいので
何か方法がありましたら、教えて頂けると幸いです。

お礼日時:2009/01/15 12:33

未フォーマットだと、ディスクにアクセスした時点でエラーが出てしまう気がするので。


WMIを使うのが簡単かと。

お使いのC言語からWMIを呼び出せるか分かりませんが。

スクリプトですけど以下のサイトが参考になると思います。
11番目のWin32_DiskDriveのスクリプトを読んでみてください。

http://www.anchorsystems.jp/anchor/ashp/netmon/s …
    • good
    • 0
この回答へのお礼

回答ありがとう御座います。

大変参考になるWebサイトを教えていただき感謝いたします。

他にも色々あるようですので、じっくり見て学習していきたいと思います。

お礼日時:2009/01/15 12:24

>ディスクは未フォーマット


フォーマットされていないと、「ドライブ」として認識されていない
ので、ドライブコード("C:"など)やディレクトリ名をパラメータと
するAPIは使用不可能です。
こういう場合はWMIを使って情報を収集します。

'★注意 == インデントに漢字空白を使用しています ==
Dim Q, A
Set Q = CreateObject("WBemScripting.SWBemLocator"). _
    ConnectServer("."). _
    ExecQuery("SELECT * FROM Win32_DiskPartition")
For Each A In Q
  WScript.Echo "Name=""" & A.Caption & """" & _
  ",Size=" & CStr(A.Size)
Next

上記をコピペし、漢字空白を半角空白に変換してから、x.vbsとして
保存します。次にコマンドプロンプトから cscript x.vbs と入力
します。
結果は見てのお楽しみということで、必要な情報のヒントが得られる
のではないかと思います。実は上記オブジェクト(A)には34個の
プロパティがありまして、他に質問者さんの知りたそうなネタが
あるのですが、全部は紹介しきれませんので、ご了承ください。
WMIには他にデバイス情報、ディスク関連の種情報を得るものなどが
多数あります。("Win32_DiskPartition"以外に沢山あるということ)
他情報のオブジェクトにも多数のプロパティがあるので、調べれば
大抵のことは知ることができます。検索キーワードは"WMI"です。

尚、VBScriptなので、For Each 文でプロパティ名が不明であっても
内容を取得できますが、C言語でこれをやる方法を寡聞にして知り
ません。こちらは別途、お調べください。
    • good
    • 0
この回答へのお礼

回答ありがとう御座います。

できました。
こんな面白い機能があったなんて驚きです。
もっと詳しく知りたいですが、そこは自分で勉強いたします。

コマンドラインから情報を取得するのは自分で何とかできそうです。
ただ、C言語で同じようなことをするにはどうするんでしょうね。
色々調べて見たいと思います。

大変ありがたい情報、感謝いたします。

お礼日時:2009/01/15 12:20

>C言語、WindowsXP環境での方法を教えてください。


「C言語」だけではありません。

開発環境として「VisualStudio」を使用していれば「GetDiskFreeSpaceEx」あたりが使用できるかもしれませんが、
それ以外の開発環境については専用のライブラリ等は知りません、
    • good
    • 0
この回答へのお礼

回答ありがとう御座います。

説明不足で申し訳ありません。
WindowsXPでWin32APIを使用できるC言語環境です。

VisualSutdioは使用していませんが、Win32APIは使えるので
教えていただいた関数を使ってみました。

>test.exe
このボリュームは認識可能なファイル システムではありません。
必要なファイル システム ドライブがすべて読み込まれているか、ボリュームが壊れていないか確認してください。

と詳細なエラーを吐き出しました。
ファイルシステムはゼロ・クリアしてあるので読み込めないようです。
ためしに他のボリュームを指定したところ上手く読み込めました。
これはこれで、勉強になりました。
ありがとうございます。

未フォーマットのディスクの容量を調べられる方法もありましたら
よろしくお願いいたします。

お礼日時:2009/01/15 12:12

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!