Форум программистов, компьютерный форум, киберфорум
Наши страницы
C++ Builder
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.53/38: Рейтинг темы: голосов - 38, средняя оценка - 4.53
FrenchOpen
13 / 13 / 4
Регистрация: 08.12.2010
Сообщений: 42
1

Отлавливание подключения флешки

18.12.2010, 13:54. Просмотров 7480. Ответов 17
Метки нет (Все метки)

Доброе время суток, такая проблема: в программе нужно ловить событие подключения флешки, я пытаюсь это сделать через событие OnMessage компонента ApplicationEvents.

Так вот суть в том, что при подключении\отключении это событие возникает раз 10 с сообщением 0x0219 (WM_DEVICECHANGE), а параметр (wParam) всегда равен 0x0007 (DBT_DEVNODES_CHANGED), lParam всегда ноль.

Как мне отловить это событие с параметром 0x8000 (DBT_DEVICEARRIVAL), или через TApplicationEvents так не получится и надо это делать руками через winapi, в котором я, к сожалению, не сильно шарю...?
1
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
18.12.2010, 13:54
Ответы с готовыми решениями:

Отслеживание подключения флешки по USB
Такой вопрос: чем увидеть подключаемую к компу флешку USB, где в реестре об этом хранится...

Отлавливание прокрутки роликом мыши
как зделать так чтоюи в Мемо1 можно било прокручивать с помощу ролика на мишке?

отлавливание определенного символа из edit
AnsiString a=Edit1->Text; float i; if (a==43) { i= a+a; } else if (a==47) { i= a/a; }...

TCppWebBrowser - отлавливание ошибок при загрузке страниц
Есть ли возможность отлавливать ошибки возникающие при загрузке страниц? И по возможности их...

Сломался планшет из-за подключения флешки
Подключил к планшету флешку(не микро, а такую как в пк вставляются) через переходник, и моментально...

17
MikeSoft
Эксперт С++
3923 / 1788 / 183
Регистрация: 21.11.2009
Сообщений: 2,540
18.12.2010, 14:06 2
Лучший ответ Сообщение было отмечено как решение

Решение

FrenchOpen, нужно обрабатывать WM_DEVICECHANGE и DBT_DEVICEARRIVAL (WParam).
Я делал это без компонента ApplicationEvents (считаю его бесполезным).
А вот перехватывать сообщения общепринятым методом я вас научу.

В заголовочном файле, в public области объявляем "перехват" сообщений WM_DEVICECHANGE:
C++
1
2
3
BEGIN_MESSAGE_MAP
  MESSAGE_HANDLER(WM_DEVICECHANGE,TMessage,WMDeviceChange);
END_MESSAGE_MAP(TForm);
В private области объявляем прототип функции-обработчика:
C++
1
void virtual __fastcall WMDeviceChange(TMessage &Message);
И в файле с кодом описываем саму функцию:
C++
1
2
3
4
5
6
void __fastcall TDevScan::WMDeviceChange(TMessage& Message)
{
  if (Message.Msg == WM_DEVICECHANGE && Message.WParam == DBT_DEVICEARRIVAL) {
    // ваши действия
  }
}


Не по теме:

TDevScan - название класса, в котором вы объявили "перехват".

