我正在尝试通过PowerShell自动执行一些耗时的任务,我必须执行这些任务以制作新的VM模板,其中一个是从VM中删除所有NIC并清理不存在的设备的设备管理器。 从VM中删除NIC之后,我尝试使用以下代码片段来执行相同的操作来清理设备管理器。
wmic nic where "(servicename is null)" delete
gwmi win32_networkadapter | ?{$_.ServiceName -eq $null} | rwmi
在这两种情况下,我都收到错误“提供程序无法进行尝试操作”。查看WMI-Activity的事件日志似乎没有帮助:ResultCode = 0x80041024; PossibleCause =未知。
有没有人能够做类似的事情,删除不存在的设备或能够找到上述命令的问题?
编辑:我已经尝试使用DevCon删除设备,但它似乎只适用于现有设备。我现在正在梳理注册表,看看是否有一个特定的密钥或一组密钥,如果删除它将从设备管理器中删除NIC。
这个问题困扰了我一段时间,我提出了一些手动方法,但它有效,所以希望这会有助于其他人:
1)首先确保您要清除的设备清单正确无误:
Get-PnpDevice -class net | ? Status -eq Unknown | Select FriendlyName,InstanceId
2)如果您对即将到来的Kaibosh的Get-NetAdapter列表感到满意,请执行以下操作:
$Devs = Get-PnpDevice -class net | ? Status -eq Unknown | Select FriendlyName,InstanceId
ForEach ($Dev in $Devs) {
Write-Host "Removing $($Dev.FriendlyName)" -ForegroundColor Cyan
$RemoveKey = "HKLM:\SYSTEM\CurrentControlSet\Enum\$($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 *”)!
此注册表项包含注册表中计算机的所有硬件设置: HKEY_LOCAL_MACHINE \系统\ CurrentControlSet \枚举 首先通过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 "hklm\system\currentcontrolset\enum\$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 'hklm\system\currentcontrolset\enum\$Orphan'"
}
以前脚本中的一些更改。
# 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 "hklm\system\currentcontrolset\enum\$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:\System\CurrentControlSet\Enum\" + $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
}
由于this page,我设法解决了类似的问题。我稍微改进了那个脚本并通过我的repo发布了它:removeGhosts.ps1
使用此版本删除所有隐藏的网络设备可以这样做:
$ removeGhosts.ps1 -narrowbyclass Net
这将在删除之前要求确认每个设备,-Force
选项可以抑制此行为。没有任何选项,脚本将删除所有隐藏的设备,听起来像提问者也感兴趣的东西。