如何在Windows服务程序中添加U盘插拔的消息

研究了下这个问题,主要要在一般的windows服务程序中修改两个地方:

一、调用RegisterServiceCtrlHandlerEx

VOID WINAPI SvcMain( DWORD dwArgc, LPTSTR *lpszArgv )
{
    // Register the handler function for the service.

    gSvcStatusHandle = RegisterServiceCtrlHandlerEx(
        SVCNAME,
        SvcCtrlHandler,
        NULL);

    if( !gSvcStatusHandle )
    {
        printf("Failed to register service control handler");
        return;
    }

    // These SERVICE_STATUS members remain as set here.

    gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
    gSvcStatus.dwServiceSpecificExitCode = 0;    

    // Report initial status to the SCM.

    ReportSvcStatus( SERVICE_START_PENDING, NO_ERROR, 3000 );

    // Perform service-specific initialization and work.

    HDEVNOTIFY hDevNotify;

    if(!DoRegisterDeviceInterface(GUID_DEVINTERFACE_VOLUME, &hDevNotify))
    {
        printf("DoRegisterDeviceInterface failed\n");
        ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
        return;
    }

    SvcInit( dwArgc, lpszArgv );

    UnregisterDeviceNotification(hDevNotify);
}

二、注册设备响应接口

/*
Routine Description:
    Registers for notification of changes in the device interfaces for
    the specified interface class GUID.

Parameters:
    InterfaceClassGuid - The interface class GUID for the device
        interfaces.

    hDevNotify - Receives the device notification handle. On failure,
        this value is NULL.

Return Value:
    If the function succeeds, the return value is TRUE.
    If the function fails, the return value is FALSE.
*/

BOOL DoRegisterDeviceInterface(
    GUID InterfaceClassGuid,
    HDEVNOTIFY *hDevNotify
)

{
    DEV_BROADCAST_DEVICEINTERFACE NotificationFilter;

    ZeroMemory( &NotificationFilter, sizeof(NotificationFilter) );
    NotificationFilter.dbcc_size =
        sizeof(DEV_BROADCAST_DEVICEINTERFACE);
    NotificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
    NotificationFilter.dbcc_classguid = InterfaceClassGuid;

    *hDevNotify = RegisterDeviceNotification(
        gSvcStatusHandle,
        &NotificationFilter,
        DEVICE_NOTIFY_SERVICE_HANDLE
    );

    if(!*hDevNotify)
    {
        printf("RegisterDeviceNotification failed: %d\n",
                GetLastError());
        return FALSE;
    }

    return TRUE;
}

三、处理U盘插拔消息


DWORD WINAPI SvcCtrlHandler(DWORD dwCtrl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
    // Handle the requested control code.
    switch(dwCtrl)
    {  
    case SERVICE_CONTROL_STOP:
        ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);

        // Signal the service to stop.

        SetEvent(ghSvcStopEvent);
        
        return NO_ERROR;

    case SERVICE_CONTROL_DEVICEEVENT:
        if (DBT_DEVICEARRIVAL  == dwEventType)
        {
            FILE *fp;
            
            DEV_BROADCAST_HDR * pHdr = (DEV_BROADCAST_HDR *)lpEventData;
            PDEV_BROADCAST_DEVICEINTERFACE pDevInf;
            PDEV_BROADCAST_HANDLE pDevHnd;
            PDEV_BROADCAST_OEM pDevOem;
            PDEV_BROADCAST_PORT pDevPort;
            PDEV_BROADCAST_VOLUME pDevVolume;

            switch( pHdr->dbch_devicetype )
            {
            case DBT_DEVTYP_DEVICEINTERFACE:
                pDevInf = (PDEV_BROADCAST_DEVICEINTERFACE)pHdr;

                fp = fopen("C:\\log.txt", "a+");
                if (fp)
                {
                    _ftprintf(fp, _T("%s\n"), pDevInf->dbcc_name);
                    fclose(fp);
                }
                break;
            case DBT_DEVTYP_HANDLE:
                pDevHnd = (PDEV_BROADCAST_HANDLE)pHdr;
                break;
            case DBT_DEVTYP_OEM:
                pDevOem = (PDEV_BROADCAST_OEM)pHdr;
                break;
            case DBT_DEVTYP_PORT:
                pDevPort = (PDEV_BROADCAST_PORT)pHdr;
                break;
            case DBT_DEVTYP_VOLUME:
                pDevVolume = (PDEV_BROADCAST_VOLUME)pHdr;
                break;
            }
        }
        break;

    case SERVICE_CONTROL_INTERROGATE:
        // Fall through to send current status.
        break;

    default:
        break;
    }

    ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
    return NO_ERROR;
}

posted @ 2014-06-18 16:46  Max Woods  阅读(1320)  评论(0编辑  收藏  举报