Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.65/68: Рейтинг темы: голосов - 68, средняя оценка - 4.65
12 / 11 / 2
Регистрация: 03.04.2016
Сообщений: 502

Грабли с WM_DEVICECHANGE

03.10.2016, 22:16. Показов 15751. Ответов 63

Студворк — интернет-сервис помощи студентам
Потратил кучу времени на изучение структур связанных с WM_DEVICECHANGE. Все работает как надо wParam == DBT_DEVICEARRIVAL , отлавливает сообщение о новом диске, lParam передает информацию о букве и т д. Но WM_DEVICECHANGE ловит сообщения только о монтировании нового диска! Но если есть встроенный картридер и пользователь вставляет в него карточку, то сообщение не приходит, так как диск уже смонтирован, а наличие карты не проверяется! На форумах самый умный совет - повесить таймер на картридер. Получаем грабли, зачем все эти манипуляции, если можно таймер повесить изначально на GetVolumeInformation? Получается в результате функция не полноценна так как пользователь может обойти любые ограничения, просто вставив карту в картридер. Что делать то ??
0
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
03.10.2016, 22:16
Ответы с готовыми решениями:

WM_DEVICECHANGE
Здравствуйте, при подключении или отключении usb устройства сообщение "WM_DEVICECHANGE" приходить несколько раз: Remove - ...

WinAPI C++ WM_DEVICECHANGE
Вообщем цель определить любое воткнутое USB устройство. Выбрал WIN API поскольку жрет мало ресурсов, выбрал С++ потому что он не тащит за...

Перехват wm_devicechange
Здравствуйте написал простенькую программку по отлову сообщений вставки usb носителей. Собственно данный код отлавливает события.Приходит и...

63
 Аватар для prokl9tiy
21 / 21 / 9
Регистрация: 09.10.2016
Сообщений: 113
10.10.2016, 00:50
Студворк — интернет-сервис помощи студентам
zombivadim, у меня не на чем проверять.
может это поможет http://stackoverflow.com/quest... on-wm-devi
кардридер же usb'шный
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
10.10.2016, 08:37
Цитата Сообщение от Dragokas Посмотреть сообщение
Не, там именно событийная схема.
Откуда инфа? Может, и код (псевдокод?) тогда есть?


Цитата Сообщение от zombivadim Посмотреть сообщение
Попробуйте пожалуйста пример который я указал выше
Во-первых, у меня нет Delphi.
Во-вторых, какой смысл мне пробовать этот пример, если я разницу не почувствую
(т.к. у меня вставка SD-карты определяется сразу)?
0
12 / 11 / 2
Регистрация: 03.04.2016
Сообщений: 502
10.10.2016, 22:26  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Попробовал SHChangeNotifyRegister, но толку от нее не много
Я был бы вам безмерно благодарен за пример, использования, этой функции, тем более вы ее тестировали. Мне очень интересно в образовательных целях.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
11.10.2016, 09:25
Лучший ответ Сообщение было отмечено zombivadim как решение

Решение

Вот код (вместе с WM_DEVICECHANGE), собирал в Visual C++ 2008:
Кликните здесь для просмотра всего текста

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
//
// Copyright (c) Убежденный
// :)
//
// ВНИМАНИЕ!
// Код только для демонстрации, нормальная проверка
// ошибок и очистка ресурсов отсутствует.
//
 
#include <Windows.h>
#include <ShlObj.h>
#include <dbt.h>
#include <string>
#include <vector>
#include <strsafe.h>
 
 
 
//
// Custom window message for SHChangeNotifyRegister.
//
#define WM_CHANGE_NOTIFY (WM_APP + 1)
 
 
 
HANDLE      volatile g_hFile     = INVALID_HANDLE_VALUE;
HMODULE     volatile g_hInst     = NULL;
HWND        volatile g_hWnd      = NULL;
HDEVNOTIFY  volatile g_hNotify   = NULL;
ULONG       volatile g_hShNotify = 0;
 
 
 
//
// Convert DBT_XXX constant (dbt.h) to string.
// 
char const * DbtToStr(WPARAM wParam)
{
#define CASE(_x_) case _x_: return #_x_
 
    switch (wParam)
    {
        CASE(DBT_CONFIGCHANGECANCELED);
        CASE(DBT_CONFIGCHANGED);
        CASE(DBT_CUSTOMEVENT);
        CASE(DBT_DEVICEARRIVAL);
        CASE(DBT_DEVICEQUERYREMOVE);
        CASE(DBT_DEVICEQUERYREMOVEFAILED);
        CASE(DBT_DEVICEREMOVECOMPLETE);
        CASE(DBT_DEVICEREMOVEPENDING);
        CASE(DBT_DEVICETYPESPECIFIC);
        CASE(DBT_DEVNODES_CHANGED);
        CASE(DBT_QUERYCHANGECONFIG);
        CASE(DBT_USERDEFINED);
    }
 
#undef CASE
 
    return "<UNKNOWN>";
}
 
 
 
//
// Convert SHCNE_XXX constant (ShlObj.h) to string.
//
char const * EvtToStr(LONG EventId)
{
#define CASE(_x_) case _x_: return #_x_
 
    switch (EventId)
    {
        CASE(SHCNE_MEDIAINSERTED);
        CASE(SHCNE_MEDIAREMOVED);
        CASE(SHCNE_DRIVEADD);
        CASE(SHCNE_DRIVEREMOVED);
    }
 
#undef CASE
 
    return "<UNKNOWN>";
}
 
 
 
//
// Create formatted string.
//
std::string FormatStr(char const * pFormat, va_list VaList)
{
    size_t const BuffSize = 1000;
    std::vector<char> Buffer(BuffSize);
    if (S_OK == StringCchVPrintfA(&Buffer[0], BuffSize, pFormat, VaList))
        return (&Buffer[0]);
    return pFormat;
}
 
 
 
//
// Show error box and exit program.
//
__declspec(noreturn) 
void ThrowExc(char const * pFormat, ...)
{
    va_list VaList;
    va_start(VaList, pFormat);
    std::string const Msg = FormatStr(pFormat, VaList);
    MessageBoxA(g_hWnd, Msg.c_str(), "ERROR", MB_ICONERROR);
    _exit(EXIT_FAILURE);
}
#define THROW_EXC(Fmt,...) ThrowExc(__FUNCTION__ ": " Fmt, __VA_ARGS__)
#define THROW_CODE(Func,Code) THROW_EXC(#Func " failed, err = 0x%.8lx.", Code)
#define THROW_GLE(Func) THROW_CODE(Func,GetLastError())
 
 
 
//
// Write string to log file.
// 
void Log(char const * pFormat, ...)
{
    SYSTEMTIME st = {0};
    GetLocalTime(&st);
    size_t const BuffSize = 256;
    std::vector<char> Buffer(BuffSize);
    std::string Msg;
    if (S_OK == StringCchPrintfA(
        &Buffer[0],
        BuffSize,
        "%.4lu.%.2lu.%.2lu-%.2lu:%.2lu:%.2lu    ",
        st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond
        ))
    {
        Msg = &Buffer[0];
    }
 
    va_list VaList;
    va_start(VaList, pFormat);
    Msg += FormatStr(pFormat, VaList) + "\r\n";
    DWORD nBytes;
    WriteFile(g_hFile, Msg.c_str(), static_cast<DWORD>(Msg.length()), &nBytes, NULL);
    FlushFileBuffers(g_hFile);
}
 
 
 
