同播放音樂,使用 winmm.dll 的 mciSendString,指令針對 CDAudio 裝置。
using System;
using System.Runtime.InteropServices;
public static class CdDriveControl
{
[DllImport("winmm.dll", EntryPoint = "mciSendString", CharSet = CharSet.Auto)]
private static extern int MciSendString(string command, StringBuilder returnValue, int returnLength, IntPtr callback);
///
/// 彈出光碟機托盤
///
public static void OpenTray(char driveLetter = 'D')
{
string cmd = $"set cdaudio drive {driveLetter} door open";
int err = MciSendString(cmd, null, 0, IntPtr.Zero);
if (err != 0) throw new InvalidOperationException($"MCI 開啟光碟機失敗: {err}, 指令: {cmd}");
}
///
/// 關閉光碟機托盤
///
public static void CloseTray(char driveLetter = 'D')
{
string cmd = $"set cdaudio drive {driveLetter} door closed";
int err = MciSendString(cmd, null, 0, IntPtr.Zero);
if (err != 0) throw new InvalidOperationException($"MCI 關閉光碟機失敗: {err}, 指令: {cmd}");
}
///
/// 切換托盤狀態
///
public static void ToggleTray(char driveLetter = 'D')
{
// MCI 無直接查詢門狀態指令,簡易做法:嘗試關閉,失敗則開啟 (或反之)
// 更穩健請使用 DeviceIoControl IOCTL_STORAGE_CHECK_VERIFY2
try { CloseTray(driveLetter); }
catch { OpenTray(driveLetter); }
}
}
private void btnEject_Click(object sender, EventArgs e)
{
try
{
CdDriveControl.OpenTray('E'); // 指定光碟機代號
MessageBox.Show("光碟機已彈出");
}
catch (Exception ex)
{
MessageBox.Show($"操作失敗: {ex.Message}");
}
}
private void btnClose_Click(object sender, EventArgs e)
{
CdDriveControl.CloseTray('E');
}
| 指令 | 說明 |
|---|---|
set cdaudio drive D door open | 彈出 D 槽托盤 |
set cdaudio drive D door closed | 關閉 D 槽托盤 |
status cdaudio mode | 查詢狀態 (playing/paused/stopped/open) |
play cdaudio from 1 to 10 | 播放第 1 到 10 軌 |
pause cdaudio | 暫停播放 |
resume cdaudio | 繼續播放 |
DriveInfo.GetDrives() 篩選 DriveType.CDRom 確認。drive X,否則作用於系統預設 CDAudio 裝置。door open/closed 可能無效或報錯。需更精確控制(如鎖定/解鎖托盤、偵測媒體是否存在)請使用 DeviceIoControl 搭配 IOCTL_STORAGE_EJECT_MEDIA、IOCTL_STORAGE_LOAD_MEDIA、IOCTL_STORAGE_CHECK_VERIFY2,屬較底層儲存體介面,程式碼較繁瑣但功能完整。
幾行 mciSendString 即可完成光碟機開關控制,適合簡單工具專案。記住指定正確磁碟機代號、處理例外、考慮槽載式/虛擬光碟機差異。