我正试图通过PowerShell自动执行许多耗时的任务,这些任务必须预先准备好才能创建新的VM模板,其中之一是从VM中删除所有NIC,并清理不存在设备的设备管理器
从虚拟机中删除NIC后,我尝试使用以下代码段来清理设备管理器,这些代码段做了同样的事情。
wmic nic where "(servicename is null)" delete
gwmi win32_networkadapter | ?{$_.ServiceName -eq $null} | rwmi
在这两种情况下,我都会收到错误"提供程序无法执行尝试的操作"。查看WMI活动的事件日志似乎没有帮助:ResultCode=0x80041024;PossibleCause=未知。
有人能够做类似的事情来删除不存在的设备吗?或者能够发现上述命令的问题吗?
编辑:我曾尝试使用DevCon删除该设备,但它似乎只适用于当前的设备。我现在正在梳理注册表,看看是否有一个特定的密钥或一组密钥,如果删除,将从设备管理器中删除NIC。
这个问题困扰了我一段时间,我想出了更多的手动方法,但它有效,所以希望这能帮助其他人:
1( 首先确保你要清除的设备列表是正确的:
Get-PnpDevice -class net | ? Status -eq Unknown | Select FriendlyName,InstanceId
2( 如果你对即将加入Kaibosh的Get-NetAdapters列表感到满意,请运行以下命令:
$Devs = Get-PnpDevice -class net | ? Status -eq Unknown | Select FriendlyName,InstanceId
ForEach ($Dev in $Devs) {
Write-Host "Removing $($Dev.FriendlyName)" -ForegroundColor Cyan
$RemoveKey = "HKLM:SYSTEMCurrentControlSetEnum$($Dev.InstanceId)"
Get-Item $RemoveKey | Select-Object -ExpandProperty Property | %{ Remove-ItemProperty -Path $RemoveKey -Name $_ -Verbose }
}
Write-Host "Done. Please restart!" -ForegroundColor Green
注意:步骤1中的适配器列表必须仅包含要清除的适配器。如果你有额外的内容,请相应地调整过滤器(?Status-eq XXX,例如:?FriendlyName-like"Broadcom*"(
多亏了这个页面,我成功地解决了类似的问题。我对该脚本进行了一些改进,并通过我的repo在这里发布了它:removeGhosts.ps1
有了这个版本,删除所有隐藏的网络设备可以这样做:
$ removeGhosts.ps1 -narrowbyclass Net
这将要求在移除之前对每个设备进行确认,-Force
选项可以抑制这种行为。如果没有任何选项,脚本将删除所有隐藏的设备,这听起来像是提问者也感兴趣的东西。
此注册表项包含注册表中机器的所有硬件设置:
HKEY_LOCAL_machine\system\currentcontrolset\enum
首先通过WMI查询当前和启用的网络适配器,并获取它们的PNPDeviceId。此值将告诉您网络适配器位于哪个子密钥中。
接下来,查询注册表中的每个子项,并找到所有适配器。解析完整的注册表项,以将其缩短为与PNPDeviceId值相同的长度;大致PCI\VEN_80AD&DEV_ 15A2&SUBSYS_062D1028&REV_02\2&11483669&0&C9。
比较这两个列表并查找任何孤立的注册表项。一旦找到,通过枚举系统帐户删除注册表项将从设备管理器中删除网络适配器。我使用PSExec.exe作为系统帐户运行reg delete命令
这里有一些代码来执行我刚才解释的内容
# Declare variables
[string]$regIds = "";
[string]$Orphans = "";
[array]$SubKeys = @();
[array]$RegKeys = @();
# Query the present and enabled Network Adapters for the PNPDeviceId value
[array]$PNPDeviceIds = (gwmi Win32_NetworkAdapter -Filter "NetEnabled = true").PNPDeviceId;
for ($i = 0; $i -lt $PNPDeviceIds.Count; $i++){
if ($SubKeys -NotContains $($PNPDeviceIds[$i].Split('')[0] + "" + $PNPDeviceIds[$i].Split('')[1])){
$SubKeys += $($PNPDeviceIds[$i].Split('')[0] + "" + $PNPDeviceIds[$i].Split('')[1]);
}}
# Query the registry for all of the adapters
foreach ($SubKey in $SubKeys){
[array]$Keys = reg query "hklmsystemcurrentcontrolsetenum$SubKey"
$Keys = $Keys[1..$($Keys.Count -1)];
$RegKeys += $Keys;
}
# Parse the Keys
for ($i = 0; $i -lt $RegKeys.Count; $i++){ $regIds += "," + $($RegKeys[$i].Split('')[4..6] -join ''); }
$regIds = $regIds.TrimStart(",");
# Compare the registry to the present devices
for ($i = 0; $i -lt $regIds.Split(',').Count; $i++){
if ($PNPDeviceIds -NotContains $regIds.Split(',')[$i]){
$Orphans += "," + $regIds.Split(',')[$i];
}}
if ($Orphans.Length -gt 0){ $Orphans = $Orphans.TrimStart(","); }
# Delete the non-present devices
foreach ($Orphan in $Orphans)
{
psexec.exe -s powershell.exe "reg delete 'hklmsystemcurrentcontrolsetenum$Orphan'"
}
previos脚本中的一些更改
# Declare variables
[string]$regIds = "";
[string]$Orphan = "";
[array]$Orphans = @();
[array]$SubKeys = @();
[array]$RegKeys = @();
# Query the present and enabled Network Adapters for the PNPDeviceId value
[array]$PNPDeviceIds = (gwmi Win32_NetworkAdapter -Filter "NetEnabled = true").PNPDeviceId;
for ($i = 0; $i -lt $PNPDeviceIds.Count; $i++) {
if ($SubKeys -NotContains $($PNPDeviceIds[$i].Split('')[0] + "" + $PNPDeviceIds[$i].Split('')[1])) {
$SubKeys += $($PNPDeviceIds[$i].Split('')[0] + "" + $PNPDeviceIds[$i].Split('')[1])
}
}
# Query the registry for all of the adapters
foreach ($SubKey in $SubKeys) {
[array]$Keys = reg query "hklmsystemcurrentcontrolsetenum$SubKey"
$Keys = $Keys[1..$($Keys.Count -1)];
$RegKeys += $Keys
}
# Parse the Keys
for ($i = 0; $i -lt $RegKeys.Count; $i++) {
$regIds += "," + $($RegKeys[$i].Split('')[4..6] -join '');
}
$regIds = $regIds.TrimStart(",")
# Compare the registry to the present devices
for ($i = 0; $i -lt $regIds.Split(',').Count; $i++) {
if ($PNPDeviceIds -NotContains $regIds.Split(',')[$i]) {
$Orphan += "," + $regIds.Split(',')[$i]
}
}
if ($Orphan.Length -gt 0) {
$Orphan = $Orphan.TrimStart(",")
# Debug: Write-Host "Orphan.Lenght = "$Orphan.Length
# Parse into Objects
for ($i = 0; $i -lt $Orphan.Split(',').Count; $i++) {
$Orphans += $Orphan.Split(',')[$i]
}
# Debug: Write-Host "Orphans = $Orphans Orphans.Lenght = "$Orphans.Length
$Orphan = ""
# Delete the non-present devices
foreach ($Orphan in $Orphans)
{
$Orphan = "HKLM:SystemCurrentControlSetEnum" + $Orphan
Write-Host "You must have Full Rights and You should be Owner" - ForegroundColor Black -BackgroundColor White
Write-Host "Deleting KEY: " -NoNewline
Write-Host $Orphan -ForegroundColor Yellow -NoNewline
If (Test-Path -Path $Orphan) {
Remove-Item -Path $Orphan -Force -Recurse -Confirm:$false -ErrorAction SilentlyContinue
if (Test-Path -Path $Orphan) {
Write-Host " UnSuccsessfully!" -ForegroundColor Red
Write-Host $Error[0] -ForegroundColor Cyan
}
else {
Write-Host " Succsessfully!" -ForegroundColor Green
}
}
else {
Write-Host " Error! Path does not exist." -ForegroundColor Red
}
}
}
else {
Write-Host "Unused Network Adapters not be found." -ForegroundColor Yellow
}