4
FrenchOpen
13 / 13 / 4
Регистрация: 08.12.2010
Сообщений: 42
18.12.2010, 14:15  [ТС] 3
Вот как раз то TDevScan он признавать не хочет:
[C++ Error] Unit1.cpp(13): E2090 Qualifier 'TDevScan' is not a class or namespace name
0
MikeSoft
Эксперт С++
3923 / 1788 / 183
Регистрация: 21.11.2009
Сообщений: 2,540
18.12.2010, 14:17 4
FrenchOpen, я же не зря написал, что это название того класса, в котором вы объявляете перехват необходимых сообщений.
Я назвал свою форму DevScan и класс называется TDevScan.
А у вас возможно будет TForm1, если вы не переименовывали форму.
1
18.12.2010, 14:17
FrenchOpen
13 / 13 / 4
Регистрация: 08.12.2010
Сообщений: 42
18.12.2010, 14:20  [ТС] 5
ах, туплю я с утра, спать надо больше... все работает, спасибо большое
0
turboq
157 / 156 / 13
Регистрация: 14.01.2010
Сообщений: 1,457
18.12.2010, 14:22 6
Можешь посмотреть как оно на Делфи здесь Реакция на флешку
0
FroL
61 / 49 / 6
Регистрация: 07.01.2010
Сообщений: 307
25.03.2011, 20:56 7
Сори за тупой вопрос, но почему пишет ошибку??
undefined symbol 'DBT_DEVICEARRIVAL'
Я закоментил эту часть, добавил ShowMessage, запустил прогу и вставил флешку - теперь раз 6 вылетает ShowMessage. Как сделать что бы эта функция вызывалась один раз???

Добавлено через 33 минуты
Нашел. поменял DBT_DEVICEARRIVAL на 0x8000. Теперь один раз вызывается функция
0
turboq
157 / 156 / 13
Регистрация: 14.01.2010
Сообщений: 1,457
26.03.2011, 10:29 8
DBT_DEVICEARRIVA это где?
0
FroL
61 / 49 / 6
Регистрация: 07.01.2010
Сообщений: 307
26.03.2011, 10:32 9
Я уже разобрался - просто надо было подключить хидеры:
C++
1
2
#include <windows.h>
#include <dbt.h>
1
Samrisbe
1353 / 723 / 66
Регистрация: 28.01.2011
Сообщений: 2,004
29.03.2011, 21:19 10
Перехват это есть хорошо а как запретить (а в случае необходимости разрешить) - отображать значок флешки в окне мой компьютер и в проводнике.

вот фото
0
Миниатюры
Отлавливание подключения флешки  
Dondok
18 / 34 / 2
Регистрация: 28.01.2012
Сообщений: 181
22.04.2012, 13:01 11
Samrisbe, можно отмонтировать файловую систему флешки функцией
C++
1
DeleteVolumeMountPoint
1
Avazart
Эксперт С++
7918 / 5739 / 568
Регистрация: 10.12.2010
Сообщений: 26,283
Записей в блоге: 17
22.04.2012, 19:22 12
Dondok, а можно пример?
Да и как узнать что надо отмонтировать?

