USBメモリの取り外しについて

解決


del弟子  2012-05-21 23:14:03  No: 42249

Windows7では、エクスプローラ上でUSBメモリのドライブを
右クリックすると「取り外し」というメニューが現れて、
これをクリックすると取り外せる状態になりますが、
(参考:http://pasofaq.jp/windows/mycomputer/removeusb.htm
これと同じ事をDelphiでできないでしょうか?
例えば、
  何かの関数('G');
とかすると、Gドライブが外れる、というものが理想ですが・・。


DEKO  2012-05-21 23:35:28  No: 42250

コレでしょうか?

[How can i remove a USB flash disk programmatically using delphi? (stack overflow)]
http://stackoverflow.com/questions/434688/how-can-i-remove-a-usb-flash-disk-programmatically-using-delphi


take  URL  2012-05-21 23:56:14  No: 42251

以前同じ事で悩んだので質問してます。

https://www.petitmonte.com/bbs/answers?question_id=6974


del弟子  2012-05-22 00:30:40  No: 42252

DEKO様、ありがとうございます。
リンク先にあったコードは一部分のようで、動作しそうも無く、
さらにあったリンク先はCのコードでして・・・

take様、ありがとうございます。
リンク先(http://okapony.hp.infoseek.co.jp/download/delphi/tips3.html)は切れていました;;


take  2012-05-22 01:29:58  No: 42253

色々リンクが切れているようですが
このライブラリには含まれているようです。
http://www42.tok2.com/home/okapony/download/delphi/SetupApiSample.lzh


Mr.XRAY  2012-05-22 01:58:03  No: 42254

こんにちは.

>リンク先にあったコードは一部分のようで、動作しそうも無く、

試してないというこですね.かわりにやってみました.
ただし,以下の修正をしました.

(1) #134を削除しました.
  RootName := ADrive + ':' + #134; -->  RootName := ADrive + ':';

(2) 最後のところに end; を追加しました.
  finally
    // Close the volume so other processes can use the dr
  end;  //追加
end;    //追加

ボタンクリックを次のようにしました.

procedure TForm1.Button2Click(Sender: TObject);
begin
  EjectVolume('E');
end;

動作確認は,Windows 7 U64 + Dlephi XE です.
「もったいないオバケ」が出てきそうですね.

>リンク先(http://okapony.hp.infoseek.co.jp/download/delphi/tips3.html)は切れてい
ました;;

これ,「おかぽん」さんのサイトです.
昨年だか,URL変わりました.
http://www42.tok2.com/home/okapony/

で,ダウンロードのリンクのリダイレクトが (CGI)が修正されていないようです.
すでにtake さんのレスがありますが,以下から
DeviceReStart.lzh あるいは,SetupApiSample.lzh をダウンロードすると含まれています.

http://www42.tok2.com/home/okapony/download/delphi/


Nov  2012-05-22 02:34:44  No: 42255

DEKOさんのリンク先で、'improve this answer'をクリックすると全文を見ることができます、念のため。
で、最後の部分は次のようになってます(原文のまま)。

        // Close the volume so other processes can use the drive
        CloseHandle(VolumeHandle);
      end;
    end;
    
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      EjectVolume('E');
    end;

  [1]: http://support.microsoft.com/default.aspx?scid=kb;en-us;165721
  [2]: http://stackoverflow.com/questions/85649/safe-remove-usb-drive-using-win32-api#321097
  [3]: http://stackoverflow.com/users/12458/concept03


Mr.XRAY  2012-05-22 02:44:58  No: 42256

Novさんどうも.

 CloseHandle(VolumeHandle);

がないとマズイですね.失礼しました.


Mr.XRAY  2012-05-22 03:20:59  No: 42257

全く関係ないのですが,

>'improve this answer'をクリックすると全文を見ることができます、念のため。

見逃しました.でも,なんでこういうもったいぶったページ構成なんでしょうね?
コードが長い場合も想定してということもあるのでしょうけど.
ややこしいです.
コードをスクロール表示するインラインも好きじゃないですが.

今はこういうのが多いですね.時代の流れについて行かれません.


Nov  2012-05-22 03:42:04  No: 42258

これも質問とは関係ないですが、
>でも,なんでこういうもったいぶったページ構成なんでしょうね?
一見様お断り的なサイトなのでしょうか。
'improve this answer'をクリックして中身が見えてしまうのは、サイト管理人の意図する使い方ではないかも知れません...もしくは、回答者については来るものは拒まず、とか...


del弟子  2012-05-22 20:31:34  No: 42259

take様、ありがとうございます。
http://www42.tok2.com/home/okapony/download/delphi/SetupApiSample.lzh
で試してみますと、OSの機能での取り外しと全く同じにできました。^^
ただ、XPでは動作したのですが、Win7では一覧にUSBのドライブが表示されず、
取り外し以前に選択もできませんでした;;

Mr.XRAY様、Nov様、ありがとうございます。
DEKOさんのリンク先のを試してみますと、XPもWin7もドライブのアクセスは
できなくなるのですが、エクスプローラ上にはドライブの表示が残ったままに
なってしまいます・・・この段階でUSBメモリを外せば自動的に表示は消えるのですが、
これが正しい姿とは思えず・・。


take  2012-05-22 21:55:38  No: 42260

>ただ、XPでは動作したのですが、Win7では一覧にUSBのドライブが表示されず

USBメモリの判定処理を工夫すればある程度対応出来ますよ。
下記コードでWindows7の環境でも動作してます。
ただしカードリーダーをUSBメモリと誤認識してしまい。
さらにそれを取り外そうとすると無限ループしました。

function TUSBEject.EjectUSB: Boolean;
var
  d : TDeviceNode;
  snn : string;
  i,j : Integer;
begin
  result := False;
  FUsbDevices.GetDeviceInfo(nil);                  // リムーバブルかつUSBの名称を含む機器情報を取得
  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 not d.Removable then continue;            // 取り外せないデバイスは無視
      if not d.DisableEnable then continue;        // 無効に出来ないデバイスは無視
      if not CheckUsbMemory(snn) then continue;    // USBメモリではない場合無視
      result := d.EjectDevice();                   // USBデバイスを取り外す
      exit;
    end;
  end;
end;


take  2012-05-22 22:00:42  No: 42261

ソースが少し不足してた
D-Zまでのドライブ名の情報のいずれかと一致するなら
USBのドライブとして判定

function TUSBEject.CheckUsbMemory(const str: string): Boolean;
var
  i : Integer;
  s : string;
begin
  result := False;
  for i := Ord('D') to Ord('Z') do begin
    s := FUsbDevices.DriveToDeviceName(Char(i));
    if str = s then begin
      result := True;
      exit;
    end;
  end;
end;


del弟子  2012-05-23 00:33:59  No: 42262

take様、何度もありがとうございます。
やはりWin7では動作しませんでした。
64bitOSなのですが、その辺りも何かあるのかもと思ったりしてます・・・

ただ、DEKOさんのリンク先のコードで試していると、Win7でも動作しました。
再起動とかしたのが良かったのかもと^^;
ただ、エクスプローラからドライブは消えるのですが、
タスクトレイで普通表示される「〜安全に取り外すことができます。」という
メッセージは表示されず、不安は残ります^^;

とりあえずこれでなんとか運用してみようと思います。

皆様、ありがとうございました。


中の人  2012-05-24 21:21:15  No: 42263

解決済みということですが、http://www42.tok2.com/home/okapony/ 
ここの中の人なので、登場してみました(が、ステハンw)。
なお、64bit環境は保持していないので、動作確認はできません。

> del弟子 2012/05/22(火) 11:31:34 <初心者>  書込者ID:[ #!( ]
> ただ、XPでは動作したのですが、Win7では一覧にUSBのドライブが表示されず、
SetupApiSample.lzhのサンプルで、「USBデバイス取得クラスのテスト」ボタンにより
ドライブが表示されないということだと思うので、Win7x64では、デバイスのクラス名が
違うのかもしれません。

サンプルでは固定値('USB' or 'CDROM' or 'Volume')にしているので、大文字小文字の違いでも
表示されなくなりますね。
サンプルのフォームで、TForm1.OnSelectDevice で 引数の aCanSelect を
無条件 True にすると、全てのデバイスが列挙されるようになります。
ここで左側のツリーに表示されるようになったのであれば、デバイスのクラス名が
Win7x64で、変更になっているからだと思われます。
'USB2.0'とかになっているのかもしれません。
解説ページを作るモチベーションもないので、あくまでサンプルということでご理解お願いします。

> DEKO 2012/05/21(月) 14:35:28 書込者ID:[ "!$#" ]
http://stackoverflow.com/questions/434688/how-can-i-remove-a-usb-flash-disk-programmatically-using-delphi
ここのコードを見てみましたが、これはCD/DVDトレイの開閉でよく見たソースです。
これでUSBデバイスのとりはずしが可能なのは初めて知りました。
エクスプローラーの表示が変わらないのが、リフレッシュ(F5)で改善されるのであれば
「WM_COMMAND 41504」(または$A220)で検索すれば、見つかります。

# 最後になりますが、cgiのリンク切れすいません(こんなとこで謝る)。
# 移転してcgiのパーミッションとかの設定も変わったり、なにかとめんどくさ・・・
# いえ、cgiを使わないように、気がついたところから修正しました。
# 直リンOKです。好きにしてください。


DEKO  2012-05-25 03:55:05  No: 42264

> エクスプローラーの表示が変わらないのが、リフレッシュ(F5)で改善されるのであれば
> 「WM_COMMAND 41504」(または$A220)で検索すれば、見つかります。
Explorer に SHChangeNotify() で更新通知してやればイケるかもです。
SHChangeNotify(SHCNE_MEDIAREMOVED, SHCNF_FLUSH, nil, nil);
or
SHChangeNotify(SHCNE_MEDIAREMOVED, SHCNF_FLUSHNOWAIT, nil, nil);


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

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






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