//
// Window procedure.
// 
LRESULT CALLBACK MyWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
    switch (Msg)
    {
        case WM_CREATE:
        {
            g_hWnd = hWnd;
 
            //
            // Create log file.
            //
 
            g_hFile = CreateFileW(
                L"C:\\Test\\Test.log",
                GENERIC_WRITE,
                FILE_SHARE_READ,
                NULL, // Security attributes.
                CREATE_ALWAYS,
                FILE_ATTRIBUTE_NORMAL,
                NULL  // Template handle.
                );
            if (INVALID_HANDLE_VALUE == g_hFile) {
                THROW_GLE(CreateFileW);
            }
 
            //
            // Register device change notification.
            //
 
            DEV_BROADCAST_DEVICEINTERFACE_W Flt = {0};
            Flt.dbcc_size       = sizeof (Flt);
            Flt.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
            
            g_hNotify = RegisterDeviceNotificationW(
                hWnd,
                &Flt,
                DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES
                );
            if (!g_hNotify) {
                THROW_GLE(RegisterDeviceNotificationW);
            }
 
            //
            // Register shell & filesystem notification.
            //
 
            SHChangeNotifyEntry Entry = {0};
            Entry.fRecursive = TRUE;
 
            LPITEMIDLIST pidl;
 
            HRESULT const Status = SHGetFolderLocation(
                NULL, // Reserved.
                CSIDL_DESKTOP,
                NULL, // Access token.
                0,    // Reserved.
                &pidl
                );
            if (!SUCCEEDED(Status)) {
                THROW_CODE(SHGetFolderLocation, Status);
            }
 
            Entry.pidl = pidl;
 
            g_hShNotify = SHChangeNotifyRegister(
                hWnd,
                SHCNRF_ShellLevel | SHCNRF_InterruptLevel | SHCNRF_NewDelivery,
                SHCNE_MEDIAINSERTED | SHCNE_MEDIAREMOVED | SHCNE_DRIVEADD | SHCNE_DRIVEREMOVED,
                WM_CHANGE_NOTIFY,
                1,
                &Entry
                );
            if (!g_hShNotify) {
                THROW_GLE(SHChangeNotifyRegister);
            }
 
            ILFree(pidl);
        }
        break;
 
        case WM_DESTROY:
        {
            //
            // Unregister shell & filesystem notification.
            //
 
            if (!SHChangeNotifyDeregister(g_hShNotify)) {
                THROW_GLE(SHChangeNotifyDeregister);
            }
 
            //
            // Unregister device change notification.
            //
 
            if (!UnregisterDeviceNotification(g_hNotify)) {
                THROW_GLE(UnregisterDeviceNotification);
            }
 
            //
            // Close log file.
            //
 
            if (!CloseHandle(g_hFile)) {
                THROW_GLE(CloseHandle);
            }
 
            PostQuitMessage(0);
            return 0;
        }
        break;
 
        case WM_DEVICECHANGE:
        {
            Log(
                "WM_DEVICECHANGE: wParam = %s (0x%.8lx)",
                DbtToStr(wParam),
                wParam
                );                
            return TRUE;
        }
        break;
 
        case WM_CHANGE_NOTIFY:
        {
            LONG EventId;
            HANDLE const hLock = SHChangeNotification_Lock(
                reinterpret_cast<HANDLE>(wParam),
                static_cast<DWORD>(lParam),
                NULL, // [out] LPITEMIDLIST **
                &EventId
                );
            SHChangeNotification_Unlock(hLock);
 
            Log(
                "WM_CHANGE_NOTIFY: EventId = %s (0x%.8lx)",
                EvtToStr(EventId),
                EventId
                );
        }
        break;
    }
 
    return (DefWindowProcW(hWnd, Msg, wParam, lParam));
}
 
 
 
//
// Program entry point.
// 
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE, LPSTR, int)
{
    g_hInst = hInst;
 
    //
    // Register window class.
    //
 
    WNDCLASSEXW wc = {0};
    wc.cbSize        = sizeof (wc);
    wc.hbrBackground = CreateSolidBrush(0x404040);
    wc.hCursor       = LoadCursorW(NULL, IDC_ARROW);
    wc.hIcon         = LoadIconW(NULL, IDI_APPLICATION);
    wc.hIconSm       = wc.hIcon;
    wc.hInstance     = hInst;
    wc.lpfnWndProc   = MyWndProc;
    wc.lpszClassName = L"SdCardDetectWndClass";
    wc.style         = CS_HREDRAW | CS_VREDRAW;
 
    ATOM const Atom = RegisterClassExW(&wc);
    if (!Atom) {
        THROW_GLE(RegisterClassExW);
    }
 
    //
    // Create window.
    //
 
    HWND const hWnd = CreateWindowExW(
        0, // Extended styles.
        reinterpret_cast<LPCWSTR>(Atom),
        L"SD Card Detect",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL, // Parent window.
        NULL, // Menu handle.
        hInst,
        NULL // Init argument.
        );
    if (!hWnd) {
        THROW_GLE(CreateWindowExW);
    }
 
    ShowWindow(hWnd, SW_SHOWNORMAL);
    UpdateWindow(hWnd);
 
    //
    // Message loop.
    //
 
    MSG Msg;
 
    for (;;)
    {
        int const Status = GetMessageW(&Msg, NULL, 0, 0);
        if ( (-1 == Status) || (0 == Status) )
        {
            break;
        }
 
        TranslateMessage(&Msg);
        DispatchMessageW(&Msg);
    }
 
    return EXIT_SUCCESS;
}


