SetupDi*系列之启用与停用设备

想要实现类似设备管理器的功能,其实也不是很难,无非就是调用一些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
从设备管理器中,可以验证我们的做法。

源自:http://blog.csdn.net/hhhbbb/article/details/7823611

 

践行渐远

实现禁用鼠标

// 必要的头文件和要链接的LIB文件

#include <stdio.h>    

#include <tchar.h>    

#include <windows.h>  

#include <setupapi.h>

#include <iostream>

#include <Rpc.h>

#pragma comment(lib, "setupapi.lib")

#pragma comment(lib, "Rpcrt4.lib") // for UuidFromString

// device information set(我把它译为设备信息集)

HDEVINFO hDevInfo = NULL;

using namespace std;

BOOL ChangeStatus(DWORD NewStatus, DWORD SelectedItem, HDEVINFO hDevInfo)

{

LPTSTR lpszMsg = NULL;

SP_PROPCHANGE_PARAMS PropChangeParams = {sizeof(SP_CLASSINSTALL_HEADER)};

SP_DEVINFO_DATA DeviceInfoData = {sizeof(SP_DEVINFO_DATA)}; 

// Get a handle to the Selected Item.

if (!SetupDiEnumDeviceInfo(hDevInfo, SelectedItem, &DeviceInfoData))

{

/*FormatMSG(GetLastError(), &lpszMsg);

throw lpszMsg;*/

printf("SetupDiEnumDeviceInfo errorcode = %d",GetLastError());

return FALSE;

}

// Set the PropChangeParams structure.

PropChangeParams.ClassInstallHeader.InstallFunction = DIF_PROPERTYCHANGE;

PropChangeParams.Scope = DICS_FLAG_GLOBAL;

PropChangeParams.StateChange = NewStatus;

if (!SetupDiSetClassInstallParams(hDevInfo, &DeviceInfoData, (SP_CLASSINSTALL_HEADER *)&PropChangeParams,

sizeof(PropChangeParams)))

{

printf("SetupDiSetClassInstallParams errorcode = %d",GetLastError());

return FALSE;

}

// Call the ClassInstaller and perform the change.

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

{

printf("SetupDiCallClassInstaller errorcode = %d",GetLastError());

return FALSE;

}

return TRUE;

}

BOOL ControlDisk(int nStatus, int nIndex)

{

LPTSTR lpszMsg = NULL;

TCHAR * GUIDString = NULL;

GUID guid;

if (-1 == nStatus)

{

return FALSE;

ZeroMemory(&guid, sizeof(GUID));

switch(nIndex)

{

case 1: // 1 代表摄像头 

GUIDString = _T("6bdd1fc6-810f-11d0-bec7-08002be2092f");

UuidFromString((RPC_WSTR)GUIDString, &guid);

break;

case 2: // 2 代表鼠标

GUIDString = _T("4D36E96F-E325-11CE-BFC1-08002BE10318");

UuidFromString((RPC_WSTR)GUIDString, &guid);

break;

}

hDevInfo = SetupDiGetClassDevs(&guid,NULL,NULL,DIGCF_PRESENT);

if (INVALID_HANDLE_VALUE == hDevInfo)

{

printf("SetupDiGetClassDevs errorcode = %d",GetLastError());

return FALSE;

}

DWORD i;

SP_DEVINFO_DATA DeviceInfoData;

ZeroMemory(&DeviceInfoData, sizeof(SP_DEVINFO_DATA));

DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);

for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData); ++i)

{

//cout <<"i= "<<i<<endl;

if (1 == nStatus)

{

ChangeStatus(DICS_ENABLE, i, hDevInfo);

}

else if (0 == nStatus)

{

ChangeStatus(DICS_DISABLE, i, hDevInfo);

}

// 释放 device information set

return SetupDiDestroyDeviceInfoList(hDevInfo);

}

int main()

{

int a;

if(ControlDisk(0,2))

{

printf("Device have Disable \n");

Sleep(5000);

     Sleep(5000);

}

else

{

printf("Device  Disable failed\n");

}

    

if(ControlDisk(1,2))

{

printf("Device have Enable \n");

}

else

{

printf("Device  Enable failed\n");

}

printf("exit \n");

cin >> a;

return 0;

}

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值