Как аккуратно(!) обнаружить подключение флешки?

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by _nic, 1 Dec 2008.

  1. _nic

    _nic Elder - Старейшина

    Joined:
    5 May 2006
    Messages:
    651
    Likes Received:
    54
    Reputations:
    3
    Как это сделать аккуратно?То есть что бы и флопик не тарахтел,и процессор излишне на слабых машинах не грузился ,и что бы не возникало никаких подозрительных симтопом при вставке\выбросе оптических дисков.
    ЗЫ:ганять в цикле по алфавиту GetDriveType как то не очень хочется.
     
    #1 _nic, 1 Dec 2008
    Last edited: 1 Dec 2008
  2. 0verbreaK

    0verbreaK Elder - Старейшина

    Joined:
    30 Apr 2008
    Messages:
    318
    Likes Received:
    42
    Reputations:
    -3
    Гоняй в цикле по алфавиту начиная с B по Z и не будет тарахтеть флопик
     
    1 person likes this.
  3. noobyara

    noobyara Member

    Joined:
    27 Jan 2008
    Messages:
    13
    Likes Received:
    8
    Reputations:
    0
    возможно стоит посмотреть в строну WMI и Win32_DeviceChangeEvent(да и других событий), только все это дело под XP и выше.
     
  4. neprovad

    neprovad Elder - Старейшина

    Joined:
    19 Oct 2007
    Messages:
    900
    Likes Received:
    275
    Reputations:
    59
    Предыдущий автор прав. Копать в сторону событий.
    http://msdn.microsoft.com/en-us/library/aa363205(VS.85).aspx
     
    #4 neprovad, 2 Dec 2008
    Last edited: 2 Dec 2008
    1 person likes this.
  5. _nic

    _nic Elder - Старейшина

    Joined:
    5 May 2006
    Messages:
    651
    Likes Received:
    54
    Reputations:
    3
    Не совсем понял технологию.Это что надо перхватывать WindowProc и смотреть что там в uMsg ?
     
  6. 0x0c0de

    0x0c0de Elder - Старейшина

    Joined:
    25 May 2007
    Messages:
    441
    Likes Received:
    396
    Reputations:
    297
    >> Это что надо перхватывать WindowProc и смотреть что там в uMsg ?

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

    http://msdn.microsoft.com/en-us/library/aa363432(VS.85).aspx
     
    #6 0x0c0de, 2 Dec 2008
    Last edited: 2 Dec 2008
  7. _nic

    _nic Elder - Старейшина

    Joined:
    5 May 2006
    Messages:
    651
    Likes Received:
    54
    Reputations:
    3
    ВОт нагуглил более простой пример чем на МСДН
    Code:
    #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 раз подряд??
     
    #7 _nic, 2 Dec 2008
    Last edited: 2 Dec 2008
  8. noobyara

    noobyara Member

    Joined:
    27 Jan 2008
    Messages:
    13
    Likes Received:
    8
    Reputations:
    0
    да хоть nepohek назови главное указать это в параметрах линкера,флаг SUBSYSTEM отвечает за тип приложения (например /SUBSYSTEM:CONSOLE) и флаг ENTRY за точку входа(/ENTRY:"nepohek"). в студии это можно сделать через опции проекта( Linker->System->SubSystem b Linker->Advanced->Entry Point)
     
  9. 0x0c0de

    0x0c0de Elder - Старейшина

    Joined:
    25 May 2007
    Messages:
    441
    Likes Received:
    396
    Reputations:
    297
    Или в самом коде...

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

    и

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

    neprovad Elder - Старейшина

    Joined:
    19 Oct 2007
    Messages:
    900
    Likes Received:
    275
    Reputations:
    59
    все верно что 5 раз, просто из всего этого изобилия надо выбрать все что попадает под event = DBT_DEVICEARRIVAL
     
  11. Suteki

    Suteki Member

    Joined:
    18 May 2009
    Messages:
    10
    Likes Received:
    7
    Reputations:
    12
    I need MFC solution

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

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

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

    НО код компилируется с ошибкой:
    Code:
    error C4716: 'OnDeviceChange' : must return a value Error executing cl.exe.
    вставляю перед последний скобкой
    Code:
    return 0;
    Появлятся 2 ошибки:
    Code:
    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
     
    1 person likes this.
  12. Suteki

    Suteki Member

    Joined:
    18 May 2009
    Messages:
    10
    Likes Received:
    7
    Reputations:
    12
    Решение под 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