Лог-файл (последовательно вставлялись и извлекались SD-карта, CD-диск и USB-флэшка):
Кликните здесь для просмотра всего текста

2016.10.11-09:08:01 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:08:01 WM_DEVICECHANGE: wParam = DBT_DEVICEARRIVAL (0x00008000)
2016.10.11-09:08:01 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:08:02 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:08:02 WM_DEVICECHANGE: wParam = DBT_DEVICEARRIVAL (0x00008000)
2016.10.11-09:08:02 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:08:02 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:08:02 WM_DEVICECHANGE: wParam = DBT_DEVICEARRIVAL (0x00008000)
2016.10.11-09:08:02 WM_DEVICECHANGE: wParam = DBT_DEVICEARRIVAL (0x00008000)
2016.10.11-09:08:02 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:08:04 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:08:04 WM_DEVICECHANGE: wParam = DBT_DEVICEARRIVAL (0x00008000)
2016.10.11-09:08:04 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:08:04 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:08:04 WM_DEVICECHANGE: wParam = DBT_DEVICEARRIVAL (0x00008000)
2016.10.11-09:08:04 WM_DEVICECHANGE: wParam = DBT_DEVICEARRIVAL (0x00008000)
2016.10.11-09:08:04 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:08:04 WM_CHANGE_NOTIFY: EventId = SHCNE_DRIVEADD (0x00000100)
2016.10.11-09:10:54 WM_CHANGE_NOTIFY: EventId = SHCNE_MEDIAINSERTED (0x00000020)
2016.10.11-09:11:24 WM_DEVICECHANGE: wParam = DBT_DEVICEARRIVAL (0x00008000)
2016.10.11-09:11:29 WM_CHANGE_NOTIFY: EventId = SHCNE_MEDIAINSERTED (0x00000020)
2016.10.11-09:12:09 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:12:09 WM_DEVICECHANGE: wParam = DBT_DEVICEARRIVAL (0x00008000)
2016.10.11-09:12:09 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:12:09 WM_DEVICECHANGE: wParam = DBT_DEVICEARRIVAL (0x00008000)
2016.10.11-09:12:09 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:12:09 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:12:09 WM_DEVICECHANGE: wParam = DBT_DEVICEARRIVAL (0x00008000)
2016.10.11-09:12:10 WM_DEVICECHANGE: wParam = DBT_DEVICEARRIVAL (0x00008000)
2016.10.11-09:12:10 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:12:10 WM_CHANGE_NOTIFY: EventId = SHCNE_DRIVEADD (0x00000100)
2016.10.11-09:12:10 WM_DEVICECHANGE: wParam = DBT_DEVICEARRIVAL (0x00008000)
2016.10.11-09:12:10 WM_DEVICECHANGE: wParam = DBT_DEVICEARRIVAL (0x00008000)
2016.10.11-09:12:10 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:12:31 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:12:31 WM_DEVICECHANGE: wParam = DBT_DEVICEREMOVECOMPLETE (0x00008004)
2016.10.11-09:12:31 WM_DEVICECHANGE: wParam = DBT_DEVICEREMOVECOMPLETE (0x00008004)
2016.10.11-09:12:31 WM_DEVICECHANGE: wParam = DBT_DEVICEREMOVECOMPLETE (0x00008004)
2016.10.11-09:12:31 WM_DEVICECHANGE: wParam = DBT_DEVICEREMOVECOMPLETE (0x00008004)
2016.10.11-09:12:31 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:12:31 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:12:31 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:12:31 WM_DEVICECHANGE: wParam = DBT_DEVICEREMOVECOMPLETE (0x00008004)
2016.10.11-09:12:31 WM_DEVICECHANGE: wParam = DBT_DEVICEREMOVECOMPLETE (0x00008004)
2016.10.11-09:12:32 WM_CHANGE_NOTIFY: EventId = SHCNE_DRIVEREMOVED (0x00000080)
2016.10.11-09:12:37 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:12:37 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:12:43 WM_DEVICECHANGE: wParam = DBT_DEVICEREMOVECOMPLETE (0x00008004)
2016.10.11-09:12:43 WM_CHANGE_NOTIFY: EventId = SHCNE_MEDIAREMOVED (0x00000040)
2016.10.11-09:12:43 WM_CHANGE_NOTIFY: EventId = SHCNE_MEDIAREMOVED (0x00000040)
2016.10.11-09:12:58 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:12:58 WM_DEVICECHANGE: wParam = DBT_DEVICEREMOVECOMPLETE (0x00008004)
2016.10.11-09:12:58 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:12:58 WM_DEVICECHANGE: wParam = DBT_DEVICEREMOVECOMPLETE (0x00008004)
2016.10.11-09:12:58 WM_DEVICECHANGE: wParam = DBT_DEVICEREMOVECOMPLETE (0x00008004)
2016.10.11-09:12:58 WM_DEVICECHANGE: wParam = DBT_DEVNODES_CHANGED (0x00000007)
2016.10.11-09:12:58 WM_DEVICECHANGE: wParam = DBT_DEVICEREMOVECOMPLETE (0x00008004)
2016.10.11-09:12:58 WM_DEVICECHANGE: wParam = DBT_DEVICEREMOVECOMPLETE (0x00008004)
2016.10.11-09:12:59 WM_CHANGE_NOTIFY: EventId = SHCNE_DRIVEREMOVED (0x00000080)
3
12 / 11 / 2
Регистрация: 03.04.2016
Сообщений: 502
11.10.2016, 19:32  [ТС]
Убежденный, Большое вам спасибо!
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
11.10.2016, 19:56
zombivadim, есть какие-нибудь продвижения?
0
12 / 11 / 2
Регистрация: 03.04.2016
Сообщений: 502
11.10.2016, 21:24  [ТС]
castaway, Могу сказать, что WM_DEVICECHANGE, не посылает сообщения если не монтируется диск, это 100 % тупиковый вариант. И как не извращаться с RegisterDeviceNotification, и с GUID, результата не будет. И проблема вовсе не в самой функции, а в устройстве, которое не посылает нужное сообщение.
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
11.10.2016, 21:50
zombivadim, когда вы вставляете флешку в кардридер, ОС говорит об этом? ОС предлагает "Открыть диск", "Воспроизвести содержимое" и т.п.? ОС как-то реагирует на это действие?
0
12 / 11 / 2
Регистрация: 03.04.2016
Сообщений: 502
11.10.2016, 21:57  [ТС]
Цитата Сообщение от castaway Посмотреть сообщение
когда вы вставляете флешку в картридер, ОС говорит об этом? ОС предлагает "Открыть диск", "Воспроизвести содержимое" и т.п.? ОС как-то реагирует на это действие?
Конечно, все как и при обычной вставке флешки в USB.
0
Эксперт С++
4986 / 3093 / 456
Регистрация: 10.11.2010
Сообщений: 11,170
Записей в блоге: 10
11.10.2016, 22:11
Мне даже самому интересно стало.. По возможности попробую найти (может даже купить) внешний кардридер.
0
12 / 11 / 2
Регистрация: 03.04.2016
Сообщений: 502
11.10.2016, 22:58  [ТС]
castaway, Ну да процесс простой. Смотрите наличие у вас флешки в сотовом телефоне, фотоаппарате, видеорегистраторе, и за пару американских рублей покупаете под него картридер. Вставляете картридер в комп, потом вставляете в него флеш карту, и смотрите сообщения WM_DEVICECHANGE, потом долгое время ковыряете RegisterDeviceNotification, и если получаете сообщение, то вам большой респект)

