Files
PowerToys/src/modules/FileLocksmith
Boliang Zhang a255ece641 [File Locksmith] Fix crash (0xc000027b) when a listed process's image file no longer exists (#48719)
## Summary of the Pull Request

`PidToIconConverter.Convert` called `Icon.ExtractAssociatedIcon(path)`
without a guard. When a running process's image path is non-empty but
the file no longer exists on disk, the call throws
`FileNotFoundException`. The converter runs per-row while the process
`ListView` virtualizes, so the exception reached
`App_UnhandledException` (which only logs and never sets `e.Handled =
true`) and WinUI 3 fast-failed the whole app (`0xc000027b`).

This is routinely triggered by self-updating software that deletes its
old versioned directory while the old process keeps running — e.g.
Windows Defender (`SenseAPZ`, `MsMpEng`, `MpDefenderCoreService` under
versioned `...\Platform\<ver>\` / `...\DataCollection\<ver>\` paths).
Right-clicking a drive root enumerates every process and reliably
includes such a stale-path process, so the crash is easy to hit in
normal use.

The fix wraps the icon extraction in a try/catch and falls through to
the existing placeholder `BitmapImage`, logging a warning — mirroring
the exception handling already present in `MainViewModel.WatchProcess`.

## PR Checklist

- [x] Closes: #48693
- [ ] **Communication:** I've discussed this with core contributors
already. If the work hasn't been agreed, this work might be rejected
- [ ] **Tests:** Added/updated and all pass — no existing test harness
covers this WinUI converter path; validated manually (steps below)
- [x] **Localization:** All end-user-facing strings can be localized —
n/a; the only new string is a developer log warning, not end-user UI
- [x] **Dev docs:** Added/updated — n/a
- [x] **New binaries:** Added on the required places — n/a; no new
binaries

## Detailed Description of the Pull Request / Additional comments


`src/modules/FileLocksmith/FileLocksmithUI/Converters/PidToIconConverter.cs`:

```csharp
if (!string.IsNullOrEmpty(y))
{
    try
    {
        icon = Icon.ExtractAssociatedIcon(y);
    }
    catch (Exception ex)
    {
        // The process image path can be non-empty but no longer exist on disk
        // (e.g. self-updating software that deletes its old versioned directory while
        // the old process is still running). ExtractAssociatedIcon then throws and,
        // because this converter runs per-row during ListView virtualization, the
        // exception would otherwise reach App_UnhandledException and fast-fail the app.
        // Fall through to the placeholder icon instead of crashing.
        Logger.LogWarning($"Couldn't extract the icon for '{y}'. {ex}");
    }
}
```

(+ `using ManagedCommon;` — already a project reference; `Logger` is
used identically in `App.xaml.cs`.)

Scope note: this keeps to the targeted converter guard. I deliberately
did **not** also blanket-set `e.Handled = true` in
`App_UnhandledException`, since that would mask unrelated genuine
crashes; the converter guard fully addresses this crash.

## Validation Steps Performed

1. Reproduced on the installed 0.100 build: right-click `C:\` → **Unlock
with File Locksmith** → scroll the list → crash (`0xc000027b`, faulting
module `Microsoft.UI.Xaml.dll`; the FileLocksmith log shows an unhandled
`FileNotFoundException` for `...\SenseAPZ.exe` in
`MainPage...ProcessBindings` / `PidToIconConverter`). Reproduced twice.
2. Built `FileLocksmithUI` (x64/Release) with the fix — 0 warnings / 0
errors.
3. Ran the produced exe on `C:\` and scrolled ~40× over the same list
(which includes the stale `SenseAPZ` row):
   - No crash; the process stayed alive and responsive.
- The log shows the new warning firing for the exact `...\SenseAPZ.exe`
path, confirming the catch branch executed on the previously-fatal row.
   - 0 unhandled exceptions in the session.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-23 14:33:06 +08:00
..