diff --git a/Fix-WMI.ps1 b/Fix-WMI.ps1 new file mode 100644 index 0000000..0012880 --- /dev/null +++ b/Fix-WMI.ps1 @@ -0,0 +1,79 @@ +# Guard to exit script if WMI does not appear to be installed at all +If ( !(Test-Path "${Env:SystemRoot}\System32\wbem") ) +{ Write-Error "WMI components are not present on this device. Please install them manually." ; Exit } + +# Function to test if WMI is functioning correctly +Function Verify-WMIFunctionality { + # Track the number of failed functionality tests + $WMIErrorLevel = 0 + + # Specify the WMI class name to query + $Class = 'Win32_OperatingSystem' + + # Specify a property in the WMI class that we can test for a value + $Property = 'LastBootUpTime' + + # Test that our property has a value, and that the WBEM folder exists. + If ( $(Get-CimInstance -ClassName $Class -ErrorAction SilentlyContinue | Select-Object $Property -ErrorAction SilentlyContinue).$Property -eq $null ) + { Write-Error "Failed to query ${Class} for the value of ${Property}" ; $WMIErrorLevel++ } + + # Test that the WMI repository is consistent + $WMIRepoStatus = (winmgmt.exe /verifyrepository) + If ( ($WMIRepoStatus -contains "inconsistent") -or ($WMIRepoStatus -contains "failed" ) ) + { Write-Error "WMI repository is in an inconsistent state" ; $WMIErrorLevel++ } + + If ( $WMIErrorLevel -eq 0 ) { Return $true } Else { Return $false } +} + +# Guard to exit script if no repair is necessary +If ( Verify-WMIFunctionality ) { Exit } + +Write-Output "Attempting to salvage WMI repository" + +# Attempt to salvage WMI repository and exit script if no further repair is necessary +$WMIRepoSalvage = (winmgmt.exe /salvagerepository) +If ( !($WMIRepoSalvage -contains "failed") -and (Verify-WMIFunctionality) ) { Exit } +Write-Error "Failed to salvage WMI repository" + +Try { + Write-Output "Attempting manual reinitialization of WMI" + + # Disable and stop the winmgmt service + Write-Output "Stopping and disabling WMI service" + Set-Service -Name winmgmt -StartupType Disabled + Stop-Service -Name winmgmt -Force + + # Set the WBEM directory for manual refresh of WMI components + $TargetDir = "${Env:WinDir}\System32\wbem" + + # Rename the Repository directory to Rep_bak + If ( Test-Path "${TargetDir}\Rep_bak" ) { Remove-Item "${TargetDir}\Rep_bak" -Recurse -Force -ErrorAction SilentlyContinue } + If ( Test-Path "${TargetDir}\Repository" ) { Rename-Item -Path "${TargetDir}\Repository" -NewName "${TargetDir}\Rep_bak" -Force } + + # Register all *.dll files + Write-Output "Registering all DLL files in ""${TargetDir}""" + $WMIDlls = Get-ChildItem -Path "${TargetDir}\*" -File -Include *.dll + ForEach ( $dll in $WMIDlls ) { $path = $dll.FullName ; Start-Process "regsvr32.exe" -ArgumentList "/s ""${path}""" -Wait } + + + #Register all *.exe files + Write-Output "Registering all EXE files in ""${TargetDir}""" + $WMIExes = Get-ChildItem -Path "${TargetDir}\*" -File -Include *.exe | Where { ($_.BaseName.ToLower() -ne "wbemcntl") -and ($_.BaseName.ToLower() -ne "wbemtest") -and ($_.BaseName.ToLower() -ne "mofcomp") } + ForEach ( $exe in $WMIExes ) { $path = $exe.FullName ; Start-Process $path -ArgumentList "/regserver" -Wait } + + # Register all *.mof and *.mfl files + Write-Output "Compiling all MOF and MFL files in ""${TargetDir}""" + $WMIMofs = Get-ChildItem -Path "${TargetDir}\*" -File -Include *.mof,*.mfl + ForEach ( $mof in $WMIMofs ) { $path = $mof.FullName ; Start-Process "${TargetDir}\mofcomp.exe" -ArgumentList """${path}""" -Wait } +} + +Catch { Write-Error $_.Exception.Message } + +Finally { + # Start the winmgmt service + Set-Service -Name winmgmt -StartupType Automatic + Start-Service -Name winmgmt +} + +# Final test of WMI +If ( !(Verify-WMIFunctionality) ) { Write-Output "WMI repair failed. Please restart this device and run this script again." } \ No newline at end of file