Добавлено через 16 минут
Можете почитать вот эти ссылки
http://minilabmaster.com/smf2/... 887.0.html
http://forum.sources.ru/index.php?showtopic=146127
и т.д

Добавлено через 22 минуты
Убежденный, Почитал ваш код в примере SHChangeNotifyRegister, это просто кладезь знаний ), одно вот это #define WM_CHANGE_NOTIFY (WM_APP + 1)!! Константа WM_APP используется, чтобы различать между значениями сообщений, которые зарезервированы для использования системой и значениями, которые могут быть использованы в приложении, чтобы отправить сообщения в пределах отдельного класса окна. Или SHGetFolderLocation CSIDL_DESKTOP Виртуальная папка, которая представляет на рабочем столе Windows, корень пространства имен. ( Даже не представляю как это работает). Такое ощущение что я понимаю принцип, но не понимаю как же это работает то.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
11.10.2016, 23:11
Цитата Сообщение от zombivadim Посмотреть сообщение
потом долгое время ковыряете RegisterDeviceNotification, и если получаете сообщение, то вам большой респект
Думаю, надо попробовать еще два варианта:

1. RegisterDeviceNotification с DBT_DEVTYP_HANDLE.

2. FindFirstChangeNotification на смонтированном томе SD-карты. Ожидание не
выносить в отдельный поток, а доверить функции RegisterWaitForSingleObject.
Хотя это тоже слегка костыльно - ждать на хэндле тома, который, может,
никогда не будет подключен (т.е. карту ведь не обязаны сразу вставлять).

