使用Powershell删除不存在的网络适配器

问题描述 投票:1回答:2

我正在尝试通过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。

powershell registry wmi nic device-manager
2个回答
1
投票

这个问题困扰了我一段时间,我提出了一些手动方法,但它有效,所以希望这会有助于其他人:

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 *”)!


0
投票

此注册表项包含注册表中计算机的所有硬件设置: 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'"
}

0
投票

以前脚本中的一些更改。

# 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
}

0
投票

由于this page,我设法解决了类似的问题。我稍微改进了那个脚本并通过我的repo发布了它:removeGhosts.ps1

使用此版本删除所有隐藏的网络设备可以这样做:

$ removeGhosts.ps1 -narrowbyclass Net

这将在删除之前要求确认每个设备,-Force选项可以抑制此行为。没有任何选项,脚本将删除所有隐藏的设备,听起来像提问者也感兴趣的东西。

© www.soinside.com 2019 - 2024. All rights reserved.