概述
想要实现类似设备管理器的功能,其实也不是很难,无非就是调用一些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 failedn");
}
if(ControlDisk(1,2))
{
printf("Device have Enable n");
}
else
{
printf("Device Enable failedn");
}
printf("exit n");
cin >> a;
return 0;
}
最后
以上就是超级钻石为你收集整理的SetupDi*系列之启用与停用设备的全部内容,希望文章能够帮你解决SetupDi*系列之启用与停用设备所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复