Я еще смотрел API для Windows Portable Devices, но там, похоже, нет
способа подписаться на появление в системе новых WPD-устройств,
только злобный polling (опрос в цикле с задержкой).
0
12 / 11 / 2
Регистрация: 03.04.2016
Сообщений: 502
12.10.2016, 10:43  [ТС]
Убежденный, Подскажите, а как с помощью FindFirstChangeNotification , получит букву диска приславшего SHCNE_DRIVEADD,SHCNE_MEDIAINSERTED?

Добавлено через 25 минут
Ой опечатался, с помощью SHChangeNotifyRegister получить букву диска приславшего SHCNE_DRIVEADD,SHCNE_MEDIAINSERTED
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
12.10.2016, 12:11
В SHChangeNotification_Lock можно передать указатель на PITEMIDLIST.
Когда функция вернет управление, там будет id соответствующей папки.
PITEMIDLIST - это что-то типа id файлового объекта. Преобразовать его в
путь можно функцией SHGetPathFromIDList.
0
12 / 11 / 2
Регистрация: 03.04.2016
Сообщений: 502
12.10.2016, 21:03  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
можно передать указатель на PITEMIDLIST
Все это ведет меня к пространству имен, о котором я пока имею лишь поверхностное представление, к сожалению.

Добавлено через 4 минуты
Мне уже неудобно как то вас просить, о примере. Но если вам не трудно, просто в данный момент я бьюсь с проблемой WM_DEVICECHANGE.
0
12 / 11 / 2
Регистрация: 03.04.2016
Сообщений: 502
14.10.2016, 20:56  [ТС]
Убежденный, У вас уже в SHChangeNotification_Lock есть, NULL, // [out] LPITEMIDLIST ** и есть LPITEMIDLIST pidl; Но как я не пытаюсь ничего не получается.

Добавлено через 2 минуты
и в msdn нет никаких примеров ...

Добавлено через 55 минут
Вот так попробовал
C++
1
2
3
4
5
6
7
8
        LPITEMIDLIST *pidl2;
        LONG EventId;
        HANDLE const hLock = SHChangeNotification_Lock(
            reinterpret_cast<HANDLE>(wParam),
            static_cast<DWORD>(lParam),
            &pidl2, // [out] LPITEMIDLIST **
            &EventId
        );
Это явно не работает так как приходят одинаковые pidl2, для всех слотов USB картридера.

