当我尝试使用 netcfg -u
删除我的NDIS LWF时,我注意到它不会从驱动程序存储中删除它(可以使用 pnputil/enum -drivers
可以看到它)。
这引起了问题,因为在某些Windows 10机器上,如果我们卸载了NDIS LWF的先前版本,并使用 netcfg
安装新的版本,则出于某些未知的原因,旧的INF仍用于安装它!我认为它是因为INF仍然具有相同的componentId?我们正在更新INF文件,以附加到我们以前无法附加的某些虚拟适配器上。请注意,这不会在Windows 7中发生,我们可以在没有任何问题的情况下安装新的。
因此,我的问题是:
-
当我们尝试安装具有不同INF的新更新驱动程序时,为什么Windows仍在使用驱动程序商店的先前INF?
-
完全删除以前的NDIS LWF的正确方法,包括从驱动程序商店中?如果我们需要使用 pnputil
将其完全从驱动程序存储中删除,那么考虑到 pnputil -d
需要一个OEM编号,找到OEM编号的正确方法是什么?
When i try to remove my NDIS LWF using netcfg -u
, i notice that it doesn't remove it from the driver store (can be seen with pnputil /enum-drivers
).
This is causing problem because on some Windows 10 machines, if we uninstall the previous version of our NDIS LWF and install the new one using netcfg
, for some unknown reason the old inf is still used to install it! And i assume its because the inf still has the same componentID? We are updating the INF file in order to attach to some virtual adapters that we previously couldn't attach. Note that this doesn't happen in Windows 7, and we can install the new one without any problem.
So my questions are:
-
Why is Windows still using the previous INF from driver store when we try to install the new updated driver that has a different INF?
-
What is the proper way to fully remove the previous NDIS LWF, including from driver store? If we need to use pnputil
to fully remove it from driver store, then what is the proper way of finding the OEM number, considering that pnputil -d
requires an OEM number?
发布评论
评论(1)
是的,正如您所注意到的那样,
netcfg.exe -i
并不是netcfg.exe -u
的完全相反。安装执行以下步骤:
安装您提供的
-L
的INF到驱动程序商店(setupcopyoeminf
)呼叫
inetcfgclasssetup :: intermant install
to:-i
(setupdibuildDriverInfolist
,setupDisePdiselectBestCompatdrv
)))addReg
,addservice
等))
ndi
注册表密钥中的信息,向系统注册LWF/协议/TDI驱动程序
卸载执行以下步骤:
inetcfgcomponent :: Deinstall
to:.remove
infor的(希望它包含delreg
,delservice
撤消在期间完成的所有工作安装步骤#2.2)(上面的描述忽略了驱动程序重新安置系统(aka
obo_token
),因为它不经常使用 - 大多数驱动程序只是使用单个重新数。如果您专门使用netcfg.exe
来管理驱动程序,那么您也可以忽略重新数。这里的背景故事是
netcfg.exe
从来没有真正成为第三方软件来管理其驱动程序的通用工具。它仅用于内部使用,用于内置在OS中的驱动程序(ms_tcpip
等)。假设是第三方驱动程序安装程序希望调用适当的API,例如inetcfg
,而不是createProcess
一些可执行文件和屏幕crape the Output。因此,netcfg.exe
仅是建立的,这是我们内部需求所需的最小值。特别是,由于内置驾驶员很少卸载,因此很少关注卸载。 (同样,参数解析是不灵活的,帮助文本无用,并且错误处理也不强大。)从Windows 10开始,内置驱动程序不再使用
netcfg.exe
,所以OS本身不再需要netcfg.exe
。但是到那时,第三方产品已经发现了它并对其进行了依赖,因此我们不能再删除netcfg.exe
。嗯。这是一个常见的陷阱。请注意,在安装过程中,步骤#1和#2之间没有关联。您可以同时安装打印机INF和LWF -
netcfg.exe -l foo.inf -i bar
毫不费力地确保实际上选择了步骤#2.2中选择的“最佳”组件来自步骤1中安装的INF。为了确保您想要的驱动程序是“最佳”驱动程序,您必须确保您最喜欢的驱动程序赢得 PNP驱动程序选择算法。我个人被此咬伤了,因为在开发迭代过程中,我没有碰到
驱动程序
行。确保您每次更改驱动程序时增加驱动程序
。老实说,如果您想真正正确完成所有操作,建议完全避免
netcfg.exe
。改用基础inetcfg
apis。然后,您的安装程序将必须管理驱动程序(setupcopyoeminf
/setUpuninStalloeMinf
)。您不会通过抛弃。从那里,您可以通过更强大的INF卸载来改进它。您甚至可以用您的componentId编写一些代码以清单所有INF,以确保不会藏有Inf的陈旧副本。
netcfg.exe
和调用inetcfg
自己而损失太多。netcfg.exe
对inetcfg
没有做任何事情,它自己的实现几乎完全取自此示例代码。如果您从那开始,然后将调用setupcopyoeminf
在顶部,您几乎已经与netcfg.exe
sate您仍然必须从安装INF到希望
InetCfGClassSetup :: install
认为您最近安装的INF是“最佳” INF。但是,如果您使用该componentId删除了每个其他 Inf,那么您可以确定唯一的剩余INF必须是最好的匹配。Right, as you've noticed,
netcfg.exe -i
is not the exact opposite ofnetcfg.exe -u
.Installation does these steps:
Install the INF you provided with
-l
to the driver store (SetupCopyOEMInf
)Call
INetCfgClassSetup::Install
to:-i
(SetupDiBuildDriverInfoList
,SetupDiSelectBestCompatDrv
)AddReg
,AddService
, etc)Ndi
registry keyUninstall does these steps:
INetCfgComponent::DeInstall
to:.Remove
section of the INF (which, hopefully, contains aDelReg
,DelService
to undo everything done during install step #2.2)(The descriptions above ignore the driver refcount system (aka
OBO_TOKEN
), since it isn't often used — most drivers just use a single refcount. If you exclusively usenetcfg.exe
to manage your driver, then you too can ignore refcounts.)You might be wondering: why is this so very less-than-awesome? The backstory here is that
netcfg.exe
was never really meant to be a general-purpose tool for 3rd party software to manage their drivers. It was only meant to be used internally, for the drivers that are built into the OS (ms_tcpip
etc). The assumption was that 3rd party driver installers would want to call proper APIs likeINetCfg
, notCreateProcess
some executable and screen-scrape the output. Sonetcfg.exe
was only built up to be the minimum needed for our internal needs. In particular, very little attention was paid to uninstall, since built-in drivers are rarely uninstalled. (Likewise, argument parsing is inflexible, the help text is not helpful, and the error handling is not robust.)Starting in Windows 10, built-in drivers are no longer installed using
netcfg.exe
, so the OS itself doesn't neednetcfg.exe
at all anymore. But by then, 3rd party products had discovered it and taken a dependency on it, so we couldn't just removenetcfg.exe
anymore. Ah well.This is a common gotcha. Note that, during install, steps #1 and #2 have no association between them. You could install a printer INF and a LWF at the same time —
netcfg.exe -l foo.inf -i bar
makes no effort whatsoever to ensure that the "best" component selected in step #2.2 actually came from the INF installed in step #1.In order to ensure that the driver you want is the "best" driver, you have to ensure that your favored driver wins the PNP driver selection algorithm. I've personally been bitten by this because I didn't bump the
DriverVer
line during development iterations. Make sure you incrementDriverVer
every time you change the driver.Honestly, if you want to do everything really correctly, I suggest avoiding
netcfg.exe
entirely. Use the underlyingINetCfg
APIs instead. Then your installer will have to manage the driver (SetupCopyOEMInf
/SetupUninstallOEMInf
).You aren't losing much by ditching
netcfg.exe
and callingINetCfg
yourself.netcfg.exe
doesn't do anything particularly fancy withINetCfg
: its own implementation is nearly exactly taken from this sample code. If you start with that and slap a call toSetupCopyOEMInf
on top, you'll pretty much be at parity withnetcfg.exe
already. From there, you can improve it with more robust INF uninstall. You can even write some code to inventory all the INFs with your componentId, to make sure there aren't stale copies of your INF hiding around.You still have to make that leap of trust from installing an INF to hoping that
INetCfgClassSetup::Install
thinks your recently-installed INF is the "best" INF. But if you've removed every other INF with that componentId, then you can be certain that the sole remaining INF must be the best match.