0

既にご存知かもしれませんが、IsReady のブール型プロパティを持つ DriveInfo 型のプロパティを持つクラスがあります。これは、ドライブが「準備完了」であることを表す値です。私にとっては、CDRom ドライブのみを選択したため、ドライブに CD があることを意味します。

私がやりたいのは、プロパティが更新されたときにイベントを呼び出すことです。現在、オブジェクトをインスタンス化し、while ループを実行して値が true になるのを待ちます。

    public bool WaitUntilReady()
    {
        while (!Cancelled)
        {
            if (Drive.IsReady) return true;
        }

        return false;
    }

私は方法、または同様のものを好むでしょう。ありがとうございました。

4

3 に答える 3

3

CD の挿入/取り出しなど、デバイスの状態の変化を待っている場合は、WM_DEVICECHANGEメッセージを聞く方がよいでしょう。

WM_DEVICECHANGE新しいデバイスまたはメディア (CD や DVD など) が追加されて使用可能になったとき、および既存のデバイスまたはメディアが削除されたときに、Windows はすべての最上位ウィンドウに一連の既定のメッセージを送信します...続きを読む

次のヘルパー クラスを使用して、メディアの挿入/削除をリッスンしてみてください。

ドライブヘルパー

public static class DriveHelper
{
  const int WM_DEVICECHANGE = 0x0219;
  const int DBT_DEVICEARRIVAL = 0x8000;
  const int DBT_DEVICEREMOVECOMPLETE = 0x8004;
  const int DBT_DEVTYP_VOLUME = 0x00000002;
  const ushort DBTF_MEDIA = 0x0001;

  [StructLayout(LayoutKind.Sequential)]
  struct DEV_BROADCAST_VOLUME
  {
    public uint dbch_Size;
    public uint dbch_Devicetype;
    public uint dbch_Reserved;
    public uint dbch_Unitmask;
    public ushort dbch_Flags;
  }

  public class StateChangedEventArgs : EventArgs
  {
    public StateChangedEventArgs(string drive, bool ready)
    {
      Drive = drive;
      Ready = ready;
    }

    public string Drive { get; private set; }

    public bool Ready { get; private set; }
  }

  public static void QueryDeviceChange(Message m, Action<StateChangedEventArgs> action)
  {
    if (action == null || m.Msg != WM_DEVICECHANGE) return;

    var devType = Marshal.ReadInt32(m.LParam, 4);
    if (devType != DBT_DEVTYP_VOLUME) return;

    var lpdbv = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_VOLUME));
    if (lpdbv.dbch_Flags != DBTF_MEDIA) return;

    var eventCode = m.WParam.ToInt32();
    var drive = GetFirstDriveFromMask(lpdbv.dbch_Unitmask);

    switch (eventCode)
    {
      case DBT_DEVICEARRIVAL:
        action(new StateChangedEventArgs(drive, true));
        break;
      case DBT_DEVICEREMOVECOMPLETE:
        action(new StateChangedEventArgs(drive, false));
        break;
    }
  }

  static string GetFirstDriveFromMask(uint mask)
  {
    int i;

    for (i = 0; i < 26; ++i)
    {
      if ((mask & 0x1) == 0x1)
        break;
      mask = mask >> 1;
    }

    return string.Concat((char)(i + 65), @":\");
  }
}

使用例 Windows Formsアプリ向け)

public partial class Form1 : Form
{    
  public Form1()
  {
    InitializeComponent();      
  }

  void OnStateChanged(DriveHelper.StateChangedEventArgs e)
  {
    // do your work here
    MessageBox.Show(string.Format("Drive: {0} => e.Ready: {1}, DriveInfo.IsReady: {2}", e.Drive, e.Ready, new DriveInfo(e.Drive).IsReady));
  }    

  protected override void WndProc(ref Message m)
  {
    DriveHelper.QueryDeviceChange(m, OnStateChanged);

    base.WndProc(ref m);
  }      
}
于 2014-02-04T06:01:48.660 に答える