Форум АНТИЧАТ

Форум АНТИЧАТ (https://forum.antichat.xyz/index.php)
-   С/С++, C#, Delphi, .NET, Asm (https://forum.antichat.xyz/forumdisplay.php?f=24)
-   -   Как аккуратно(!) обнаружить подключение флешки? (https://forum.antichat.xyz/showthread.php?t=94381)

_nic 01.12.2008 23:03

Как аккуратно(!) обнаружить подключение флешки?
 
Как это сделать аккуратно?То есть что бы и флопик не тарахтел,и процессор излишне на слабых машинах не грузился ,и что бы не возникало никаких подозрительных симтопом при вставке\выбросе оптических дисков.
ЗЫ:ганять в цикле по алфавиту GetDriveType как то не очень хочется.

0verbreaK 02.12.2008 03:00

Гоняй в цикле по алфавиту начиная с B по Z и не будет тарахтеть флопик

noobyara 02.12.2008 05:33

Цитата:

Сообщение от _nic
Как это сделать аккуратно?То есть что бы и флопик не тарахтел,и процессор излишне на слабых машинах не грузился ,и что бы не возникало никаких подозрительных симтопом при вставке\выбросе оптических дисков.
ЗЫ:ганять в цикле по алфавиту GetDriveType как то не очень хочется.

возможно стоит посмотреть в строну WMI и Win32_DeviceChangeEvent(да и других событий), только все это дело под XP и выше.

neprovad 02.12.2008 11:34

Предыдущий автор прав. Копать в сторону событий.
http://msdn.microsoft.com/en-us/library/aa363205(VS.85).aspx

_nic 02.12.2008 17:37

Не совсем понял технологию.Это что надо перхватывать WindowProc и смотреть что там в uMsg ?

0x0c0de 02.12.2008 18:03

>> Это что надо перхватывать WindowProc и смотреть что там в uMsg ?

нет. вы регистрируете свой обработчик. и система его вызовет, котгда устройство будет присоединено

http://msdn.microsoft.com/en-us/library/aa363432(VS.85).aspx

_nic 02.12.2008 23:02

ВОт нагуглил более простой пример чем на МСДН
Код:

#include <windows.h>
#include <iostream>
#include <dbt.h>

class CatchAll
{
public:
    LRESULT DeviceChange(DWORD event, PDEV_BROADCAST_HDR pHdr);
    HWND    m_hwnd;
};

LRESULT CatchAll::DeviceChange(DWORD event, PDEV_BROADCAST_HDR pHdr)
{
 BOOL fEvent = FALSE ;
 switch (event)
 {
  case DBT_DEVICEARRIVAL:
  printf("Begin");
  fEvent = TRUE ;
  break ;
  case DBT_DEVICEREMOVECOMPLETE:
  printf( "End");
  fEvent = TRUE ;
 }

 if (fEvent)
 {
  switch( pHdr->dbch_devicetype )
  {
  case DBT_DEVTYP_VOLUME:
    PDEV_BROADCAST_VOLUME pDevVolume = (PDEV_BROADCAST_VOLUME)pHdr;
            // do something...
            printf ("WM_DEVICECHANGE      hurra!!!");
            break;
        }
    }
    return 0;

}

LRESULT CALLBACK MessageLoopProc(HWND m_hwnd,UINT Message,WPARAM wParam,LPARAM lParam)
    {
    CatchAll ca;
    switch ( Message )
        {
        case WM_DEVICECHANGE:
          MessageBox(m_hwnd,TEXT("Device changed"),TEXT("Sys message"),MB_OK);
            printf ("WM_DEVICECHANGE in MessageLoopProc!");
            ca.DeviceChange( wParam, (PDEV_BROADCAST_HDR)lParam);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(m_hwnd,Message,wParam,lParam);
        }

        return 0;

    }

int main()
{

    HINSTANCE hInst = GetModuleHandle(NULL);
    WNDCLASSEX  WndClass;
    HWND m_hwnd;

    char szClassName[] = "HiddenWindow";

    WndClass.cbSize = sizeof(WNDCLASSEX);
    WndClass.style=CS_HREDRAW | CS_VREDRAW;
    WndClass.lpfnWndProc = /*(WNDPROC)*/MessageLoopProc;
    WndClass.cbClsExtra = 0;
    WndClass.cbWndExtra = 0;
    WndClass.hInstance = hInst;
    WndClass.hIcon = 0l;
    WndClass.hCursor = NULL;
    WndClass.hbrBackground = NULL;
    WndClass.lpszMenuName = NULL;
    WndClass.lpszClassName = szClassName;
    WndClass.hIconSm = 0l;

    RegisterClassEx(&WndClass);

    m_hwnd = CreateWindow(  szClassName, "Hidden Window",
                            WS_OVERLAPPEDWINDOW,
                            0,
                            0,
                            10,
                            10,
                            NULL,
                            NULL,
                            hInst,
                            NULL);
    ShowWindow(m_hwnd,SW_SHOW);        // SW_HIDE
    UpdateWindow(m_hwnd);


    MSG                msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

/*  return CatchAll().MessageLoop();*/
    return 0;
}

только вот меня смущяет то что код хоть и выглядит гуевым но точка входа main :confused: Да и ещё непонятно почему мессагбокс вылазит раз 5 при вставке флешки.WM_DEVICECHANGE это что получается при вставке флэхи это событие происходит 5 раз подряд??

noobyara 02.12.2008 23:43

Цитата:

Сообщение от _nic
ВОт нагуглил более простой пример чем на МСДН
Код:

#include <windows.h>
#include <iostream>
#include <dbt.h>

class CatchAll
{
public:
    LRESULT DeviceChange(DWORD event, PDEV_BROADCAST_HDR pHdr);
    HWND    m_hwnd;
};

LRESULT CatchAll::DeviceChange(DWORD event, PDEV_BROADCAST_HDR pHdr)
{
 BOOL fEvent = FALSE ;
 switch (event)
 {
  case DBT_DEVICEARRIVAL:
  printf("Begin");
  fEvent = TRUE ;
  break ;
  case DBT_DEVICEREMOVECOMPLETE:
  printf( "End");
  fEvent = TRUE ;
 }

 if (fEvent)
 {
  switch( pHdr->dbch_devicetype )
  {
  case DBT_DEVTYP_VOLUME:
    PDEV_BROADCAST_VOLUME pDevVolume = (PDEV_BROADCAST_VOLUME)pHdr;
            // do something...
            printf ("WM_DEVICECHANGE      hurra!!!");
            break;
        }
    }
    return 0;

}

LRESULT CALLBACK MessageLoopProc(HWND m_hwnd,UINT Message,WPARAM wParam,LPARAM lParam)
    {
    CatchAll ca;
    switch ( Message )
        {
        case WM_DEVICECHANGE:
          MessageBox(m_hwnd,TEXT("Device changed"),TEXT("Sys message"),MB_OK);
            printf ("WM_DEVICECHANGE in MessageLoopProc!");
            ca.DeviceChange( wParam, (PDEV_BROADCAST_HDR)lParam);
            break;
        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(m_hwnd,Message,wParam,lParam);
        }

        return 0;

    }

int main()
{

    HINSTANCE hInst = GetModuleHandle(NULL);
    WNDCLASSEX  WndClass;
    HWND m_hwnd;

    char szClassName[] = "HiddenWindow";

    WndClass.cbSize = sizeof(WNDCLASSEX);
    WndClass.style=CS_HREDRAW | CS_VREDRAW;
    WndClass.lpfnWndProc = /*(WNDPROC)*/MessageLoopProc;
    WndClass.cbClsExtra = 0;
    WndClass.cbWndExtra = 0;
    WndClass.hInstance = hInst;
    WndClass.hIcon = 0l;
    WndClass.hCursor = NULL;
    WndClass.hbrBackground = NULL;
    WndClass.lpszMenuName = NULL;
    WndClass.lpszClassName = szClassName;
    WndClass.hIconSm = 0l;

    RegisterClassEx(&WndClass);

    m_hwnd = CreateWindow(  szClassName, "Hidden Window",
                            WS_OVERLAPPEDWINDOW,
                            0,
                            0,
                            10,
                            10,
                            NULL,
                            NULL,
                            hInst,
                            NULL);
    ShowWindow(m_hwnd,SW_SHOW);        // SW_HIDE
    UpdateWindow(m_hwnd);


    MSG                msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

/*  return CatchAll().MessageLoop();*/
    return 0;
}

только вот меня смущяет то что код хоть и выглядит гуевым но точка входа main :confused: Да и ещё непонятно почему мессагбокс вылазит раз 5 при вставке флешки.WM_DEVICECHANGE это что получается при вставке флэхи это событие происходит 5 раз подряд??

да хоть nepohek назови главное указать это в параметрах линкера,флаг SUBSYSTEM отвечает за тип приложения (например /SUBSYSTEM:CONSOLE) и флаг ENTRY за точку входа(/ENTRY:"nepohek"). в студии это можно сделать через опции проекта( Linker->System->SubSystem b Linker->Advanced->Entry Point)

0x0c0de 03.12.2008 06:08

Цитата:

да хоть nepohek назови главное указать это в параметрах линкера,флаг SUBSYSTEM отвечает за тип приложения (например /SUBSYSTEM:CONSOLE) и флаг ENTRY за точку входа(/ENTRY:"nepohek"). в студии это можно сделать через опции проекта( Linker->System->SubSystem b Linker->Advanced->Entry Point)
Или в самом коде...

#pragma comment(linker,"/ENTRY:main")

и

#pragma comment(linker,"/SUBSYSTEM:CONSOLE")

neprovad 03.12.2008 20:27

все верно что 5 раз, просто из всего этого изобилия надо выбрать все что попадает под event = DBT_DEVICEARRIVAL

Suteki 20.05.2009 01:34

I need MFC solution
 
Данный код отлично собирается как Win32 Application.

Подскажите как реализовать с использованием MFC :confused:

гугл выдал кусок кода:

Цитата:

Чтобы приложение основанное на MFC могло отловить и отроботать данное сообщение в карте сообщений необходимо написать следующее:

Код:

ON_MESSAGE(WM_DEVICECHANGE, OnDeviceChange)
Из значений которые может принимать wParam для интересующего нас случая важно следующее:
DBT_DEVICEARRIVAL – подключили новое устройство
DBT_DEVICEREMOVECOMPLETE – устройство было отключено

Код:

#include <dbt.h>

LRESULT OnDeviceChange(WPARAM wParam, LPARAM lParam)
{
  // следует обратить внимание на эту строку:
  PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;

  switch(wParam)
  {
      case DBT_DEVICEARRIVAL:
      if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
      {
          PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;

            if (lpdbv -> dbcv_flags & DBTF_MEDIA)
              {
                  MessageBox (NULL, _T(“Устройство подключено”),  _T("WM_DEVICECHANGE"), MB_OK );
              }
        }
        break;

      case DBT_DEVICEREMOVECOMPLETE:
        if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME)
        {
            PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;

            if (lpdbv -> dbcv_flags & DBTF_MEDIA)
              {
                  MessageBox (NULL, _T(“Устройство отключено”),  _T("WM_DEVICECHANGE"), MB_OK );
              }
        }
        break;
  }
}


НО код компилируется с ошибкой:
Код:

error C4716: 'OnDeviceChange' : must return a value Error executing cl.exe.
вставляю перед последний скобкой
Код:

return 0;
Появлятся 2 ошибки:
Код:

MainFrm.obj : error LNK2001: unresolved external symbol "public: long __thiscall CMainFrame::OnDeviceChange(unsigned int,long)" (?OnDeviceChange@CMainFrame@@QAEJIJ@Z)

Debug/FLA.exe : fatal error LNK1120: 1 unresolved externals


Suteki 21.05.2009 03:24

Решение под MFC
 
Проблему решил. Привожу ниже мануал.
Мини-Мануал для MFC

1) В хайдер мейнфрейма (MainFrm.h) добавляем в описание класса прототип функции OnDeviceChangeprotected:)
PHP код:

