USBメモリを安全に取り外すには?

解決


take  2010-05-13 22:34:33  No: 38437

XPでタスクバーを隠して前面表示するアプリケーションを作成しています。
その機能としてUSBメモリに出力することがあるのですが、出力した後安全に取り外したいのですが、タスクバーを隠しているため操作できません。

ボタン1つでUSBメモリを安全に取り外せる状態にしたいのですが、なにか良い方法はありますでしょうか?


KHE00221  2010-05-13 23:25:48  No: 38438

ハードウェアの安全な取り外し
rundll32 shell32.dll,Control_RunDLL hotplug.dll


ぽむぽむ  2010-05-14 01:00:13  No: 38439

SetupDiGetClassDevs でデバイスを読み込み準備?

SetupDiEnumDeviceInfoで順にデバイスを列挙する

CM_Get_DevNode_Statusでデバイスがリムーバブルか判定する
ついでに、必要ならGetDeviceStatusNameでクラス名に「USB」が含まれているか判断する。

デバイス名はCM_Get_DevNode_Registry_Propertyで取得

CM_Request_Device_Eject でイジェクトする

こんな感じで、Cfg.h、SetupApi.h、CfgMgr32.h とかのDelphi用ユニットが別途必要かな?


take  URL  2010-05-14 01:17:42  No: 38440

KHE00221様、ぽむぽむ様返信ありがとうございます。

提示していただいたキーワード(CM_Request_Device_Eject)で検索をかけると
USBデバイス取り外しのDelphi用サンプルプログラムが見つかりました。

http://okapony.hp.infoseek.co.jp/download/delphi/tips3.html

かなりのコード量ですが、このサンプルクラスから取り外しが出来るようです。
早速明日から取りかかりたいと思います。


take  2010-05-14 02:06:11  No: 38441

意外と簡単に対応できました。
クラスの作成者にも感謝です。

USBDev.pasをプロジェクトに加えて
FormのPrivateクラスに
  private
    { Private 宣言 }
    FUsbDevices : TDeviceNodes;
    procedure OnGetDeviceInfo(aDevInst: Cardinal; var aCanSelect: Boolean);

と定義して

FormCreateイベント内に
procedure TForm1.FormCreate(Sender: TObject);
begin
  LoadApiLib;                                  // 初期化?
  FUsbDevices := TDeviceNodes.Create;          // USBデバイス情報取得クラス生成
  FUsbDevices.GetDeviceInfo(OnGetDeviceInfo);  // 情報を取得する?(取得完了/変化イベント?発生)
end;

あとは取り外しボタンのクリックイベントにて下記コードを記述すると目的の動作になりました。
おかげで間に合いそうです。ありがとうございました。

procedure TForm1.Button2Click(Sender: TObject);
var
  d : TDeviceNode;
  s,snn : string;
  i,j : Integer;
begin
  s := FUsbDevices.DriveToDeviceName('E');         // ドライブEのデバイス名を取得
  for j := 0 to FUsbDevices.Count-1 do begin       // USBデバイスの数だけループ
    d := FUsbDevices.Items[j];                     // j番目のUSBデバイスクラス参照
    for i := 0 to d.DeviceNodeCount-1 do begin     // USBデバイスに関連するノード分ループ
      snn := d.DeviceNodeName[i];                  // USBのデバイス名称を取得
      if (snn = s) and (d.Removable) then begin    // USBデバイス名が一致かつ取り外し可能な場合
        d.EjectDevice(i);                          // USBデバイスを取り外す
      end;
    end;
  end;
end;


take  2010-05-14 16:58:34  No: 38442

ソースの一部を間違えていました。

×:d.EjectDevice(i);
○:d.EjectDevice();


ぽむぽむ  2010-05-14 17:49:28  No: 38443

> FUsbDevices.GetDeviceInfo(OnGetDeviceInfo);  
これは、デバイスの情報を全部取得するのだけど、特定のデバイス(USB関連のみとか)を
絞り込みするためにデバイス毎に発生するイベントを渡します。
nilを与えると、CM_Get_DevNode_Statusでリムーバブルかつ、名前に「USB」が含まれるものだけ選択されます(たしか)。
基本的に、USB機器を取り外すのが目的なので。

あと、LoadApiLibしたら、最後にUnloadApiLibも忘れずに。
ロード・アンロード共に、USBDev.pasのユニット内では行っていません。


※返信する前に利用規約をご確認ください。








  このエントリーをはてなブックマークに追加