XPでタスクバーを隠して前面表示するアプリケーションを作成しています。
その機能としてUSBメモリに出力することがあるのですが、出力した後安全に取り外したいのですが、タスクバーを隠しているため操作できません。
ボタン1つでUSBメモリを安全に取り外せる状態にしたいのですが、なにか良い方法はありますでしょうか?
ハードウェアの安全な取り外し
rundll32 shell32.dll,Control_RunDLL hotplug.dll
SetupDiGetClassDevs でデバイスを読み込み準備?
SetupDiEnumDeviceInfoで順にデバイスを列挙する
CM_Get_DevNode_Statusでデバイスがリムーバブルか判定する
ついでに、必要ならGetDeviceStatusNameでクラス名に「USB」が含まれているか判断する。
デバイス名はCM_Get_DevNode_Registry_Propertyで取得
CM_Request_Device_Eject でイジェクトする
こんな感じで、Cfg.h、SetupApi.h、CfgMgr32.h とかのDelphi用ユニットが別途必要かな?
KHE00221様、ぽむぽむ様返信ありがとうございます。
提示していただいたキーワード(CM_Request_Device_Eject)で検索をかけると
USBデバイス取り外しのDelphi用サンプルプログラムが見つかりました。
http://okapony.hp.infoseek.co.jp/download/delphi/tips3.html
かなりのコード量ですが、このサンプルクラスから取り外しが出来るようです。
早速明日から取りかかりたいと思います。
意外と簡単に対応できました。
クラスの作成者にも感謝です。
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;
ソースの一部を間違えていました。
×:d.EjectDevice(i);
○:d.EjectDevice();
> FUsbDevices.GetDeviceInfo(OnGetDeviceInfo);
これは、デバイスの情報を全部取得するのだけど、特定のデバイス(USB関連のみとか)を
絞り込みするためにデバイス毎に発生するイベントを渡します。
nilを与えると、CM_Get_DevNode_Statusでリムーバブルかつ、名前に「USB」が含まれるものだけ選択されます(たしか)。
基本的に、USB機器を取り外すのが目的なので。
あと、LoadApiLibしたら、最後にUnloadApiLibも忘れずに。
ロード・アンロード共に、USBDev.pasのユニット内では行っていません。
ツイート | ![]() |