BOOL OnDeviceChangeUINT nEventTypeDWORD dwData ); 

2) В мейнфрейм (MainFrm.cpp) подключаем хайдер dbt.h
PHP код:

#include <dbt.h> 

3) Дописываем в карту откликов после //}}AFX_MSG_MAP отклик ON_WM_DEVICECHANGE ()
PHP код:

ON_WM_DEVICECHANGE () 

4) В конец мейнфрейма дописываем следующий код:

PHP код:


bool inline IsBitSet 
(DWORD64 dwMaskUINT nTHBit)
{
    
DWORD64 dwBit 1;
    
dwBit <<= nTHBit;
    
dwMask &= dwBit;
    return 
dwMask true false;
}

BOOL CMainFrame::OnDeviceChangeUINT nEventTypeDWORD dwData )
{
    
BOOL bReturn CWnd::OnDeviceChange (nEventTypedwData);

    
DEV_BROADCAST_VOLUME *volume = (DEV_BROADCAST_VOLUME *)dwData;
    
CString log;

    if (
nEventType == DBT_DEVICEARRIVAL)
    {
        if (
volume->dbcv_devicetype == DBT_DEVTYP_VOLUME)
        {
            for (
int n 032n++)
            {
                if (
IsBitSet (volume->dbcv_unitmaskn))
                {
                    
log.Format ("Drive %c: Inserted\n"'A');
        ::
AfxMessageBox(log);

        
log.Format ("%c"'A');
        
// Флешка подключена. Имя флешки в системе содержит строковая переменная log
                
}
            }
        }
    }

    if (
nEventType == DBT_DEVICEREMOVECOMPLETE)
    {
        if (
volume->dbcv_devicetype == DBT_DEVTYP_VOLUME)
        {
            for (
int n 032n++)
            {
                if (
IsBitSet (volume->dbcv_unitmaskn))
                {
                    
log.Format ("Drive %c: Removed\n"'A');
        ::
AfxMessageBox(log);

        
log.Format ("%c"'A');
        
// Флешка извлечена. Имя флешки в системе содержит строковая переменная log
                
}
            }
        }
    }

    return 
bReturn;



Файл проекта + собранный exe


Время: 05:37