Route all file and folder pickers through elevation-safe Win32 dialogs#664
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Routes all remaining file/folder picker flows away from WinRT/WinUI brokered pickers (which fail under elevated execution) and onto elevation-safe procedural Win32 dialogs, while also making file saves atomic and testable. This aligns with the app’s needs when run as Administrator (per #661) and reduces reliance on broker activation.
Changes:
- Switches “Open File” to use
IFilePickerService(Win32 comdlg32 open dialogs) instead ofMicrosoft.Maui.Storage.FilePicker. - Reworks file saving to pick destinations via
IFilePickerService.PickSaveAsyncand commit content via the newAtomicFileWriter(temp-in-parent + atomicFile.Move(overwrite: true)). - Replaces the WinRT folder picker with a new
Win32FolderDialog(SHBrowseForFolderW+SHGetPathFromIDListEx) and adds a source-scan unit test guard against reintroducing unsafe picker APIs.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/Unit/EventLogExpert.Windows.Tests/PickerSafetyGuardTests.cs | Adds a source-scan guard test preventing reintroduction of WinRT/MAUI picker APIs under src/. |
| tests/Unit/EventLogExpert.Runtime.Tests/Common/Files/AtomicFileWriterTests.cs | Adds unit coverage for atomic write semantics, cancellation, and cleanup behavior. |
| src/EventLogExpert/Platforms/Windows/WinUiFolderPicker.cs | Removes WinRT FolderPicker implementation now replaced by Win32 dialog. |
| src/EventLogExpert/Platforms/Windows/Win32FolderDialog.cs | Introduces elevation-safe Win32 folder picker implementation. |
| src/EventLogExpert/Platforms/Windows/Win32FileDialogService.cs | Adds PickFolderAsync and routes folder selection through STA-threaded Win32 dialog execution. |
| src/EventLogExpert/Platforms/Windows/PickerHostWindow.cs | Removes WinRT InitializeWithWindow helper, keeping only HWND acquisition. |
| src/EventLogExpert/Adapters/Menu/MauiMenuActionService.cs | Routes File > Open through IFilePickerService with improved error surfacing. |
| src/EventLogExpert/Adapters/FileSave/MauiFileSaveService.cs | Switches save flow to Win32 destination picking + AtomicFileWriter commit. |
| src/EventLogExpert/Adapters/FilePicker/MauiFolderPickerService.cs | Routes folder picking through Win32 folder dialog via the Win32 service. |
| src/EventLogExpert.Runtime/Common/Files/AtomicFileWriter.cs | Adds a reusable atomic file writer abstraction for save paths. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
jschick04
force-pushed
the
jschick/fix-elevated-pickers
branch
from
July 23, 2026 15:06
d60726f to
37b19a0
Compare
jschick04
force-pushed
the
jschick/fix-elevated-pickers
branch
from
July 23, 2026 15:31
37b19a0 to
3d61bfc
Compare
jschick04
force-pushed
the
jschick/fix-elevated-pickers
branch
from
July 23, 2026 16:00
3d61bfc to
8a47b77
Compare
jschick04
marked this pull request as ready for review
July 23, 2026 16:08
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #661. When EventLogExpert runs elevated, the WinRT/WinUI file and folder pickers throw
COMException 0x80004005(the broker-activation path is unavailable to elevated callers), so File > Open, File > Open Folder, and every Save failed. This routes every remaining picker through the procedural Win32 dialogs the codebase already uses for elevation-safe file open/save, so they work for standard-user, unpackaged-elevated, and MSIX-packaged-elevated processes alike.Changes
OpenFileAsync) now uses the injectedIFilePickerService(comdlg32GetOpenFileNameW) instead ofMauiFilePicker.Default(WinUIFileOpenPicker).MauiFileSaveService) picks viaIFilePickerService.PickSaveAsync(comdlg32GetSaveFileNameW) and commits through a new, testableAtomicFileWriter(temp-in-parent + atomicFile.Move(overwrite)), replacing the WinRTFileSavePicker+StorageFile/CachedFileManagerbroker machinery.OpenFolderAsync+ scenario launch) uses a newWin32FolderDialog(proceduralshell32!SHBrowseForFolderW+SHGetPathFromIDListExon an STA thread), replacing the WinRTFolderPicker.WinUiFolderPickerandPickerHostWindow.Initialize(WinRTInitializeWithWindow).PickerSafetyGuardTests, a source-scan guard that fails the build if any WinRT/MAUI picker API is reintroduced.Testing
AtomicFileWriterTests(9): new-file create, replace-existing, whole-file replace of a longer original, cancel-before/after-write, writeContent-throws cleanup, and argument validation.PickerSafetyGuardTests(1): asserts noWindows.Storage.Pickers/FilePicker.Default/Microsoft.Maui.Storage.FilePickerreference remains undersrc/.Win32FolderDialog) and the host adapters are not unit-testable (real modal dialogs / WinRT-coupled host), consistent with the existingWin32FileDialog; owed a manual elevated packaged x64 + ARM64 acceptance pass (File > Open, File > Open Folder, scenario launch, and each Save: export CSV/JSON, debug log, database-tools log).Notes
File.Move(overwrite: true)(MoveFileExMOVEFILE_REPLACE_EXISTING) rather thanFile.Replace, whose underlyingReplaceFilehas documented partial-failure states that can delete the destination while orphaning the replacement, a data-loss hazard in a save path. The design and post-code review panels converged unanimously.