Добавлено через 20 часов 58 минут
Убежденный, Я не знаю уже как вас попросить помочь. Пожалуйста помогите мне получить путь к диску, у меня никак не получается.

Добавлено через 7 минут
У меня уже голова кругом идет от этих PITEMIDLIST, LPITEMIDLIST, LPCITEMIDLIST.
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
14.10.2016, 21:15
Цитата Сообщение от zombivadim Посмотреть сообщение
Пожалуйста помогите мне получить путь к диску, у меня никак не получается.
Что именно не получается?

Цитата Сообщение от zombivadim Посмотреть сообщение
и в msdn нет никаких примеров ...
Зато они есть в Windows SDK и других источниках. Тот же Codeproject.

Цитата Сообщение от zombivadim Посмотреть сообщение
Это явно не работает так как приходят одинаковые pidl2, для всех слотов USB картридера.
Как ты определил, что они одинаковые?

Цитата Сообщение от zombivadim Посмотреть сообщение
У меня уже голова кругом идет от этих PITEMIDLIST, LPITEMIDLIST, LPCITEMIDLIST.
Код я привел, направление дальнейших поисков тоже.
Надо попробовать еще FindFirstChangeNotification на букве диска, например.

И я думаю, что копать в сторону WM_DEVICECHANGE вообще бессмысленно,
так как это сообщение приходит при изменении конфигурации оборудования, а
в твоем случае эти изменения случаются только в момент подключения
кардридера. Надо копать в сторону получения уведомлений от самих дисков или
файловых систем. Как раз то, что делает FindFirstChangeNotification и
ReadDirectoryChanges. Других путей я не вижу (кроме, ну разве что, написания
драйвера-минифильтра файловой системы, но это явный overkill в данном случае).
0
12 / 11 / 2
Регистрация: 03.04.2016
Сообщений: 502
14.10.2016, 21:44  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
Код я привел, направление дальнейших поисков тоже
Дело в том что я думаю что SHChangeNotifyRegister, это и есть решение! Все в принципе работает, только осталось получить нормально букву диска, неужели вам трудно черкнуть пару строк кода..

Добавлено через 2 минуты
Цитата Сообщение от Убежденный Посмотреть сообщение
Как ты определил, что они одинаковые?
cout << pidl2 << endl;

Добавлено через 2 минуты
Цитата Сообщение от Убежденный Посмотреть сообщение
Что именно не получается?
Не получается нормально передать указатель на PITEMIDLIST В SHChangeNotification_Lock, а потом получить путь SHGetPathFromIDList((struct _ITEMIDLIST *)pidl2, drive);

Добавлено через 5 минут
Убежденный, SHChangeNotifyRegister выдает SHCNE_DRIVEADD, когда устройства нормально монтируются ( в этом случае их можно отследить и в WM_DEVICECHANGE), но иначе приходит сообщение SHCNE_MEDIAINSERTED и это работает для картридеров которые WM_DEVICECHANGE не видит!
0
Ушел с форума
Эксперт С++
 Аватар для Убежденный
16481 / 7444 / 1187
Регистрация: 02.05.2013
Сообщений: 11,616
Записей в блоге: 1
15.10.2016, 08:42
Цитата Сообщение от zombivadim Посмотреть сообщение
Все в принципе работает, только осталось получить нормально букву диска, неужели вам трудно черкнуть пару строк кода..
Я уже написал - вызывай SHGetPathFromIDList. Не понимаю, какие могут быть трудности
вызвать фукцию с двумя аргументами и проверить, что в буфере, который она заполняет.

Цитата Сообщение от zombivadim Посмотреть сообщение
cout << pidl2 << endl;
Надо сравнивать не PIDL-ы, а то, на что они указывают.
Т.е. сравнивать пути, которые возвращает SHGetPathFromIDList.

Цитата Сообщение от zombivadim Посмотреть сообщение
Не получается нормально передать указатель на PITEMIDLIST В SHChangeNotification_Lock, а потом получить путь SHGetPathFromIDList((struct _ITEMIDLIST *)pidl2, drive);
"Не получается" - это не описание проблемы.
Что конкретно не получается?

Цитата Сообщение от zombivadim Посмотреть сообщение
SHChangeNotifyRegister выдает SHCNE_DRIVEADD, когда устройства нормально монтируются ( в этом случае их можно отследить и в WM_DEVICECHANGE), но иначе приходит сообщение SHCNE_MEDIAINSERTED и это работает для картридеров которые WM_DEVICECHANGE не видит!
Это интересно. Возможно, мы на правильном пути.

Да, и я добавлю по поводу третьего параметра функции SHChangeNotification_Lock,
что он записывает не адрес PIDL, а адрес массива PIDL:
The address of a pointer to a PIDLIST_ABSOLUTE that, when this function returns successfully, receives the list of affected PIDLs.
У Microsoft есть сэмпл под названием Change Notify Watcher
(https://github.com/pauldotknop... ifyWatcher
кстати, рекомендую изучить), там есть такой код:

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
    // in your window procedure call this message to dispatch the events
    void OnChangeMessage(WPARAM wParam, LPARAM lParam)
    {
        long lEvent;
        PIDLIST_ABSOLUTE *rgpidl;
        HANDLE hNotifyLock = SHChangeNotification_Lock((HANDLE)wParam, (DWORD)lParam, &rgpidl, &lEvent);
        if (hNotifyLock)
        {
            if (IsItemNotificationEvent(lEvent))
            {
                IShellItem2 *psi1 = NULL, *psi2 = NULL;
 
                if (rgpidl[0])
                {
                    SHCreateItemFromIDList(rgpidl[0], IID_PPV_ARGS(&psi1));
                }
 
                if (rgpidl[1])
                {
                    SHCreateItemFromIDList(rgpidl[1], IID_PPV_ARGS(&psi2));
                }
 
                // derived class implements this method, that is where the events are delivered
                OnChangeNotify(lEvent, psi1, psi2);
 
                SafeRelease(&psi1);
                SafeRelease(&psi2);
            }
            else
            {
                // dispatch non-item events here in the future
            }
            SHChangeNotification_Unlock(hNotifyLock);
        }
    }
1
12 / 11 / 2
Регистрация: 03.04.2016
Сообщений: 502
15.10.2016, 14:21  [ТС]
Цитата Сообщение от Убежденный Посмотреть сообщение
он записывает не адрес PIDL, а адрес массива PIDL
Огромное спасибо!!Я разобрался, в этом и была моя проблема.Код работает!!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
15.10.2016, 14:21

WM_DEVICECHANGE RegisterDeviceNotification PDEV_BROADCAST_HDR
При приведении происходит исключение System.OverflowException что-то там переполнение из-за чего так? case DBT_DEVICEARRIVAL: { ...

Как обработать WM_DEVICECHANGE?
Нужна помощь, как заделать хук на событие - вставка изъятие USB-устройства???? Алгоритм такой воткнул/вынул флешку и получил месэдж от...

Не могу разобраться с WM_DEVICECHANGE
Здравствуйте! Необходимо перертсовать дерево со списком дисков в системе, когда в(из) USB разъем(а) вставляется (вынимается) флешка или...

RegisterDeviceNotification / WM_DEVICECHANGE / VID _ PID
Не могу подписаться на WM_DEVICECHANGE какие-то неизвестные ошибки не пойму что не так virtual void WndProc(Message% m) override ...

Обработка события подключения и отключения USB(WM_DEVICECHANGE)
Всем привет . Такая задача, требуется отследить подключение и отключение USB. Следующий код работает но выдает одно и тоже в события...


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

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
GitHub Copilot в JetBrains: модель по умолчанию, Fix и контроль MCP
and_y87 12.10.2026
10 октября 2026 года GitHub обновил Copilot для JetBrains: добавил настройки стартовой модели, исправления из диагностики и управление автозапуском MCP. Поддержка IDE 2025. 1 прекращена — требуется. . .
День 5 из 28: Codex подсказывает следующий запрос
and_y87 12.10.2026
9 октября 2026 года OpenAI запустила бету Composer predictions — подсказок следующего сообщения в текущем диалоге Codex. Это помощь с формулировкой запроса, а не автоматическое продолжение задачи. . . .
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru