400-087-2658/3369821412微信同号

USB设备的管控

来源:内蒙古网络工程师培训学校 发布时间:2015/8/28 17:08:17

想要实现类似设备管理器的功能,其实也不是很难,无非就是调用一些API函数,就像本文描述的,采用的API函数就是SetupDi系列的函数。不过这类函数有很多,具体的请参见MSDN,而实现设备启用、停用仅需要用到的就只有5个函数:

       SetupDiGetClassDevs                   // 获取设备信息集

       SetupDiEnumDeviceInfo                 // 从设备信息集中枚举每个设备的具体信息

       SetupDiGetDeviceRegistryProperty      // 从注册表中读取PnP设备的属性

       SetupDiSetClassInstallParams          // 设置(包括取消)设备类的安装参数

       SetupDiCallClassInstaller             // 安装指定设备

以上函数均在setupapi.h头文件中声明,该头文件包含在setupapi.lib函数库中(使用以上函数前需要声明这个头文件)。

接下来就是如何实现设备的启用与停用。

从原理上讲,设备的启用与停用其实就是对该设备进行重安装。


首先,我们需要声明两个变量用来保存指定设备类的属性信息:

   HDEVINFO        m_hDevInfo;              // 类似设备句柄,以下暂且称为设备句柄

   SP_DEVINFO_DATA m_DeviceInfoData;         // 设备详细属性信息


然后调用SetupDiGetClassDevs函数获取设备句柄的值。(在这个函数中,需要指定设备类的GUID,如果不清楚这个GUID,可以在相应的安装文件.inf中查找。注意:是设备类的GUID,不是设备的GUID!)


接着循环使用SetupDiEnumDeviceInfo函数枚举对应设备类中的设备,并使用 SetupDiGetDeviceRegistryProperty函数获取得到的设备的详细信息,进行判断是否为所需的设备(判断的方式有多种,具体参考MSDN,本文采用设备描述进行判断)。

一旦枚举结束(即枚举不成功,而且用GetLastError()可以得到错误码259)即可退出循环。当然如果找到设备,即可break退出。


如果找到对应的设备,就调用SetupDiSetClassInstallParams函数设置安装的属性。这里有个注意的地方需要详细说明一下:

SetupDiSetClassInstallParams的函数原型如下:

WINSETUPAPI BOOL WINAPI

SetupDiSetClassInstallParams(

   IN HDEVINFO DeviceInfoSet,

   IN PSP_DEVINFO_DATA DeviceInfoData, OPTIONAL

   IN PSP_CLASSINSTALL_HEADER ClassInstallParams, OPTIONAL

   IN DWORD ClassInstallParamsSize

   );

注意第三个参数PSP_CLASSINSTALL_HEADER ClassInstallParams,

这里我们不采用这个结构,而是采用另外一个结构:SP_PROPCHANGE_PARAMS

并在这个结构中,

设置ClassInstallHeader字段中(我们发现这个字段也是一个结构,就是PSP_CLASSINSTALL_HEADER结构)的InstallFunction字段值为DIF_PROPERTYCHANGE,

设置StateChange值为DICS_ENABLE(该值为启用,若是停用则为DICS_DISABLE)

然后采用强行转换将其转为PSP_CLASSINSTALL_HEADER结构。


较后,调用SetupDiCallClassInstaller函数执行设备的安装(即:启用或者停用),注意该函数个参数值应为DIF_PROPERTYCHANGE。

从设备管理器中,可以验证我们的做法。


以下贴出我程序中的主要源码。


BOOL               rlt            = FALSE;

  CString            csFriendlyName = myDevcieName;

// 请修改该值


GUID               devGUID         = {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX};

// 这个值不用我再说了吧?!


HDEVINFO           m_hDevInfo     = INVALID_HANDLE_VALUE;


SP_DEVINFO_DATA    m_DeviceInfoData;

RtlZeroMemory(&m_DeviceInfoData, sizeof(SP_DEVINFO_DATA));

m_DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

// 初始化m_DeviceInfoData,当然这只是范例,

// 有其他初始化的方法,大家见仁见智


m_hDevInfo = SetupDiGetClassDevs(&devGUID,0,0,DIGCF_PRESENT );


for (DWORD i = 0; SetupDiEnumDeviceInfo ( m_hDevInfo, i, &m_DeviceInfoData ); i++ )

{

       DWORD DataT;

       LPTSTR buffer   = NULL;

       DWORD buffersize = 0;

       

       while ( !SetupDiGetDeviceRegistryProperty

             (

                  m_hDevInfo,

                  &m_DeviceInfoData,

                  SPDRP_DEVICEDESC,

                  &DataT,

                   (PBYTE)buffer,

                  buffersize,

                   &buffersize

         ) )

       {

           if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)

           {

                // Change the buffer size.

                if (buffer)

                {

                      LocalFree(buffer);

                 }

                buffer = (char*)LocalAlloc(LPTR,buffersize);

           }

            else

           {

                break;

            }

        }        if ( ( buffer != NULL ) && ( csFriendlyName.Find ( buffer, 0 ) != ( -1 ) ) )

       {

           if (buffer)

           {

                LocalFree(buffer);

           }

            break;

        }

               

        if (buffer)

       {

            LocalFree(buffer);

       }

}

SP_PROPCHANGE_PARAMS propChange = { sizeof ( SP_CLASSINSTALL_HEADER ) };

propChange.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;

propChange.Scope = DICS_FLAG_GLOBAL;

propChange.StateChange = DICS_ENABLE;    // 启用,或是停用,请使用DICS_DISABLE

if (m_DeviceInfoData.DevInst != NULL)

{

       rlt = SetupDiSetClassInstallParams

       (      

               m_hDevInfo,

               &m_DeviceInfoData,

               ( SP_CLASSINSTALL_HEADER * ) &propChange,

               sizeof ( propChange )

        );

}

if ( rlt )

{

        rlt = SetupDiCallClassInstaller ( DIF_PROPERTYCHANGE, m_hDevInfo, &m_DeviceInfoData );

  }

领取试听课
每天限量名额,先到先得
温馨提示:为不影响您的学业,来校区前请先电话或QQ咨询,方便我校安排相关的专业老师为您解答
  • 详情请进入 内蒙古网络工程师培训...

关于我们 | 招生信息 | 新闻中心 | 学校动态

版权所有:搜学搜课(www.soxsok.com)