背景
项目背景为非UVC标准USB工业相机,连接Windows PC,需要安装特定USB驱动。我负责开发PC端相机软件部分(已完成),所以也需要把驱动安装这部分囊括进来。
USB芯片厂商已经提供了winxp/winvista/win7/win8/win8.1/win10、32bits/64bits不同平台的不同驱动文件,包括.inf、.sys、.cat、.dll文件。因此插上相机设备后,可以找到对应平台驱动,通过Windows设备管理器或者右键.inf文件进行驱动的安装。但是这些事情对于开发人员只是鼠标点点的操作,对于用户却会成为很麻烦的事情。因此开发PC端软件的我需要简化驱动安装的一切操作,尽量做到对用户透明。
捣鼓了不少时间,写出目前的解决方案。
驱动安装
为了让用户接触不到驱动安装的繁琐操作,只能用代码解决了,解决过程中在《竹林蹊径——深入浅出Windows驱动开发》这本书上受益匪浅,大概阅读,也算是加深了硬件设备与Windows系统间连接过程的理解。
开发环境win8.1 vs2013 c++ 控制台应用程序(有预编译头)
spdlog为日志输出(github开源项目)
使用的ANSI字符串
- 驱动预安装部分,上代码,参考竹林蹊径第12章
API参考链接
该函数成功运行需要程序具有管理员权限,具体可在项目属性->链接器->清单文件->UAC执行级别中更改为requireAdministrator。
BOOL InstallDriver(TCHAR* inf_path, TCHAR* inf_name_out)
{
/*
* inf_path: .inf文件所在路径,例如C:\\driver.inf
* inf_name_out: inf文件预安装成功或系统已存在,则返回相应文件名,如oemxx.inf
*/
TCHAR path1[MAX_PATH] = {
0};
TCHAR *path2;
if (FALSE == SetupCopyOEMInf(inf_path, NULL, SPOST_PATH, SP_COPY_NOOVERWRITE, path1, MAX_PATH, NULL, &path2)) //需要管理员权限
{
DWORD error = GetLastError();
if (error == ERROR_FILE_EXISTS)
{
spdlog::get("driver_install_info")->info("the driver file has existed, so succeeded");
//cout << "the driver file has existed, so succeeded" << endl;
//_tprintf(_T("the oem name is: %s\n"), path2);
spdlog::get("driver_install_info")->info("the oem name is: \n" + string(path2));
//cout << path2;
//printf("the file name is: %s", path2);
_tcscpy_s(inf_name_out, MAX_PATH, path2);
return TRUE;
}
else
{
spdlog::get("driver_install_info")->info("install failed, ");