小弟目前做的项目需要在Windows下安装一个简单的USB驱动,驱动程序由第三方提供(没有经过MS认证),包含DLL、INF、SYS等等文件。
一般情况下,当即插即用设备连上PC后,如果PC中没有该设备的驱动,会弹出安装驱动的提示,用户根据提示来一步步安装就可以了。
现在这个项目需要事先就把驱动安装到PC中去,也就是把安装驱动这件事放在安装软件(项目最终的发布软件)的过程中完成。那么应该怎么去安装驱动呢?
并且由于软件最终会运行在XP、VISTA和Windows7下面,那么这三个系统下的自动安装的过程有多大的区别呢?
PS:请教过一个高手,写个精简DOS程序即可,但还是没有弄清楚。正在看《Windows驱动开发技术详解》,由于不是写驱动,只是安装驱动,这本书中也没有找到可行的办法。
32 个解决方案
#1
楼主关键是要实现你的设备的HID,我们采用一个带USB的单片机,开始也没实现免驱,后来市场需求,我们采用挂接在HID上,实现了免驱设计。即可以利用电脑的自带的USB的等驱动文件,自动识别我的设备。
oogle与百度下“免驱设计 HID”
一下几篇文章很不错,
http://www.dzsc.com/data/html/2009-7-21/77757.html
http://www.abc188.com/info/html/wangzhanyunying/jianzhanjingyan/20080417/67834.html
http://linux.chinaunix.net/techdoc/install/2008/03/14/983179.shtml
oogle与百度下“免驱设计 HID”
一下几篇文章很不错,
http://www.dzsc.com/data/html/2009-7-21/77757.html
http://www.abc188.com/info/html/wangzhanyunying/jianzhanjingyan/20080417/67834.html
http://linux.chinaunix.net/techdoc/install/2008/03/14/983179.shtml
#2
感谢楼上解答。
只是楼上提供的是关于libUSB的相关资料。
而且驱动程序已经有提供了,我需要安装这个驱动。
只是楼上提供的是关于libUSB的相关资料。
而且驱动程序已经有提供了,我需要安装这个驱动。
#3
这个感觉向是把你的驱动 要加载到操作系统中,做到即插即用的,就跟我们使用U盘是一样的
楼主可以写个啥程序,把驱动加载到PC上,只要插上你的设备 就可以识别
这只是我的想法 具体这软件咋写 我也不会
楼主可以写个啥程序,把驱动加载到PC上,只要插上你的设备 就可以识别
这只是我的想法 具体这软件咋写 我也不会
#4
我也想知道,好像没有见过类似的做法。
#5
回cfanlwn: 是的。因为用到了一个USB转串口的芯片,所以要安装下驱动,当然就像平常那样的,当硬件接上PC后,按照提示一步一步安装也可以。但是这样子一来是使得用户的使用变得麻烦,而且增加了安装过程的风险(比如说MS的数字认证问题)。所以现在要将驱动在安装程序的时候就安装上去。
就是不晓得应该怎么做啊。。。
就是不晓得应该怎么做啊。。。
#6
你说让他自动获取,然后我们一步步安装,最后安装上也就是把一些信息放在WINDOWS下,然后在注册表中加写信息,楼主可以查查这些资料,看能不能写个批处理程序
#7
回cfanlwn:
是不是大家都是通过批处理来做这件事的?因为我问了其他版块的高手,有人也这么说的。
有个高手提供了如下的批处理脚本:
echo 安装驱动
rundll32.exe setupapi.dll,InstallHinfSection DefaultInstall 128 %inf%
echo 安装完成
我没有写过批处理脚本,刚刚找了一篇批处理的文章正在屁颠屁颠的看。
能帮忙分析一下这个脚本么?
是不是大家都是通过批处理来做这件事的?因为我问了其他版块的高手,有人也这么说的。
有个高手提供了如下的批处理脚本:
echo 安装驱动
rundll32.exe setupapi.dll,InstallHinfSection DefaultInstall 128 %inf%
echo 安装完成
我没有写过批处理脚本,刚刚找了一篇批处理的文章正在屁颠屁颠的看。
能帮忙分析一下这个脚本么?
#8
请教cfanlwn:
我刚刚试了一下。
批处理代码如下:
@echo off
echo 判断系统版本
set inf=D:\XP\DRIVER\CH341WDM.INF
echo 安装驱动
rundll32.exe setupapi.dll,InstallHinfSection DefaultInstall 128 %inf%
echo 安装完成
发现没有安装上去,请问是怎么一回事呢? 问题出在哪里了呢?
我刚刚试了一下。
批处理代码如下:
@echo off
echo 判断系统版本
set inf=D:\XP\DRIVER\CH341WDM.INF
echo 安装驱动
rundll32.exe setupapi.dll,InstallHinfSection DefaultInstall 128 %inf%
echo 安装完成
发现没有安装上去,请问是怎么一回事呢? 问题出在哪里了呢?
#9
用DeviceTree查看了一下,确实没有安装上去。。。
#10
一般的USB转串口的芯片,都会由这个芯片厂家提供PC端的驱动,一般只要实现在PC上安装驱动,之后你随时插拔,系统就会自动识别你的设备。
我们用到很多USB转串口的转接线都是这样的,我们用CP2102做的一款产品也是这样,先人为安装驱动,之后就不用管了、
#11
既然第三方已经提供了“包含DLL、INF、SYS等等文件。”
楼主是否可以百度或者google下,“如何生成exe可执行文件”。
我们当时做项目,就把这个DLL和一些系统文件,用专用的软件人为生成了一个exe,之后一点就自动运行。
楼主是否可以百度或者google下,“如何生成exe可执行文件”。
我们当时做项目,就把这个DLL和一些系统文件,用专用的软件人为生成了一个exe,之后一点就自动运行。
#12
回kyzf:
谢谢提示啊~~
因为这个驱动没有取得MS的认证,所以如果人工安装的话可能对那些警告提示感到头疼。
关于生成exe可执行文件,是个不错的方法,我现在看到有人用批处理程序就搞定了,所以就先按照那个方法先试了一下。。
没找到专业软件生成EXE文件,能提供一个下载的链接或者方法么?谢谢咯~~
另外,“把这个DLL和一些系统文件,用专用的软件人为生成了一个exe”,请问还需要哪些系统文件呢?最后生成的EXE可执行文件会不会很大啊??
谢谢提示啊~~
因为这个驱动没有取得MS的认证,所以如果人工安装的话可能对那些警告提示感到头疼。
关于生成exe可执行文件,是个不错的方法,我现在看到有人用批处理程序就搞定了,所以就先按照那个方法先试了一下。。
没找到专业软件生成EXE文件,能提供一个下载的链接或者方法么?谢谢咯~~
另外,“把这个DLL和一些系统文件,用专用的软件人为生成了一个exe”,请问还需要哪些系统文件呢?最后生成的EXE可执行文件会不会很大啊??
#13
为什么我按照系统提示来安装的时候 那个进度条显示的安装内容是DLL文件 而用批处理倒的时候 显示安装的内容是SYS文件
一般驱动程序不都是INF+VXD+SYS么? 我知道那个DLL文件里提供了一些操作数据流的接口。
不明白的是,安装驱动到底是要copy哪些内容到系统文件夹呢?
一般驱动程序不都是INF+VXD+SYS么? 我知道那个DLL文件里提供了一些操作数据流的接口。
不明白的是,安装驱动到底是要copy哪些内容到系统文件夹呢?
#14
重新测试过了,DLL文件和SYS文件都已经COPY到了正确的系统文件夹下面。但是插上硬件的时候,系统还是会弹出安装驱动的提示。
是不是和注册表有关系呢?
我按照系统提示安装的驱动 和 通过批处理程序安装的驱动 所调用的INF文件时同一个文件啊。
按理说应该不会出现注册表的修改内容不一致的情况。
请教各位老大 , 这到底是什么情况呢?
是不是和注册表有关系呢?
我按照系统提示安装的驱动 和 通过批处理程序安装的驱动 所调用的INF文件时同一个文件啊。
按理说应该不会出现注册表的修改内容不一致的情况。
请教各位老大 , 这到底是什么情况呢?
#15
Windows DDK中有一个例子叫做BindView可以实现你的目的,不过如果没有数字证书,是一定会弹出提示“驱动可能不安全”的窗口的。前几天我刚把BindView中自动安装的代码分离了出来,有需要的话可以跟我联系。
#16
回hzy_76:
BindView的实现原理是什么呢? 也是通过WDM加载的么?还是通过NT方式加载的(这个方法在《Windows驱动开发技术详解》第三章有附带的源代码)。
另外怎么联系你呢?
BindView的实现原理是什么呢? 也是通过WDM加载的么?还是通过NT方式加载的(这个方法在《Windows驱动开发技术详解》第三章有附带的源代码)。
另外怎么联系你呢?
#17
应该是WDM吧,我是用来安装我自己写的NDIS驱动的,已经调试通过。如果需要的话,留言给我,我可以把代码发给你。
驱动开发我也是初学者,有问题一起探讨!
驱动开发我也是初学者,有问题一起探讨!
#18
回楼上: 给你留言了,指点我一下吧。
#19
回头看了一下,那段代码好像是安装网络驱动的,你这种驱动可能不适合。
我把代码贴出来吧,你自己研究看看是否可以借鉴:
我把代码贴出来吧,你自己研究看看是否可以借鉴:
//这两个是对应网络服务和网卡的定义,安装其他驱动时需要修改
const GUID *pguidClassService = &GUID_DEVCLASS_NETSERVICE;
const GUID *pguidClassNet = &GUID_DEVCLASS_NET;
//
// Function: ReleaseRef
//
// Purpose: Release reference.
//
// Arguments:
// punk [in] IUnknown reference to release.
//
// Returns: Reference count.
//
// Notes:
//
VOID CTryCodeDlg::ReleaseRef (IN IUnknown* punk)
{
if (punk)
{
punk->Release();
}
return;
}
//
// Function: HrGetINetCfg
//
// Purpose: Get a reference to INetCfg.
//
// Arguments:
// fGetWriteLock [in] If TRUE, Write lock.requested.
// lpszAppName [in] Application name requesting the reference.
// ppnc [out] Reference to INetCfg.
// lpszLockedBy [in] Optional. Application who holds the write lock.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetINetCfg (IN BOOL fGetWriteLock, IN LPCWSTR lpszAppName, OUT INetCfg** ppnc, OUT LPWSTR *lpszLockedBy)
{
INetCfg *pnc = NULL;
INetCfgLock *pncLock = NULL;
HRESULT hr = S_OK;
//
// Initialize the output parameters.
//
*ppnc = NULL;
if (lpszLockedBy)
{
*lpszLockedBy = NULL;
}
//
// Create the object implementing INetCfg.
//
hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (void**)&pnc);
if (hr == S_OK)
{
if (fGetWriteLock)
{
//
// Get the locking reference
//
hr = pnc->QueryInterface(IID_INetCfgLock, (LPVOID *)&pncLock);
if (hr == S_OK)
{
//
// Attempt to lock the INetCfg for read/write
//
hr = pncLock->AcquireWriteLock(LOCK_TIME_OUT, lpszAppName, lpszLockedBy);
if (hr == S_FALSE)
{
hr = NETCFG_E_NO_WRITE_LOCK;
}
}
}
if (hr == S_OK)
{
//
// Initialize the INetCfg object.
//
hr = pnc->Initialize(NULL);
if (hr == S_OK)
{
*ppnc = pnc;
pnc->AddRef();
}
else
{
//
// Initialize failed, if obtained lock, release it
//
if (pncLock)
{
pncLock->ReleaseWriteLock();
}
}
}
ReleaseRef(pncLock);
ReleaseRef(pnc);
}
return hr;
}
//
// Function: HrReleaseINetCfg
//
// Purpose: Get a reference to INetCfg.
//
// Arguments:
// pnc [in] Reference to INetCfg to release.
// fHasWriteLock [in] If TRUE, reference was held with write lock.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrReleaseINetCfg (IN INetCfg* pnc, IN BOOL fHasWriteLock)
{
INetCfgLock *pncLock = NULL;
HRESULT hr = S_OK;
//
// If write lock is present, unlock it
//
if (hr == S_OK && fHasWriteLock)
{
//
// Get the locking reference
//
hr = pnc->QueryInterface(IID_INetCfgLock, (LPVOID *)&pncLock);
if (hr == S_OK)
{
hr = pncLock->ReleaseWriteLock();
ReleaseRef(pncLock);
}
}
ReleaseRef(pnc);
return hr;
}
//
// Function: HrInstallComponent
//
// Purpose: Install a network component(protocols, clients and services)
// given its INF file.
// Arguments:
// pnc [in] Reference to INetCfg.
// lpszComponentId [in] PnpID of the network component.
// pguidClass [in] Class GUID of the network component.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrInstallComponent(IN INetCfg* pnc, IN LPCWSTR szComponentId, IN const GUID* pguidClass)
{
INetCfgClassSetup *pncClassSetup = NULL;
INetCfgComponent *pncc = NULL;
OBO_TOKEN OboToken;
HRESULT hr = S_OK;
//
// OBO_TOKEN specifies on whose behalf this
// component is being installed.
// Set it to OBO_USER so that szComponentId will be installed
// on behalf of the user.
//
ZeroMemory(&OboToken, sizeof(OboToken));
OboToken.Type = OBO_USER;
//
// Get component's setup class reference.
//
hr = pnc->QueryNetCfgClass (pguidClass, IID_INetCfgClassSetup, (void**)&pncClassSetup);
if (hr == S_OK)
{
hr = pncClassSetup->Install(szComponentId,
&OboToken,
0,
0, // Upgrade from build number.
NULL, // Answerfile name
NULL, // Answerfile section name
&pncc); // Reference after the component
if (S_OK == hr)
{
// is installed.
//
// we don't need to use pncc (INetCfgComponent), release it
//
ReleaseRef(pncc);
}
ReleaseRef(pncClassSetup);
}
return hr;
}
//
// Function: HrInstallNetComponent
//
// Purpose: Install a network component(protocols, clients and services)
// given its INF file.
//
// Arguments:
// pnc [in] Reference to INetCfg.
// lpszComponentId [in] PnpID of the network component.
// pguidClass [in] Class GUID of the network component.
// lpszInfFullPath [in] INF file to install from.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrInstallNetComponent (IN INetCfg *pnc, IN LPCWSTR lpszComponentId, IN const GUID *pguidClass, IN LPCWSTR lpszInfFullPath)
{
DWORD dwError;
HRESULT hr = S_OK;
WCHAR Drive[_MAX_DRIVE];
WCHAR Dir[_MAX_DIR];
WCHAR DirWithDrive[_MAX_DRIVE+_MAX_DIR];
//
// If full path to INF has been specified, the INF
// needs to be copied using Setup API to ensure that any other files
// that the primary INF copies will be correctly found by Setup API
//
if (lpszInfFullPath)
{
//
// Get the path where the INF file is.
//
_wsplitpath(lpszInfFullPath, Drive, Dir, NULL, NULL);
wcscpy(DirWithDrive, Drive);
wcscat(DirWithDrive, Dir);
//
// Copy the INF file and other files referenced in the INF file.
//
if (!SetupCopyOEMInfW(lpszInfFullPath,
DirWithDrive, // Other files are in the
// same dir. as primary INF
SPOST_PATH, // First param is path to INF
0, // Default copy style
NULL, // Name of the INF after
// it's copied to %windir%\inf
0, // Max buf. size for the above
NULL, // Required size if non-null
NULL))
{
// Optionally get the filename
// part of Inf name after it is copied.
dwError = GetLastError();
hr = HRESULT_FROM_WIN32(dwError);
}
}
if (S_OK == hr)
{
//
// Install the network component.
//
hr = HrInstallComponent(pnc, lpszComponentId, pguidClass);
if (hr == S_OK)
{
//
// On success, apply the changes
//
hr = pnc->Apply();
}
}
return hr;
}
//
// Function: HrUninstallNetComponent
//
// Purpose: Uninstall a network component(protocols, clients and services).
//
// Arguments:
// pnc [in] Reference to INetCfg.
// szComponentId [in] PnpID of the network component to uninstall.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrUninstallNetComponent(IN INetCfg* pnc, IN LPCWSTR szComponentId)
{
INetCfgComponent *pncc = NULL;
INetCfgClass *pncClass = NULL;
INetCfgClassSetup *pncClassSetup = NULL;
OBO_TOKEN OboToken;
GUID guidClass;
HRESULT hr = S_OK;
//
// OBO_TOKEN specifies on whose behalf this
// component is being installed.
// Set it to OBO_USER so that szComponentId will be installed
// on behalf of the user.
//
ZeroMemory(&OboToken, sizeof(OboToken));
OboToken.Type = OBO_USER;
//
// Get the component's reference.
//
hr = pnc->FindComponent(szComponentId, &pncc);
if (S_OK == hr)
{
//
// Get the component's class GUID.
//
hr = pncc->GetClassGuid(&guidClass);
if (hr == S_OK)
{
//
// Get component's class reference.
//
hr = pnc->QueryNetCfgClass(&guidClass, IID_INetCfgClass, (void**)&pncClass);
if (hr == S_OK)
{
//
// Get Setup reference.
//
hr = pncClass->QueryInterface(IID_INetCfgClassSetup, (void**)&pncClassSetup);
if (hr == S_OK)
{
hr = pncClassSetup->DeInstall(pncc, &OboToken, NULL);
if (hr == S_OK)
{
//
// Apply the changes
//
hr = pnc->Apply();
}
ReleaseRef(pncClassSetup);
}
ReleaseRef(pncClass);
}
}
ReleaseRef(pncc);
}
return hr;
}
#20
//
// Function: HrGetComponentEnum
//
// Purpose: Get network component enumerator reference.
//
// Arguments:
// pnc [in] Reference to INetCfg.
// pguidClass [in] Class GUID of the network component.
// ppencc [out] Enumerator reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetComponentEnum (INetCfg* pnc, IN const GUID* pguidClass, OUT IEnumNetCfgComponent **ppencc)
{
INetCfgClass *pncclass;
HRESULT hr;
*ppencc = NULL;
//
// Get the class reference.
//
hr = pnc->QueryNetCfgClass(pguidClass, IID_INetCfgClass, (PVOID *)&pncclass);
if (hr == S_OK)
{
//
// Get the enumerator reference.
//
hr = pncclass->EnumComponents(ppencc);
//
// We don't need the class reference any more.
//
ReleaseRef(pncclass);
}
return hr;
}
//
// Function: HrGetFirstComponent
//
// Purpose: Enumerates the first network component.
//
// Arguments:
// pencc [in] Component enumerator reference.
// ppncc [out] Network component reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetFirstComponent (IN IEnumNetCfgComponent* pencc, OUT INetCfgComponent **ppncc)
{
HRESULT hr;
ULONG ulCount;
*ppncc = NULL;
pencc->Reset();
hr = pencc->Next(1, ppncc, &ulCount);
return hr;
}
//
// Function: HrGetNextComponent
//
// Purpose: Enumerate the next network component.
//
// Arguments:
// pencc [in] Component enumerator reference.
// ppncc [out] Network component reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes: The function behaves just like HrGetFirstComponent if
// it is called right after HrGetComponentEnum.
//
//
HRESULT CTryCodeDlg::HrGetNextComponent (IN IEnumNetCfgComponent* pencc, OUT INetCfgComponent **ppncc)
{
HRESULT hr;
ULONG ulCount;
*ppncc = NULL;
hr = pencc->Next(1, ppncc, &ulCount);
return hr;
}
//
// Function: HrGetBindingPathEnum
//
// Purpose: Get network component's binding path enumerator reference.
//
// Arguments:
// pncc [in] Network component reference.
// dwBindingType [in] EBP_ABOVE or EBP_BELOW.
// ppencbp [out] Enumerator reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetBindingPathEnum (IN INetCfgComponent *pncc, IN DWORD dwBindingType, OUT IEnumNetCfgBindingPath **ppencbp)
{
INetCfgComponentBindings *pnccb = NULL;
HRESULT hr;
*ppencbp = NULL;
//
// Get component's binding.
//
hr = pncc->QueryInterface(IID_INetCfgComponentBindings, (PVOID *)&pnccb);
if (hr == S_OK)
{
//
// Get binding path enumerator reference.
//
hr = pnccb->EnumBindingPaths(dwBindingType, ppencbp);
ReleaseRef(pnccb);
}
return hr;
}
//
// Function: HrGetFirstBindingPath
//
// Purpose: Enumerates the first binding path.
//
// Arguments:
// pencc [in] Binding path enumerator reference.
// ppncc [out] Binding path reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetFirstBindingPath (IN IEnumNetCfgBindingPath *pencbp, OUT INetCfgBindingPath **ppncbp)
{
ULONG ulCount;
HRESULT hr;
*ppncbp = NULL;
pencbp->Reset();
hr = pencbp->Next(1, ppncbp, &ulCount);
return hr;
}
//
// Function: HrGetNextBindingPath
//
// Purpose: Enumerate the next binding path.
//
// Arguments:
// pencbp [in] Binding path enumerator reference.
// ppncbp [out] Binding path reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes: The function behaves just like HrGetFirstBindingPath if
// it is called right after HrGetBindingPathEnum.
//
//
HRESULT CTryCodeDlg::HrGetNextBindingPath (IN IEnumNetCfgBindingPath *pencbp, OUT INetCfgBindingPath **ppncbp)
{
ULONG ulCount;
HRESULT hr;
*ppncbp = NULL;
hr = pencbp->Next(1, ppncbp, &ulCount);
return hr;
}
//
// Function: HrGetBindingInterfaceEnum
//
// Purpose: Get binding interface enumerator reference.
//
// Arguments:
// pncbp [in] Binding path reference.
// ppencbp [out] Enumerator reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetBindingInterfaceEnum (IN INetCfgBindingPath *pncbp, OUT IEnumNetCfgBindingInterface **ppencbi)
{
HRESULT hr;
*ppencbi = NULL;
hr = pncbp->EnumBindingInterfaces(ppencbi);
return hr;
}
//
// Function: HrGetFirstBindingInterface
//
// Purpose: Enumerates the first binding interface.
//
// Arguments:
// pencbi [in] Binding interface enumerator reference.
// ppncbi [out] Binding interface reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetFirstBindingInterface (IN IEnumNetCfgBindingInterface *pencbi, OUT INetCfgBindingInterface **ppncbi)
{
ULONG ulCount;
HRESULT hr;
*ppncbi = NULL;
pencbi->Reset();
hr = pencbi->Next(1, ppncbi, &ulCount);
return hr;
}
#21
//
// Function: HrGetNextBindingInterface
//
// Purpose: Enumerate the next binding interface.
//
// Arguments:
// pencbi [in] Binding interface enumerator reference.
// ppncbi [out] Binding interface reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes: The function behaves just like HrGetFirstBindingInterface if
// it is called right after HrGetBindingInterfaceEnum.
//
//
HRESULT CTryCodeDlg::HrGetNextBindingInterface (IN IEnumNetCfgBindingInterface *pencbi, OUT INetCfgBindingInterface **ppncbi)
{
ULONG ulCount;
HRESULT hr;
*ppncbi = NULL;
hr = pencbi->Next(1, ppncbi, &ulCount);
return hr;
}
BOOL CTryCodeDlg::GetFileName (HWND hwndDlg, LPWSTR lpszFilter, LPWSTR lpszTitle, DWORD dwFlags, LPWSTR lpszFile, LPWSTR lpszDefExt)
{
OPENFILENAMEW ofn;
lpszFile[0] = NULL;
ZeroMemory(&ofn, sizeof(OPENFILENAMEW));
ofn.lStructSize = sizeof(OPENFILENAMEW);
ofn.hwndOwner = hwndDlg;
ofn.lpstrFilter = lpszFilter;
ofn.lpstrFile = lpszFile;
ofn.lpstrDefExt = lpszDefExt;
ofn.nMaxFile = MAX_PATH+1;
ofn.lpstrTitle = lpszTitle;
ofn.Flags = dwFlags;
return GetOpenFileNameW(&ofn);
}
HRESULT CTryCodeDlg::InstallSpecifiedComponent (LPWSTR lpszInfFile, LPWSTR lpszPnpID, const GUID *pguidClass)
{
INetCfg *pnc;
LPWSTR lpszApp;
HRESULT hr;
hr = HrGetINetCfg(TRUE, APP_NAME, &pnc, &lpszApp);
if (hr == S_OK)
{
//
// Install the network component.
//
hr = HrInstallNetComponent(pnc, lpszPnpID, pguidClass, lpszInfFile);
if ((hr == S_OK) || (hr == NETCFG_S_REBOOT))
{
hr = pnc->Apply();
}
else
{
if (hr != HRESULT_FROM_WIN32(ERROR_CANCELLED))
{
AfxMessageBox("Couldn't install the network component.");
}
}
HrReleaseINetCfg(pnc, TRUE);
}
else
{
if ((hr == NETCFG_E_NO_WRITE_LOCK) && lpszApp)
{
AfxMessageBox("%s currently holds the lock, try later.");
CoTaskMemFree(lpszApp);
}
else
{
AfxMessageBox("Couldn't the get notify object interface.");
}
}
return hr;
}
HRESULT CTryCodeDlg::GetKeyValue (HINF hInf, LPCWSTR lpszSection, LPCWSTR lpszKey, DWORD dwIndex, LPWSTR *lppszValue)
{
INFCONTEXT infCtx;
DWORD dwSizeNeeded;
HRESULT hr;
*lppszValue = NULL;
if (SetupFindFirstLineW(hInf, lpszSection, lpszKey, &infCtx) == FALSE)
{
return HRESULT_FROM_WIN32(GetLastError());
}
SetupGetStringFieldW(&infCtx, dwIndex, NULL, 0, &dwSizeNeeded);
*lppszValue = (LPWSTR) CoTaskMemAlloc(sizeof(WCHAR) * dwSizeNeeded);
if (!*lppszValue)
{
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
if (SetupGetStringFieldW(&infCtx, dwIndex, *lppszValue, dwSizeNeeded, NULL) == FALSE)
{
hr = HRESULT_FROM_WIN32(GetLastError());
CoTaskMemFree(*lppszValue);
*lppszValue = NULL;
}
else
{
hr = S_OK;
}
return hr;
}
HRESULT CTryCodeDlg::GetPnpID (LPWSTR lpszInfFile, LPWSTR *lppszPnpID)
{
HINF hInf;
LPWSTR lpszModelSection;
HRESULT hr;
*lppszPnpID = NULL;
hInf = SetupOpenInfFileW(lpszInfFile, NULL, INF_STYLE_WIN4, NULL);
if (hInf == INVALID_HANDLE_VALUE)
{
return HRESULT_FROM_WIN32(GetLastError());
}
//
// Read the Model section name from Manufacturer section.
//
hr = GetKeyValue(hInf, L"Manufacturer", NULL, 1, &lpszModelSection);
if (hr == S_OK)
{
//
// Read PnpID from the Model section.
//
hr = GetKeyValue(hInf, lpszModelSection, NULL, 2, lppszPnpID);
CoTaskMemFree(lpszModelSection);
}
SetupCloseInfFile(hInf);
return hr;
}
VOID CTryCodeDlg::InstallSelectedComponentType (HWND hwndDlg, LPWSTR lpszInfFile)
{
HRESULT hr;
if (lpszInfFile)
{
LPWSTR lpszPnpID;
//
// Inf file name specified, install the network component
// from this file.
//
hr = GetPnpID(lpszInfFile, &lpszPnpID);
if (hr == S_OK)
{
hr = InstallSpecifiedComponent(lpszInfFile, lpszPnpID, pguidClassService);
CoTaskMemFree(lpszPnpID);
}
else
{
AfxMessageBox("Error read inf file.");
}
}
else
{
AfxMessageBox("No inf file.");
}
switch(hr)
{
case S_OK:
MessageBoxW(hwndDlg,
L"Component installed successfully.",
L"Network Component Installation",
MB_OK | MB_ICONINFORMATION);
break;
case NETCFG_S_REBOOT:
MessageBoxW(hwndDlg,
L"Component installed successfully: "
L"Reboot required.",
L"Network Component Installation",
MB_OK | MB_ICONINFORMATION);
}
return;
}
//这里使用“文件”对话框选择inf文件,可以更改为其他方式
void CTryCodeDlg::OnInstallDriver()
{
// TODO: Add your control notification handler code here
WCHAR lpszInfFile[MAX_PATH + 1];
if (GetFileName(this->m_hWnd,
L"INF files (*.inf)\0*.inf\0",
L"Select the INF file of the network component to install",
OFN_DONTADDTORECENT | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST,
lpszInfFile,
NULL))
{
InstallSelectedComponentType(this->m_hWnd, lpszInfFile);
}
}
#22
最近在给客户做一个类似于三星的DNW的工具,用到的驱动文件也是和DNW同样的,也需要考虑和楼主同样的问题,还不清楚怎么实现呢
#23
回hzy_76:
非常感谢你提供源代码,我正在研究呢。
我看到你的安装驱动的核心步骤就是调用setupCopyOEMInf函数。
关于这个函数我还不是很了解其内部机制是什么?MSDN上说,这个函数就是将INF文件以及其相关的文件COPY到系统文件夹中去。
那么这个函数和InstallHinfSection有什么区别呢?我想用DOS批处理脚本来安装驱动,论坛上许多人建议过这样的方法。InstallHinfSection也是将INF文件及其相关文件COPY到系统文件夹下面,并修改注册表。(这一点我在系统文件夹和注册表都有监视过)。结果还是没有安装成功(硬件插上后还是会弹出提示)。
另外,我现在同时还在试验用InstallShield来做个exe的安装包。不知道哪位老大有InstallShield 12 的电子版教材啊? 能分享一下吗? 谢谢咯!
非常感谢你提供源代码,我正在研究呢。
我看到你的安装驱动的核心步骤就是调用setupCopyOEMInf函数。
关于这个函数我还不是很了解其内部机制是什么?MSDN上说,这个函数就是将INF文件以及其相关的文件COPY到系统文件夹中去。
那么这个函数和InstallHinfSection有什么区别呢?我想用DOS批处理脚本来安装驱动,论坛上许多人建议过这样的方法。InstallHinfSection也是将INF文件及其相关文件COPY到系统文件夹下面,并修改注册表。(这一点我在系统文件夹和注册表都有监视过)。结果还是没有安装成功(硬件插上后还是会弹出提示)。
另外,我现在同时还在试验用InstallShield来做个exe的安装包。不知道哪位老大有InstallShield 12 的电子版教材啊? 能分享一下吗? 谢谢咯!
#24
是的,复制安装文件是必要的步骤。修改注册表部分,BindView里边是用INetCfgClassSetup来做的,看起来是针对网络的,估计你用不着了。不过你可以沿这个思路看是否有类似的解决方案。
我原来也想过用InstallShield来做,它的帮助里边也提到过可以制作驱动安装程序,但没有进展,后来就去研究BindView代码了。
我原来也想过用InstallShield来做,它的帮助里边也提到过可以制作驱动安装程序,但没有进展,后来就去研究BindView代码了。
#25
嘿嘿,不好意思,刚看到你的留言。
1.现在这个项目需要事先就把驱动安装到PC中去,也就是把安装驱动这件事放在安装软件(项目最终的发布软件)的过程中完成。那么应该怎么去安装驱动呢?
我看了你的那个脚本,你把设备插在上边然后安装一下,试试看能不能成功,不过安装过程中肯定要提示的。装好之后换个口插入肯定也会提示。(因为你没有经过ms认证。)
一般安装驱动的程序都是使用setupapi或者difx这两套库通过自己的程序实现的。
2. 并且由于软件最终会运行在XP、VISTA和Windows7下面,那么这三个系统下的自动安装的过程有多大的区别呢?
如果没有经过ms认证的驱动的话,在64位操作系统和32位操作系统下是有区别的。区别就是64位下不能使用。^_^.32位下,都一样,使用正规的操作装上之后,第一次插入设备时,还是会提示安装,只是这时选择自动搜索可以自动装上去。而且在安装过程中会有未经过认证的提示。
#26
如果使用InstallShield 12的话,这个工具里自带了安装驱动的接口,你只需要在里边点击几下,配置一下你驱动的路径就可以了。
#27
硬件插上后还是会弹出提示,这个情况是因为你的驱动程序没有经过签名,你可以找一台裸机,或者把你的机器上的驱动删干净试。和你的脚本程序是一样的,如果没有运行过程序或者脚本,在插入设备后提示安装驱动,这时你选择自动搜索,不能将驱动更新。如果运行过了,那就可以更新驱动了。
#28
我现在也是这个问题,用InstallShield 做的包太大了, 换成Setup Factory在搞,可是研究了几天都还没搞定,用SetupCopyOEMInfA拷贝文件到INF文件夹,可是好像没有成功!不知道怎么回事?拷贝文件后还需要做些什么操作吗?
在网上找了下,说要再去写注册表,可是不知道写啥?郁闷,
关注中!!!
在网上找了下,说要再去写注册表,可是不知道写啥?郁闷,
关注中!!!
#29
驱动的安装方式大至有二种:
1,在插上设备的时候进行安装,即使用函数UpdateDriverForPlugAndPlayDevice()。
2,在没有物理设备的时候安装,即通常所说的驱动预安装(SetupCopyOEMInf)。
需要注意的是:
1,SetupCopyOEMInf()只是生成一个oem*.inf文件和oem*.pnf文件到Windows\inf\文件夹中,
即没有修改任何注册表,也没有复制文件。生成的pnf文件包含源文件路径信息,以便在真正
插上设备的时候能够找到相应的sys等文件。
2,UpdateDriverForPlugAndPlayDevice()在没有插上设备的时候是会执行失败的。
Windows插上设备到找到合适的驱动的大致步骤是:
1,插上设备后Windows设备信息到硬件键[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\下去寻找相应的项。
2,如果在Enum键下没有相应的信息,则Windows到预安装目录中去寻找相应的oem*.inf和oem*.pnf文件(oem*.inf和oem*.pnf只要前面的文件名相同就可以,故如果对二个同时改成相同的名字不会有什么影响).
如果进行了预安装,则可以在这里找到相应的inf和pnf文件。于是弹出发现新硬件对话框,点自动安装就可成功(这个对话框可以通过协助安装程序搞掉它)。安装时会弹出徽标论证的对话框(XP下可以通过改注册表的方式搞掉,Vista下暂没发现办法)
3,注册CoInstall的方法即修改以下键值:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\CoDeviceInstallers],子键名为要注册CoInstall的GUID,值为dll的名字和函数名。
1,在插上设备的时候进行安装,即使用函数UpdateDriverForPlugAndPlayDevice()。
2,在没有物理设备的时候安装,即通常所说的驱动预安装(SetupCopyOEMInf)。
需要注意的是:
1,SetupCopyOEMInf()只是生成一个oem*.inf文件和oem*.pnf文件到Windows\inf\文件夹中,
即没有修改任何注册表,也没有复制文件。生成的pnf文件包含源文件路径信息,以便在真正
插上设备的时候能够找到相应的sys等文件。
2,UpdateDriverForPlugAndPlayDevice()在没有插上设备的时候是会执行失败的。
Windows插上设备到找到合适的驱动的大致步骤是:
1,插上设备后Windows设备信息到硬件键[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\下去寻找相应的项。
2,如果在Enum键下没有相应的信息,则Windows到预安装目录中去寻找相应的oem*.inf和oem*.pnf文件(oem*.inf和oem*.pnf只要前面的文件名相同就可以,故如果对二个同时改成相同的名字不会有什么影响).
如果进行了预安装,则可以在这里找到相应的inf和pnf文件。于是弹出发现新硬件对话框,点自动安装就可成功(这个对话框可以通过协助安装程序搞掉它)。安装时会弹出徽标论证的对话框(XP下可以通过改注册表的方式搞掉,Vista下暂没发现办法)
3,注册CoInstall的方法即修改以下键值:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\CoDeviceInstallers],子键名为要注册CoInstall的GUID,值为dll的名字和函数名。
#30
你的驱动目前打包完成没?
#31
我的方法:
DPInst.exe是WDK中的一个实用工具,它可以自动搜索指定目录的inf文件,并安装相应设备的驱动程序。
MSDN中有关于DPInst.exe的详细资料:
http://msdn.microsoft.com/en-us/library/ms790308.aspx
http://www.microsoft.com/china/whdc/driver/install/difxtools.mspx
下载地址:
http://www.microsoft.com/china/whdc/driver/install/DIFxtls.mspx
http://www.microsoft.com/downloads/details.aspx?FamilyID=2105564e-1a9a-4bf4-8d74-ec5b52da3d00&displaylang=en
DPInst.exe支持命令行,它支持的参数可以使用DPInst.exe /?查看。
示例:
1.自动搜索C:\VGA目录下的INF文件并安装驱动程序:
DPInst.exe /PATH "C:\VGA" /F /Q /LM /A
2.自动搜索C:\目录下的INF文件并安装驱动程序:
DPInst.exe /PATH C:\ /LM
http://qingfengju.com/article.asp?id=183
DPInst.exe是WDK中的一个实用工具,它可以自动搜索指定目录的inf文件,并安装相应设备的驱动程序。
MSDN中有关于DPInst.exe的详细资料:
http://msdn.microsoft.com/en-us/library/ms790308.aspx
http://www.microsoft.com/china/whdc/driver/install/difxtools.mspx
下载地址:
http://www.microsoft.com/china/whdc/driver/install/DIFxtls.mspx
http://www.microsoft.com/downloads/details.aspx?FamilyID=2105564e-1a9a-4bf4-8d74-ec5b52da3d00&displaylang=en
DPInst.exe支持命令行,它支持的参数可以使用DPInst.exe /?查看。
示例:
1.自动搜索C:\VGA目录下的INF文件并安装驱动程序:
DPInst.exe /PATH "C:\VGA" /F /Q /LM /A
2.自动搜索C:\目录下的INF文件并安装驱动程序:
DPInst.exe /PATH C:\ /LM
http://qingfengju.com/article.asp?id=183
#32
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\CoDeviceInstallers 下面注册coinstaller,不过coinstaller 里面SetupDiEnumDriverInfo会失败,没找到好的办法
#1
楼主关键是要实现你的设备的HID,我们采用一个带USB的单片机,开始也没实现免驱,后来市场需求,我们采用挂接在HID上,实现了免驱设计。即可以利用电脑的自带的USB的等驱动文件,自动识别我的设备。
oogle与百度下“免驱设计 HID”
一下几篇文章很不错,
http://www.dzsc.com/data/html/2009-7-21/77757.html
http://www.abc188.com/info/html/wangzhanyunying/jianzhanjingyan/20080417/67834.html
http://linux.chinaunix.net/techdoc/install/2008/03/14/983179.shtml
oogle与百度下“免驱设计 HID”
一下几篇文章很不错,
http://www.dzsc.com/data/html/2009-7-21/77757.html
http://www.abc188.com/info/html/wangzhanyunying/jianzhanjingyan/20080417/67834.html
http://linux.chinaunix.net/techdoc/install/2008/03/14/983179.shtml
#2
感谢楼上解答。
只是楼上提供的是关于libUSB的相关资料。
而且驱动程序已经有提供了,我需要安装这个驱动。
只是楼上提供的是关于libUSB的相关资料。
而且驱动程序已经有提供了,我需要安装这个驱动。
#3
这个感觉向是把你的驱动 要加载到操作系统中,做到即插即用的,就跟我们使用U盘是一样的
楼主可以写个啥程序,把驱动加载到PC上,只要插上你的设备 就可以识别
这只是我的想法 具体这软件咋写 我也不会
楼主可以写个啥程序,把驱动加载到PC上,只要插上你的设备 就可以识别
这只是我的想法 具体这软件咋写 我也不会
#4
我也想知道,好像没有见过类似的做法。
#5
回cfanlwn: 是的。因为用到了一个USB转串口的芯片,所以要安装下驱动,当然就像平常那样的,当硬件接上PC后,按照提示一步一步安装也可以。但是这样子一来是使得用户的使用变得麻烦,而且增加了安装过程的风险(比如说MS的数字认证问题)。所以现在要将驱动在安装程序的时候就安装上去。
就是不晓得应该怎么做啊。。。
就是不晓得应该怎么做啊。。。
#6
你说让他自动获取,然后我们一步步安装,最后安装上也就是把一些信息放在WINDOWS下,然后在注册表中加写信息,楼主可以查查这些资料,看能不能写个批处理程序
#7
回cfanlwn:
是不是大家都是通过批处理来做这件事的?因为我问了其他版块的高手,有人也这么说的。
有个高手提供了如下的批处理脚本:
echo 安装驱动
rundll32.exe setupapi.dll,InstallHinfSection DefaultInstall 128 %inf%
echo 安装完成
我没有写过批处理脚本,刚刚找了一篇批处理的文章正在屁颠屁颠的看。
能帮忙分析一下这个脚本么?
是不是大家都是通过批处理来做这件事的?因为我问了其他版块的高手,有人也这么说的。
有个高手提供了如下的批处理脚本:
echo 安装驱动
rundll32.exe setupapi.dll,InstallHinfSection DefaultInstall 128 %inf%
echo 安装完成
我没有写过批处理脚本,刚刚找了一篇批处理的文章正在屁颠屁颠的看。
能帮忙分析一下这个脚本么?
#8
请教cfanlwn:
我刚刚试了一下。
批处理代码如下:
@echo off
echo 判断系统版本
set inf=D:\XP\DRIVER\CH341WDM.INF
echo 安装驱动
rundll32.exe setupapi.dll,InstallHinfSection DefaultInstall 128 %inf%
echo 安装完成
发现没有安装上去,请问是怎么一回事呢? 问题出在哪里了呢?
我刚刚试了一下。
批处理代码如下:
@echo off
echo 判断系统版本
set inf=D:\XP\DRIVER\CH341WDM.INF
echo 安装驱动
rundll32.exe setupapi.dll,InstallHinfSection DefaultInstall 128 %inf%
echo 安装完成
发现没有安装上去,请问是怎么一回事呢? 问题出在哪里了呢?
#9
用DeviceTree查看了一下,确实没有安装上去。。。
#10
一般的USB转串口的芯片,都会由这个芯片厂家提供PC端的驱动,一般只要实现在PC上安装驱动,之后你随时插拔,系统就会自动识别你的设备。
我们用到很多USB转串口的转接线都是这样的,我们用CP2102做的一款产品也是这样,先人为安装驱动,之后就不用管了、
#11
既然第三方已经提供了“包含DLL、INF、SYS等等文件。”
楼主是否可以百度或者google下,“如何生成exe可执行文件”。
我们当时做项目,就把这个DLL和一些系统文件,用专用的软件人为生成了一个exe,之后一点就自动运行。
楼主是否可以百度或者google下,“如何生成exe可执行文件”。
我们当时做项目,就把这个DLL和一些系统文件,用专用的软件人为生成了一个exe,之后一点就自动运行。
#12
回kyzf:
谢谢提示啊~~
因为这个驱动没有取得MS的认证,所以如果人工安装的话可能对那些警告提示感到头疼。
关于生成exe可执行文件,是个不错的方法,我现在看到有人用批处理程序就搞定了,所以就先按照那个方法先试了一下。。
没找到专业软件生成EXE文件,能提供一个下载的链接或者方法么?谢谢咯~~
另外,“把这个DLL和一些系统文件,用专用的软件人为生成了一个exe”,请问还需要哪些系统文件呢?最后生成的EXE可执行文件会不会很大啊??
谢谢提示啊~~
因为这个驱动没有取得MS的认证,所以如果人工安装的话可能对那些警告提示感到头疼。
关于生成exe可执行文件,是个不错的方法,我现在看到有人用批处理程序就搞定了,所以就先按照那个方法先试了一下。。
没找到专业软件生成EXE文件,能提供一个下载的链接或者方法么?谢谢咯~~
另外,“把这个DLL和一些系统文件,用专用的软件人为生成了一个exe”,请问还需要哪些系统文件呢?最后生成的EXE可执行文件会不会很大啊??
#13
为什么我按照系统提示来安装的时候 那个进度条显示的安装内容是DLL文件 而用批处理倒的时候 显示安装的内容是SYS文件
一般驱动程序不都是INF+VXD+SYS么? 我知道那个DLL文件里提供了一些操作数据流的接口。
不明白的是,安装驱动到底是要copy哪些内容到系统文件夹呢?
一般驱动程序不都是INF+VXD+SYS么? 我知道那个DLL文件里提供了一些操作数据流的接口。
不明白的是,安装驱动到底是要copy哪些内容到系统文件夹呢?
#14
重新测试过了,DLL文件和SYS文件都已经COPY到了正确的系统文件夹下面。但是插上硬件的时候,系统还是会弹出安装驱动的提示。
是不是和注册表有关系呢?
我按照系统提示安装的驱动 和 通过批处理程序安装的驱动 所调用的INF文件时同一个文件啊。
按理说应该不会出现注册表的修改内容不一致的情况。
请教各位老大 , 这到底是什么情况呢?
是不是和注册表有关系呢?
我按照系统提示安装的驱动 和 通过批处理程序安装的驱动 所调用的INF文件时同一个文件啊。
按理说应该不会出现注册表的修改内容不一致的情况。
请教各位老大 , 这到底是什么情况呢?
#15
Windows DDK中有一个例子叫做BindView可以实现你的目的,不过如果没有数字证书,是一定会弹出提示“驱动可能不安全”的窗口的。前几天我刚把BindView中自动安装的代码分离了出来,有需要的话可以跟我联系。
#16
回hzy_76:
BindView的实现原理是什么呢? 也是通过WDM加载的么?还是通过NT方式加载的(这个方法在《Windows驱动开发技术详解》第三章有附带的源代码)。
另外怎么联系你呢?
BindView的实现原理是什么呢? 也是通过WDM加载的么?还是通过NT方式加载的(这个方法在《Windows驱动开发技术详解》第三章有附带的源代码)。
另外怎么联系你呢?
#17
应该是WDM吧,我是用来安装我自己写的NDIS驱动的,已经调试通过。如果需要的话,留言给我,我可以把代码发给你。
驱动开发我也是初学者,有问题一起探讨!
驱动开发我也是初学者,有问题一起探讨!
#18
回楼上: 给你留言了,指点我一下吧。
#19
回头看了一下,那段代码好像是安装网络驱动的,你这种驱动可能不适合。
我把代码贴出来吧,你自己研究看看是否可以借鉴:
我把代码贴出来吧,你自己研究看看是否可以借鉴:
//这两个是对应网络服务和网卡的定义,安装其他驱动时需要修改
const GUID *pguidClassService = &GUID_DEVCLASS_NETSERVICE;
const GUID *pguidClassNet = &GUID_DEVCLASS_NET;
//
// Function: ReleaseRef
//
// Purpose: Release reference.
//
// Arguments:
// punk [in] IUnknown reference to release.
//
// Returns: Reference count.
//
// Notes:
//
VOID CTryCodeDlg::ReleaseRef (IN IUnknown* punk)
{
if (punk)
{
punk->Release();
}
return;
}
//
// Function: HrGetINetCfg
//
// Purpose: Get a reference to INetCfg.
//
// Arguments:
// fGetWriteLock [in] If TRUE, Write lock.requested.
// lpszAppName [in] Application name requesting the reference.
// ppnc [out] Reference to INetCfg.
// lpszLockedBy [in] Optional. Application who holds the write lock.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetINetCfg (IN BOOL fGetWriteLock, IN LPCWSTR lpszAppName, OUT INetCfg** ppnc, OUT LPWSTR *lpszLockedBy)
{
INetCfg *pnc = NULL;
INetCfgLock *pncLock = NULL;
HRESULT hr = S_OK;
//
// Initialize the output parameters.
//
*ppnc = NULL;
if (lpszLockedBy)
{
*lpszLockedBy = NULL;
}
//
// Create the object implementing INetCfg.
//
hr = CoCreateInstance(CLSID_CNetCfg, NULL, CLSCTX_INPROC_SERVER, IID_INetCfg, (void**)&pnc);
if (hr == S_OK)
{
if (fGetWriteLock)
{
//
// Get the locking reference
//
hr = pnc->QueryInterface(IID_INetCfgLock, (LPVOID *)&pncLock);
if (hr == S_OK)
{
//
// Attempt to lock the INetCfg for read/write
//
hr = pncLock->AcquireWriteLock(LOCK_TIME_OUT, lpszAppName, lpszLockedBy);
if (hr == S_FALSE)
{
hr = NETCFG_E_NO_WRITE_LOCK;
}
}
}
if (hr == S_OK)
{
//
// Initialize the INetCfg object.
//
hr = pnc->Initialize(NULL);
if (hr == S_OK)
{
*ppnc = pnc;
pnc->AddRef();
}
else
{
//
// Initialize failed, if obtained lock, release it
//
if (pncLock)
{
pncLock->ReleaseWriteLock();
}
}
}
ReleaseRef(pncLock);
ReleaseRef(pnc);
}
return hr;
}
//
// Function: HrReleaseINetCfg
//
// Purpose: Get a reference to INetCfg.
//
// Arguments:
// pnc [in] Reference to INetCfg to release.
// fHasWriteLock [in] If TRUE, reference was held with write lock.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrReleaseINetCfg (IN INetCfg* pnc, IN BOOL fHasWriteLock)
{
INetCfgLock *pncLock = NULL;
HRESULT hr = S_OK;
//
// If write lock is present, unlock it
//
if (hr == S_OK && fHasWriteLock)
{
//
// Get the locking reference
//
hr = pnc->QueryInterface(IID_INetCfgLock, (LPVOID *)&pncLock);
if (hr == S_OK)
{
hr = pncLock->ReleaseWriteLock();
ReleaseRef(pncLock);
}
}
ReleaseRef(pnc);
return hr;
}
//
// Function: HrInstallComponent
//
// Purpose: Install a network component(protocols, clients and services)
// given its INF file.
// Arguments:
// pnc [in] Reference to INetCfg.
// lpszComponentId [in] PnpID of the network component.
// pguidClass [in] Class GUID of the network component.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrInstallComponent(IN INetCfg* pnc, IN LPCWSTR szComponentId, IN const GUID* pguidClass)
{
INetCfgClassSetup *pncClassSetup = NULL;
INetCfgComponent *pncc = NULL;
OBO_TOKEN OboToken;
HRESULT hr = S_OK;
//
// OBO_TOKEN specifies on whose behalf this
// component is being installed.
// Set it to OBO_USER so that szComponentId will be installed
// on behalf of the user.
//
ZeroMemory(&OboToken, sizeof(OboToken));
OboToken.Type = OBO_USER;
//
// Get component's setup class reference.
//
hr = pnc->QueryNetCfgClass (pguidClass, IID_INetCfgClassSetup, (void**)&pncClassSetup);
if (hr == S_OK)
{
hr = pncClassSetup->Install(szComponentId,
&OboToken,
0,
0, // Upgrade from build number.
NULL, // Answerfile name
NULL, // Answerfile section name
&pncc); // Reference after the component
if (S_OK == hr)
{
// is installed.
//
// we don't need to use pncc (INetCfgComponent), release it
//
ReleaseRef(pncc);
}
ReleaseRef(pncClassSetup);
}
return hr;
}
//
// Function: HrInstallNetComponent
//
// Purpose: Install a network component(protocols, clients and services)
// given its INF file.
//
// Arguments:
// pnc [in] Reference to INetCfg.
// lpszComponentId [in] PnpID of the network component.
// pguidClass [in] Class GUID of the network component.
// lpszInfFullPath [in] INF file to install from.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrInstallNetComponent (IN INetCfg *pnc, IN LPCWSTR lpszComponentId, IN const GUID *pguidClass, IN LPCWSTR lpszInfFullPath)
{
DWORD dwError;
HRESULT hr = S_OK;
WCHAR Drive[_MAX_DRIVE];
WCHAR Dir[_MAX_DIR];
WCHAR DirWithDrive[_MAX_DRIVE+_MAX_DIR];
//
// If full path to INF has been specified, the INF
// needs to be copied using Setup API to ensure that any other files
// that the primary INF copies will be correctly found by Setup API
//
if (lpszInfFullPath)
{
//
// Get the path where the INF file is.
//
_wsplitpath(lpszInfFullPath, Drive, Dir, NULL, NULL);
wcscpy(DirWithDrive, Drive);
wcscat(DirWithDrive, Dir);
//
// Copy the INF file and other files referenced in the INF file.
//
if (!SetupCopyOEMInfW(lpszInfFullPath,
DirWithDrive, // Other files are in the
// same dir. as primary INF
SPOST_PATH, // First param is path to INF
0, // Default copy style
NULL, // Name of the INF after
// it's copied to %windir%\inf
0, // Max buf. size for the above
NULL, // Required size if non-null
NULL))
{
// Optionally get the filename
// part of Inf name after it is copied.
dwError = GetLastError();
hr = HRESULT_FROM_WIN32(dwError);
}
}
if (S_OK == hr)
{
//
// Install the network component.
//
hr = HrInstallComponent(pnc, lpszComponentId, pguidClass);
if (hr == S_OK)
{
//
// On success, apply the changes
//
hr = pnc->Apply();
}
}
return hr;
}
//
// Function: HrUninstallNetComponent
//
// Purpose: Uninstall a network component(protocols, clients and services).
//
// Arguments:
// pnc [in] Reference to INetCfg.
// szComponentId [in] PnpID of the network component to uninstall.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrUninstallNetComponent(IN INetCfg* pnc, IN LPCWSTR szComponentId)
{
INetCfgComponent *pncc = NULL;
INetCfgClass *pncClass = NULL;
INetCfgClassSetup *pncClassSetup = NULL;
OBO_TOKEN OboToken;
GUID guidClass;
HRESULT hr = S_OK;
//
// OBO_TOKEN specifies on whose behalf this
// component is being installed.
// Set it to OBO_USER so that szComponentId will be installed
// on behalf of the user.
//
ZeroMemory(&OboToken, sizeof(OboToken));
OboToken.Type = OBO_USER;
//
// Get the component's reference.
//
hr = pnc->FindComponent(szComponentId, &pncc);
if (S_OK == hr)
{
//
// Get the component's class GUID.
//
hr = pncc->GetClassGuid(&guidClass);
if (hr == S_OK)
{
//
// Get component's class reference.
//
hr = pnc->QueryNetCfgClass(&guidClass, IID_INetCfgClass, (void**)&pncClass);
if (hr == S_OK)
{
//
// Get Setup reference.
//
hr = pncClass->QueryInterface(IID_INetCfgClassSetup, (void**)&pncClassSetup);
if (hr == S_OK)
{
hr = pncClassSetup->DeInstall(pncc, &OboToken, NULL);
if (hr == S_OK)
{
//
// Apply the changes
//
hr = pnc->Apply();
}
ReleaseRef(pncClassSetup);
}
ReleaseRef(pncClass);
}
}
ReleaseRef(pncc);
}
return hr;
}
#20
//
// Function: HrGetComponentEnum
//
// Purpose: Get network component enumerator reference.
//
// Arguments:
// pnc [in] Reference to INetCfg.
// pguidClass [in] Class GUID of the network component.
// ppencc [out] Enumerator reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetComponentEnum (INetCfg* pnc, IN const GUID* pguidClass, OUT IEnumNetCfgComponent **ppencc)
{
INetCfgClass *pncclass;
HRESULT hr;
*ppencc = NULL;
//
// Get the class reference.
//
hr = pnc->QueryNetCfgClass(pguidClass, IID_INetCfgClass, (PVOID *)&pncclass);
if (hr == S_OK)
{
//
// Get the enumerator reference.
//
hr = pncclass->EnumComponents(ppencc);
//
// We don't need the class reference any more.
//
ReleaseRef(pncclass);
}
return hr;
}
//
// Function: HrGetFirstComponent
//
// Purpose: Enumerates the first network component.
//
// Arguments:
// pencc [in] Component enumerator reference.
// ppncc [out] Network component reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetFirstComponent (IN IEnumNetCfgComponent* pencc, OUT INetCfgComponent **ppncc)
{
HRESULT hr;
ULONG ulCount;
*ppncc = NULL;
pencc->Reset();
hr = pencc->Next(1, ppncc, &ulCount);
return hr;
}
//
// Function: HrGetNextComponent
//
// Purpose: Enumerate the next network component.
//
// Arguments:
// pencc [in] Component enumerator reference.
// ppncc [out] Network component reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes: The function behaves just like HrGetFirstComponent if
// it is called right after HrGetComponentEnum.
//
//
HRESULT CTryCodeDlg::HrGetNextComponent (IN IEnumNetCfgComponent* pencc, OUT INetCfgComponent **ppncc)
{
HRESULT hr;
ULONG ulCount;
*ppncc = NULL;
hr = pencc->Next(1, ppncc, &ulCount);
return hr;
}
//
// Function: HrGetBindingPathEnum
//
// Purpose: Get network component's binding path enumerator reference.
//
// Arguments:
// pncc [in] Network component reference.
// dwBindingType [in] EBP_ABOVE or EBP_BELOW.
// ppencbp [out] Enumerator reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetBindingPathEnum (IN INetCfgComponent *pncc, IN DWORD dwBindingType, OUT IEnumNetCfgBindingPath **ppencbp)
{
INetCfgComponentBindings *pnccb = NULL;
HRESULT hr;
*ppencbp = NULL;
//
// Get component's binding.
//
hr = pncc->QueryInterface(IID_INetCfgComponentBindings, (PVOID *)&pnccb);
if (hr == S_OK)
{
//
// Get binding path enumerator reference.
//
hr = pnccb->EnumBindingPaths(dwBindingType, ppencbp);
ReleaseRef(pnccb);
}
return hr;
}
//
// Function: HrGetFirstBindingPath
//
// Purpose: Enumerates the first binding path.
//
// Arguments:
// pencc [in] Binding path enumerator reference.
// ppncc [out] Binding path reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetFirstBindingPath (IN IEnumNetCfgBindingPath *pencbp, OUT INetCfgBindingPath **ppncbp)
{
ULONG ulCount;
HRESULT hr;
*ppncbp = NULL;
pencbp->Reset();
hr = pencbp->Next(1, ppncbp, &ulCount);
return hr;
}
//
// Function: HrGetNextBindingPath
//
// Purpose: Enumerate the next binding path.
//
// Arguments:
// pencbp [in] Binding path enumerator reference.
// ppncbp [out] Binding path reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes: The function behaves just like HrGetFirstBindingPath if
// it is called right after HrGetBindingPathEnum.
//
//
HRESULT CTryCodeDlg::HrGetNextBindingPath (IN IEnumNetCfgBindingPath *pencbp, OUT INetCfgBindingPath **ppncbp)
{
ULONG ulCount;
HRESULT hr;
*ppncbp = NULL;
hr = pencbp->Next(1, ppncbp, &ulCount);
return hr;
}
//
// Function: HrGetBindingInterfaceEnum
//
// Purpose: Get binding interface enumerator reference.
//
// Arguments:
// pncbp [in] Binding path reference.
// ppencbp [out] Enumerator reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetBindingInterfaceEnum (IN INetCfgBindingPath *pncbp, OUT IEnumNetCfgBindingInterface **ppencbi)
{
HRESULT hr;
*ppencbi = NULL;
hr = pncbp->EnumBindingInterfaces(ppencbi);
return hr;
}
//
// Function: HrGetFirstBindingInterface
//
// Purpose: Enumerates the first binding interface.
//
// Arguments:
// pencbi [in] Binding interface enumerator reference.
// ppncbi [out] Binding interface reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes:
//
HRESULT CTryCodeDlg::HrGetFirstBindingInterface (IN IEnumNetCfgBindingInterface *pencbi, OUT INetCfgBindingInterface **ppncbi)
{
ULONG ulCount;
HRESULT hr;
*ppncbi = NULL;
pencbi->Reset();
hr = pencbi->Next(1, ppncbi, &ulCount);
return hr;
}
#21
//
// Function: HrGetNextBindingInterface
//
// Purpose: Enumerate the next binding interface.
//
// Arguments:
// pencbi [in] Binding interface enumerator reference.
// ppncbi [out] Binding interface reference.
//
// Returns: S_OK on sucess, otherwise an error code.
//
// Notes: The function behaves just like HrGetFirstBindingInterface if
// it is called right after HrGetBindingInterfaceEnum.
//
//
HRESULT CTryCodeDlg::HrGetNextBindingInterface (IN IEnumNetCfgBindingInterface *pencbi, OUT INetCfgBindingInterface **ppncbi)
{
ULONG ulCount;
HRESULT hr;
*ppncbi = NULL;
hr = pencbi->Next(1, ppncbi, &ulCount);
return hr;
}
BOOL CTryCodeDlg::GetFileName (HWND hwndDlg, LPWSTR lpszFilter, LPWSTR lpszTitle, DWORD dwFlags, LPWSTR lpszFile, LPWSTR lpszDefExt)
{
OPENFILENAMEW ofn;
lpszFile[0] = NULL;
ZeroMemory(&ofn, sizeof(OPENFILENAMEW));
ofn.lStructSize = sizeof(OPENFILENAMEW);
ofn.hwndOwner = hwndDlg;
ofn.lpstrFilter = lpszFilter;
ofn.lpstrFile = lpszFile;
ofn.lpstrDefExt = lpszDefExt;
ofn.nMaxFile = MAX_PATH+1;
ofn.lpstrTitle = lpszTitle;
ofn.Flags = dwFlags;
return GetOpenFileNameW(&ofn);
}
HRESULT CTryCodeDlg::InstallSpecifiedComponent (LPWSTR lpszInfFile, LPWSTR lpszPnpID, const GUID *pguidClass)
{
INetCfg *pnc;
LPWSTR lpszApp;
HRESULT hr;
hr = HrGetINetCfg(TRUE, APP_NAME, &pnc, &lpszApp);
if (hr == S_OK)
{
//
// Install the network component.
//
hr = HrInstallNetComponent(pnc, lpszPnpID, pguidClass, lpszInfFile);
if ((hr == S_OK) || (hr == NETCFG_S_REBOOT))
{
hr = pnc->Apply();
}
else
{
if (hr != HRESULT_FROM_WIN32(ERROR_CANCELLED))
{
AfxMessageBox("Couldn't install the network component.");
}
}
HrReleaseINetCfg(pnc, TRUE);
}
else
{
if ((hr == NETCFG_E_NO_WRITE_LOCK) && lpszApp)
{
AfxMessageBox("%s currently holds the lock, try later.");
CoTaskMemFree(lpszApp);
}
else
{
AfxMessageBox("Couldn't the get notify object interface.");
}
}
return hr;
}
HRESULT CTryCodeDlg::GetKeyValue (HINF hInf, LPCWSTR lpszSection, LPCWSTR lpszKey, DWORD dwIndex, LPWSTR *lppszValue)
{
INFCONTEXT infCtx;
DWORD dwSizeNeeded;
HRESULT hr;
*lppszValue = NULL;
if (SetupFindFirstLineW(hInf, lpszSection, lpszKey, &infCtx) == FALSE)
{
return HRESULT_FROM_WIN32(GetLastError());
}
SetupGetStringFieldW(&infCtx, dwIndex, NULL, 0, &dwSizeNeeded);
*lppszValue = (LPWSTR) CoTaskMemAlloc(sizeof(WCHAR) * dwSizeNeeded);
if (!*lppszValue)
{
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
}
if (SetupGetStringFieldW(&infCtx, dwIndex, *lppszValue, dwSizeNeeded, NULL) == FALSE)
{
hr = HRESULT_FROM_WIN32(GetLastError());
CoTaskMemFree(*lppszValue);
*lppszValue = NULL;
}
else
{
hr = S_OK;
}
return hr;
}
HRESULT CTryCodeDlg::GetPnpID (LPWSTR lpszInfFile, LPWSTR *lppszPnpID)
{
HINF hInf;
LPWSTR lpszModelSection;
HRESULT hr;
*lppszPnpID = NULL;
hInf = SetupOpenInfFileW(lpszInfFile, NULL, INF_STYLE_WIN4, NULL);
if (hInf == INVALID_HANDLE_VALUE)
{
return HRESULT_FROM_WIN32(GetLastError());
}
//
// Read the Model section name from Manufacturer section.
//
hr = GetKeyValue(hInf, L"Manufacturer", NULL, 1, &lpszModelSection);
if (hr == S_OK)
{
//
// Read PnpID from the Model section.
//
hr = GetKeyValue(hInf, lpszModelSection, NULL, 2, lppszPnpID);
CoTaskMemFree(lpszModelSection);
}
SetupCloseInfFile(hInf);
return hr;
}
VOID CTryCodeDlg::InstallSelectedComponentType (HWND hwndDlg, LPWSTR lpszInfFile)
{
HRESULT hr;
if (lpszInfFile)
{
LPWSTR lpszPnpID;
//
// Inf file name specified, install the network component
// from this file.
//
hr = GetPnpID(lpszInfFile, &lpszPnpID);
if (hr == S_OK)
{
hr = InstallSpecifiedComponent(lpszInfFile, lpszPnpID, pguidClassService);
CoTaskMemFree(lpszPnpID);
}
else
{
AfxMessageBox("Error read inf file.");
}
}
else
{
AfxMessageBox("No inf file.");
}
switch(hr)
{
case S_OK:
MessageBoxW(hwndDlg,
L"Component installed successfully.",
L"Network Component Installation",
MB_OK | MB_ICONINFORMATION);
break;
case NETCFG_S_REBOOT:
MessageBoxW(hwndDlg,
L"Component installed successfully: "
L"Reboot required.",
L"Network Component Installation",
MB_OK | MB_ICONINFORMATION);
}
return;
}
//这里使用“文件”对话框选择inf文件,可以更改为其他方式
void CTryCodeDlg::OnInstallDriver()
{
// TODO: Add your control notification handler code here
WCHAR lpszInfFile[MAX_PATH + 1];
if (GetFileName(this->m_hWnd,
L"INF files (*.inf)\0*.inf\0",
L"Select the INF file of the network component to install",
OFN_DONTADDTORECENT | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST,
lpszInfFile,
NULL))
{
InstallSelectedComponentType(this->m_hWnd, lpszInfFile);
}
}
#22
最近在给客户做一个类似于三星的DNW的工具,用到的驱动文件也是和DNW同样的,也需要考虑和楼主同样的问题,还不清楚怎么实现呢
#23
回hzy_76:
非常感谢你提供源代码,我正在研究呢。
我看到你的安装驱动的核心步骤就是调用setupCopyOEMInf函数。
关于这个函数我还不是很了解其内部机制是什么?MSDN上说,这个函数就是将INF文件以及其相关的文件COPY到系统文件夹中去。
那么这个函数和InstallHinfSection有什么区别呢?我想用DOS批处理脚本来安装驱动,论坛上许多人建议过这样的方法。InstallHinfSection也是将INF文件及其相关文件COPY到系统文件夹下面,并修改注册表。(这一点我在系统文件夹和注册表都有监视过)。结果还是没有安装成功(硬件插上后还是会弹出提示)。
另外,我现在同时还在试验用InstallShield来做个exe的安装包。不知道哪位老大有InstallShield 12 的电子版教材啊? 能分享一下吗? 谢谢咯!
非常感谢你提供源代码,我正在研究呢。
我看到你的安装驱动的核心步骤就是调用setupCopyOEMInf函数。
关于这个函数我还不是很了解其内部机制是什么?MSDN上说,这个函数就是将INF文件以及其相关的文件COPY到系统文件夹中去。
那么这个函数和InstallHinfSection有什么区别呢?我想用DOS批处理脚本来安装驱动,论坛上许多人建议过这样的方法。InstallHinfSection也是将INF文件及其相关文件COPY到系统文件夹下面,并修改注册表。(这一点我在系统文件夹和注册表都有监视过)。结果还是没有安装成功(硬件插上后还是会弹出提示)。
另外,我现在同时还在试验用InstallShield来做个exe的安装包。不知道哪位老大有InstallShield 12 的电子版教材啊? 能分享一下吗? 谢谢咯!
#24
是的,复制安装文件是必要的步骤。修改注册表部分,BindView里边是用INetCfgClassSetup来做的,看起来是针对网络的,估计你用不着了。不过你可以沿这个思路看是否有类似的解决方案。
我原来也想过用InstallShield来做,它的帮助里边也提到过可以制作驱动安装程序,但没有进展,后来就去研究BindView代码了。
我原来也想过用InstallShield来做,它的帮助里边也提到过可以制作驱动安装程序,但没有进展,后来就去研究BindView代码了。
#25
嘿嘿,不好意思,刚看到你的留言。
1.现在这个项目需要事先就把驱动安装到PC中去,也就是把安装驱动这件事放在安装软件(项目最终的发布软件)的过程中完成。那么应该怎么去安装驱动呢?
我看了你的那个脚本,你把设备插在上边然后安装一下,试试看能不能成功,不过安装过程中肯定要提示的。装好之后换个口插入肯定也会提示。(因为你没有经过ms认证。)
一般安装驱动的程序都是使用setupapi或者difx这两套库通过自己的程序实现的。
2. 并且由于软件最终会运行在XP、VISTA和Windows7下面,那么这三个系统下的自动安装的过程有多大的区别呢?
如果没有经过ms认证的驱动的话,在64位操作系统和32位操作系统下是有区别的。区别就是64位下不能使用。^_^.32位下,都一样,使用正规的操作装上之后,第一次插入设备时,还是会提示安装,只是这时选择自动搜索可以自动装上去。而且在安装过程中会有未经过认证的提示。
#26
如果使用InstallShield 12的话,这个工具里自带了安装驱动的接口,你只需要在里边点击几下,配置一下你驱动的路径就可以了。
#27
硬件插上后还是会弹出提示,这个情况是因为你的驱动程序没有经过签名,你可以找一台裸机,或者把你的机器上的驱动删干净试。和你的脚本程序是一样的,如果没有运行过程序或者脚本,在插入设备后提示安装驱动,这时你选择自动搜索,不能将驱动更新。如果运行过了,那就可以更新驱动了。
#28
我现在也是这个问题,用InstallShield 做的包太大了, 换成Setup Factory在搞,可是研究了几天都还没搞定,用SetupCopyOEMInfA拷贝文件到INF文件夹,可是好像没有成功!不知道怎么回事?拷贝文件后还需要做些什么操作吗?
在网上找了下,说要再去写注册表,可是不知道写啥?郁闷,
关注中!!!
在网上找了下,说要再去写注册表,可是不知道写啥?郁闷,
关注中!!!
#29
驱动的安装方式大至有二种:
1,在插上设备的时候进行安装,即使用函数UpdateDriverForPlugAndPlayDevice()。
2,在没有物理设备的时候安装,即通常所说的驱动预安装(SetupCopyOEMInf)。
需要注意的是:
1,SetupCopyOEMInf()只是生成一个oem*.inf文件和oem*.pnf文件到Windows\inf\文件夹中,
即没有修改任何注册表,也没有复制文件。生成的pnf文件包含源文件路径信息,以便在真正
插上设备的时候能够找到相应的sys等文件。
2,UpdateDriverForPlugAndPlayDevice()在没有插上设备的时候是会执行失败的。
Windows插上设备到找到合适的驱动的大致步骤是:
1,插上设备后Windows设备信息到硬件键[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\下去寻找相应的项。
2,如果在Enum键下没有相应的信息,则Windows到预安装目录中去寻找相应的oem*.inf和oem*.pnf文件(oem*.inf和oem*.pnf只要前面的文件名相同就可以,故如果对二个同时改成相同的名字不会有什么影响).
如果进行了预安装,则可以在这里找到相应的inf和pnf文件。于是弹出发现新硬件对话框,点自动安装就可成功(这个对话框可以通过协助安装程序搞掉它)。安装时会弹出徽标论证的对话框(XP下可以通过改注册表的方式搞掉,Vista下暂没发现办法)
3,注册CoInstall的方法即修改以下键值:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\CoDeviceInstallers],子键名为要注册CoInstall的GUID,值为dll的名字和函数名。
1,在插上设备的时候进行安装,即使用函数UpdateDriverForPlugAndPlayDevice()。
2,在没有物理设备的时候安装,即通常所说的驱动预安装(SetupCopyOEMInf)。
需要注意的是:
1,SetupCopyOEMInf()只是生成一个oem*.inf文件和oem*.pnf文件到Windows\inf\文件夹中,
即没有修改任何注册表,也没有复制文件。生成的pnf文件包含源文件路径信息,以便在真正
插上设备的时候能够找到相应的sys等文件。
2,UpdateDriverForPlugAndPlayDevice()在没有插上设备的时候是会执行失败的。
Windows插上设备到找到合适的驱动的大致步骤是:
1,插上设备后Windows设备信息到硬件键[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\下去寻找相应的项。
2,如果在Enum键下没有相应的信息,则Windows到预安装目录中去寻找相应的oem*.inf和oem*.pnf文件(oem*.inf和oem*.pnf只要前面的文件名相同就可以,故如果对二个同时改成相同的名字不会有什么影响).
如果进行了预安装,则可以在这里找到相应的inf和pnf文件。于是弹出发现新硬件对话框,点自动安装就可成功(这个对话框可以通过协助安装程序搞掉它)。安装时会弹出徽标论证的对话框(XP下可以通过改注册表的方式搞掉,Vista下暂没发现办法)
3,注册CoInstall的方法即修改以下键值:
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\CoDeviceInstallers],子键名为要注册CoInstall的GUID,值为dll的名字和函数名。
#30
你的驱动目前打包完成没?
#31
我的方法:
DPInst.exe是WDK中的一个实用工具,它可以自动搜索指定目录的inf文件,并安装相应设备的驱动程序。
MSDN中有关于DPInst.exe的详细资料:
http://msdn.microsoft.com/en-us/library/ms790308.aspx
http://www.microsoft.com/china/whdc/driver/install/difxtools.mspx
下载地址:
http://www.microsoft.com/china/whdc/driver/install/DIFxtls.mspx
http://www.microsoft.com/downloads/details.aspx?FamilyID=2105564e-1a9a-4bf4-8d74-ec5b52da3d00&displaylang=en
DPInst.exe支持命令行,它支持的参数可以使用DPInst.exe /?查看。
示例:
1.自动搜索C:\VGA目录下的INF文件并安装驱动程序:
DPInst.exe /PATH "C:\VGA" /F /Q /LM /A
2.自动搜索C:\目录下的INF文件并安装驱动程序:
DPInst.exe /PATH C:\ /LM
http://qingfengju.com/article.asp?id=183
DPInst.exe是WDK中的一个实用工具,它可以自动搜索指定目录的inf文件,并安装相应设备的驱动程序。
MSDN中有关于DPInst.exe的详细资料:
http://msdn.microsoft.com/en-us/library/ms790308.aspx
http://www.microsoft.com/china/whdc/driver/install/difxtools.mspx
下载地址:
http://www.microsoft.com/china/whdc/driver/install/DIFxtls.mspx
http://www.microsoft.com/downloads/details.aspx?FamilyID=2105564e-1a9a-4bf4-8d74-ec5b52da3d00&displaylang=en
DPInst.exe支持命令行,它支持的参数可以使用DPInst.exe /?查看。
示例:
1.自动搜索C:\VGA目录下的INF文件并安装驱动程序:
DPInst.exe /PATH "C:\VGA" /F /Q /LM /A
2.自动搜索C:\目录下的INF文件并安装驱动程序:
DPInst.exe /PATH C:\ /LM
http://qingfengju.com/article.asp?id=183
#32
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\CoDeviceInstallers 下面注册coinstaller,不过coinstaller 里面SetupDiEnumDriverInfo会失败,没找到好的办法