Как отследить момент отключения флэшки
В устройстве нет диска. Вставьте диск в устройство
0
Ddv122
Почемучка)
1241 / 301 / 30
Регистрация: 23.12.2010
Сообщений: 2,000
Записей в блоге: 1
22.04.2012, 20:23 13
Вот полностью рабочий код, всё ловит.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
void __fastcall TForm1::WMDeviceChange( TMessage &Message ) {
    if ( Message.Msg == WM_DEVICECHANGE && Message.WParam == 0x8000 ) {
        char DiskLabel[MAX_PATH];
        WORD OldErrorMode;
        AnsiString dl;
        DWORD dr = GetLogicalDrives( );  // функция возвращает битовую маску
        for ( int x = 0; x < 26; x++ ) { // проходимся циклом по битам
            if ( ( dr >> x ) & 1 ) {     // узнаём значение текущего бита, если единица - диск с номером x есть
                dl = AnsiString( ( char )( 65 + x ) ) + "://"; // получаем литеру диска
                OldErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS ); // убираем показ ошибок
                bool ready = DirectoryExists(dl); // пытаемcя открыть корневую директорию
                if (ready)
                {   // пытаемcя открыть корневую директорию
                    UINT DriveType = GetDriveType( dl.c_str( ) ); // получаем тип диска
                    if ( DriveType != DRIVE_CDROM && // исключаем CDROMы
                            DriveType != DRIVE_FIXED && // исключаем  HDD
                             DriveType != DRIVE_RAMDISK &&
                             DriveType != DRIVE_REMOTE &&
                             DriveType != DRIVE_NO_ROOT_DIR &&
                             DriveType != DRIVE_UNKNOWN)
                            {
                        PlaySoundW( L"alert.wav", 0, SND_ASYNC );   //проигрываем звук
                        GetVolumeInformation( dl.c_str( ), DiskLabel, MAX_PATH, NULL, NULL, NULL, NULL, 0 );
                        ComboBox1->Items->Add(( dl + "//" ));
 
                        // для отчета
                        dt = Now( ); // формат даты
                        memo->Lines->Add( DateToStr( dt ) + " " + TimeToStr( dt ) +
                                          " " + " - " + " Подключен накопитель: " "(" + ( dl ) +
                                          ")" + " " + DiskLabel + "" );
1
Dondok
18 / 34 / 2
Регистрация: 28.01.2012
Сообщений: 181
22.04.2012, 21:30 14
Лучший ответ Сообщение было отмечено как решение

Решение

EdarGp, отлавливать момент подключения одно дело, а вот блокирование/разблокирование это уже другое. Я например блокировку производил путем отмонтирования файловой системы флешки, но с учетом того что вдруг потом снова надо разблокировать надо вычислить GUID этой флешки перед отмонтированием. Приду домой рабочий код выложу, а пока просто перечислю какие функции надо использовать
C++
1
2
3
GetVolumeNameForVolumeMountPoint //вычисление GUID
DeleteVolumeMountPoint //отмонтирование (блокировка)
SetVolumeMountPoint //монтирование (разблокировка)
Добавлено через 30 секунд
Avazart, пример вечером выложу

Добавлено через 44 минуты
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
AnsiString word;
char GUID[40];
char Drive[22]={'E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
for(int i=0; i<22; i++)
        {
        word = AnsiString(Drive[i]) + ":\\" ;
        if(GetDriveType(word.c_str()) == DRIVE_REMOVABLE) //перебираем все буквы в системе и 
                                                            //смотрим не флешка ли это
                {
                GetVolumeNameForVolumeMountPoint(word.c_str(),GUID,50); //вычисление GUID флешки
                                                                              //для монтирования пригодится
                Label1->Caption = String(GUID);          //запоминаем GUID(при желании можно сохранять в 
                                                  //файл, если планируется закрывать программу)
                DeleteVolumeMountPoint(word.c_str());//отмонтирование файловой системы
                }
        }
а теперь как производить монтирование
C++
1
2
3
4
5
6
7
8
AnsiString GUID = Label1->Caption; //грузим GUID
char Drive[22]={'E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
for(int i=0; i<22; i++)
        {
        word = AnsiString(Drive[i]) + ":\\" ;
        SetVolumeMountPoint(word.c_str(),GUID.c_str()); //сам процесс монтирования на первую 
                                                        //незанятую букву в системе
        }
3
QWIPQ
142 / 121 / 14
Регистрация: 10.10.2011
Сообщений: 359
Записей в блоге: 2
24.04.2012, 00:56 15
Допустим флешка размонтирована и GUID не записан, как его узнать можно?

Добавлено через 2 часа 18 минут
C++
1
2
3
4
5
6
7
8
AnsiString GUID = Label1->Caption; //грузим GUID
char Drive[22]={'E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
for(int i=0; i<22; i++)
        {
        word = AnsiString(Drive[i]) + ":\\" ;
        SetVolumeMountPoint(word.c_str(),GUID.c_str()); //сам процесс монтирования на первую 
                                                        //незанятую букву в системе
        }
в каком виде GUID должен передаваться?
№1: {******-******-****-******}

№2: ******-******-****-******
0
Dondok
18 / 34 / 2
Регистрация: 28.01.2012
Сообщений: 181
24.04.2012, 20:48 16
QWIPQ, GUID должен передаваться в таком формате:
C++
1
"\\\\?\\Volume{18456e7f-529b-11e1-b536-005056c00008}\\"
Добавлено через 1 минуту
QWIPQ, если не знаешь GUID, то может в цикле перебрать все параметры из реестра по пути HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices

Добавлено через 6 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
void __fastcall TForm1::Button3Click(TObject *Sender)
{
bool flag3;
////////////////////
TRegistry *Registry=new TRegistry;
try
        {
        Registry->RootKey=HKEY_LOCAL_MACHINE;
        Registry->OpenKey("SYSTEM\\MountedDevices\\", true);
        Registry->GetValueNames(ListBox1->Items);
        }
__finally
        {
        delete Registry;
        }
////////////////////
TSysCharSet Tws,Tcs;
Tcs<<'{'<<'}'; // Г°Г*çäåëèòåëè
char drv[3];
////////////////////
for (int i=0; i<ListBox1->Items->Count; i++)
        {
        AnsiString vol=ListBox1->Items->Strings[i];
        ExtractStrings(Tcs,Tws,vol.c_str(),Memo1->Lines);
        }
for (drv[0] = TEXT('C'); drv[0] <= TEXT('Z'); drv[0]++)
        {
        drv[1] = TEXT(':');
        Label3->Caption = AnsiString(drv)+"\\";
        for (int j=0; j<Memo1->Lines->Count; j++)
                {
                AnsiString nomer=Memo1->Lines->Strings[j];
                AnsiString stroka = "\\\\?\\Volume{"+ nomer +"}\\";
                Label1->Caption=stroka;
                flag3=SetVolumeMountPoint(Label3->Caption.c_str(),stroka.c_str());
                if (flag3==1) {ShowMessage("ìîГ*òèðîâГ*Г*Г®");};
                }
        }
}
//---------------------------------------------------------------------------
Добавлено через 1 минуту
необходимо перед чтением из реестра повысить права в реестре, иначе не получится прочитать значения из реестра
1
QWIPQ
142 / 121 / 14
Регистрация: 10.10.2011
Сообщений: 359
Записей в блоге: 2
25.04.2012, 13:45 17
спасибо уже разобрался, в таком виде мы его получаем
C++
1
\\?\Volume{0c3ef84f-78f9-11e1-8ff4-005056c00008}
для того чтобы смонтировать флешку обратно, нужно смонтировать сперва вод так:
C++
1
0c3ef84f-78f9-11e1-8ff4-005056c00008
после этого необходимо зайти по адресу:
C++
1
\\\Редактор реестра\HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices\
и удалить там файл который появляется после размонтирования флешки:
C++
1
#{b5052ba8-8d8a-11e1-9022-005056c00008}
название файла и его содержимое не зависит от файла с GUID флешки

вот пример:

C++
1
2
3
4
5
6
7
8
AnsiString GUID = Label1->Caption; //грузим GUID
char Drive[22]={'E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'};
for(int i=0; i<22; i++)
        {
        word = AnsiString(Drive[i]) + ":\\" ;
        SetVolumeMountPoint(word.c_str(),GUID.c_str()); //сам процесс монтирования на первую 
                                                        //незанятую букву в системе
        }
Отлавливание подключения флешки


Dondok объясни плз как эт, на первую незанятую букву в системе? проверка на занятость никакая не идет, просто буквы циклом перебираются... по сути дела присваивается каждой букве, а какая последняя будет на ту в итоге и монтируется... или все же не так?
0
Freesket
0 / 0 / 0
Регистрация: 09.11.2016
Сообщений: 1
20.03.2017, 11:10 18
У меня, почему-то, не совпадает GUID который выдает формула SetVolumeMountPoint с тем, который записывается в реестр. Кто знает, что это может быть?
0
20.03.2017, 11:10
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
20.03.2017, 11:10

Отслеживание события подключения флешки
Есть несколько вопросов: 1. Для отслеживания происходящего в Windows (в данном случае...

Скрыть факт подключения флешки
Коллеги! подскажите пожалуйста где можно в XP узнать список всех когда либо подключенных usb...

Событие подключения флешки и её форматирования
Здравствуйте, есть программа. Первая задача - в ней нужно отслеживать события...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru