如何在PowerShell中查找进程加载失败的DLL文件?
Great question! You’re right that listing loaded DLLs for a process (like with Get-Process | Select-Object -ExpandProperty Modules) is straightforward, but tracking failed DLL load attempts isn’t exposed through basic PowerShell process cmdlets. The good news is you can replicate Procmon’s "Result: Not Found" functionality using Windows’ built-in Event Tracing for Windows (ETW) — the same underlying tech Procmon uses. Here’s how to do it:
Method 1: Real-Time ETW Tracing (Most Accurate)
This method captures live DLL load events, including failures, just like Procmon. You’ll need administrator privileges to run these commands.
Step 1: Start an ETW Trace Session
First, create a trace session targeting the Windows Kernel Image provider, which logs DLL load operations. Run this in an elevated PowerShell window:
logman create trace DLLLoadFailures -p Microsoft-Windows-Kernel-Image 0x8000000000000008 -o C:\Temp\DLLLoads.etl -ets
DLLLoadFailures: A custom name for your trace session (feel free to change it).Microsoft-Windows-Kernel-Image: The ETW provider responsible for logging image/DLL load events.0x8000000000000008: A filter mask that specifically targets failed DLL load attempts.C:\Temp\DLLLoads.etl: The output file where trace data will be stored (ensure theC:\Tempfolder exists first).-ets: Starts the trace session immediately instead of scheduling it.
Step 2: Reproduce the Scenario
Run the process or action you want to monitor (the one that’s attempting to load missing DLLs). Let it run long enough to trigger the failed load attempts.
Step 3: Stop the Trace Session
Once you’ve captured enough data, stop the session:
logman stop DLLLoadFailures -ets
Step 4: Parse the Trace Data for Failures
Extract the failed load records from the ETL file with this command. It filters for Event ID 256 (the ImageLoad event) and checks for non-zero error codes (indicating failure):
Get-WinEvent -Path C:\Temp\DLLLoads.etl | Where-Object { $_.Id -eq 256 -and $_.Properties[1].Value -ne 0 } | Select-Object TimeCreated, @{Name='ProcessName'; Expression={$_.Properties[0].Value}}, @{Name='MissingDLLPath'; Expression={$_.Properties[2].Value}}, @{Name='ErrorCode'; Expression={$_.Properties[1].Value}}
The output will show:
TimeCreated: When the failed load attempt occurred.ProcessName: The name of the process that tried to load the DLL.MissingDLLPath: The path of the DLL that couldn’t be found.ErrorCode: The Windows error code (e.g.,0x80070002translates to "File not found").
Method 2: Check Windows Event Logs (Limited Use Case)
If you don’t need real-time tracking, you can check the Application event log for failed DLL loads that caused application crashes. Look for Event ID 1000 (Application Error), where the "Faulting module name" might indicate a missing DLL. Use this command to filter those events:
Get-WinEvent -FilterHashtable @{LogName='Application'; ID=1000} | Select-Object TimeCreated, @{Name='ProcessName'; Expression={$_.Properties[0].Value}}, @{Name='FaultingDLL'; Expression={$_.Properties[9].Value}}
Note: This only captures failures that caused an application crash, not all silent failed load attempts (which is what Procmon shows).
Key Notes
- Always run PowerShell as an administrator when working with ETW traces — regular user accounts don’t have permission to create kernel-level trace sessions.
- Clean up the trace session and file after you’re done with:
logman delete DLLLoadFailures -ets Remove-Item C:\Temp\DLLLoads.etl -Force
内容的提问来源于stack exchange,提问作者RandomUser

