域环境排查McAfee残留软件的PowerShell脚本问题咨询
Hey there! Let's break down your problem step by step—first addressing whether your current script is the most effective, then tackling that pesky RPC error you're hitting.
First: Is Your Current Script the Best Approach?
Your core idea (scanning AD computers for McAfee installs) is solid, but using Win32_Product is not recommended. Here's why:
- This WMI class triggers a Windows Installer consistency check every time you query it. That can slow down target PCs, trigger unexpected repair prompts for installed software, and even cause rare installation corruption.
- It's also slower than alternative methods, since it has to validate every MSI-installed application.
A far better approach is to query the Windows Registry, where all installed software (MSI and some EXE-based) registers itself. The registry paths for uninstall info are:
HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*(64-bit software)HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*(32-bit software on 64-bit systems)
Optimized PowerShell Script
Here's a rewritten script that fixes the Win32_Product issue, adds error handling, checks if PCs are online first, and uses modern PowerShell remote tools (instead of outdated WMI):
# Get all enabled AD computers (filter out disabled ones to save time) $adComputers = Get-ADComputer -Filter { Enabled -eq $true } | Select-Object -ExpandProperty Name # Set your output file path (update this to your actual path!) $outputFile = "C:\Users\username\Desktop\McAfee_Scan_Results.txt" # Clear existing output file (remove this line if you want to append to previous results) if (Test-Path $outputFile) { Remove-Item $outputFile } foreach ($pc in $adComputers) { Write-Host "Scanning $pc..." # First check if the PC is online to avoid unnecessary errors if (Test-Connection -ComputerName $pc -Count 1 -Quiet -TimeoutSeconds 2) { try { # Use Invoke-Command (WinRM) to remotely query the registry $mcAfeeApps = Invoke-Command -ComputerName $pc -ScriptBlock { # Query both 64-bit and 32-bit uninstall paths Get-ItemProperty -Path @( 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*', 'HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*' ) -ErrorAction SilentlyContinue | # Filter for any McAfee-related display names Where-Object { $_.DisplayName -like "*McAfee*" } | Select-Object DisplayName, DisplayVersion } -ErrorAction Stop if ($mcAfeeApps) { foreach ($app in $mcAfeeApps) { "$pc | Installed: $($app.DisplayName) | Version: $($app.DisplayVersion)" | Out-File -Path $outputFile -Append } } else { "$pc | No McAfee software detected" | Out-File -Path $outputFile -Append } } catch { "$pc | Connection failed: $($_.Exception.Message)" | Out-File -Path $outputFile -Append } } else { "$pc | Offline or unreachable" | Out-File -Path $outputFile -Append } } Write-Host "Scan complete! Results saved to $outputFile"
Key improvements in this script:
- Pre-checks for online PCs: Uses
Test-Connectionto skip offline machines, reducing RPC errors upfront - Registry-based scanning: Faster, no Windows Installer overhead, and captures more software types
- Modern remote management:
Invoke-Command(WinRM) is more reliable than old WMI, and is the recommended PowerShell remote method - Error logging: Catches and records connection issues, so you know exactly which PCs need attention
- Version tracking: Includes software versions, which is helpful for targeting specific old McAfee builds
Fixing the "RPC Server Unavailable" Error
That error you're seeing is almost always related to one of these issues:
- Firewall restrictions: Target PCs have Windows Firewall blocking RPC traffic (port 135 plus dynamic high ports). This is the most common cause, as you suspected.
- Offline PCs: Your original script doesn't check if a PC is online before querying WMI, leading to errors for unreachable machines.
- WMI service stopped: The
Windows Management Instrumentationservice isn't running on the target PC. - Permission issues: Your account doesn't have admin rights or remote WMI access on the target PCs.
If you can't modify group policy yet, try these workarounds:
- Use the optimized script above—it skips offline PCs and uses WinRM, which has different firewall requirements (though you still need WinRM allowed, which is often enabled by default in domains).
- On a test PC, manually enable WMI firewall exceptions:
netsh advfirewall firewall set rule group="Windows Management Instrumentation (WMI)" new enable=yes - Verify your account is in the local Administrators group on target PCs, or has been granted remote WMI access via group policy.
Final Thoughts
Your original script's logic is correct, but using Win32_Product is a common pitfall. The optimized script will be faster, more reliable, and avoid unintended side effects on target PCs. If you need to narrow down the scope, you can export a list of AD computers to a CSV first (using Get-ADComputer | Export-Csv) and loop through that instead of querying AD every time.
内容的提问来源于stack exchange,提问作者Brenen Hatch

