Извлечение компакт-диска Windows
Вопрос
Кто-нибудь знает способ программного закрытия лотка для компакт-дисков в Windows 2000 или выше?Открытый лоток для компакт-дисков существует, но я не могу его закрыть, особенно под W2k.
Я особенно ищу способ сделать это из пакетного файла, если это возможно, но вызовы API будут в порядке.
Решение
Вот простой способ использования Win32 API:
[DllImport("winmm.dll", EntryPoint = "mciSendStringA", CharSet = CharSet.Ansi)]
protected static extern int mciSendString(string lpstrCommand,StringBuilder lpstrReturnString,int uReturnLength,IntPtr hwndCallback);
public void OpenCloseCD(bool Open)
{
if (Open)
{
mciSendString("set cdaudio door open", null, 0, IntPtr.Zero);
}
else
{
mciSendString("set cdaudio door closed", null, 0, IntPtr.Zero);
}
}
Другие советы
Мне нравится использовать DeviceIOControl, поскольку он дает мне возможность извлечь любой съемный диск (например, USB-диски и флэш-диски, а также лотки для компакт-дисков).Код для правильного извлечения диска с помощью DeviceIOControl (просто добавьте правильную обработку ошибок):
bool ejectDisk(TCHAR driveLetter)
{
TCHAR tmp[10];
_stprintf(tmp, _T("\\\\.\\%c:"), driveLetter);
HANDLE handle = CreateFile(tmp, GENERIC_READ, FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
DWORD bytes = 0;
DeviceIoControl(handle, FSCTL_LOCK_VOLUME, 0, 0, 0, 0, &bytes, 0);
DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0, &bytes, 0);
DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, 0, 0, 0, 0, &bytes, 0);
CloseHandle(handle);
return true;
}
Я заметил, что ответ Андреаса Магнуссона работал не совсем так, как кнопка «Извлечь» в Проводнике.В частности, диск не был выделен серым цветом в Проводнике с использованием кода Андреаса, но был, если вы использовали команду «Извлечь».Поэтому я провел небольшое расследование.
Я запустил API Monitor, одновременно выполняя команду Eject из проводника (64-разрядная версия Windows 7 SP1).Я также нашел хорошую статью MSKB 165721 под названием Как извлечь съемный носитель в Windows NT/Windows 2000/Windows XP.Самая интересная часть статьи MSKB приведена ниже:
- Вызовите CreateFile с помощью GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE и OPEN_EXISTING.Параметр lpFileName должен быть \.\X:(где X — настоящая буква диска).Все остальные параметры могут быть нулевыми.
- Заблокируйте том, выдав FSCTL_LOCK_VOLUME IOCTL через DeviceIoControl.Если какое-либо другое приложение или система использует том, этот IOCTL не будет выполнен.После успешного завершения этой функции приложению гарантируется, что том не используется ничем другим в системе.
- Отключите том, выполнив FSCTL_DISMOUNT_VOLUME IOCTL.Это приводит к тому, что файловая система удаляет все сведения о томе и всю внутреннюю информацию, хранящуюся в отношении тома.
- Убедитесь, что носитель можно удалить, выполнив IOCTL_STORAGE_MEDIA_REMOVAL IOCTL.Установите для элемента PreventMediaRemoval структуры PREVENT_MEDIA_REMOVAL значение FALSE перед вызовом этого IOCTL.Это не позволяет устройству препятствовать извлечению носителя.
- Извлеките носитель с помощью IOCTL_STORAGE_EJECT_MEDIA IOCTL.Если устройство не поддерживает автоматическое извлечение, то IOCTL_STORAGE_EJECT_MEDIA можно пропустить и дать пользователю указание удалить носитель.
- Закройте дескриптор тома, полученный на первом этапе, или выполните FSCTL_UNLOCK_VOLUME IOCTL.Это позволяет использовать диск другим процессами.
Ответ Андреаса, статью MSKB и мой анализ API Explorer можно резюмировать следующим образом:
CreateFile
вызывается, чтобы открыть том.(Все методы).DeviceIoControl
позвонил сFSCTL_LOCK_VOLUME
.(Все методы).DeviceIoControl
позвонил сFSCTL_DISMOUNT_VOLUME
.(Только методы Андреаса и MSKB.Explorer почему-то этого не вызывает.Похоже, что этот IOCTL влияет на то, будет ли диск выделен серым цветом в Проводнике или нет.Я не уверен, почему Explorer не вызывает это).DeviceIoControl
позвонил сIOCTL_STORAGE_MEDIA_REMOVAL
иPREVENT_MEDIA_REMOVAL
член настроен наFALSE
(методы MSKB и Explorer.Этот шаг отсутствует в ответе Андреаса).DeviceIoControl
позвонил сIOCTL_STORAGE_EJECT_MEDIA
(статья Андреаса и MSKB) илиIOCTL_DISK_EJECT_MEDIA
(Проводник;обратите внимание, что этот IOCTL устарел и заменен STORAGE IOCTL.Непонятно, почему Explorer до сих пор использует старую версию).
В заключение я решил следовать процедуре, описанной в статье MSKB, поскольку она показалась мне наиболее тщательной и полной процедурой, подкрепленной статьей MSKB.
Ниркмд — очень удобная бесплатная утилита командной строки с различными опциями, включая открытие и закрытие лотка для компакт-дисков.
Чтобы закрыть лоток для дисков, сделайте, как описано. здесь но вместо использования DeviceIoControl с IOCTL_STORAGE_EJECT_MEDIA вам нужно вызвать DeviceIoControl с IOCTL_STORAGE_LOAD_MEDIA.