Introduction
If you’ve ever encountered issues with WMI, you know they can be a real headache. It’s one of those things that seem to go wrong for no apparent reason, especially when you’re dealing with VPNs like GlobalProtect, SCCM, or Intune.
In this blog post, I’m going to walk you through a solution that could save you hours of troubleshooting. We’re going to automate the detection and remediation of WMI issues, focusing specifically on those related to network adapters.
Why do we focus on network adapters?
In my recent experience, many users at home suddenly lost their VPN connection due to an error message: “virtual adapter was not set up correctly…” with GlobalProtect. The root cause? A corrupt WMI, preventing connection with GlobalProtect. However, since SCCM and Intune also use WMI for different purposes, it was necessary to perform a WMI repair.
How do I detect WMI errors with Network Adapters?
Quite simply, we’re working with PowerShell, and one well-known command is:
Get-NetAdapter
In this example, the WMI classes are showing errors like “Invalid class” MSFT_NetAdapter (0x80041010),
leading to corrupted Software Center as well.
How can I solve this problem?
I have written a script that automatically checks for WMI errors related to network adapters. If any are found, it initiates a remediation process. Additionally, at the end of the script, I’ve added an SCCM Agent Health scan, which automatically resolves any WMI issues associated with the agent. The status of the health scan can then be checked in the log file located at C:\Windows\CCM\ccmeval.log. If repair is required, the progress can be found in the log file C:\Windows\CCMSetup\logs\ccmsetup-ccmeval.log.
Link to Github
<#
.SYNOPSIS
A PowerShell script designed to detect and remedy potential WMI class or namespace issues.
.DESCRIPTION
This script checks for specific errors related to the WMI class. If such errors are identified, various remediation steps are undertaken,
including the re-registration of WBEM DLLs and EXEs, the restoration of the WMI repository, and the restarting of associated services.
.PARAMETER None required
.EXAMPLE
PS> .\WMIRemediation.ps1
.NOTES
Date Created: 2023-08-18
Author: Ditor Sahiti
#>
# Define the log file path
$logFilePath = "C:\Windows\Logs\WMIRemediation.log"
# Function to write logs
function Write-Log {
param (
[string]$Message
)
Add-Content -Path $logFilePath -Value "$(Get-Date) - $Message"
}
# Attempt to retrieve Network Adapters
$adapters = $null
$errorOccurred = $false
# Redirect error stream to variable
$adapters = Get-NetAdapter 2>&1
# Check if the error message contains the substring 'Invalid class'
if ($adapters -like "*Invalid*") {
$errorOccurred = $true
Write-Log "Error occurred: Invalid class in network adapters."
}
# If WMI class related error occurred
if ($errorOccurred) {
Write-Log "WMI class appears to be missing. Attempting to fix..."
# Attempt to stop ConfigManager service and WMI service
Write-Log 'Stopping ConfigManager service if it exists'
Stop-Service -Force 'ccmexec' -ErrorAction 'SilentlyContinue'
# Temporarily disable the WMI service to perform corrective actions
Write-Log 'Temporarily disabling Windows Management Instrumentation service'
Set-Service -Name 'winmgmt' -StartupType 'Disabled'
Write-Log 'Stopping Windows Management Instrumentation service'
Stop-Service -Force 'winmgmt' -ErrorAction 'SilentlyContinue'
# Run the commands to re-register WMI components
Write-Log 'Running commands to re-register WMI components'
Set-Location "$env:windir\system32\wbem"
cmd /c "for /f %s in ('dir /b *.dll') do regsvr32 /s %s"
cmd /c "wmiprvse /regserver"
cmd /c "winmgmt /regserver"
cmd /c "for /f %s in ('dir /s /b *.mof *.mfl') do mofcomp %s"
# Restore the WMI service to its original state and restart it
Write-Log 'Setting Windows Management Instrumentation service back to Automatic'
Set-Service -Name 'winmgmt' -StartupType 'Automatic'
Write-Log 'Starting Windows Management Instrumentation service'
Start-Service winmgmt -ErrorAction SilentlyContinue
# Compile the provided MOF file
Write-Log "Executed mofcomp on 'ExtendedStatus.mof'"
mofcomp "C:\Program Files\Microsoft Policy Platform\ExtendedStatus.mof"
# Run ccmeval.exe without waiting for it to finish
Write-Log "Running ConfigMgr Evaluation"
Start-Job -ScriptBlock {
& "C:\Windows\ccm\ccmeval.exe"
}
Write-Log 'Remediation process completed'
# Retry the retrieval of network adapters
$adapters = Get-NetAdapter 2>&1
if ($adapters -like "*Invalid*") {
Write-Log "Error still present: Invalid class in network adapters. Running additional fix."
Set-Location "$env:windir\system32\wbem"
# Run the additional remediation steps
cmd /c "regsvr32.exe /s /i .\NetAdapterCim.dll"
cmd /c ".\mofcomp.exe .\NetAdapterCim.mof"
Write-Log 'Remediation process completed'
}
}
else {
Write-Log "No issues detected with WMI class for network adapters."
}
How can I automate this?
You can either create a scheduled task via GPO or package, if the WMI is not yet corrupted, that executes the script at startup. This ensures that if there are any WMI issues present, the problem will be automatically resolved. In my example I created a scheduled task, exported it, and then created a package via PSADT.
Here are the steps I have taken:
1. Open Task Scheduler and create a new task using “Create Task…”
2. Enter the name of the scheduled task, run the task as SYSTEM, enable Run with highest privileges.
3. Create a new trigger and select “Run at system startup.”
4. Assuming the script is located at C:\Company\Scripts, create new actions as follows:
Program/Script: Powershell.exe
Add arguments: -ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File “C:\Company\Scripts\WMINetAdapterCheck\WMIRemediation.ps1”
5. Export the XML file or use the example below and create your PSADT package.
XML File:
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.4" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
<RegistrationInfo>
<Date>2023-11-07T18:00:59.9736386</Date>
<Author>SYSTEM</Author>
<URI>\WMINetadapterCheck</URI>
</RegistrationInfo>
<Triggers>
<BootTrigger>
<Enabled>true</Enabled>
</BootTrigger>
</Triggers>
<Principals>
<Principal id="Author">
<UserId>S-1-5-18</UserId>
<RunLevel>HighestAvailable</RunLevel>
</Principal>
</Principals>
<Settings>
<MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
<DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
<StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
<AllowHardTerminate>true</AllowHardTerminate>
<StartWhenAvailable>false</StartWhenAvailable>
<RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
<IdleSettings>
<StopOnIdleEnd>true</StopOnIdleEnd>
<RestartOnIdle>false</RestartOnIdle>
</IdleSettings>
<AllowStartOnDemand>true</AllowStartOnDemand>
<Enabled>true</Enabled>
<Hidden>true</Hidden>
<RunOnlyIfIdle>false</RunOnlyIfIdle>
<DisallowStartOnRemoteAppSession>false</DisallowStartOnRemoteAppSession>
<UseUnifiedSchedulingEngine>true</UseUnifiedSchedulingEngine>
<WakeToRun>false</WakeToRun>
<ExecutionTimeLimit>PT1H</ExecutionTimeLimit>
<Priority>7</Priority>
</Settings>
<Actions Context="Author">
<Exec>
<Command>Powershell.exe</Command>
<Arguments>-ExecutionPolicy Bypass -NoProfile -WindowStyle Hidden -File "C:\Company\Scripts\WMINetAdapterCheck\WMIRemediation.ps1"</Arguments>
</Exec>
</Actions>
</Task>
Install:
#Check if the folder exists, and if not, create it at the following path:
$path = "C:\Company\Scripts\WMINetAdapterCheck"
if (-not (Test-Path -Path $path)) {
New-Item -Path $path -ItemType Directory
}
#Copy the WMIRemediation.ps1 from $dirScript to the specified path:
Copy-Item -Path "$dirFiles\WMIRemediation.ps1" -Destination $path -Force
#Silently import the Scheduled Task named "ConfigMgr Client Health.xml" located in $dirScript
$taskName = "WMINetadapterCheck"
$taskPath = "$dirFiles\WMINetadapterCheck.xml"
# Check if the task exists
if (Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue) {
# If it exists, unregister/delete it
Unregister-ScheduledTask -TaskName $taskName -Confirm:$false
}
# Import the task (this will create a new task if it doesn't exist, or overwrite if it does)
if (Test-Path -Path $taskPath) {
Register-ScheduledTask -Xml (Get-Content $taskPath | Out-String) -TaskName $taskName
} else {
Write-Host "Scheduled Task not found!"
}
Uninstall:
# Path to the WMINetadapterCheck folder
$path = "C:\Company\Scripts\WMINetadapterCheck"
# Name of the scheduled task
$taskName = "WMINetadapterCheck"
# Check if the scheduled task exists and delete it if found
if (Get-ScheduledTask -TaskName $taskName -ErrorAction SilentlyContinue) {
Unregister-ScheduledTask -TaskName $taskName -Confirm:$false
Write-Host "Scheduled Task '$taskName' has been deleted."
} else {
Write-Host "Scheduled Task '$taskName' not found."
}
# Check if the folder exists and delete it if found
if (Test-Path -Path $path) {
Remove-Item -Path $path -Recurse -Force
Write-Host "Folder '$path' has been deleted."
} else {
Write-Host "Folder '$path' not found."
}
Conclusion
In summary, we’ve learned to detect and automatically fix WMI errors related to network adapters. Understanding the root cause of these errors can be tricky, but having automation in place is highly beneficial, especially in today’s remote work environment. This saves users the inconvenience of bringing their notebooks into the office unnecessarily.
Could you possibly create this task and make it available to download for those of us who have no idea how to do this?
Thank you for your feedback. The XML code is now available.
Had a employee have this same exact error, unable to go into software center either. Took the code from GitHub, copy and pasted in PS as ADMIN. let it runs its course and PowerShell was able to see the Net adapters and also connect to VPN as normal. Thank you so much I have created a script in SCCM to run this if needed. Life saver and thanks again for helping people out like this
Thanks for your feedback. I’m really glad it’s helping people. I automated it with a Scheduled Task because the script won’t run through SCCM if WMI is broken.
HI Ditor Sahiti,
Thank you very much! Your script solved my issue.
I simply run your script ( I am local admin) .
After some Windows update, the GlobalProtect client on my laptop could not connect. The error message read: “globalprotect virtual adapter was not set up correctly due to a delay”.
Your script created this logs while it was fixing my issue:
======== WMIRemediation.log ============
08/01/2024 12:48:41 – Error occurred: Invalid class in network adapters.
08/01/2024 12:48:41 – WMI class appears to be missing. Attempting to fix…
08/01/2024 12:48:41 – Stopping ConfigManager service if it exists
08/01/2024 12:48:41 – Temporarily disabling Windows Management Instrumentation service
08/01/2024 12:48:41 – Stopping Windows Management Instrumentation service
08/01/2024 12:48:41 – Running commands to re-register WMI components
08/01/2024 12:50:09 – Setting Windows Management Instrumentation service back to Automatic
08/01/2024 12:50:09 – Starting Windows Management Instrumentation service
08/01/2024 12:50:09 – Executed mofcomp on ‘ExtendedStatus.mof’
08/01/2024 12:50:10 – Running ConfigMgr Evaluation
08/01/2024 12:50:12 – Remediation process completed
08/01/2024 12:50:12 – Error still present: Invalid class in network adapters. Running additional fix.
08/01/2024 12:50:12 – Remediation process completed