启用禁用设备

想要实现类似设备管理器的功能,其实也不是很难,无非就是调用一些API函数,就像本文描述的,采用的API函数就是SetupDi系列的函数。不过这类函数有很多,具体的请参见MSDN,而实现设备启用、停用仅需要用到的就只有5个函数:
       SetupDiGetClassDevs                  // 获取设备信息集
       SetupDiEnumDeviceInfo                // 从设备信息集中枚举每个设备的具体信息
       SetupDiGetDeviceRegistryProperty     // 从注册表中读取PnP设备的属性
       SetupDiSetClassInstallParams         // 设置(包括取消)设备类的安装参数
       SetupDiCallClassInstaller            // 安装指定设备
以上函数均在setupapi.h头文件中声明,该头文件包含在setupapi.lib函数库中(使用以上函数前需要声明这个头文件)。

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

首先,我们需要声明两个变量用来保存指定设备类的属性信息:
    HDEVINFO       m_hDevInfo;             // 类似设备句柄,以下暂且称为设备句柄
    SP_DEVINFO_DATAm_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。
从设备管理器中,可以验证我们的做法。  

int index = 0;

         DWORD DataType, length;

         HDEVINFO hDevInfo;

         SP_DEVINFO_DATA devInfoElem;

         TCHAR szDevDetail[SPDRP_MAXIMUM_PROPERTY][NORMAL_LEN];

         GUIDnguid{0X4D36E96F,0XE325,0X11CE,0XBF,0XC1,0X08,0X00,0X2B,0XE1,0X03,0X18 };

         hDevInfo = SetupDiGetClassDevs((LPGUID)&nguid, NULL, NULL, DIGCF_PRESENT);

 

         if (INVALID_HANDLE_VALUE != hDevInfo)

         {

                   devInfoElem.cbSize = sizeof(SP_DEVINFO_DATA);

                   while (SetupDiEnumDeviceInfo(hDevInfo, index++, &devInfoElem))

                   {

                            memset((TCHAR*)szDevDetail, 0x00, sizeof(szDevDetail) / sizeof(TCHAR));

                            SetupDiGetDeviceRegistryProperty(

                                     hDevInfo,

                                     &devInfoElem,

                                     SPDRP_DEVICEDESC,

                                     &DataType,

                                     (PBYTE)szDevDetail[SPDRP_DEVICEDESC],

                                     NORMAL_LEN,

                                     (LPDWORD)&length);

 

                            strrchr(szDevDetail[SPDRP_DEVICEDESC], _T(' '));

 

                            SetupDiGetDeviceRegistryProperty(

                                     hDevInfo,

                                     &devInfoElem,

                                     SPDRP_HARDWAREID,

                                     &DataType,

                                     (PBYTE)szDevDetail[SPDRP_HARDWAREID],

                                     NORMAL_LEN,

                                     (LPDWORD)&length);

 

                            _strlwr_s(szDevDetail[SPDRP_HARDWAREID]);

                            CString gszHardwareID_PC,gszHardwareID_Phone(szDevDetail[SPDRP_HARDWAREID]);

                           

#if 1

                            CString Outstr;

                            Outstr.Format(_T("\nAct data is %s,Act data is %s"), szDevDetail[SPDRP_DEVICEDESC], szDevDetail[SPDRP_HARDWAREID]);

                            OutputDebugString(Outstr);

#endif

                            SP_PROPCHANGE_PARAMS PropChangeParams;

                            SP_DEVINSTALL_PARAMS devParams;

                            DWORD dwResult;

 

                            //设置设备属性变化参数

                            PropChangeParams.ClassInstallHeader.cbSize= sizeof(SP_CLASSINSTALL_HEADER);

                            PropChangeParams.ClassInstallHeader.InstallFunction= DIF_PROPERTYCHANGE;

                            PropChangeParams.Scope= DICS_FLAG_GLOBAL; //使修改的属性保存在所有的硬件属性文件

                            PropChangeParams.StateChange= DICS_DISABLE;

                            PropChangeParams.HwProfile= 0;

 

                            //改变设备属性

                            if (!SetupDiSetClassInstallParams(hDevInfo,

                                     &devInfoElem,

                                     (SP_CLASSINSTALL_HEADER *)&PropChangeParams,

                                     sizeof(PropChangeParams)))

                            {

                                     dwResult =GetLastError();

                                     Outstr.Format("\nSetupDiSetClassInstallParams1FAILED, Error Code is %d", dwResult);

                                     OutputDebugString(Outstr);

                                     return;

                            }

 

                            PropChangeParams.ClassInstallHeader.cbSize= sizeof(SP_CLASSINSTALL_HEADER);

                            PropChangeParams.ClassInstallHeader.InstallFunction= DIF_PROPERTYCHANGE;

                            PropChangeParams.Scope= DICS_FLAG_CONFIGSPECIFIC;//使修改的属性保存在指定的属性文件

                            PropChangeParams.StateChange= DICS_DISABLE;

                            PropChangeParams.HwProfile= 0;

 

                            //改变设备属性并调用安装服务

                            if (!SetupDiSetClassInstallParams(hDevInfo,&devInfoElem,(SP_CLASSINSTALL_HEADER *)&PropChangeParams,sizeof(PropChangeParams)))

                            {

                                     dwResult =GetLastError();

                                     Outstr.Format("\nSetupDiSetClassInstallParams2FAILED, Error Code is %d", dwResult);

                                     OutputDebugString(Outstr);

                                     return;

                            }

                            if (!SetupDiCallClassInstaller(DIF_PROPERTYCHANGE, hDevInfo, &devInfoElem))

                            {

                                     dwResult =GetLastError();

                                     Outstr.Format("\nSetupDiCallClassInstallerFAILED, Error Code is %d", dwResult);

                                     OutputDebugString(Outstr);

                                     return;

                            }

                            else

                            {

                                     //判断是否需要重新启动

                                     devParams.cbSize= sizeof(devParams);

                                     if (!SetupDiGetDeviceInstallParams(hDevInfo, &devInfoElem, &devParams))

                                     {

Outstr.Format("\nSetupDiGetDeviceInstallParams, Error Code is %d", dwResult);

                                      OutputDebugString(Outstr);


                                               return;

                                     }

 

                                     if (devParams.Flags & (DI_NEEDRESTART | DI_NEEDREBOOT))

                                     {

                                               OutputDebugString("Need Restart Computer");

                                               return;

                                     }

                            }

 

                   } //while

                   SetupDiDestroyDeviceInfoList(hDevInfo);

         }

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值