FindMyFiles
FindMyFiles Assembly
FindMyFiles
FindMyFiles
App Class
Application entry point and process-wide composition root. `OnLaunched` resolves the engine boundary (EngineClient) and stands up the single MainWindow. On fatal init failure it falls back to `FakeEngineClient` to avoid crashing silently.
public class App : Microsoft.UI.Xaml.Application, Microsoft.UI.Xaml.Markup.IXamlMetadataProvider
Inheritance System.Object → Microsoft.UI.Xaml.Application → App
Implements Microsoft.UI.Xaml.Markup.IXamlMetadataProvider
Constructors
App() Constructor
Initialize in order: apply language override → `InitializeComponent`
→ ExceptionPolicy.Install. The language override must run before
`InitializeComponent` so `x:Uid`/`ResourceLoader` resolve to the correct
language on the first XAML load.
public App();
Properties
App.DispatcherQueue Property
The UI thread's DispatcherQueue (cached in `OnLaunched`).
Marshal UI work from background threads via TryEnqueue on this
(UI rule: cache it on the UI thread before use).
public static Microsoft.UI.Dispatching.DispatcherQueue DispatcherQueue { get; }
Property Value
Microsoft.UI.Dispatching.DispatcherQueue
App.EngineClient Property
The engine boundary. `--fake-engine` swaps in deterministic data so UI tests and unelevated development never touch real volumes.
public static FindMyFiles.Engine.IEngineClient EngineClient { get; }
Property Value
App.Window Property
The single top-level window. Created in `OnLaunched`; the origin for the HWND lookup via `WinRT.Interop` (WindowHandle).
public static Microsoft.UI.Xaml.Window Window { get; }
Property Value
App.WindowHandle Property
The main window's Win32 HWND. Passed to init of WinRT APIs that take a parent window (file pickers, etc.) — the unpackaged WinUI 3 way.
public static nint WindowHandle { get; }
Property Value
Methods
App.GetXamlType(string) Method
GetXamlType(String)
public Microsoft.UI.Xaml.Markup.IXamlType GetXamlType(string fullName);
Parameters
fullName System.String
Implements GetXamlType(string)
Returns
Microsoft.UI.Xaml.Markup.IXamlType
App.GetXamlType(Type) Method
GetXamlType(Type)
public Microsoft.UI.Xaml.Markup.IXamlType GetXamlType(System.Type type);
Parameters
type System.Type
Implements GetXamlType(Type)
Returns
Microsoft.UI.Xaml.Markup.IXamlType
App.GetXmlnsDefinitions() Method
GetXmlnsDefinitions()
public Microsoft.UI.Xaml.Markup.XmlnsDefinition[] GetXmlnsDefinitions();
Implements GetXmlnsDefinitions()
Returns
Microsoft.UI.Xaml.Markup.XmlnsDefinition[]
App.InitializeComponent() Method
InitializeComponent()
public void InitializeComponent();
FindMyFiles
FindMyFiles.Controls
ResultsViewportManager Class
Imperative ListView companion for the results list: viewport placement after each published result, best-effort selection restore across seeded Resets, ScrollViewer discovery, and the selection-driven row actions (open / reveal / copy — all via ShellOps, which sheds elevation through explorer.exe).
UI thread only: every member touches the ListView, and the class is constructed and wired from the page constructor on the UI thread. The pure decision helpers (FindMyFiles.Controls.ResultsViewportManager.CanRestoreViewport(System.Nullable{System.Int32},System.Int32), FindMyFiles.Controls.ResultsViewportManager.FindSelectionIndex(System.Func{System.Int32,System.Object},System.Int32,System.Int32,System.Int32,System.UInt64), FindMyFiles.Controls.ResultsViewportManager.CopyablePaths(System.Collections.IEnumerable)) are static and unit-tested without a ListView.
public sealed class ResultsViewportManager
Inheritance System.Object → ResultsViewportManager
Constructors
ResultsViewportManager(ListView) Constructor
Wrap the results list and start tracking its selection so the last real (non-placeholder) row's engine identity (EntryRef) can be re-found and reselected after a position-preserving requery's Reset clears the ListView selection.
public ResultsViewportManager(Microsoft.UI.Xaml.Controls.ListView list);
Parameters
list Microsoft.UI.Xaml.Controls.ListView
The results ListView to wrap and track.
Methods
ResultsViewportManager.CopySelectedPaths() Method
Copy the full paths of all real selected rows to the clipboard, CRLF-separated; no-op when the selection holds no real rows.
public void CopySelectedPaths();
ResultsViewportManager.FocusTopRow() Method
Down from the search box: focus the list on its top row.
public void FocusTopRow();
ResultsViewportManager.OnResultsPublished(ResultsPublication) Method
Reset origins (typing, sort…) land at the top; position-preserving origins (index changed, stale…) restore the previous first visible row and, best effort, the selection. Explicit placement — the ListView's own behavior after a Reset is version-dependent.
public void OnResultsPublished(FindMyFiles.ViewModels.ResultsPublication pub);
Parameters
The freshly published result and its restore hints.
ResultsViewportManager.OpenSelected() Method
Open the selected row's file via the shell (no-op if nothing or a placeholder is selected).
public void OpenSelected();
ResultsViewportManager.OpenSelectedOrTop() Method
Open the selected row, or the top row when none is selected (Enter from the search box).
public void OpenSelectedOrTop();
ResultsViewportManager.RevealSelected() Method
Reveal the selected row's file in Explorer (selected in its folder); no-op for an empty or placeholder selection.
public void RevealSelected();
ResultsViewportManager.SelectedOrTopRow() Method
The selected row, falling back to the top row — what Enter from the search box opens when the user never moved into the list.
public FindMyFiles.ViewModels.ResultRow? SelectedOrTopRow();
Returns
ResultRow
The selected row, the top row, or null when empty.
ResultsViewportManager.SelectedRow() Method
The currently selected row, or null if nothing (or a
non-row) is selected.
public FindMyFiles.ViewModels.ResultRow? SelectedRow();
Returns
ResultRow
The selected ResultRow, or null.
FindMyFiles
FindMyFiles.Controls Namespace
| Classes | |
|---|---|
| ResultsViewportManager | Imperative ListView companion for the results list: viewport placement after each published result, best-effort selection restore across seeded Resets, ScrollViewer discovery, and the selection-driven row actions (open / reveal / copy — all via ShellOps, which sheds elevation through explorer.exe). UI thread only: every member touches the ListView, and the class is constructed and wired from the page constructor on the UI thread. The pure decision helpers (FindMyFiles.Controls.ResultsViewportManager.CanRestoreViewport(System.Nullable{System.Int32},System.Int32), FindMyFiles.Controls.ResultsViewportManager.FindSelectionIndex(System.Func{System.Int32,System.Object},System.Int32,System.Int32,System.Int32,System.UInt64), FindMyFiles.Controls.ResultsViewportManager.CopyablePaths(System.Collections.IEnumerable)) are static and unit-tested without a ListView. |
FindMyFiles
FindMyFiles.Converters
UiConverters Class
Pure x:Bind function-binding converters — no IValueConverter plumbing, x:Bind calls these statically and stays typed end to end.
public static class UiConverters
Inheritance System.Object → UiConverters
Methods
UiConverters.BoolToVis(bool) Method
Maps true to Visible and false to Collapsed
(negate on the bind side where inversion is needed).
public static Microsoft.UI.Xaml.Visibility BoolToVis(bool value);
Parameters
value System.Boolean
The bound boolean to map to a visibility.
Returns
Microsoft.UI.Xaml.Visibility
Visible when value is true, otherwise Collapsed.
UiConverters.ToInfoSeverity(NotifySeverity) Method
App severity → InfoBar severity (the InfoBar enum is the view's vocabulary; the app's is NotifySeverity).
public static Microsoft.UI.Xaml.Controls.InfoBarSeverity ToInfoSeverity(FindMyFiles.Services.NotifySeverity s);
Parameters
The app-side severity to translate.
Returns
Microsoft.UI.Xaml.Controls.InfoBarSeverity
The matching Microsoft.UI.Xaml.Controls.InfoBarSeverity for the view.
UiConverters.VisibleIfNotEmpty(string) Method
Visible when the string is non-null and non-empty, otherwise Collapsed.
Used to show an element only when a value exists (e.g. error text).
public static Microsoft.UI.Xaml.Visibility VisibleIfNotEmpty(string? value);
Parameters
value System.String
The bound string whose presence drives visibility.
Returns
Microsoft.UI.Xaml.Visibility
Visible when value is non-null and non-empty, otherwise Collapsed.
FindMyFiles
FindMyFiles.Converters Namespace
| Classes | |
|---|---|
| UiConverters | Pure x:Bind function-binding converters — no IValueConverter plumbing, x:Bind calls these statically and stays typed end to end. |
FindMyFiles
FindMyFiles.Engine
CountersData Class
Degradation counters of the stats JSON (snake_case keys — deserialize with SnakeCaseLower). Generated from the contract's counter-name registry; nonzero values surface in the F12 panel.
public sealed class CountersData
Inheritance System.Object → CountersData
FindMyFiles
FindMyFiles.Engine
EngineClientFactory Class
Engine transport selection, in priority order: CLI flags (--fake-engine / --engine=pipe|inproc / --pipe-name=…) > settings.json "engine" > auto. Auto probes the service pipe for 250ms (through Hello) and falls back to the in-proc FFI engine when no service answers.
public static class EngineClientFactory
Inheritance System.Object → EngineClientFactory
Methods
EngineClientFactory.Resolve(string[]) Method
Called once at startup; resolves and returns a single engine implementation by the priority above. When in-proc is unavailable (no service plus not elevated), degrades to the empty engine (CreateEmpty()) and steers the UI to the setup screen (no auto-runas).
public static FindMyFiles.Engine.IEngineClient Resolve(string[] args);
Parameters
args System.String[]
Process command-line args (reads `--fake-engine` / `--engine=` / `--pipe-name=`).
Returns
IEngineClient
The single chosen IEngineClient implementation instance.
FindMyFiles
FindMyFiles.Engine
EngineConnectionState Enum
Transport state of the engine boundary. In-proc clients are always InProc; the pipe client reports its supervisor state.
public enum EngineConnectionState
Fields
InProc 0
In-process engine (FFI): no transport, so always connected.
Connecting 1
The pipe client is establishing its first connection to the service.
Connected 2
The pipe client has a live connection to the service.
Reconnecting 3
The pipe connection dropped; the supervisor is re-establishing it.
FindMyFiles
FindMyFiles.Engine
EngineEventMarshaler Class
The single crossing point from engine threads to the UI thread. IEngineClient events fire on engine / pipe read-loop threads; this class subscribes to all four, marshals each through TryEnqueue(Action) and re-raises it as its own event on the UI thread. Consumers (ViewModels, the orchestrator) attach plain handlers and never marshal themselves — the per-subscriber inline `dispatcher.TryEnqueue` lambdas this replaces were the audit's "scattered crossing" finding. The upstream delegates are held in fields for the subscription lifetime (the GC-rooting rule for callback delegates, satisfied structurally).
public sealed class EngineEventMarshaler : System.IDisposable
Inheritance System.Object → EngineEventMarshaler
Implements System.IDisposable
Constructors
EngineEventMarshaler(IEngineClient, IDispatcher) Constructor
Subscribes to the four events of engine, marshals each payload to the UI thread via dispatcher, and re-raises it as this class's same-named event. The upstream delegates are held in fields (subscription lifetime = GC root) and detached in Dispose().
public EngineEventMarshaler(FindMyFiles.Engine.IEngineClient engine, FindMyFiles.Services.IDispatcher dispatcher);
Parameters
engine IEngineClient
The source engine client to subscribe to.
dispatcher IDispatcher
The UI-thread marshal target.
Methods
EngineEventMarshaler.Dispose() Method
Detaches all four upstream subscriptions (after this the marshaler re-raises no further events).
public void Dispose();
Implements Dispose()
Events
EngineEventMarshaler.ConnectionChanged Event
Re-raised on the UI thread from ConnectionChanged (same payload, same order).
public event Action<EngineConnectionState>? ConnectionChanged;
Event Type
System.Action<EngineConnectionState>
EngineEventMarshaler.EngineErrorOccurred Event
Re-raised on the UI thread from EngineErrorOccurred (same severity, same order).
public event Action<int>? EngineErrorOccurred;
Event Type
EngineEventMarshaler.IndexChanged Event
Re-raised on the UI thread from IndexChanged. Payload and the engine's relative firing order are preserved (TryEnqueue is FIFO).
public event Action<string>? IndexChanged;
Event Type
EngineEventMarshaler.VolumeUpdated Event
Re-raised on the UI thread from VolumeUpdated (same payload, same order).
public event Action<VolumeStatus>? VolumeUpdated;
Event Type
FindMyFiles
FindMyFiles.Engine
EngineException Class
The engine rejected an operation with a structured error code (the transport is alive but the engine returned a failure). The code maps to the `FMF_E_*` table in docs/ARCHITECTURE.md.
public sealed class EngineException : System.Exception
Inheritance System.Object → System.Exception → EngineException
Constructors
EngineException(string, int) Constructor
The engine rejected an operation with a structured error code (the transport is alive but the engine returned a failure). The code maps to the `FMF_E_*` table in docs/ARCHITECTURE.md.
public EngineException(string message, int code);
Parameters
message System.String
The human-readable message returned by the engine.
code System.Int32
The numeric `FMF_E_*` code (held in Code).
Properties
EngineException.Code Property
The `FMF_E_*` code returned by the engine. Used for UI branching (e.g. `FMF_E_LOCKED` routes to the setup screen).
public int Code { get; }
Property Value
FindMyFiles
FindMyFiles.Engine
EngineStatsData Class
The whole observability snapshot behind the F12 perf panel —
what GetStatsAsync(CancellationToken) returns (the UI subset of
fmf-core's MetricsSnapshot).
public sealed class EngineStatsData
Inheritance System.Object → EngineStatsData
Properties
EngineStatsData.Counters Property
Degradation counters; nonzero values flag silent fallbacks.
public FindMyFiles.Engine.CountersData Counters { get; set; }
Property Value
EngineStatsData.Indexes Property
Per-volume index accounting, one entry per indexed volume.
public System.Collections.Generic.List<FindMyFiles.Engine.IndexStatsData> Indexes { get; set; }
Property Value
System.Collections.Generic.List<IndexStatsData>
EngineStatsData.P50Us Property
Median query latency in µs across the histogram's lifetime.
public ulong P50Us { get; set; }
Property Value
EngineStatsData.P99Us Property
99th-percentile query latency in µs — the figure measured against the ≤50 ms search gate.
public ulong P99Us { get; set; }
Property Value
EngineStatsData.RecentErrors Property
WARN+ diagnostics and panics from the engine's ring, oldest first.
public System.Collections.Generic.List<FindMyFiles.Engine.ErrorEventData> RecentErrors { get; set; }
Property Value
System.Collections.Generic.List<ErrorEventData>
EngineStatsData.RecentQueries Property
Recent query traces, oldest first (a bounded ring on the engine side).
public System.Collections.Generic.List<FindMyFiles.Engine.QueryTraceData> RecentQueries { get; set; }
Property Value
System.Collections.Generic.List<QueryTraceData>
EngineStatsData.RecentUsn Property
Recently applied USN batches, oldest first.
public System.Collections.Generic.List<FindMyFiles.Engine.UsnTraceData> RecentUsn { get; set; }
Property Value
System.Collections.Generic.List<UsnTraceData>
EngineStatsData.Transport Property
Pipe transport metrics, or null for in-proc clients (Ffi/Fake) where there is no wire.
public FindMyFiles.Engine.TransportStatsData? Transport { get; set; }
Property Value
FindMyFiles
FindMyFiles.Engine
EngineUnavailableException Class
The engine transport is down (pipe disconnected, request timed out, service not running). Pending requests fail fast with this; the supervisor keeps reconnecting in the background.
public sealed class EngineUnavailableException : System.Exception
Inheritance System.Object → System.Exception → EngineUnavailableException
Constructors
EngineUnavailableException(string) Constructor
The engine transport is down (pipe disconnected, request timed out, service not running). Pending requests fail fast with this; the supervisor keeps reconnecting in the background.
public EngineUnavailableException(string message);
Parameters
message System.String
Human-readable description of which transport failure occurred.
FindMyFiles
FindMyFiles.Engine
ErrorEventData Class
One entry from the engine's diagnostic ring (WARN+ events and
panics; mirrors fmf-core's ErrorEvent). Pulled on demand after an
EngineErrorOccurred signal and listed in the
F12 panel.
public sealed class ErrorEventData
Inheritance System.Object → ErrorEventData
Properties
ErrorEventData.Area Property
Originating tracing target (module path) — the "where"
of the event.
public string Area { get; set; }
Property Value
ErrorEventData.Message Property
Human-readable description of what happened.
public string Message { get; set; }
Property Value
ErrorEventData.Seq Property
Monotonic emit sequence — orders events and lets the UI detect ones it has already shown.
public ulong Seq { get; set; }
Property Value
ErrorEventData.Severity Property
Level as a lowercase string: "warn", "error" or
"panic" (the same 1/2/3 the FFI event carries numerically).
public string Severity { get; set; }
Property Value
ErrorEventData.UptimeMs Property
Engine uptime in ms when the event fired ("when").
public ulong UptimeMs { get; set; }
Property Value
ErrorEventData.Volume Property
Drive label the event is attributed to, or null when it is not volume-scoped.
public string? Volume { get; set; }
Property Value
FindMyFiles
FindMyFiles.Engine
FakeEngineClient Class
Deterministic in-memory engine for UI tests and unelevated development (`--fake-engine`). 100k entries from a fixed seed; substring search only. Contract-conforming (EngineClientContractTests): query-syntax verdicts come from the shared golden fixture (contract/golden/invalid_queries.json, pinned by the real Rust parser — verdict drift is caught on the Rust side), cancellation is honored, and BumpEpoch() lets tests drive the Stale→requery recovery path without a real engine.
public sealed class FakeEngineClient : FindMyFiles.Engine.IEngineClient, System.IDisposable
Inheritance System.Object → FakeEngineClient
Implements IEngineClient, System.IDisposable
Constructors
FakeEngineClient(bool) Constructor
Builds the fake. The default (empty false)
generates the deterministic 100k-row dataset that backs
--fake-engine; CreateEmpty() passes
empty true for the unelevated no-service
stand-in.
public FakeEngineClient(bool empty=false);
Parameters
empty System.Boolean
When true, no rows are generated (the disconnected auto-fallback); when false, the seeded demo dataset is built.
Properties
FakeEngineClient.Connection Property
In-proc: no transport, no state transitions.
public FindMyFiles.Engine.EngineConnectionState Connection { get; }
Implements Connection
Property Value
FakeEngineClient.IsEmpty Property
True for the unelevated auto-fallback instance (no rows) — the status badge says disconnected, not fake.
public bool IsEmpty { get; }
Property Value
Methods
FakeEngineClient.BumpEpoch() Method
Test hook: structurally invalidate every result handed out so far — their next GetRangeAsync throws StaleResultException, exactly like a real index rebuild (UI Stale→requery recovery).
public void BumpEpoch();
FakeEngineClient.CreateEmpty() Method
Visibly empty stand-in for the unelevated no-service start —
searching demo rows has no practical value (user verdict), so the
auto-fallback shows zero results plus the setup notification instead.
The data-bearing fake stays what --fake-engine is for.
public static FindMyFiles.Engine.FakeEngineClient CreateEmpty();
Returns
FakeEngineClient
A rowless fake that reports disconnected and yields no results.
FakeEngineClient.Dispose() Method
Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
public void Dispose();
Implements Dispose()
FakeEngineClient.GetStatsAsync(CancellationToken) Method
Observability snapshot for the performance panel.
public System.Threading.Tasks.Task<FindMyFiles.Engine.EngineStatsData?> GetStatsAsync(System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
ct System.Threading.CancellationToken
Cooperative cancellation token.
Implements GetStatsAsync(CancellationToken)
Returns
System.Threading.Tasks.Task<EngineStatsData>
The current engine stats, or null if unavailable.
FakeEngineClient.GetStatusAsync(CancellationToken) Method
Returns a snapshot of the current state (VolumeStatus) of every volume. Used for the initial display at startup and for the setup screen's decisions.
public System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<FindMyFiles.Engine.VolumeStatus>> GetStatusAsync(System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
ct System.Threading.CancellationToken
Cooperative cancellation token.
Implements GetStatusAsync(CancellationToken)
Returns
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<VolumeStatus>>
A snapshot of the current status of every known volume.
Exceptions
EngineUnavailableException
service unreachable
FakeEngineClient.ListVolumesAsync(CancellationToken) Method
Returns the labels of the indexed volumes (those the engine currently recognizes).
public System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<string>> ListVolumesAsync(System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
ct System.Threading.CancellationToken
Cooperative cancellation token.
Implements ListVolumesAsync(CancellationToken)
Returns
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<System.String>>
The labels of the volumes the engine currently knows about.
Exceptions
EngineUnavailableException
service unreachable
FakeEngineClient.SearchAsync(string, SearchOptions, CancellationToken) Method
Executes the query and returns a sort-settled result handle (Result) plus an optional timing trace. Pages are read lazily through the returned ISearchResult.
public System.Threading.Tasks.Task<FindMyFiles.Engine.SearchOutcome> SearchAsync(string query, FindMyFiles.Engine.SearchOptions options, System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
query System.String
The query text to execute.
options SearchOptions
Search options (sort order, flags).
ct System.Threading.CancellationToken
Cooperative cancellation token.
Implements SearchAsync(string, SearchOptions, CancellationToken)
Returns
System.Threading.Tasks.Task<SearchOutcome>
The sort-ordered result handle plus an optional timing trace.
Exceptions
QuerySyntaxException
malformed query text
EngineUnavailableException
service unreachable
FakeEngineClient.StartIndexingAsync(IReadOnlyList<string>, CancellationToken) Method
Requests that indexing/re-indexing start for the given volumes (fire-and-trigger: progress arrives via VolumeUpdated / IndexChanged). MFT reads require elevation, so the work runs on the service side.
public System.Threading.Tasks.Task StartIndexingAsync(System.Collections.Generic.IReadOnlyList<string> volumes, System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
volumes System.Collections.Generic.IReadOnlyList<System.String>
Labels of the volumes to (re)index.
ct System.Threading.CancellationToken
Cooperative cancellation token.
Implements StartIndexingAsync(IReadOnlyList<string>, CancellationToken)
Returns
System.Threading.Tasks.Task
A task that completes once the indexing request is accepted.
Exceptions
EngineUnavailableException
service unreachable
Events
FakeEngineClient.ConnectionChanged Event
Fires when the current Connection transitions. In-proc implementations never fire (always InProc). Fires from the pipe client's supervisor thread → marshal.
public event Action<EngineConnectionState>? ConnectionChanged;
Implements ConnectionChanged
Event Type
System.Action<EngineConnectionState>
FakeEngineClient.EngineErrorOccurred Event
The engine recorded a diagnostic (1=warn 2=error 3=panic). Details live in RecentErrors — pull on demand.
public event Action<int>? EngineErrorOccurred;
Implements EngineErrorOccurred
Event Type
FakeEngineClient.IndexChanged Event
New index content was published (USN apply or scan progress). The payload is the triggering volume label. The signal to re-evaluate the displayed query. Fires from an engine thread, so marshal to the UI thread (EngineEventMarshaler is the only crossing point).
public event Action<string>? IndexChanged;
Implements IndexChanged
Event Type
FakeEngineClient.VolumeUpdated Event
One volume's state transitioned (`Scanning`→`Ready` etc.). Emits the latest VolumeStatus. Fires from an engine thread → marshal.
public event Action<VolumeStatus>? VolumeUpdated;
Implements VolumeUpdated
Event Type
FindMyFiles
FindMyFiles.Engine
FfiEngineClient Class
In-proc engine client over fmf_engine.dll. Events arrive on engine threads; consumers marshal to the UI thread themselves.
public sealed class FfiEngineClient : FindMyFiles.Engine.IEngineClient, System.IDisposable
Inheritance System.Object → FfiEngineClient
Implements IEngineClient, System.IDisposable
Constructors
FfiEngineClient() Constructor
Creates the in-proc engine over the default machine index at
%ProgramData%\find-my-files\index.
public FfiEngineClient();
Properties
FfiEngineClient.Connection Property
In-proc: no transport, no state transitions.
public FindMyFiles.Engine.EngineConnectionState Connection { get; }
Implements Connection
Property Value
FfiEngineClient.IsScopeMode Property
True when this client runs in scope mode (ADR-0024: folder-walk over FindMyFiles.Engine.FfiEngineClient._scopeRoots) rather than whole-volume mode. Lets the ViewModel pick the scope-vs-privileged UI without reaching past IEngineClient.
public bool IsScopeMode { get; }
Property Value
Methods
FfiEngineClient.CreateScope(IReadOnlyList<string>, IReadOnlyList<string>) Method
Creates a non-elevated **scope-mode** engine (ADR-0024) indexing
only roots by folder-walk — no admin, no service. The
index and the engine log both live under the portable data root
(AppPaths): <exe>\data\{index,logs} by default, so
scope mode pollutes nothing outside the app's own folder.
public static FindMyFiles.Engine.FfiEngineClient CreateScope(System.Collections.Generic.IReadOnlyList<string> roots, System.Collections.Generic.IReadOnlyList<string> excludes);
Parameters
roots System.Collections.Generic.IReadOnlyList<System.String>
Absolute folder roots to folder-walk and index.
excludes System.Collections.Generic.IReadOnlyList<System.String>
Absolute subfolders to prune from the walk (ADR-0025).
Returns
FfiEngineClient
A scope-mode client over the portable data root.
FfiEngineClient.Dispose() Method
Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
public void Dispose();
Implements Dispose()
FfiEngineClient.GetStatsAsync(CancellationToken) Method
Observability snapshot for the performance panel.
public System.Threading.Tasks.Task<FindMyFiles.Engine.EngineStatsData?> GetStatsAsync(System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
ct System.Threading.CancellationToken
Cooperative cancellation token.
Implements GetStatsAsync(CancellationToken)
Returns
System.Threading.Tasks.Task<EngineStatsData>
The current engine stats, or null if unavailable.
FfiEngineClient.GetStatusAsync(CancellationToken) Method
Returns a snapshot of the current state (VolumeStatus) of every volume. Used for the initial display at startup and for the setup screen's decisions.
public System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<FindMyFiles.Engine.VolumeStatus>> GetStatusAsync(System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
ct System.Threading.CancellationToken
Cooperative cancellation token.
Implements GetStatusAsync(CancellationToken)
Returns
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<VolumeStatus>>
A snapshot of the current status of every known volume.
Exceptions
EngineUnavailableException
service unreachable
FfiEngineClient.ListVolumesAsync(CancellationToken) Method
Returns the labels of the indexed volumes (those the engine currently recognizes).
public System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<string>> ListVolumesAsync(System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
ct System.Threading.CancellationToken
Cooperative cancellation token.
Implements ListVolumesAsync(CancellationToken)
Returns
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<System.String>>
The labels of the volumes the engine currently knows about.
Exceptions
EngineUnavailableException
service unreachable
FfiEngineClient.SearchAsync(string, SearchOptions, CancellationToken) Method
Executes the query and returns a sort-settled result handle (Result) plus an optional timing trace. Pages are read lazily through the returned ISearchResult.
public System.Threading.Tasks.Task<FindMyFiles.Engine.SearchOutcome> SearchAsync(string query, FindMyFiles.Engine.SearchOptions options, System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
query System.String
The query text to execute.
options SearchOptions
Search options (sort order, flags).
ct System.Threading.CancellationToken
Cooperative cancellation token.
Implements SearchAsync(string, SearchOptions, CancellationToken)
Returns
System.Threading.Tasks.Task<SearchOutcome>
The sort-ordered result handle plus an optional timing trace.
Exceptions
QuerySyntaxException
malformed query text
EngineUnavailableException
service unreachable
FfiEngineClient.StartIndexingAsync(IReadOnlyList<string>, CancellationToken) Method
Requests that indexing/re-indexing start for the given volumes (fire-and-trigger: progress arrives via VolumeUpdated / IndexChanged). MFT reads require elevation, so the work runs on the service side.
public System.Threading.Tasks.Task StartIndexingAsync(System.Collections.Generic.IReadOnlyList<string> volumes, System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
volumes System.Collections.Generic.IReadOnlyList<System.String>
Labels of the volumes to (re)index.
ct System.Threading.CancellationToken
Cooperative cancellation token.
Implements StartIndexingAsync(IReadOnlyList<string>, CancellationToken)
Returns
System.Threading.Tasks.Task
A task that completes once the indexing request is accepted.
Exceptions
EngineUnavailableException
service unreachable
Events
FfiEngineClient.ConnectionChanged Event
Fires when the current Connection transitions. In-proc implementations never fire (always InProc). Fires from the pipe client's supervisor thread → marshal.
public event Action<EngineConnectionState>? ConnectionChanged;
Implements ConnectionChanged
Event Type
System.Action<EngineConnectionState>
FfiEngineClient.EngineErrorOccurred Event
The engine recorded a diagnostic (1=warn 2=error 3=panic). Details live in RecentErrors — pull on demand.
public event Action<int>? EngineErrorOccurred;
Implements EngineErrorOccurred
Event Type
FfiEngineClient.IndexChanged Event
New index content was published (USN apply or scan progress). The payload is the triggering volume label. The signal to re-evaluate the displayed query. Fires from an engine thread, so marshal to the UI thread (EngineEventMarshaler is the only crossing point).
public event Action<string>? IndexChanged;
Implements IndexChanged
Event Type
FfiEngineClient.VolumeUpdated Event
One volume's state transitioned (`Scanning`→`Ready` etc.). Emits the latest VolumeStatus. Fires from an engine thread → marshal.
public event Action<VolumeStatus>? VolumeUpdated;
Implements VolumeUpdated
Event Type
FindMyFiles
FindMyFiles.Engine
FmfCase Enum
Case-matching mode (wire values of fmf-core's CaseMode).
public enum FmfCase
Fields
Smart 0
Case-insensitive unless the query contains an uppercase letter, in which case it becomes case-sensitive.
Insensitive 1
Always case-insensitive.
Sensitive 2
Always case-sensitive.
FindMyFiles
FindMyFiles.Engine
FmfSort Enum
Result sort key (wire values of fmf-core's SortKey).
public enum FmfSort
Fields
Name 0
Sort by file name.
Size 1
Sort by file size in bytes.
Mtime 2
Sort by modification time.
FindMyFiles
FindMyFiles.Engine
IEngineClient Interface
The single boundary the app uses to talk to the engine (docs/ARCHITECTURE.md). Implementations: PipeEngineClient (named pipe to fmf-service), FfiEngineClient (in-proc DLL, --engine=inproc) and FakeEngineClient (deterministic data for UI tests via --fake-engine). The shared observable behavior is executable: Tests/Contract/EngineClientContractTests runs the same suite against all implementations.
Cancellation is cooperative and fully plumbed (ADR-0018): a cancelled
ct surfaces as System.OperationCanceledException (or a
subclass) from every async member. Data shapes live in EngineTypes.cs.
public interface IEngineClient : System.IDisposable
Derived
↳ FakeEngineClient
↳ FfiEngineClient
↳ PipeEngineClient
Implements System.IDisposable
Properties
IEngineClient.Connection Property
InProc for Ffi/Fake (fixed, never raises ConnectionChanged); the pipe client moves through Connecting/Connected/Reconnecting.
FindMyFiles.Engine.EngineConnectionState Connection { get; }
Property Value
Methods
IEngineClient.GetStatsAsync(CancellationToken) Method
Observability snapshot for the performance panel.
System.Threading.Tasks.Task<FindMyFiles.Engine.EngineStatsData?> GetStatsAsync(System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
ct System.Threading.CancellationToken
Cooperative cancellation token.
Returns
System.Threading.Tasks.Task<EngineStatsData>
The current engine stats, or null if unavailable.
IEngineClient.GetStatusAsync(CancellationToken) Method
Returns a snapshot of the current state (VolumeStatus) of every volume. Used for the initial display at startup and for the setup screen's decisions.
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<FindMyFiles.Engine.VolumeStatus>> GetStatusAsync(System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
ct System.Threading.CancellationToken
Cooperative cancellation token.
Returns
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<VolumeStatus>>
A snapshot of the current status of every known volume.
Exceptions
EngineUnavailableException
service unreachable
IEngineClient.ListVolumesAsync(CancellationToken) Method
Returns the labels of the indexed volumes (those the engine currently recognizes).
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<string>> ListVolumesAsync(System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
ct System.Threading.CancellationToken
Cooperative cancellation token.
Returns
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<System.String>>
The labels of the volumes the engine currently knows about.
Exceptions
EngineUnavailableException
service unreachable
IEngineClient.SearchAsync(string, SearchOptions, CancellationToken) Method
Executes the query and returns a sort-settled result handle (Result) plus an optional timing trace. Pages are read lazily through the returned ISearchResult.
System.Threading.Tasks.Task<FindMyFiles.Engine.SearchOutcome> SearchAsync(string query, FindMyFiles.Engine.SearchOptions options, System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
query System.String
The query text to execute.
options SearchOptions
Search options (sort order, flags).
ct System.Threading.CancellationToken
Cooperative cancellation token.
Returns
System.Threading.Tasks.Task<SearchOutcome>
The sort-ordered result handle plus an optional timing trace.
Exceptions
QuerySyntaxException
malformed query text
EngineUnavailableException
service unreachable
IEngineClient.StartIndexingAsync(IReadOnlyList<string>, CancellationToken) Method
Requests that indexing/re-indexing start for the given volumes (fire-and-trigger: progress arrives via VolumeUpdated / IndexChanged). MFT reads require elevation, so the work runs on the service side.
System.Threading.Tasks.Task StartIndexingAsync(System.Collections.Generic.IReadOnlyList<string> volumes, System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
volumes System.Collections.Generic.IReadOnlyList<System.String>
Labels of the volumes to (re)index.
ct System.Threading.CancellationToken
Cooperative cancellation token.
Returns
System.Threading.Tasks.Task
A task that completes once the indexing request is accepted.
Exceptions
EngineUnavailableException
service unreachable
Events
IEngineClient.ConnectionChanged Event
Fires when the current Connection transitions. In-proc implementations never fire (always InProc). Fires from the pipe client's supervisor thread → marshal.
event Action<EngineConnectionState>? ConnectionChanged;
Event Type
System.Action<EngineConnectionState>
IEngineClient.EngineErrorOccurred Event
The engine recorded a diagnostic (1=warn 2=error 3=panic). Details live in RecentErrors — pull on demand.
event Action<int>? EngineErrorOccurred;
Event Type
IEngineClient.IndexChanged Event
New index content was published (USN apply or scan progress). The payload is the triggering volume label. The signal to re-evaluate the displayed query. Fires from an engine thread, so marshal to the UI thread (EngineEventMarshaler is the only crossing point).
event Action<string>? IndexChanged;
Event Type
IEngineClient.VolumeUpdated Event
One volume's state transitioned (`Scanning`→`Ready` etc.). Emits the latest VolumeStatus. Fires from an engine thread → marshal.
event Action<VolumeStatus>? VolumeUpdated;
Event Type
FindMyFiles
FindMyFiles.Engine
ISearchResult Interface
Materialized, sort-ordered result; pages are O(1) reads.
public interface ISearchResult : System.IDisposable
Implements System.IDisposable
Properties
ISearchResult.Count Property
The settled total match count (the upper bound on rows obtainable via GetRangeAsync(long, int, CancellationToken)). This determines the virtualized list's scroll range.
long Count { get; }
Property Value
Methods
ISearchResult.GetRangeAsync(long, int, CancellationToken) Method
Fetches up to count rows from offset in the result (page read of the visible window).
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<FindMyFiles.Engine.RowData>> GetRangeAsync(long offset, int count, System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
offset System.Int64
0-based row offset from the start.
count System.Int32
Maximum number of rows to fetch.
ct System.Threading.CancellationToken
Cooperative cancellation token.
Returns
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<RowData>>
The RowData for the requested range (may be fewer
than count near the end).
Exceptions
StaleResultException
The index was structurally rebuilt — re-run the query.
FindMyFiles
FindMyFiles.Engine
IndexStatsData Class
Memory accounting and generation state for one volume index
(subset of fmf-core's IndexStats the UI surfaces). Feeds the
bytes/entry gate in the F12 panel.
public sealed class IndexStatsData
Inheritance System.Object → IndexStatsData
Properties
IndexStatsData.BytesPerEntry Property
TotalBytes / Entries; the headline RAM-efficiency
figure measured against the ≤110 B/file target.
public double BytesPerEntry { get; set; }
Property Value
IndexStatsData.ContentGeneration Property
Bumps on every content change (USN apply, rescan). A stable value means an Unchanged re-query is possible; the structural generation (not exposed here) is what invalidates a result with StaleResultException.
public ulong ContentGeneration { get; set; }
Property Value
IndexStatsData.Entries Property
Total rows including tombstones — the physical slot count.
public ulong Entries { get; set; }
Property Value
IndexStatsData.LiveEntries Property
Rows that still resolve to a live file (the searchable population).
public ulong LiveEntries { get; set; }
Property Value
IndexStatsData.Tombstones Property
Dead rows awaiting compaction (deleted entries not yet
reclaimed); Entries - LiveEntries.
public ulong Tombstones { get; set; }
Property Value
IndexStatsData.TotalBytes Property
Resident bytes of this index in the engine process (all columns + derived query caches) — the numerator of the bytes/entry gate.
public ulong TotalBytes { get; set; }
Property Value
IndexStatsData.Volume Property
Drive label this index covers (e.g. "C:").
public string Volume { get; set; }
Property Value
FindMyFiles
FindMyFiles.Engine
PipeEngineClient Class
Engine client over the fmf-service named pipe (docs/ARCHITECTURE.md "Pipe protocol"). This class is the connection *supervisor* plus the request multiplexing table; the established connection itself (stream, read loop, serialized writer, epoch) is one FindMyFiles.Engine.PipeConnection object, replaced wholesale on every (re)connect. The supervisor loop: connect → server-is-SYSTEM check (default pipe name only; SECURITY.md Threat 4) → Hello (version check; a mismatch is fatal) → Subscribe → IndexStatus (synthesized VolumeUpdated + IndexChanged) → Connected. On disconnect every pending request fails fast with EngineUnavailableException, live results turn stale because their connection's epoch can never be current again, and reconnection retries forever with 250ms→5s backoff. Events fire on the read-loop thread — consumers marshal (see EngineEventMarshaler), same contract as the FFI client. No DispatcherQueue dependency.
public sealed class PipeEngineClient : FindMyFiles.Engine.IEngineClient, System.IDisposable
Inheritance System.Object → PipeEngineClient
Implements IEngineClient, System.IDisposable
Constructors
PipeEngineClient(string) Constructor
Connects to the fmf-service named pipe and starts the supervisor loop immediately. pipeName defaults to FindMyFiles.Engine.PipeProtocol.DefaultPipeName; only that default name has its server identity verified (SECURITY.md Threat 4) — a custom name (tests) skips the SYSTEM check.
public PipeEngineClient(string pipeName="fmf-engine-v2");
Parameters
pipeName System.String
Pipe to connect to, as either the short name or
the full \\.\pipe\… path.
Properties
PipeEngineClient.Connection Property
InProc for Ffi/Fake (fixed, never raises ConnectionChanged); the pipe client moves through Connecting/Connected/Reconnecting.
public FindMyFiles.Engine.EngineConnectionState Connection { get; }
Implements Connection
Property Value
Methods
PipeEngineClient.Dispose() Method
Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
public void Dispose();
Implements Dispose()
PipeEngineClient.GetStatsAsync(CancellationToken) Method
Observability snapshot for the performance panel.
public System.Threading.Tasks.Task<FindMyFiles.Engine.EngineStatsData?> GetStatsAsync(System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
ct System.Threading.CancellationToken
Cooperative cancellation token.
Implements GetStatsAsync(CancellationToken)
Returns
System.Threading.Tasks.Task<EngineStatsData>
The current engine stats, or null if unavailable.
PipeEngineClient.GetStatusAsync(CancellationToken) Method
Returns a snapshot of the current state (VolumeStatus) of every volume. Used for the initial display at startup and for the setup screen's decisions.
public System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<FindMyFiles.Engine.VolumeStatus>> GetStatusAsync(System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
ct System.Threading.CancellationToken
Cooperative cancellation token.
Implements GetStatusAsync(CancellationToken)
Returns
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<VolumeStatus>>
A snapshot of the current status of every known volume.
Exceptions
EngineUnavailableException
service unreachable
PipeEngineClient.ListVolumesAsync(CancellationToken) Method
Returns the labels of the indexed volumes (those the engine currently recognizes).
public System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<string>> ListVolumesAsync(System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
ct System.Threading.CancellationToken
Cooperative cancellation token.
Implements ListVolumesAsync(CancellationToken)
Returns
System.Threading.Tasks.Task<System.Collections.Generic.IReadOnlyList<System.String>>
The labels of the volumes the engine currently knows about.
Exceptions
EngineUnavailableException
service unreachable
PipeEngineClient.Probe(string, TimeSpan) Method
Can a server be reached and Hello'd on this pipe within the timeout? Used by the factory's `auto` mode (250ms budget).
public static bool Probe(string pipeName, System.TimeSpan timeout);
Parameters
pipeName System.String
Pipe to probe, short name or full path.
timeout System.TimeSpan
Budget for connect plus the Hello round-trip.
Returns
System.Boolean
True if a protocol-compatible server answered within the timeout.
PipeEngineClient.SearchAsync(string, SearchOptions, CancellationToken) Method
Executes the query and returns a sort-settled result handle (Result) plus an optional timing trace. Pages are read lazily through the returned ISearchResult.
public System.Threading.Tasks.Task<FindMyFiles.Engine.SearchOutcome> SearchAsync(string query, FindMyFiles.Engine.SearchOptions options, System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
query System.String
The query text to execute.
options SearchOptions
Search options (sort order, flags).
ct System.Threading.CancellationToken
Cooperative cancellation token.
Implements SearchAsync(string, SearchOptions, CancellationToken)
Returns
System.Threading.Tasks.Task<SearchOutcome>
The sort-ordered result handle plus an optional timing trace.
Exceptions
QuerySyntaxException
malformed query text
EngineUnavailableException
service unreachable
PipeEngineClient.StartIndexingAsync(IReadOnlyList<string>, CancellationToken) Method
Requests that indexing/re-indexing start for the given volumes (fire-and-trigger: progress arrives via VolumeUpdated / IndexChanged). MFT reads require elevation, so the work runs on the service side.
public System.Threading.Tasks.Task StartIndexingAsync(System.Collections.Generic.IReadOnlyList<string> volumes, System.Threading.CancellationToken ct=default(System.Threading.CancellationToken));
Parameters
volumes System.Collections.Generic.IReadOnlyList<System.String>
Labels of the volumes to (re)index.
ct System.Threading.CancellationToken
Cooperative cancellation token.
Implements StartIndexingAsync(IReadOnlyList<string>, CancellationToken)
Returns
System.Threading.Tasks.Task
A task that completes once the indexing request is accepted.
Exceptions
EngineUnavailableException
service unreachable
Events
PipeEngineClient.ConnectionChanged Event
Fires when the current Connection transitions. In-proc implementations never fire (always InProc). Fires from the pipe client's supervisor thread → marshal.
public event Action<EngineConnectionState>? ConnectionChanged;
Implements ConnectionChanged
Event Type
System.Action<EngineConnectionState>
PipeEngineClient.EngineErrorOccurred Event
The engine recorded a diagnostic (1=warn 2=error 3=panic). Details live in RecentErrors — pull on demand.
public event Action<int>? EngineErrorOccurred;
Implements EngineErrorOccurred
Event Type
PipeEngineClient.IndexChanged Event
New index content was published (USN apply or scan progress). The payload is the triggering volume label. The signal to re-evaluate the displayed query. Fires from an engine thread, so marshal to the UI thread (EngineEventMarshaler is the only crossing point).
public event Action<string>? IndexChanged;
Implements IndexChanged
Event Type
PipeEngineClient.VolumeUpdated Event
One volume's state transitioned (`Scanning`→`Ready` etc.). Emits the latest VolumeStatus. Fires from an engine thread → marshal.
public event Action<VolumeStatus>? VolumeUpdated;
Implements VolumeUpdated
Event Type
FindMyFiles
FindMyFiles.Engine
QuerySyntaxException Class
The query string is syntactically malformed and SearchAsync(string, SearchOptions, CancellationToken) failed to parse it.
public sealed class QuerySyntaxException : System.Exception
Inheritance System.Object → System.Exception → QuerySyntaxException
Constructors
QuerySyntaxException(string) Constructor
The query string is syntactically malformed and SearchAsync(string, SearchOptions, CancellationToken) failed to parse it.
public QuerySyntaxException(string message);
Parameters
message System.String
The human-readable reason returned by the parser.
FindMyFiles
FindMyFiles.Engine
QueryTraceData Class
Stage breakdown of one query (mirrors fmf-core metrics.rs).
public sealed class QueryTraceData
Inheritance System.Object → QueryTraceData
Properties
QueryTraceData.Cache Property
Per-volume query-cache outcome: "miss", "refine" (all volumes narrowed the previous result) or "partial" (mixed).
public string Cache { get; set; }
Property Value
QueryTraceData.CompileUs Property
µs spent compiling the AST into the matcher.
public ulong CompileUs { get; set; }
Property Value
QueryTraceData.Driver Property
Which execution strategy generated the candidates (shown in
the perf panel): e.g. "full-scan", "pool-scan",
"suffix", "perm-walk".
public string Driver { get; set; }
Property Value
QueryTraceData.EntriesScanned Property
Entries examined by the scan (the denominator of the match rate; far larger than Hits for a full scan).
public ulong EntriesScanned { get; set; }
Property Value
QueryTraceData.ExcludedSkipped Property
Entries skipped by exclusion rules (hidden/system filtering, excluded paths) before matching.
public ulong ExcludedSkipped { get; set; }
Property Value
QueryTraceData.Hits Property
Rows that matched — the resulting Count.
public ulong Hits { get; set; }
Property Value
QueryTraceData.MaterializeUs Property
µs spent materializing matched rows into the result.
public ulong MaterializeUs { get; set; }
Property Value
QueryTraceData.MemoUs Property
µs spent on the dir-path memo (path queries only; 0 when warm or not a path query).
public ulong MemoUs { get; set; }
Property Value
QueryTraceData.MergeUs Property
µs spent on the multi-volume k-way merge (0 for one volume).
public ulong MergeUs { get; set; }
Property Value
QueryTraceData.ParseUs Property
µs spent parsing the query text into its AST.
public ulong ParseUs { get; set; }
Property Value
QueryTraceData.Query Property
The query text exactly as the engine parsed it.
public string Query { get; set; }
Property Value
QueryTraceData.ScanUs Property
µs spent scanning candidates across all volumes.
public ulong ScanUs { get; set; }
Property Value
QueryTraceData.TotalUs Property
End-to-end µs for the whole query; the value fed into the p50/p99 histogram.
public ulong TotalUs { get; set; }
Property Value
QueryTraceData.Unchanged Property
Engine-verified: same query as last time with identical id lists on every volume — the screen has nothing to change.
public bool Unchanged { get; set; }
Property Value
QueryTraceData.Volumes Property
How many volume indexes participated in this query.
public uint Volumes { get; set; }
Property Value
FindMyFiles
FindMyFiles.Engine
RegexScope Enum
Which haystack a whole-query regex runs against (wire values of
fmf-core's RegexScope; the regex_mode bit1).
public enum RegexScope
Fields
Name 0
Match the file name.
Path 1
Match the full path.
FindMyFiles
FindMyFiles.Engine
RowData Class
One result row decoded from a page (the C# face of fmf-core's
48-byte FmfRow plus its WTF-8 name/path strings). Immutable; the
UI's ResultRow view-model is filled from it.
public sealed record RowData : System.IEquatable<FindMyFiles.Engine.RowData>
Inheritance System.Object → RowData
Implements System.IEquatable<RowData>
Constructors
RowData(ulong, ulong, ulong, long, uint, string, string) Constructor
One result row decoded from a page (the C# face of fmf-core's
48-byte FmfRow plus its WTF-8 name/path strings). Immutable; the
UI's ResultRow view-model is filled from it.
public RowData(ulong EntryRef, ulong Frn, ulong Size, long Mtime, uint Flags, string Name, string ParentPath);
Parameters
EntryRef System.UInt64
Engine-internal stable handle for the entry within
its volume index (the identity used for refine/unchanged
comparisons) — not the NTFS reference.
Frn System.UInt64
NTFS File Reference Number (record number in the low 48 bits, sequence in the high 16) — the identity to correlate with USN records and the filesystem.
Size System.UInt64
File size in bytes (0 for directories).
Mtime System.Int64
Last-modified time as a Windows FILETIME
(100 ns ticks since 1601-01-01 UTC); 0 means unknown/unset and renders as
an empty timestamp.
Flags System.UInt32
Bit field of NTFS attributes; bit 0 is the directory flag (see IsDirectory).
Name System.String
Leaf file or directory name.
ParentPath System.String
Containing directory path including its trailing
separator (e.g. "C:\"), so FullPath is a plain
concatenation.
Properties
RowData.EntryRef Property
Engine-internal stable handle for the entry within
its volume index (the identity used for refine/unchanged
comparisons) — not the NTFS reference.
public ulong EntryRef { get; init; }
Property Value
RowData.Flags Property
Bit field of NTFS attributes; bit 0 is the directory flag (see IsDirectory).
public uint Flags { get; init; }
Property Value
RowData.Frn Property
NTFS File Reference Number (record number in the low 48 bits, sequence in the high 16) — the identity to correlate with USN records and the filesystem.
public ulong Frn { get; init; }
Property Value
RowData.FullPath Property
The full path, ParentPath (which already ends in a separator) concatenated with Name.
public string FullPath { get; }
Property Value
RowData.IsDirectory Property
True when this row is a directory (bit 0 of Flags).
public bool IsDirectory { get; }
Property Value
RowData.Mtime Property
Last-modified time as a Windows FILETIME
(100 ns ticks since 1601-01-01 UTC); 0 means unknown/unset and renders as
an empty timestamp.
public long Mtime { get; init; }
Property Value
RowData.Name Property
Leaf file or directory name.
public string Name { get; init; }
Property Value
RowData.ParentPath Property
Containing directory path including its trailing
separator (e.g. "C:\"), so FullPath is a plain
concatenation.
public string ParentPath { get; init; }
Property Value
RowData.Size Property
File size in bytes (0 for directories).
public ulong Size { get; init; }
Property Value
FindMyFiles
FindMyFiles.Engine
SearchOptions Class
The knobs that shape a search, passed to
SearchAsync(string, SearchOptions, CancellationToken) (the C# face of fmf-core's
FmfQueryOptions).
public sealed record SearchOptions : System.IEquatable<FindMyFiles.Engine.SearchOptions>
Inheritance System.Object → SearchOptions
Implements System.IEquatable<SearchOptions>
Constructors
SearchOptions(FmfSort, bool, FmfCase, bool, bool, RegexScope) Constructor
The knobs that shape a search, passed to
SearchAsync(string, SearchOptions, CancellationToken) (the C# face of fmf-core's
FmfQueryOptions).
public SearchOptions(FindMyFiles.Engine.FmfSort Sort, bool Descending, FindMyFiles.Engine.FmfCase Case, bool IncludeHiddenSystem=false, bool RegexMode=false, FindMyFiles.Engine.RegexScope Scope=FindMyFiles.Engine.RegexScope.Name);
Parameters
Sort FmfSort
Which key to order results by.
Descending System.Boolean
True for descending order; false for ascending.
Case FmfCase
How query case is matched against names.
IncludeHiddenSystem System.Boolean
When true, hidden/system entries are included; they are excluded by default.
RegexMode System.Boolean
When true, the whole query text is one regular
expression (the regex: per-term syntax still works regardless).
Scope RegexScope
Which haystack the whole-query regex matches against (ignored unless RegexMode).
Fields
SearchOptions.Default Field
The app's default search: by Name, ascending, Smart case, hidden/system excluded, regex mode off.
public static readonly SearchOptions Default;
Field Value
Properties
SearchOptions.Case Property
How query case is matched against names.
public FindMyFiles.Engine.FmfCase Case { get; init; }
Property Value
SearchOptions.Descending Property
True for descending order; false for ascending.
public bool Descending { get; init; }
Property Value
SearchOptions.IncludeHiddenSystem Property
When true, hidden/system entries are included; they are excluded by default.
public bool IncludeHiddenSystem { get; init; }
Property Value
SearchOptions.RegexMode Property
When true, the whole query text is one regular
expression (the regex: per-term syntax still works regardless).
public bool RegexMode { get; init; }
Property Value
SearchOptions.RegexModeBits Property
The packed FmfQueryOptions.regex_mode wire value:
bit0 = whole-query regex on, bit1 = scope (0 name / 1 path).
public uint RegexModeBits { get; }
Property Value
SearchOptions.Scope Property
Which haystack the whole-query regex matches against (ignored unless RegexMode).
public FindMyFiles.Engine.RegexScope Scope { get; init; }
Property Value
SearchOptions.Sort Property
Which key to order results by.
public FindMyFiles.Engine.FmfSort Sort { get; init; }
Property Value
FindMyFiles
FindMyFiles.Engine
SearchOutcome Class
What SearchAsync(string, SearchOptions, CancellationToken) returns: the materialized ISearchResult the UI pages through, paired with the per-query QueryTraceData the engine attached (null when tracing was unavailable, e.g. a serialization failure — the result is still valid).
public sealed record SearchOutcome : System.IEquatable<FindMyFiles.Engine.SearchOutcome>
Inheritance System.Object → SearchOutcome
Implements System.IEquatable<SearchOutcome>
Constructors
SearchOutcome(ISearchResult, QueryTraceData) Constructor
What SearchAsync(string, SearchOptions, CancellationToken) returns: the materialized ISearchResult the UI pages through, paired with the per-query QueryTraceData the engine attached (null when tracing was unavailable, e.g. a serialization failure — the result is still valid).
public SearchOutcome(FindMyFiles.Engine.ISearchResult Result, FindMyFiles.Engine.QueryTraceData? Trace);
Parameters
Result ISearchResult
The sort-ordered, O(1)-paged result set.
Trace QueryTraceData
Stage timings for the F12 perf panel, or null.
Properties
SearchOutcome.Result Property
The sort-ordered, O(1)-paged result set.
public FindMyFiles.Engine.ISearchResult Result { get; init; }
Property Value
SearchOutcome.Trace Property
Stage timings for the F12 perf panel, or null.
public FindMyFiles.Engine.QueryTraceData? Trace { get; init; }
Property Value
FindMyFiles
FindMyFiles.Engine
StaleResultException Class
The index was structurally rebuilt and the row IDs of a held result handle are now invalid (thrown from GetRangeAsync(long, int, CancellationToken)). Recovery is to re-run the query.
public sealed class StaleResultException : System.Exception
Inheritance System.Object → System.Exception → StaleResultException
Constructors
StaleResultException() Constructor
Initializes with the canned message.
public StaleResultException();
FindMyFiles
FindMyFiles.Engine
TransportStatsData Class
Client-side pipe transport metrics. Null for in-proc clients; the pipe client fills it on every GetStatsAsync(CancellationToken).
public sealed class TransportStatsData
Inheritance System.Object → TransportStatsData
Properties
TransportStatsData.AbiVersion Property
ABI version the server reported at handshake — must match the
client's EngineContract.AbiVersion.
public uint AbiVersion { get; set; }
Property Value
TransportStatsData.PageRttEwmaUs Property
EWMA of page-fetch round-trip latency in µs (the wire cost a page read adds on top of the engine's own time).
public double PageRttEwmaUs { get; set; }
Property Value
TransportStatsData.Reconnects Property
How many times the supervisor has re-established the pipe since process start — a churn indicator.
public long Reconnects { get; set; }
Property Value
TransportStatsData.ServerPid Property
PID of the fmf-service process on the other end (from the Hello handshake); shown so users can find it in Task Manager.
public uint ServerPid { get; set; }
Property Value
TransportStatsData.State Property
Current EngineConnectionState rendered as text
(e.g. "Connected", "Reconnecting").
public string State { get; set; }
Property Value
FindMyFiles
FindMyFiles.Engine
UsnTraceData Class
One applied USN journal batch — how a burst of filesystem changes
landed in the index (mirrors fmf-core's UsnTrace). Drives the
change-reflection latency shown in the perf panel.
public sealed class UsnTraceData
Inheritance System.Object → UsnTraceData
Properties
UsnTraceData.ApplyUs Property
µs to apply the whole batch to the index.
public ulong ApplyUs { get; set; }
Property Value
UsnTraceData.Deleted Property
Entries tombstoned (deletes/renames-away).
public ulong Deleted { get; set; }
Property Value
UsnTraceData.Records Property
Raw USN records in the batch (before coalescing).
public ulong Records { get; set; }
Property Value
UsnTraceData.StatFailures Property
Stat fetches that failed (the entry keeps its prior size/mtime); also counted in FindMyFiles.Engine.CountersData.StatFetchFailures.
public ulong StatFailures { get; set; }
Property Value
UsnTraceData.StatUpdated Property
Entries whose size/mtime were refreshed via a stat fetch.
public ulong StatUpdated { get; set; }
Property Value
UsnTraceData.Upserted Property
Entries created or updated in the index.
public ulong Upserted { get; set; }
Property Value
UsnTraceData.Volume Property
Drive label the batch was applied to.
public string Volume { get; set; }
Property Value
FindMyFiles
FindMyFiles.Engine
VolumeState Enum
Lifecycle of a volume's index (wire values of fmf-core's
VolumeState), reported via VolumeUpdated.
public enum VolumeState
Fields
Scanning 0
Initial scan in progress; results are incomplete.
Ready 1
Index is complete and searchable.
Rescanning 2
A rescan is rebuilding an already-ready index (e.g. after a USN gap); the prior result stays usable.
Failed 3
Indexing failed (access denied, unsupported filesystem); this volume contributes no results.
FindMyFiles
FindMyFiles.Engine
VolumeStatus Class
A volume's current index status — the payload of an VolumeUpdated event and of GetStatusAsync(CancellationToken).
public sealed record VolumeStatus : System.IEquatable<FindMyFiles.Engine.VolumeStatus>
Inheritance System.Object → VolumeStatus
Implements System.IEquatable<VolumeStatus>
Constructors
VolumeStatus(string, VolumeState, ulong) Constructor
A volume's current index status — the payload of an VolumeUpdated event and of GetStatusAsync(CancellationToken).
public VolumeStatus(string Label, FindMyFiles.Engine.VolumeState State, ulong Entries);
Parameters
Label System.String
Drive label (e.g. "C:").
State VolumeState
Where the index is in its lifecycle.
Entries System.UInt64
Indexed entry count so far (grows while Scanning).
Properties
VolumeStatus.Entries Property
Indexed entry count so far (grows while Scanning).
public ulong Entries { get; init; }
Property Value
VolumeStatus.Label Property
Drive label (e.g. "C:").
public string Label { get; init; }
Property Value
VolumeStatus.State Property
Where the index is in its lifecycle.
public FindMyFiles.Engine.VolumeState State { get; init; }
Property Value
FindMyFiles
FindMyFiles.Engine Namespace
| Classes | |
|---|---|
| CountersData | Degradation counters of the stats JSON (snake_case keys — deserialize with SnakeCaseLower). Generated from the contract's counter-name registry; nonzero values surface in the F12 panel. |
| EngineClientFactory | Engine transport selection, in priority order: CLI flags (--fake-engine / --engine=pipe|inproc / --pipe-name=…) > settings.json "engine" > auto. Auto probes the service pipe for 250ms (through Hello) and falls back to the in-proc FFI engine when no service answers. |
| EngineEventMarshaler | The single crossing point from engine threads to the UI thread. IEngineClient events fire on engine / pipe read-loop threads; this class subscribes to all four, marshals each through TryEnqueue(Action) and re-raises it as its own event on the UI thread. Consumers (ViewModels, the orchestrator) attach plain handlers and never marshal themselves — the per-subscriber inline `dispatcher.TryEnqueue` lambdas this replaces were the audit's "scattered crossing" finding. The upstream delegates are held in fields for the subscription lifetime (the GC-rooting rule for callback delegates, satisfied structurally). |
| EngineException | The engine rejected an operation with a structured error code (the transport is alive but the engine returned a failure). The code maps to the `FMF_E_*` table in docs/ARCHITECTURE.md. |
| EngineStatsData | The whole observability snapshot behind the F12 perf panel — what GetStatsAsync(CancellationToken) returns (the UI subset of fmf-core's MetricsSnapshot). |
| EngineUnavailableException | The engine transport is down (pipe disconnected, request timed out, service not running). Pending requests fail fast with this; the supervisor keeps reconnecting in the background. |
| ErrorEventData | One entry from the engine's diagnostic ring (WARN+ events and panics; mirrors fmf-core's ErrorEvent). Pulled on demand after an EngineErrorOccurred signal and listed in the F12 panel. |
| FakeEngineClient | Deterministic in-memory engine for UI tests and unelevated development (`--fake-engine`). 100k entries from a fixed seed; substring search only. Contract-conforming (EngineClientContractTests): query-syntax verdicts come from the shared golden fixture (contract/golden/invalid_queries.json, pinned by the real Rust parser — verdict drift is caught on the Rust side), cancellation is honored, and BumpEpoch() lets tests drive the Stale→requery recovery path without a real engine. |
| FfiEngineClient | In-proc engine client over fmf_engine.dll. Events arrive on engine threads; consumers marshal to the UI thread themselves. |
| IndexStatsData | Memory accounting and generation state for one volume index (subset of fmf-core's IndexStats the UI surfaces). Feeds the bytes/entry gate in the F12 panel. |
| PipeEngineClient | Engine client over the fmf-service named pipe (docs/ARCHITECTURE.md "Pipe protocol"). This class is the connection *supervisor* plus the request multiplexing table; the established connection itself (stream, read loop, serialized writer, epoch) is one FindMyFiles.Engine.PipeConnection object, replaced wholesale on every (re)connect. The supervisor loop: connect → server-is-SYSTEM check (default pipe name only; SECURITY.md Threat 4) → Hello (version check; a mismatch is fatal) → Subscribe → IndexStatus (synthesized VolumeUpdated + IndexChanged) → Connected. On disconnect every pending request fails fast with EngineUnavailableException, live results turn stale because their connection's epoch can never be current again, and reconnection retries forever with 250ms→5s backoff. Events fire on the read-loop thread — consumers marshal (see EngineEventMarshaler), same contract as the FFI client. No DispatcherQueue dependency. |
| QuerySyntaxException | The query string is syntactically malformed and SearchAsync(string, SearchOptions, CancellationToken) failed to parse it. |
| QueryTraceData | Stage breakdown of one query (mirrors fmf-core metrics.rs). |
| RowData | One result row decoded from a page (the C# face of fmf-core's 48-byte FmfRow plus its WTF-8 name/path strings). Immutable; the UI's ResultRow view-model is filled from it. |
| SearchOptions | The knobs that shape a search, passed to SearchAsync(string, SearchOptions, CancellationToken) (the C# face of fmf-core's FmfQueryOptions). |
| SearchOutcome | What SearchAsync(string, SearchOptions, CancellationToken) returns: the materialized ISearchResult the UI pages through, paired with the per-query QueryTraceData the engine attached (null when tracing was unavailable, e.g. a serialization failure — the result is still valid). |
| StaleResultException | The index was structurally rebuilt and the row IDs of a held result handle are now invalid (thrown from GetRangeAsync(long, int, CancellationToken)). Recovery is to re-run the query. |
| TransportStatsData | Client-side pipe transport metrics. Null for in-proc clients; the pipe client fills it on every GetStatsAsync(CancellationToken). |
| UsnTraceData | One applied USN journal batch — how a burst of filesystem changes landed in the index (mirrors fmf-core's UsnTrace). Drives the change-reflection latency shown in the perf panel. |
| VolumeStatus | A volume's current index status — the payload of an VolumeUpdated event and of GetStatusAsync(CancellationToken). |
| Interfaces | |
|---|---|
| IEngineClient | The single boundary the app uses to talk to the engine (docs/ARCHITECTURE.md). Implementations: PipeEngineClient (named pipe to fmf-service), FfiEngineClient (in-proc DLL, --engine=inproc) and FakeEngineClient (deterministic data for UI tests via --fake-engine). The shared observable behavior is executable: Tests/Contract/EngineClientContractTests runs the same suite against all implementations. Cancellation is cooperative and fully plumbed (ADR-0018): a cancelled ct surfaces as System.OperationCanceledException (or a subclass) from every async member. Data shapes live in EngineTypes.cs. |
| ISearchResult | Materialized, sort-ordered result; pages are O(1) reads. |
| Enums | |
|---|---|
| EngineConnectionState | Transport state of the engine boundary. In-proc clients are always InProc; the pipe client reports its supervisor state. |
| FmfCase | Case-matching mode (wire values of fmf-core's CaseMode). |
| FmfSort | Result sort key (wire values of fmf-core's SortKey). |
| RegexScope | Which haystack a whole-query regex runs against (wire values of fmf-core's RegexScope; the regex_mode bit1). |
| VolumeState | Lifecycle of a volume's index (wire values of fmf-core's VolumeState), reported via VolumeUpdated. |
FindMyFiles
FindMyFiles.FindMyFiles_XamlTypeInfo
XamlMetaDataProvider Class
Main class for providing metadata for the app or library
public sealed class XamlMetaDataProvider : Microsoft.UI.Xaml.Markup.IXamlMetadataProvider
Inheritance System.Object → XamlMetaDataProvider
Implements Microsoft.UI.Xaml.Markup.IXamlMetadataProvider
Methods
XamlMetaDataProvider.GetXamlType(string) Method
GetXamlType(String)
public Microsoft.UI.Xaml.Markup.IXamlType GetXamlType(string fullName);
Parameters
fullName System.String
Implements GetXamlType(string)
Returns
Microsoft.UI.Xaml.Markup.IXamlType
XamlMetaDataProvider.GetXamlType(Type) Method
GetXamlType(Type)
public Microsoft.UI.Xaml.Markup.IXamlType GetXamlType(System.Type type);
Parameters
type System.Type
Implements GetXamlType(Type)
Returns
Microsoft.UI.Xaml.Markup.IXamlType
XamlMetaDataProvider.GetXmlnsDefinitions() Method
GetXmlnsDefinitions()
public Microsoft.UI.Xaml.Markup.XmlnsDefinition[] GetXmlnsDefinitions();
Implements GetXmlnsDefinitions()
Returns
Microsoft.UI.Xaml.Markup.XmlnsDefinition[]
FindMyFiles
FindMyFiles.FindMyFiles_XamlTypeInfo Namespace
| Classes | |
|---|---|
| XamlMetaDataProvider | Main class for providing metadata for the app or library |
FindMyFiles
FindMyFiles.Highlighting
CompiledHighlighter Class
A query compiled into the positive text needles worth highlighting. Pure (no WinUI), so it is unit-testable and reusable across rows. Built once per query by Compile(string) and queried per displayed string by Ranges(string, HighlightField).
Highlighting deliberately mirrors only the *simple, certain* slice of the
engine's match semantics (fmf-core query/): plain substrings, anchored
lit*/*lit/*lit* wildcards, and smart-case folding
(engine/crates/fmf-core/src/wtf8.rs). Anything the UI cannot reproduce
exactly — user regex, general wildcards, negation, path wildcards — is left
un-highlighted rather than guessed at: a row the engine returned is never
hidden, only its emphasis is skipped (don't crash / don't go silent). This guarantees
the UI never lights up a position the engine did not actually match.
public sealed class CompiledHighlighter : FindMyFiles.Highlighting.IHighlighter
Inheritance System.Object → CompiledHighlighter
Implements IHighlighter
Fields
CompiledHighlighter.Empty Field
A highlighter with no terms — every Ranges(string, HighlightField) call returns empty. Used for empty/filter-only queries.
public static readonly CompiledHighlighter Empty;
Field Value
Properties
CompiledHighlighter.IsEmpty Property
True when nothing will ever be highlighted — the caller can skip per-row work entirely.
public bool IsEmpty { get; }
Implements IsEmpty
Property Value
Methods
CompiledHighlighter.Ranges(string, HighlightField) Method
The ranges of text matched by the terms targeting field, sorted by start and with overlapping/adjacent runs merged. Indices/lengths are UTF-16 units of text itself, ready to slice. Empty when nothing matches (or the query has no terms for this field).
public System.Collections.Generic.IReadOnlyList<FindMyFiles.Highlighting.HighlightRange> Ranges(string text, FindMyFiles.Highlighting.HighlightField field);
Parameters
text System.String
The displayed string (a name, or a full path).
field HighlightField
Which term family to apply.
Implements Ranges(string, HighlightField)
Returns
System.Collections.Generic.IReadOnlyList<HighlightRange>
The sorted, merged highlight ranges; empty when nothing matches.
FindMyFiles
FindMyFiles.Highlighting
HighlightField Enum
Which displayed string a highlight term is matched against — the file name leaf, or the full path (parent + name).
public enum HighlightField
Fields
Name 0
The file/folder name (leaf).
Path 1
The full path — a term that contained \ or used
path:.
FindMyFiles
FindMyFiles.Highlighting
HighlightRange Struct
A half-open run of UTF-16 code units to emphasize, in the coordinate space of the string handed to Ranges(string, HighlightField).
public readonly record struct HighlightRange : System.IEquatable<FindMyFiles.Highlighting.HighlightRange>
Implements System.IEquatable<HighlightRange>
Constructors
HighlightRange(int, int) Constructor
A half-open run of UTF-16 code units to emphasize, in the coordinate space of the string handed to Ranges(string, HighlightField).
public HighlightRange(int Start, int Length);
Parameters
Start System.Int32
Zero-based UTF-16 index of the first highlighted unit.
Length System.Int32
Number of UTF-16 units highlighted (always ≥ 1).
Properties
HighlightRange.Length Property
Number of UTF-16 units highlighted (always ≥ 1).
public int Length { get; init; }
Property Value
HighlightRange.Start Property
Zero-based UTF-16 index of the first highlighted unit.
public int Start { get; init; }
Property Value
FindMyFiles
FindMyFiles.Highlighting
HighlightSegment Struct
One piece of a string for highlighted rendering.
public readonly record struct HighlightSegment : System.IEquatable<FindMyFiles.Highlighting.HighlightSegment>
Implements System.IEquatable<HighlightSegment>
Constructors
HighlightSegment(string, bool) Constructor
One piece of a string for highlighted rendering.
public HighlightSegment(string Text, bool Highlighted);
Parameters
Text System.String
The piece's text.
Highlighted System.Boolean
True when this piece should be emphasized.
Properties
HighlightSegment.Highlighted Property
True when this piece should be emphasized.
public bool Highlighted { get; init; }
Property Value
HighlightSegment.Text Property
The piece's text.
public string Text { get; init; }
Property Value
FindMyFiles
FindMyFiles.Highlighting
HighlightSegmenter Class
Splits a string into consecutive highlighted/plain segments from a set of merged ranges — the pure, unit-tested core of the highlight renderer, kept free of WinUI so it runs headless. Ranges are clamped to the string, so a stale or out-of-bounds range can never throw.
public static class HighlightSegmenter
Inheritance System.Object → HighlightSegmenter
Methods
HighlightSegmenter.Split(string, IReadOnlyList<HighlightRange>) Method
Cut text at the boundaries of ranges (assumed sorted and non-overlapping — as produced by Ranges(string, HighlightField)), tagging each piece as highlighted or not. Empty ranges yield the whole string as one plain segment; zero-length or out-of-range entries are skipped/clamped.
public static System.Collections.Generic.List<FindMyFiles.Highlighting.HighlightSegment> Split(string text, System.Collections.Generic.IReadOnlyList<FindMyFiles.Highlighting.HighlightRange> ranges);
Parameters
text System.String
The full string being rendered.
ranges System.Collections.Generic.IReadOnlyList<HighlightRange>
The spans to emphasize.
Returns
System.Collections.Generic.List<HighlightSegment>
The string split into consecutive plain and highlighted pieces, in order.
FindMyFiles
FindMyFiles.Highlighting
HighlightText Class
Attached behavior that renders SourceProperty into a TextBlock's Inlines, emphasizing the spans named by RangesProperty with bold + accent foreground. Lets the result list's name/path cells show match highlights without giving up their TextBlock styles, x:Phase, or virtualization: the same cell instance is reused across rows, and FindMyFiles.Highlighting.HighlightText.Rebuild(Microsoft.UI.Xaml.Controls.TextBlock,System.String,System.Collections.Generic.IReadOnlyList{FindMyFiles.Highlighting.HighlightRange}) clears and refills it on every change so a reused container never shows the previous row's text.
public static class HighlightText
Inheritance System.Object → HighlightText
Fields
HighlightText.RangesProperty Field
Ranges of SourceProperty to emphasize (UTF-16 coordinates, sorted and merged by the highlighter).
public static readonly DependencyProperty RangesProperty;
Field Value
Microsoft.UI.Xaml.DependencyProperty
HighlightText.SourceProperty Field
The full text to display (set with RangesProperty; either change rebuilds the inlines).
public static readonly DependencyProperty SourceProperty;
Field Value
Microsoft.UI.Xaml.DependencyProperty
Methods
HighlightText.GetRanges(DependencyObject) Method
Get the highlight ranges from element.
public static System.Collections.Generic.IReadOnlyList<FindMyFiles.Highlighting.HighlightRange>? GetRanges(Microsoft.UI.Xaml.DependencyObject element);
Parameters
element Microsoft.UI.Xaml.DependencyObject
The element to read the highlight ranges from.
Returns
System.Collections.Generic.IReadOnlyList<HighlightRange>
The highlight ranges, or null if none are set.
HighlightText.GetSource(DependencyObject) Method
Get the display text from element.
public static string? GetSource(Microsoft.UI.Xaml.DependencyObject element);
Parameters
element Microsoft.UI.Xaml.DependencyObject
The element to read the display text from.
Returns
System.String
The display text, or null if none is set.
HighlightText.SetRanges(DependencyObject, IReadOnlyList<HighlightRange>) Method
Set the highlight ranges on element.
public static void SetRanges(Microsoft.UI.Xaml.DependencyObject element, System.Collections.Generic.IReadOnlyList<FindMyFiles.Highlighting.HighlightRange>? value);
Parameters
element Microsoft.UI.Xaml.DependencyObject
The element to set the highlight ranges on.
value System.Collections.Generic.IReadOnlyList<HighlightRange>
The ranges to emphasize.
HighlightText.SetSource(DependencyObject, string) Method
Set the display text on element.
public static void SetSource(Microsoft.UI.Xaml.DependencyObject element, string? value);
Parameters
element Microsoft.UI.Xaml.DependencyObject
The element to set the display text on.
value System.String
The text to display.
FindMyFiles
FindMyFiles.Highlighting
IHighlighter Interface
A compiled query that can emphasize the slices of a displayed string it matched. Implemented by the substring/wildcard CompiledHighlighter and the whole-query RegexHighlighter; the results list and rows depend only on this seam.
public interface IHighlighter
Derived
↳ CompiledHighlighter
↳ RegexHighlighter
Properties
IHighlighter.IsEmpty Property
True when nothing will ever be highlighted — the caller can skip per-row work entirely.
bool IsEmpty { get; }
Property Value
Methods
IHighlighter.Ranges(string, HighlightField) Method
The ranges of text to emphasize for field (UTF-16 units of text), sorted and merged; empty when nothing matches.
System.Collections.Generic.IReadOnlyList<FindMyFiles.Highlighting.HighlightRange> Ranges(string text, FindMyFiles.Highlighting.HighlightField field);
Parameters
text System.String
The displayed string (a name, or a full path).
field HighlightField
Which displayed string the ranges target.
Returns
System.Collections.Generic.IReadOnlyList<HighlightRange>
The sorted, merged highlight ranges; empty when nothing matches.
FindMyFiles
FindMyFiles.Highlighting
MatchHighlighter Class
Compiles query text into a CompiledHighlighter. Mirrors the engine tokenizer/compiler (engine/crates/fmf-core/src/query/ast.rs and compile.rs) for the subset that can be highlighted exactly, and drops the rest (see CompiledHighlighter).
public static class MatchHighlighter
Inheritance System.Object → MatchHighlighter
Methods
MatchHighlighter.Compile(string) Method
Compile query (the user's raw text, before any
focused-mode rewrite) into a highlighter. Case handling is smart-case,
matching the product default (MainViewModel uses
FmfCase.Smart). An empty/whitespace or
filter-only query yields Empty.
public static FindMyFiles.Highlighting.CompiledHighlighter Compile(string query);
Parameters
query System.String
Raw user query text.
Returns
CompiledHighlighter
A highlighter for the query, or Empty when nothing is highlightable.
MatchHighlighter.CompileRegex(string, RegexScope) Method
Compile a whole-query regex highlighter (regex mode, ADR-0023): the entire query is one pattern, emphasized in the name or full path per scope. Smart-case (insensitive unless the pattern carries an uppercase-ish scalar), matching the product default. A pattern .NET cannot compile yields Empty — the engine reports the syntax error; the highlighter just stays dark rather than guess.
public static FindMyFiles.Highlighting.IHighlighter CompileRegex(string query, FindMyFiles.Engine.RegexScope scope);
Parameters
query System.String
Raw user query text, treated as one regex pattern.
scope RegexScope
Which haystack the pattern runs against (name or full path).
Returns
IHighlighter
A regex highlighter, or Empty when the pattern cannot compile.
FindMyFiles
FindMyFiles.Highlighting
RegexHighlighter Class
Highlights a whole-query regex (regex mode) by re-matching the displayed
string. Emphasizes the name field for a name-scope pattern and the path
field for a path-scope one — the same field the engine matched, so
ResultRow's parent/name split applies unchanged. A match-timeout (or
any mismatch with the engine's rust regex) simply yields no ranges: a row
the engine returned is never hidden, only its emphasis is skipped.
public sealed class RegexHighlighter : FindMyFiles.Highlighting.IHighlighter
Inheritance System.Object → RegexHighlighter
Implements IHighlighter
Constructors
RegexHighlighter(Regex, RegexScope) Constructor
Highlights a whole-query regex (regex mode) by re-matching the displayed
string. Emphasizes the name field for a name-scope pattern and the path
field for a path-scope one — the same field the engine matched, so
ResultRow's parent/name split applies unchanged. A match-timeout (or
any mismatch with the engine's rust regex) simply yields no ranges: a row
the engine returned is never hidden, only its emphasis is skipped.
public RegexHighlighter(System.Text.RegularExpressions.Regex re, FindMyFiles.Engine.RegexScope scope);
Parameters
re System.Text.RegularExpressions.Regex
scope RegexScope
Properties
RegexHighlighter.IsEmpty Property
True when nothing will ever be highlighted — the caller can skip per-row work entirely.
public bool IsEmpty { get; }
Implements IsEmpty
Property Value
Methods
RegexHighlighter.Ranges(string, HighlightField) Method
The ranges of text to emphasize for field (UTF-16 units of text), sorted and merged; empty when nothing matches.
public System.Collections.Generic.IReadOnlyList<FindMyFiles.Highlighting.HighlightRange> Ranges(string text, FindMyFiles.Highlighting.HighlightField field);
Parameters
text System.String
The displayed string (a name, or a full path).
field HighlightField
Which displayed string the ranges target.
Implements Ranges(string, HighlightField)
Returns
System.Collections.Generic.IReadOnlyList<HighlightRange>
The sorted, merged highlight ranges; empty when nothing matches.
FindMyFiles
FindMyFiles.Highlighting Namespace
| Classes | |
|---|---|
| CompiledHighlighter | A query compiled into the positive text needles worth highlighting. Pure (no WinUI), so it is unit-testable and reusable across rows. Built once per query by Compile(string) and queried per displayed string by Ranges(string, HighlightField). Highlighting deliberately mirrors only the *simple, certain* slice of the engine's match semantics (fmf-core query/): plain substrings, anchored lit*/*lit/*lit* wildcards, and smart-case folding (engine/crates/fmf-core/src/wtf8.rs). Anything the UI cannot reproduce exactly — user regex, general wildcards, negation, path wildcards — is left un-highlighted rather than guessed at: a row the engine returned is never hidden, only its emphasis is skipped (don't crash / don't go silent). This guarantees the UI never lights up a position the engine did not actually match. |
| HighlightSegmenter | Splits a string into consecutive highlighted/plain segments from a set of merged ranges — the pure, unit-tested core of the highlight renderer, kept free of WinUI so it runs headless. Ranges are clamped to the string, so a stale or out-of-bounds range can never throw. |
| HighlightText | Attached behavior that renders SourceProperty into a TextBlock's Inlines, emphasizing the spans named by RangesProperty with bold + accent foreground. Lets the result list's name/path cells show match highlights without giving up their TextBlock styles, x:Phase, or virtualization: the same cell instance is reused across rows, and FindMyFiles.Highlighting.HighlightText.Rebuild(Microsoft.UI.Xaml.Controls.TextBlock,System.String,System.Collections.Generic.IReadOnlyList{FindMyFiles.Highlighting.HighlightRange}) clears and refills it on every change so a reused container never shows the previous row's text. |
| MatchHighlighter | Compiles query text into a CompiledHighlighter. Mirrors the engine tokenizer/compiler (engine/crates/fmf-core/src/query/ast.rs and compile.rs) for the subset that can be highlighted exactly, and drops the rest (see CompiledHighlighter). |
| RegexHighlighter | Highlights a whole-query regex (regex mode) by re-matching the displayed string. Emphasizes the name field for a name-scope pattern and the path field for a path-scope one — the same field the engine matched, so ResultRow's parent/name split applies unchanged. A match-timeout (or any mismatch with the engine's rust regex) simply yields no ranges: a row the engine returned is never hidden, only its emphasis is skipped. |
| Structs | |
|---|---|
| HighlightRange | A half-open run of UTF-16 code units to emphasize, in the coordinate space of the string handed to Ranges(string, HighlightField). |
| HighlightSegment | One piece of a string for highlighted rendering. |
| Interfaces | |
|---|---|
| IHighlighter | A compiled query that can emphasize the slices of a displayed string it matched. Implemented by the substring/wildcard CompiledHighlighter and the whole-query RegexHighlighter; the results list and rows depend only on this seam. |
| Enums | |
|---|---|
| HighlightField | Which displayed string a highlight term is matched against — the file name leaf, or the full path (parent + name). |
FindMyFiles
FindMyFiles
MainPage Class
Wiring only: builds the ViewModel graph and connects view events to it. Imperative ListView work (viewport/selection restore, row actions) lives in ResultsViewportManager; the F12 panel chrome in PerfPanel; converters in UiConverters.
public sealed class MainPage : Microsoft.UI.Xaml.Controls.Page, Microsoft.UI.Xaml.Markup.IComponentConnector
Inheritance System.Object → Microsoft.UI.Xaml.DependencyObject → Microsoft.UI.Xaml.UIElement → Microsoft.UI.Xaml.FrameworkElement → Microsoft.UI.Xaml.Controls.Control → Microsoft.UI.Xaml.Controls.UserControl → Microsoft.UI.Xaml.Controls.Page → MainPage
Implements Microsoft.UI.Xaml.Markup.IComponentConnector
Constructors
MainPage() Constructor
Builds the ViewModel graph and wires view events (IME composition, drag & drop, keyboard, sort headers) to the ViewModel and ResultsViewportManager. Localized tooltips/automation names are set in code here, and the language radio reflects persisted settings. Finally initializes the empty/results visual state and starts `StartAsync`.
public MainPage();
Properties
MainPage.ViewModel Property
Root of the page's ViewModel graph. The sole `x:Bind` source; it ties together the search, results, notification and diagnostics-panel sub-ViewModels.
public FindMyFiles.ViewModels.MainViewModel ViewModel { get; }
Property Value
Methods
MainPage.Connect(int, object) Method
Connect()
public void Connect(int connectionId, object target);
Parameters
connectionId System.Int32
target System.Object
Implements Connect(int, object)
MainPage.GetBindingConnector(int, object) Method
GetBindingConnector(int connectionId, object target)
public Microsoft.UI.Xaml.Markup.IComponentConnector GetBindingConnector(int connectionId, object target);
Parameters
connectionId System.Int32
target System.Object
Implements GetBindingConnector(int, object)
Returns
Microsoft.UI.Xaml.Markup.IComponentConnector
MainPage.InitializeComponent() Method
InitializeComponent()
public void InitializeComponent();
FindMyFiles
FindMyFiles
MainWindow Class
The application window: hosts the root Frame; app UI lives in MainPage.
public sealed class MainWindow : Microsoft.UI.Xaml.Window, Microsoft.UI.Xaml.Markup.IComponentConnector
Inheritance System.Object → Microsoft.UI.Xaml.Window → MainWindow
Implements Microsoft.UI.Xaml.Markup.IComponentConnector
Constructors
MainWindow() Constructor
Extends the title bar into the content, sets the window icon, and navigates the root Frame to MainPage.
public MainWindow();
Methods
MainWindow.Connect(int, object) Method
Connect()
public void Connect(int connectionId, object target);
Parameters
connectionId System.Int32
target System.Object
Implements Connect(int, object)
MainWindow.GetBindingConnector(int, object) Method
GetBindingConnector(int connectionId, object target)
public Microsoft.UI.Xaml.Markup.IComponentConnector GetBindingConnector(int connectionId, object target);
Parameters
connectionId System.Int32
target System.Object
Implements GetBindingConnector(int, object)
Returns
Microsoft.UI.Xaml.Markup.IComponentConnector
MainWindow.InitializeComponent() Method
InitializeComponent()
public void InitializeComponent();
FindMyFiles
FindMyFiles
Program Class
Program class
public static class Program
Inheritance System.Object → Program
FindMyFiles
FindMyFiles.Services
AppNotification Class
One entry in the InfoBar stack. Immutable, identity-stamped, and carries an optional action button so a notification can offer its own remedy (e.g. "restart the app" after a service install).
public sealed record AppNotification : System.IEquatable<FindMyFiles.Services.AppNotification>
Inheritance System.Object → AppNotification
Implements System.IEquatable<AppNotification>
Constructors
AppNotification(NotifySeverity, string, string, string, Action) Constructor
One entry in the InfoBar stack. Immutable, identity-stamped, and carries an optional action button so a notification can offer its own remedy (e.g. "restart the app" after a service install).
public AppNotification(FindMyFiles.Services.NotifySeverity Severity, string Message, string? Detail=null, string? ActionLabel=null, System.Action? Action=null);
Parameters
Severity NotifySeverity
Visual style + log level + auto-dismiss policy.
Message System.String
The headline shown in the InfoBar.
Detail System.String
Optional secondary line (often an exception message).
ActionLabel System.String
Caption for the action button; null hides it.
Action System.Action
Invoked when the action button is pressed; see Invoke().
Properties
AppNotification.Action Property
Invoked when the action button is pressed; see Invoke().
public System.Action? Action { get; init; }
Property Value
AppNotification.ActionLabel Property
Caption for the action button; null hides it.
public string? ActionLabel { get; init; }
Property Value
AppNotification.Detail Property
Optional secondary line (often an exception message).
public string? Detail { get; init; }
Property Value
AppNotification.Id Property
Stable per-notification identity (a hex GUID) so the InfoBar list can track and remove this exact entry.
public string Id { get; }
Property Value
AppNotification.Message Property
The headline shown in the InfoBar.
public string Message { get; init; }
Property Value
AppNotification.Severity Property
Visual style + log level + auto-dismiss policy.
public FindMyFiles.Services.NotifySeverity Severity { get; init; }
Property Value
Methods
AppNotification.Invoke() Method
x:Bind target for the InfoBar action button (no-op when the notification carries no action).
public void Invoke();
FindMyFiles
FindMyFiles.Services
AppPaths Class
Resolves where the app keeps its state — <b>portable by default</b> (ADR-0024). On first access it picks one data root, once, in this order:
--data-dir=<path>when given (tests, scratch, power users);<exe>\datawhen it can be created and written — the default, so a copied/unzipped build keeps everything in its own folder and touches neither the user profile nor the registry ("just drop it / just delete it");- the per-user profile (
%APPDATA%/%LOCALAPPDATA%) only when the app folder is read-only (e.g. installed under Program Files).
The machine-scope service index (%ProgramData%) and the admin in-proc
index are intentionally <i>not</i> redirected — that path is an install by
nature, the opposite of portable.
Resolution is silent: it must not call FileLog, because FileLog's directory comes from here (a cycle otherwise).
public static class AppPaths
Inheritance System.Object → AppPaths
Properties
AppPaths.IsPortable Property
True when state lives next to the exe (or --data-dir),
not in the user profile.
public static bool IsPortable { get; }
Property Value
AppPaths.LogDir Property
App + scope-engine log directory — portable <data>\logs,
else %APPDATA%\find-my-files\logs.
public static string LogDir { get; }
Property Value
AppPaths.PortableRoot Property
The portable data root, or null when falling back to the per-user profile. Surfaced for the setup screen / diagnostics ("running portable from …").
public static string? PortableRoot { get; }
Property Value
AppPaths.ScopeIndexDir Property
Scope-mode (ADR-0024) index directory — portable
<data>\index, else %LOCALAPPDATA%\find-my-files\index.
public static string ScopeIndexDir { get; }
Property Value
AppPaths.SettingsFile Property
User-scope settings file — portable <data>\settings.json,
else %APPDATA%\find-my-files\settings.json.
public static string SettingsFile { get; }
Property Value
FindMyFiles
FindMyFiles.Services
AppSettings Class
User-scope settings at %APPDATA%\find-my-files\settings.json — UI-owned, deliberately separate from the machine-scope service.json the service owns. A corrupt file degrades to defaults: warn, quarantine as .bad, and the next save starts clean.
public sealed class AppSettings
Inheritance System.Object → AppSettings
Properties
AppSettings.Engine Property
Engine transport: "auto" (pipe probe → FFI fallback), "pipe", or "inproc". CLI flags override this.
public string Engine { get; set; }
Property Value
AppSettings.FocusedExcludePaths Property
Noise directories excluded in focused mode, each appended as
a quoted !path:"…" term. Plain substring match against the full
path (engine semantics) — no wildcards needed.
public string[] FocusedExcludePaths { get; set; }
Property Value
AppSettings.FocusedExtensions Property
Extension whitelist applied in focused mode as a single
OR-semantics ext:a;b;… term: documents, images, audio, video,
archives and launchables — what a person actually goes looking for.
public string[] FocusedExtensions { get; set; }
Property Value
AppSettings.FocusedSearch Property
Focused-search mode (ADR-0019): rewrite queries in the UI with the two lists below before they reach the engine. On by default — the casual user wants a handful of hits, not 10,000; the toolbar toggle flips it per session and persists here.
public bool FocusedSearch { get; set; }
Property Value
AppSettings.Language Property
UI language: "auto" (follow the OS), "ja", "en", or "zh-Hans". Applied via PrimaryLanguageOverride in the App ctor; the gear menu's switcher persists it here and relaunches to take effect.
public string Language { get; set; }
Property Value
AppSettings.RegexMode Property
Regex mode (ADR-0023): treat the whole query as one regex. Off by default; the gear-menu toggle flips it and persists here.
public bool RegexMode { get; set; }
Property Value
AppSettings.RegexScope Property
Which haystack the whole-query regex matches — "name" or "path". Kept independent of RegexMode so the choice survives toggling regex off and back on. Unknown values fall back to "name".
public string RegexScope { get; set; }
Property Value
AppSettings.ScopeExcludes Property
Absolute subfolder paths pruned from the scope walk (ADR-0025). Each must lie under one of ScopeRoots; the walk skips the matching subtree so it is never indexed. Empty = index everything under the roots.
public string[] ScopeExcludes { get; set; }
Property Value
AppSettings.ScopeRoots Property
Absolute paths of the root folders to index in non-elevated
scope mode (ADR-0024). Empty = unconfigured, and the setup screen mainly
pushes the admin path (all drives, fastest). One or more entries resolve
to EngineChoice.WalkInProc on the next launch, so folder-walk
search works on a corporate PC where neither the service nor admin rights
are available.
public string[] ScopeRoots { get; set; }
Property Value
AppSettings.SettingsPath Property
Absolute path to the user-scope settings file. Portable by
default (<exe>\data\settings.json); falls back to
%APPDATA%\find-my-files\settings.json when the app folder is
read-only. See AppPaths.
public static string SettingsPath { get; }
Property Value
Methods
AppSettings.Load() Method
Load settings from SettingsPath, falling back to defaults (and quarantining the file) if it is missing or corrupt.
public static FindMyFiles.Services.AppSettings Load();
Returns
AppSettings
The loaded settings, or a fresh default instance.
AppSettings.Save() Method
Persist the current settings to SettingsPath (snake_case JSON, indented). Best-effort: a write failure is logged, not thrown.
public void Save();
FindMyFiles
FindMyFiles.Services
DispatcherQueueDispatcher Class
Production IDispatcher: a thin wrapper over the UI thread's cached Microsoft.UI.Dispatching.DispatcherQueue (CLAUDE.md UI rules — cache on the UI thread, TryEnqueue from background threads).
public sealed class DispatcherQueueDispatcher : FindMyFiles.Services.IDispatcher
Inheritance System.Object → DispatcherQueueDispatcher
Implements IDispatcher
Constructors
DispatcherQueueDispatcher(DispatcherQueue) Constructor
Production IDispatcher: a thin wrapper over the UI thread's cached Microsoft.UI.Dispatching.DispatcherQueue (CLAUDE.md UI rules — cache on the UI thread, TryEnqueue from background threads).
public DispatcherQueueDispatcher(Microsoft.UI.Dispatching.DispatcherQueue queue);
Parameters
queue Microsoft.UI.Dispatching.DispatcherQueue
The UI thread's Microsoft.UI.Dispatching.DispatcherQueue, captured once on that thread at construction.
Properties
DispatcherQueueDispatcher.HasThreadAccess Property
True when the caller is already on the UI thread.
public bool HasThreadAccess { get; }
Implements HasThreadAccess
Property Value
Methods
DispatcherQueueDispatcher.CreateOneShotTimer(TimeSpan, Action) Method
One-shot timer: fires tick once per Start(). Start() while pending restarts the interval (debounce semantics).
public FindMyFiles.Services.IDispatcherTimer CreateOneShotTimer(System.TimeSpan interval, System.Action tick);
Parameters
interval System.TimeSpan
Delay between Start() and the tick.
tick System.Action
Callback fired on the UI thread when the interval elapses.
Implements CreateOneShotTimer(TimeSpan, Action)
Returns
IDispatcherTimer
A restartable timer handle bound to this dispatcher.
DispatcherQueueDispatcher.TryEnqueue(Action) Method
Queue action to run on the UI thread. Returns false if the queue is shutting down and the work was not accepted.
public bool TryEnqueue(System.Action action);
Parameters
action System.Action
Work to marshal onto the UI thread.
Implements TryEnqueue(Action)
Returns
System.Boolean
True if enqueued; false if the dispatcher is no longer
accepting work.
FindMyFiles
FindMyFiles.Services
EngineServiceState Enum
SCM registration/run state of the fmf-engine service, as seen by the unelevated UI via QueryState() — drives whether the app offers to install, start, or nothing at all.
public enum EngineServiceState
Fields
NotInstalled 0
No FindMyFiles.Engine.EngineContract.ServiceName entry in the SCM (or the SCM is unreachable) — the UI offers a one-time install.
Stopped 1
Registered but not running — the UI offers to start it.
Running 2
Running (or on its way up: START/CONTINUE_PENDING) — no offer needed; the pipe transport can connect.
FindMyFiles
FindMyFiles.Services
ExceptionPolicy Class
The single home for the process-wide exception funnels (don't crash / don't hang / don't go silent). Three sources, three suppression rules:
1. XAML Microsoft.UI.Xaml.Application.UnhandledException — suppressed
(Handled = true) and surfaced as an error InfoBar for the first
FindMyFiles.Services.ExceptionPolicy.XamlStormBudget occurrences. Beyond that the process is
in an exception storm: a crash marker is written and the exception is
left unhandled so the process dies honestly.
2. System.AppDomain.UnhandledException — never suppressible by
contract: log + crash marker, then the runtime terminates.
3. System.Threading.Tasks.TaskScheduler.UnobservedTaskException — always observed
(the task is already dead; tearing the process down helps nobody) and
surfaced as an error InfoBar.
Log routing: every path writes to FileLog (%APPDATA%\find-my-files\logs\app.log); user-visible surfaces go through Notifier, which mirrors to the same log. Crash markers are written by the fatal paths (1-storm and 2) and read back + cleared by ReportPreviousCrash() on the next launch, so no crash is ever silent.
public sealed class ExceptionPolicy
Inheritance System.Object → ExceptionPolicy
Methods
ExceptionPolicy.Install(Application) Method
Wire all three funnels. Call once, from the App constructor.
public static void Install(Microsoft.UI.Xaml.Application app);
Parameters
app Microsoft.UI.Xaml.Application
The WinUI application whose exception events are hooked.
ExceptionPolicy.ReportPreviousCrash() Method
Surface the previous run's crash marker (if any) as a warning InfoBar; reading clears the marker.
public static void ReportPreviousCrash();
FindMyFiles
FindMyFiles.Services
FileLog Class
Zero-dependency file logger for the app process. Covers everything on the
C# side; the log directory is resolved by AppPaths (portable
<exe>\data\logs by default, else %APPDATA%\find-my-files\logs) —
the same dir the scope engine logs into. Thread-safe, single rotation
generation.
public static class FileLog
Inheritance System.Object → FileLog
Properties
FileLog.CrashMarkerPath Property
Absolute path to the crash marker dropped on a fatal exit and read back on the next launch (see WriteCrashMarker(string) / TakeCrashMarker()).
public static string CrashMarkerPath { get; }
Property Value
FileLog.LogPath Property
Absolute path to the active log file (…\logs\app.log under
the resolved data root) — surfaced for the diagnostics "open log folder"
affordance.
public static string LogPath { get; }
Property Value
Methods
FileLog.Error(string, string, Exception) Method
Log an error under area, optionally appending the full ex for the stack trace.
public static void Error(string area, string message, System.Exception? ex=null);
Parameters
area System.String
Subsystem tag.
message System.String
The message text.
Optional exception to append verbatim.
FileLog.Info(string, string) Method
Log an informational line under area (the subsystem tag shown in brackets).
public static void Info(string area, string message);
Parameters
area System.String
Subsystem tag, e.g. "notify" or "settings".
message System.String
The message text.
FileLog.Tail(int) Method
Last `lines` of the log — for the diagnostics clipboard dump.
public static string Tail(int lines);
Parameters
lines System.Int32
How many trailing lines to return.
Returns
System.String
The joined tail, or a placeholder if missing/unreadable.
FileLog.TakeCrashMarker() Method
Returns and clears the crash marker from the previous run.
public static string? TakeCrashMarker();
Returns
System.String
The marker contents, or null if absent or unreadable.
FileLog.Warn(string, string, Exception) Method
Log a warning under area, optionally appending the full ex for the stack trace.
public static void Warn(string area, string message, System.Exception? ex=null);
Parameters
area System.String
Subsystem tag.
message System.String
The message text.
Optional exception to append verbatim.
FileLog.WriteCrashMarker(string) Method
Drop a crash marker (timestamp + detail) so the next launch can detect an abnormal exit and offer to report it. Best-effort; failures are swallowed.
public static void WriteCrashMarker(string detail);
Parameters
detail System.String
Crash context to record alongside the timestamp.
FindMyFiles
FindMyFiles.Services
IDispatcher Interface
UI-thread dispatch boundary. The single seam that lets the search pipeline and the virtualized list run under unit tests without a real DispatcherQueue — two implementations by necessity: DispatcherQueueDispatcher (production) and a manual fake in the test project.
public interface IDispatcher
Derived
↳ DispatcherQueueDispatcher
Properties
IDispatcher.HasThreadAccess Property
True when the caller is already on the UI thread.
bool HasThreadAccess { get; }
Property Value
Methods
IDispatcher.CreateOneShotTimer(TimeSpan, Action) Method
One-shot timer: fires tick once per Start(). Start() while pending restarts the interval (debounce semantics).
FindMyFiles.Services.IDispatcherTimer CreateOneShotTimer(System.TimeSpan interval, System.Action tick);
Parameters
interval System.TimeSpan
Delay between Start() and the tick.
tick System.Action
Callback fired on the UI thread when the interval elapses.
Returns
IDispatcherTimer
A restartable timer handle bound to this dispatcher.
IDispatcher.TryEnqueue(Action) Method
Queue action to run on the UI thread. Returns false if the queue is shutting down and the work was not accepted.
bool TryEnqueue(System.Action action);
Parameters
action System.Action
Work to marshal onto the UI thread.
Returns
System.Boolean
True if enqueued; false if the dispatcher is no longer
accepting work.
FindMyFiles
FindMyFiles.Services
IDispatcherTimer Interface
The one-shot timer handle returned by CreateOneShotTimer(TimeSpan, Action) — fires on the UI thread and is restartable for debounce.
public interface IDispatcherTimer
Methods
IDispatcherTimer.Start() Method
Arm the timer. Calling while a tick is still pending restarts the interval (debounce semantics).
void Start();
IDispatcherTimer.Stop() Method
Cancel a pending tick, if any. Idempotent.
void Stop();
FindMyFiles
FindMyFiles.Services
Loc Class
Localized-string facade over the Windows App SDK ResourceLoader (PRI built from Strings/<lang>/Resources.resw). Code keys are flat identifiers (Area_Thing, e.g. Status_Preparing); XAML strings come from x:Uid instead. The Override seam lets unit tests resolve keys without a PRI in the test host.
public static class Loc
Inheritance System.Object → Loc
Properties
Loc.Override Property
Test seam: when set, resolves keys instead of the ResourceLoader.
public static System.Func<string,string>? Override { get; set; }
Property Value
System.Func<System.String,System.String>
Methods
Loc.Get(string) Method
Resolve a key to the current UI language. A missing key falls back to the key itself so the gap is visible, never an empty UI.
public static string Get(string key);
Parameters
key System.String
Flat resource identifier (e.g. Status_Preparing).
Returns
System.String
The localized string, or the key itself when unresolved.
Loc.Get(string, object[]) Method
Resolve a key whose value is a composite format string (placeholders {0}, {1}, …) and fill it.
public static string Get(string key, params object[] args);
Parameters
key System.String
Flat resource identifier whose value is a format string.
args System.Object[]
Values substituted into the {0}, {1}, … placeholders.
Returns
System.String
The localized string with the arguments formatted in.
FindMyFiles
FindMyFiles.Services
Notifier Class
Process-wide notification funnel. Anything (global handlers, background tasks, the engine callback) can post from any thread; the ViewModel subscribes and marshals to the UI InfoBar stack. Posts are also mirrored to the file log so nothing the user saw is missing from a bug report.
public static class Notifier
Inheritance System.Object → Notifier
Methods
Notifier.Attach(Action<AppNotification>) Method
Drain posts that arrived before the UI was ready.
public static void Attach(System.Action<FindMyFiles.Services.AppNotification> handler);
Parameters
handler System.Action<AppNotification>
Subscriber invoked for each notification, including the replayed pre-subscription backlog.
Notifier.Post(NotifySeverity, string, string, string, Action) Method
Post a notification from any thread. Mirrors it to the file log at the level matching severity (so nothing the user saw is missing from a bug report), then hands it to the subscriber — or queues it until one attaches.
public static void Post(FindMyFiles.Services.NotifySeverity severity, string message, string? detail=null, string? actionLabel=null, System.Action? action=null);
Parameters
severity NotifySeverity
Style/level and auto-dismiss policy.
message System.String
Headline text.
detail System.String
Optional secondary line (e.g. exception message).
actionLabel System.String
Caption for an optional action button.
action System.Action
Callback for the action button, if any.
Events
Notifier.Posted Event
Raised on the posting thread for each notification once a subscriber exists. Subscribe via Attach(Action<AppNotification>) (which also replays the pre-subscription backlog) rather than touching this directly; the ViewModel handler marshals to the UI thread.
public static event Action<AppNotification>? Posted;
Event Type
System.Action<AppNotification>
FindMyFiles
FindMyFiles.Services
NotifySeverity Enum
Severity of an AppNotification — selects the InfoBar style and the file-log level, and decides whether the entry auto-dismisses (Info) or stays until the user closes it.
public enum NotifySeverity
Fields
Info 0
Transient confirmation — logged at INFO; dissolves on its own.
Warning 1
A degraded path the user should know about — logged at WARN; stays until dismissed.
Error 2
A failure — logged at ERROR; stays until dismissed.
FindMyFiles
FindMyFiles.Services
ScopeFolderPicker Class
Folder picker for scope mode (ADR-0024). Unpackaged WinUI 3 requires a picker to be associated with the app window's HWND before it is shown — it throws otherwise — so this always initializes with WindowHandle.
public static class ScopeFolderPicker
Inheritance System.Object → ScopeFolderPicker
Methods
ScopeFolderPicker.PickAsync() Method
Show the folder picker and return the chosen absolute path (null when the user cancels). Windows.Storage.Pickers.FolderPicker has no multi-select, so the caller invokes this once per folder. Must be called on the UI thread.
public static System.Threading.Tasks.Task<string?> PickAsync();
Returns
System.Threading.Tasks.Task<System.String>
The selected folder path, or null on cancel.
FindMyFiles
FindMyFiles.Services
ScopePaths Class
Pure path helpers for scope mode (ADR-0024/-0025). The engine treats scope roots as independent and would double-walk a nested pair, so the UI normalizes the chosen set; excludes must sit under a root to mean anything. No I/O — unit-tested directly.
public static class ScopePaths
Inheritance System.Object → ScopePaths
Methods
ScopePaths.IsUnderAnyRoot(string, IEnumerable<string>) Method
True when path sits strictly under one of roots — the guard for adding a scope exclude, which must be inside the indexed set to prune anything (ADR-0025). Excluding a whole root (equal path) is rejected: drop the root instead.
public static bool IsUnderAnyRoot(string path, System.Collections.Generic.IEnumerable<string> roots);
Parameters
path System.String
The candidate exclude path.
roots System.Collections.Generic.IEnumerable<System.String>
The selected scope roots.
Returns
System.Boolean
True when the path is a proper descendant of some root.
ScopePaths.Normalize(IEnumerable<string>) Method
Drop any root nested under another selected root (and exact
case-insensitive duplicates), so e.g. {C:\A, C:\A\B} collapses to
{C:\A}. The surviving roots keep their original strings (no
trailing-separator rewriting — C:\ must stay C:\) and their
first-seen order.
public static System.Collections.Generic.List<string> Normalize(System.Collections.Generic.IEnumerable<string> roots);
Parameters
roots System.Collections.Generic.IEnumerable<System.String>
The chosen roots, in selection order.
Returns
System.Collections.Generic.List<System.String>
The covering roots with nested/duplicate entries removed.
FindMyFiles
FindMyFiles.Services
ServiceActionOutcome Enum
Verdict of one elevated lifecycle action (RunElevated(string, string)). Output is unreadable under ShellExecute, so the exit code is the only signal; a declined UAC prompt is distinguished from a genuine failure so the UI can say so.
public enum ServiceActionOutcome
Fields
Ok 0
The elevated action exited 0 — the verb succeeded.
Failed 1
The action ran but exited non-zero (or could not be launched/timed out) — a genuine failure to surface to the user.
Cancelled 2
The user dismissed the UAC prompt (ERROR_CANCELLED 1223) — not a failure, so the UI says "cancelled" rather than "error".
FindMyFiles
FindMyFiles.Services
ServiceActionResult Struct
Result of one RunElevated(string, string) call: the classified Outcome plus the raw process ExitCode (-1 when the process never produced one).
public readonly record struct ServiceActionResult : System.IEquatable<FindMyFiles.Services.ServiceActionResult>
Implements System.IEquatable<ServiceActionResult>
Constructors
ServiceActionResult(ServiceActionOutcome, int) Constructor
Result of one RunElevated(string, string) call: the classified Outcome plus the raw process ExitCode (-1 when the process never produced one).
public ServiceActionResult(FindMyFiles.Services.ServiceActionOutcome Outcome, int ExitCode);
Parameters
Outcome ServiceActionOutcome
Success / failure / user-cancelled classification.
ExitCode System.Int32
fmf-service.exe exit code, or -1 if it could not be launched, timed out, or the UAC prompt was declined.
Properties
ServiceActionResult.ExitCode Property
fmf-service.exe exit code, or -1 if it could not be launched, timed out, or the UAC prompt was declined.
public int ExitCode { get; init; }
Property Value
ServiceActionResult.Outcome Property
Success / failure / user-cancelled classification.
public FindMyFiles.Services.ServiceActionOutcome Outcome { get; init; }
Property Value
FindMyFiles
FindMyFiles.Services
ServiceProvisioner Class
The shared "make file search usable" steps, behind both the setup screen's one-click button and the management dialog's register action: register the fmf-engine service elevated, then wait for its pipe to start serving and relaunch so this (unelevated, empty-fake) instance comes back connected. The engine transport is chosen once at startup, so a relaunch is how a freshly registered service takes effect.
Instance-based so the elevated setup, the pipe probe, the relaunch and the inter-probe delay are injectable boundaries (ADR-0022) — production code uses Real, which wires the real statics; tests drive fakes.
public sealed class ServiceProvisioner
Inheritance System.Object → ServiceProvisioner
Properties
ServiceProvisioner.Real Property
The production provisioner: the real elevated setup, the real pipe probe, Relaunch(), and System.Threading.Tasks.Task.Delay(System.TimeSpan). Callers default to this.
public static FindMyFiles.Services.ServiceProvisioner Real { get; }
Property Value
Methods
ServiceProvisioner.RegisterAsync() Method
install (idempotent) + restart in one elevated step (the fmf-service `setup` verb), forwarding the daily user's SID so OTS elevation doesn't lock them out (docs/SECURITY.md threat 1). Blocking work runs off the UI thread.
public System.Threading.Tasks.Task<FindMyFiles.Services.ServiceActionOutcome> RegisterAsync();
Returns
System.Threading.Tasks.Task<ServiceActionOutcome>
The outcome of the elevated setup step (success, declined, or failed).
ServiceProvisioner.WaitForServiceThenRelaunchAsync() Method
After register/start the service's pipe needs a moment to start serving — poll until it answers (≈8s budget), then relaunch this app so the fresh instance connects. Returns false if the pipe never came up in time (the caller then offers a manual retry). On success this process exits and never returns.
public System.Threading.Tasks.Task<bool> WaitForServiceThenRelaunchAsync();
Returns
System.Threading.Tasks.Task<System.Boolean>
True once the pipe answered and a relaunch was triggered; false if it never came up in time.
FindMyFiles
FindMyFiles.Services
ServiceSetup Class
In-app service setup — the GUI half ADR-0016 left to a terminal: detects the fmf-engine SCM registration (read-only, works unelevated) and drives fmf-service.exe install/start so the one-time elevation never needs PowerShell. Mutations are strictly user-initiated (the notification button); install is idempotent on the service side.
public static class ServiceSetup
Inheritance System.Object → ServiceSetup
Methods
ServiceSetup.CurrentUserSid() Method
The current user's SID string, forwarded to `fmf-service install --owner-sid` so OTS elevation (a *different* admin account) does not lock this user out of the pipe (threat 1). Null when unavailable — install then authorizes only the elevated account.
public static string? CurrentUserSid();
Returns
System.String
The current user's SID string, or null when it cannot be read.
ServiceSetup.IsProcessElevated() Method
True when *this* process is already running with an Administrator token — the in-proc engine path needs it, and when set the in-app install/start verbs can skip their own UAC prompt.
public static bool IsProcessElevated();
Returns
System.Boolean
True when the current process token is in the Administrators role.
ServiceSetup.IsValidSid(string) Method
A well-formed SID string (S-1-… of digits and hyphens) — guards the value going onto the fmf-service command line against argument injection before it is interpolated.
public static bool IsValidSid(string? s);
Parameters
Candidate SID string to validate.
Returns
System.Boolean
True when the value is a well-formed SID safe to pass on the command line.
ServiceSetup.LocateServiceExe(string) Method
fmf-service.exe next to the app (the dist bundle) or in the dev tree (build\engine\release, walking up from the bin dir).
public static string? LocateServiceExe(string baseDir);
Parameters
baseDir System.String
Directory to start the search from (typically the app's bin dir).
Returns
System.String
Full path to fmf-service.exe, or null when it cannot be found.
ServiceSetup.QueryServiceProcessId() Method
PID of the running fmf-engine service process, or 0 when it is not installed/running. The client-side fake-server check (threat 4) compares this to the pipe's server PID — an unelevated client can read it (unlike a SYSTEM process's token), and a squatter never matches because registering the service needs admin.
public static uint QueryServiceProcessId();
Returns
System.UInt32
The running service's process id, or 0 when not installed/running.
ServiceSetup.QueryState() Method
Read-only SCM query for FindMyFiles.Engine.EngineContract.ServiceName.
public static FindMyFiles.Services.EngineServiceState QueryState();
Returns
EngineServiceState
The service's install/run state for the offer logic.
ServiceSetup.RunElevated(string, string) Method
Run one fmf-service lifecycle verb elevated via a per-action UAC prompt (Verb=runas) — the in-app service manager, where the app itself stays asInvoker. Output can't be captured under ShellExecute, so the verdict is the exit code; a declined prompt (ERROR_CANCELLED 1223) is reported distinctly. args is built from fixed verbs plus SID-validated flags, never raw user text. Blocking — call off the UI thread.
public static FindMyFiles.Services.ServiceActionResult RunElevated(string exe, string args);
Parameters
exe System.String
Path to fmf-service.exe to launch elevated.
args System.String
Service verb plus SID-validated flags to pass on the command line.
Returns
ServiceActionResult
The classified outcome and raw exit code of the elevated action.
FindMyFiles
FindMyFiles.Services
ShellOps Class
Shell-facing operations, centralized so every failure path notifies the user instead of crashing. Targets launch via explorer.exe to shed the process's elevation (CLAUDE.md UI rules).
public static class ShellOps
Inheritance System.Object → ShellOps
Methods
ShellOps.CopyText(string, string) Method
Put text on the clipboard. A failure is logged and surfaced as a warning notification (clipboard access can be transiently denied by other apps).
public static void CopyText(string text, string what);
Parameters
text System.String
The content to copy.
what System.String
Short label for what is being copied, used in the failure log/notification (e.g. "path", "diagnostics").
ShellOps.Open(string) Method
Open a file or folder with its default handler via explorer.exe, shedding the app's elevation. Failures notify the user (with a Win32-specific hint) rather than throwing.
public static void Open(string fullPath);
Parameters
fullPath System.String
Absolute path to open; treated as data, never as a command line (see FindMyFiles.Services.ShellOps.BuildOpenStartInfo(System.String)).
ShellOps.Relaunch() Method
Relaunch this app (unelevated — no runas) and exit, used right after an in-app service registration so the fresh instance picks up the now-running service over the pipe (the engine transport is chosen once, at startup). Strictly user-initiated (the "restart app" button). A failed launch notifies and leaves the current instance running.
public static void Relaunch();
ShellOps.Reveal(string) Method
Reveal a file in Explorer with it selected, via the shell API
(SHParseDisplayName + SHOpenFolderAndSelectItems) — never
explorer.exe /select,<path>, whose switch parser needs a literal
quoted path it does not escape, so a '"' in an MFT-sourced name could inject
switches. Runs on a dedicated STA thread with COM initialised: on the WinUI
UI thread (an ASTA) SHOpenFolderAndSelectItems returns S_OK but
opens nothing. Failures notify off-thread (Notifier/
FileLog are thread-safe; the ViewModel marshals the InfoBar to
the UI).
public static void Reveal(string fullPath);
Parameters
fullPath System.String
Absolute path to reveal and select.
FindMyFiles
FindMyFiles.Services
TaskExtensions Class
Extensions for safely launching fire-and-forget System.Threading.Tasks.Tasks
(CLAUDE.md rule: never _ = SomeAsync()).
public static class TaskExtensions
Inheritance System.Object → TaskExtensions
Methods
TaskExtensions.Forget(this Task, string) Method
The only sanctioned way to fire-and-forget (CLAUDE.md rule): unexpected exceptions land in the log and the notification bar instead of being silently dropped by an abandoned Task.
public static void Forget(this System.Threading.Tasks.Task task, string area);
Parameters
task System.Threading.Tasks.Task
The task to observe to completion.
area System.String
Subsystem tag for the log/notification if it faults.
FindMyFiles
FindMyFiles.Services Namespace
| Classes | |
|---|---|
| AppNotification | One entry in the InfoBar stack. Immutable, identity-stamped, and carries an optional action button so a notification can offer its own remedy (e.g. "restart the app" after a service install). |
| AppPaths | Resolves where the app keeps its state — <b>portable by default</b> (ADR-0024). On first access it picks one data root, once, in this order: ... The machine-scope service index (%ProgramData%) and the admin in-proc index are intentionally <i>not</i> redirected — that path is an install by nature, the opposite of portable. Resolution is silent: it must not call FileLog, because FileLog's directory comes from here (a cycle otherwise). |
| AppSettings | User-scope settings at %APPDATA%\find-my-files\settings.json — UI-owned, deliberately separate from the machine-scope service.json the service owns. A corrupt file degrades to defaults: warn, quarantine as .bad, and the next save starts clean. |
| DispatcherQueueDispatcher | Production IDispatcher: a thin wrapper over the UI thread's cached Microsoft.UI.Dispatching.DispatcherQueue (CLAUDE.md UI rules — cache on the UI thread, TryEnqueue from background threads). |
| ExceptionPolicy | The single home for the process-wide exception funnels (don't crash / don't hang / don't go silent). Three sources, three suppression rules: 1. XAML Microsoft.UI.Xaml.Application.UnhandledException — suppressed (Handled = true) and surfaced as an error InfoBar for the first FindMyFiles.Services.ExceptionPolicy.XamlStormBudget occurrences. Beyond that the process is in an exception storm: a crash marker is written and the exception is left unhandled so the process dies honestly. 2. System.AppDomain.UnhandledException — never suppressible by contract: log + crash marker, then the runtime terminates. 3. System.Threading.Tasks.TaskScheduler.UnobservedTaskException — always observed (the task is already dead; tearing the process down helps nobody) and surfaced as an error InfoBar. Log routing: every path writes to FileLog (%APPDATA%\find-my-files\logs\app.log); user-visible surfaces go through Notifier, which mirrors to the same log. Crash markers are written by the fatal paths (1-storm and 2) and read back + cleared by ReportPreviousCrash() on the next launch, so no crash is ever silent. |
| FileLog | Zero-dependency file logger for the app process. Covers everything on the C# side; the log directory is resolved by AppPaths (portable <exe>\data\logs by default, else %APPDATA%\find-my-files\logs) — the same dir the scope engine logs into. Thread-safe, single rotation generation. |
| Loc | Localized-string facade over the Windows App SDK ResourceLoader (PRI built from Strings/<lang>/Resources.resw). Code keys are flat identifiers (Area_Thing, e.g. Status_Preparing); XAML strings come from x:Uid instead. The Override seam lets unit tests resolve keys without a PRI in the test host. |
| Notifier | Process-wide notification funnel. Anything (global handlers, background tasks, the engine callback) can post from any thread; the ViewModel subscribes and marshals to the UI InfoBar stack. Posts are also mirrored to the file log so nothing the user saw is missing from a bug report. |
| ScopeFolderPicker | Folder picker for scope mode (ADR-0024). Unpackaged WinUI 3 requires a picker to be associated with the app window's HWND before it is shown — it throws otherwise — so this always initializes with WindowHandle. |
| ScopePaths | Pure path helpers for scope mode (ADR-0024/-0025). The engine treats scope roots as independent and would double-walk a nested pair, so the UI normalizes the chosen set; excludes must sit under a root to mean anything. No I/O — unit-tested directly. |
| ServiceProvisioner | The shared "make file search usable" steps, behind both the setup screen's one-click button and the management dialog's register action: register the fmf-engine service elevated, then wait for its pipe to start serving and relaunch so this (unelevated, empty-fake) instance comes back connected. The engine transport is chosen once at startup, so a relaunch is how a freshly registered service takes effect. Instance-based so the elevated setup, the pipe probe, the relaunch and the inter-probe delay are injectable boundaries (ADR-0022) — production code uses Real, which wires the real statics; tests drive fakes. |
| ServiceSetup | In-app service setup — the GUI half ADR-0016 left to a terminal: detects the fmf-engine SCM registration (read-only, works unelevated) and drives fmf-service.exe install/start so the one-time elevation never needs PowerShell. Mutations are strictly user-initiated (the notification button); install is idempotent on the service side. |
| ShellOps | Shell-facing operations, centralized so every failure path notifies the user instead of crashing. Targets launch via explorer.exe to shed the process's elevation (CLAUDE.md UI rules). |
| TaskExtensions | Extensions for safely launching fire-and-forget System.Threading.Tasks.Tasks (CLAUDE.md rule: never _ = SomeAsync()). |
| Structs | |
|---|---|
| ServiceActionResult | Result of one RunElevated(string, string) call: the classified Outcome plus the raw process ExitCode (-1 when the process never produced one). |
| Interfaces | |
|---|---|
| IDispatcher | UI-thread dispatch boundary. The single seam that lets the search pipeline and the virtualized list run under unit tests without a real DispatcherQueue — two implementations by necessity: DispatcherQueueDispatcher (production) and a manual fake in the test project. |
| IDispatcherTimer | The one-shot timer handle returned by CreateOneShotTimer(TimeSpan, Action) — fires on the UI thread and is restartable for debounce. |
| Enums | |
|---|---|
| EngineServiceState | SCM registration/run state of the fmf-engine service, as seen by the unelevated UI via QueryState() — drives whether the app offers to install, start, or nothing at all. |
| NotifySeverity | Severity of an AppNotification — selects the InfoBar style and the file-log level, and decides whether the entry auto-dismisses (Info) or stays until the user closes it. |
| ServiceActionOutcome | Verdict of one elevated lifecycle action (RunElevated(string, string)). Output is unreadable under ShellExecute, so the exit code is the only signal; a declined UAC prompt is distinguished from a genuine failure so the UI can say so. |
FindMyFiles
FindMyFiles.ViewModels
FocusedQueryRewriter Class
Focused search: a pure query rewrite in the UI layer —
the engine is never touched (ADR-0019). Every top-level OR group of the
user's query gets the configured noise-path exclusions (!path:"…")
and the extension whitelist (one ext:a;b;… term) appended, except
where the user already expressed intent: a group mentioning
ext:/regex: keeps its own type filter, a group mentioning
path: or containing \ keeps its own location.
public static class FocusedQueryRewriter
Inheritance System.Object → FocusedQueryRewriter
Methods
FocusedQueryRewriter.Compose(string, IReadOnlyList<string>, IReadOnlyList<string>) Method
Rewrites userQuery for focused mode. An empty/whitespace query is returned unchanged — the "no query, no results" rule stays the orchestrator's, and a rewrite must never turn an empty query into a non-empty one.
public static string Compose(string userQuery, System.Collections.Generic.IReadOnlyList<string> excludePaths, System.Collections.Generic.IReadOnlyList<string> extensions);
Parameters
userQuery System.String
The user's raw query text.
excludePaths System.Collections.Generic.IReadOnlyList<System.String>
Noise paths appended as !path:"…" exclusions.
extensions System.Collections.Generic.IReadOnlyList<System.String>
The extension whitelist appended as one ext: term.
Returns
System.String
The rewritten query, or the input unchanged when empty or already constrained.
FindMyFiles
FindMyFiles.ViewModels
MainViewModel Class
Provides a mechanism for releasing unmanaged resources.
public sealed class MainViewModel : CommunityToolkit.Mvvm.ComponentModel.ObservableObject, System.IDisposable
Inheritance System.Object → CommunityToolkit.Mvvm.ComponentModel.ObservableObject → MainViewModel
Implements System.IDisposable
Constructors
MainViewModel(IEngineClient, IDispatcher, AppSettings, Func<Task<string>>, Action, Func<bool>, ServiceProvisioner) Constructor
Builds the focused components, restores focused-search settings, and subscribes the engine events (volume updates, errors, connection changes). Call StartAsync() afterwards to begin indexing.
public MainViewModel(FindMyFiles.Engine.IEngineClient engine, FindMyFiles.Services.IDispatcher dispatcher, FindMyFiles.Services.AppSettings? settings=null, System.Func<System.Threading.Tasks.Task<string?>>? folderPicker=null, System.Action? relaunch=null, System.Func<bool>? isScopeMode=null, FindMyFiles.Services.ServiceProvisioner? provisioner=null);
Parameters
engine IEngineClient
The engine client (Fake / Ffi / Pipe) this page drives.
dispatcher IDispatcher
UI dispatcher used to marshal engine callbacks and back timers.
settings AppSettings
App settings to read/persist; loaded from disk when null.
folderPicker System.Func<System.Threading.Tasks.Task<System.String>>
Scope-folder picker; defaults to the real PickAsync() (tests inject a fake).
relaunch System.Action
Unelevated relaunch action; defaults to the real Relaunch() (tests inject a no-op).
isScopeMode System.Func<System.Boolean>
Reports whether the engine is a scope-mode walk; defaults to inspecting the real FfiEngineClient (tests inject a constant to drive the mode-dependent UI).
provisioner ServiceProvisioner
The register→wait→relaunch steps behind the setup screen's one-click button; defaults to Real (tests inject fakes so EnableSearchAsync() runs without UAC).
Properties
MainViewModel.CanStartScope Property
The "start scope search" button is enabled only once at least one folder has been chosen.
public bool CanStartScope { get; }
Property Value
MainViewModel.DataLocationText Property
The portable-data-root footnote (only shown when IsPortable).
public string DataLocationText { get; }
Property Value
MainViewModel.IsDisconnected Property
True when the engine is the empty fake (unelevated, no service) — the page shows the setup screen instead of a search box that can only return zero rows. Fixed for this instance's lifetime (the transport is chosen once; registering relaunches), so x:Bind OneTime is enough.
public bool IsDisconnected { get; }
Property Value
MainViewModel.IsPortable Property
True when app state lives next to the exe rather than the user profile (AppPaths) — drives the setup screen's "nothing leaves this folder" footnote. Fixed at startup, so x:Bind OneTime.
public bool IsPortable { get; }
Property Value
MainViewModel.IsPrivilegedMode Property
True once indexing in the elevated whole-volume mode (service or in-proc). Gates the gear menu's "manage service" item — the complement of IsScopeMode while ready, both false while disconnected. Fixed at startup, so x:Bind OneTime.
public bool IsPrivilegedMode { get; }
Property Value
MainViewModel.IsReady Property
Inverse of IsDisconnected — true when the search UI (box + result list) should be shown instead of the setup screen.
public bool IsReady { get; }
Property Value
MainViewModel.IsScopeMode Property
True once indexing in **scope mode** (ADR-0024: a user-chosen set of folders, not all drives). Gates the gear menu's "change search folders" item. Fixed at startup (the transport is chosen once), so x:Bind OneTime is enough.
public bool IsScopeMode { get; }
Property Value
MainViewModel.ModeText Property
The current index mode for the status submenu's info row (selected folders vs all drives). Fixed at startup, so x:Bind OneTime.
public string ModeText { get; }
Property Value
MainViewModel.Notifications Property
The InfoBar stack — failures and transient notices are pushed here.
public FindMyFiles.ViewModels.NotificationCenter Notifications { get; }
Property Value
MainViewModel.Perf Property
State behind the F12 performance panel (last trace, stats, latency history).
public FindMyFiles.ViewModels.PerfPanelViewModel Perf { get; }
Property Value
MainViewModel.Results Property
How results land in the virtualized list (publish / refresh in place / empty) — the seam the orchestrator hands outcomes to.
public FindMyFiles.ViewModels.ResultsPresenter Results { get; }
Property Value
MainViewModel.ScopeCoverageNote Property
A note naming the folders already inside a larger selected one, so the user sees the bigger set subsumes them (they merge on apply). Empty when the selection has no nesting. Recomputed on every ScopeFolders change.
public string ScopeCoverageNote { get; }
Property Value
MainViewModel.ScopeExcludes Property
Subfolders to prune from the walk (ADR-0025), shown in the scope manager dialog. Each must sit under a ScopeFolders root; seeded from settings, persisted by ApplyScopeChange().
public System.Collections.ObjectModel.ObservableCollection<string> ScopeExcludes { get; }
Property Value
System.Collections.ObjectModel.ObservableCollection<System.String>
MainViewModel.ScopeFolders Property
Folders the user has chosen to fold-walk in scope mode, edited in the scope dialog. Seeded from settings; ApplyScopeChange() persists them as ScopeRoots and relaunches.
public System.Collections.ObjectModel.ObservableCollection<string> ScopeFolders { get; }
Property Value
System.Collections.ObjectModel.ObservableCollection<System.String>
MainViewModel.Search Property
Decides when and what to search (debounce, generation, requery triggers); the page forwards box edits and toggles to it.
public FindMyFiles.ViewModels.SearchOrchestrator Search { get; }
Property Value
MainViewModel.SearchPlaceholder Property
The search box hint — regex/scope-aware, so the box itself signals that regex mode is on (the toggle lives in the gear menu).
public string SearchPlaceholder { get; }
Property Value
MainViewModel.SetupNotBusy Property
Inverse of FindMyFiles.ViewModels.MainViewModel.SetupBusy — gates the setup button's enabled state.
public bool SetupNotBusy { get; }
Property Value
Methods
MainViewModel.ApplyScopeChange() Method
Apply the current ScopeFolders as the scope: drop
roots nested under another (Normalize(IEnumerable<string>)), and if the
set actually changed, persist it as ScopeRoots
and relaunch (unelevated) into a fresh WalkInProc that folder-walks
the new set (ADR-0024). The engine has no live root-swap
(index_start_scope no-ops on an existing scope slot), so a relaunch
is the only way to re-walk. No-op when empty or unchanged, so re-opening
the manager and closing it without edits never restarts.
public void ApplyScopeChange();
MainViewModel.Dispose() Method
Unsubscribe the engine-event marshaler — the one owned disposable — so its handlers stop holding this view model rooted.
public void Dispose();
Implements Dispose()
MainViewModel.EnableSearchAsync() Method
Setup screen's one-click action: register the service elevated, then (on success) wait for its pipe and relaunch — so a first-time user goes from the setup screen to a working search box in one click. The app stays unelevated; only fmf-service is elevated (per-action UAC).
public System.Threading.Tasks.Task EnableSearchAsync();
Returns
System.Threading.Tasks.Task
A task that completes when registration finishes, or before relaunch on success.
MainViewModel.PickScopeExcludeAsync() Method
Manager dialog (scope mode): pick a subfolder to prune from the walk (ADR-0025). Rejected with a notice when it is not inside one of the chosen ScopeFolders roots (an exclude outside the indexed set prunes nothing). Case-insensitive dedupe.
public System.Threading.Tasks.Task PickScopeExcludeAsync();
Returns
System.Threading.Tasks.Task
A task that completes once the picked folder (if valid) is added.
MainViewModel.PickScopeFoldersAsync() Method
Setup screen (no-admin path): open the folder picker and add the chosen folder to ScopeFolders (case-insensitive dedupe). The picker is single-select, so this adds one folder per click.
public System.Threading.Tasks.Task PickScopeFoldersAsync();
Returns
System.Threading.Tasks.Task
A task that completes once the picked folder (if any) has been added.
MainViewModel.RemoveScopeExclude(string) Method
Drop one excluded subfolder (the per-row × button).
public void RemoveScopeExclude(string path);
Parameters
path System.String
The exclude path to remove.
MainViewModel.RemoveScopeFolder(string) Method
Drop one folder from the scope list (the per-row × button).
public void RemoveScopeFolder(string path);
Parameters
path System.String
The folder path to remove.
MainViewModel.SetSort(FmfSort) Method
Column-header click: re-clicking the active FindMyFiles.ViewModels.MainViewModel.Sort column toggles FindMyFiles.ViewModels.MainViewModel.SortDescending, a new column switches to it ascending. Either way requeries with Sort.
public void SetSort(FindMyFiles.Engine.FmfSort key);
Parameters
key FmfSort
The sort column the clicked header maps to.
MainViewModel.StartAsync() Method
Startup sequence, in order: status text → StartIndexing → initial requery. Runs on the UI thread; the engine calls are awaited so a pipe transport never blocks it.
public System.Threading.Tasks.Task StartAsync();
Returns
System.Threading.Tasks.Task
A task that completes once startup indexing and the initial requery are kicked off.
FindMyFiles
FindMyFiles.ViewModels
NotificationCenter Class
The InfoBar notification stack: capped at three, Info entries dissolve after five seconds. Every error path in the app funnels through here via Notifier. UI thread only (the Notifier subscription marshals).
public sealed class NotificationCenter
Inheritance System.Object → NotificationCenter
Constructors
NotificationCenter(IDispatcher) Constructor
Create the stack bound to dispatcher, used to marshal posts onto the UI thread and to drive the Info auto-dismiss timer.
public NotificationCenter(FindMyFiles.Services.IDispatcher dispatcher);
Parameters
dispatcher IDispatcher
UI-thread dispatch boundary.
Properties
NotificationCenter.Items Property
The live InfoBar stack (oldest first, capped at three), x:Bind'd by the view. Mutated on the UI thread only.
public System.Collections.ObjectModel.ObservableCollection<FindMyFiles.Services.AppNotification> Items { get; }
Property Value
System.Collections.ObjectModel.ObservableCollection<AppNotification>
Methods
NotificationCenter.AttachToNotifier() Method
Drain the process-wide funnel into this stack.
public void AttachToNotifier();
NotificationCenter.Push(AppNotification) Method
Append n to the stack, evicting the oldest entries to stay within the three-item cap; Info entries also schedule their own five-second removal. UI thread only.
public void Push(FindMyFiles.Services.AppNotification n);
Parameters
The notification to show.
NotificationCenter.Remove(AppNotification) Method
Remove n from the stack — the InfoBar close button's target. No-op if it is already gone. UI thread only.
public void Remove(FindMyFiles.Services.AppNotification n);
Parameters
The notification to dismiss.
FindMyFiles
FindMyFiles.ViewModels
PerfPanelViewModel Class
Supports all classes in the .NET Framework class hierarchy and provides low-level services to derived classes. This is the ultimate base class of all classes in the .NET Framework; it is the root of the type hierarchy.
public sealed class PerfPanelViewModel : CommunityToolkit.Mvvm.ComponentModel.ObservableObject
Inheritance System.Object → CommunityToolkit.Mvvm.ComponentModel.ObservableObject → PerfPanelViewModel
Constructors
PerfPanelViewModel(IEngineClient) Constructor
Binds the panel to engine — the source of both the stats snapshot and the transport label.
public PerfPanelViewModel(FindMyFiles.Engine.IEngineClient engine);
Parameters
engine IEngineClient
Engine client supplying stats and the transport label.
Properties
PerfPanelViewModel.EngineMode Property
Engine transport label for the F12 panel — moved off the gear menu, where its internal terms (fake / in-proc) confused end users; F12 is diagnostic, so the precise vocabulary stays here.
public string EngineMode { get; }
Property Value
PerfPanelViewModel.RecentTotalsUs Property
Latencies of the most recent queries (µs, oldest first).
public System.Collections.Generic.IReadOnlyList<ulong> RecentTotalsUs { get; }
Property Value
System.Collections.Generic.IReadOnlyList<System.UInt64>
Methods
PerfPanelViewModel.RecordTrace(QueryTraceData) Method
Record one completed query (trace may be null).
public void RecordTrace(FindMyFiles.Engine.QueryTraceData? trace);
Parameters
trace QueryTraceData
Stage breakdown of the query, or null when none was emitted.
PerfPanelViewModel.RefreshStatsAsync() Method
Pull a fresh FindMyFiles.ViewModels.PerfPanelViewModel.Stats snapshot from the engine and raise PerfDataChanged. Awaitable so a pipe round-trip doesn't block the caller.
public System.Threading.Tasks.Task RefreshStatsAsync();
Returns
System.Threading.Tasks.Task
A System.Threading.Tasks.Task that completes once the snapshot is refreshed.
PerfPanelViewModel.Toggle() Method
Flip the panel's visibility (the F12 shortcut / debug menu).
public void Toggle();
Events
PerfPanelViewModel.PerfDataChanged Event
Raised on the UI thread whenever trace/stats data moved.
public event Action? PerfDataChanged;
Event Type
FindMyFiles
FindMyFiles.ViewModels
RequeryOrigin Enum
Why a requery ran. Reset origins land the user at the top of the list; position-preserving origins restore the previous viewport (docs/ARCHITECTURE.md "two requery families").
public enum RequeryOrigin
Fields
Initial 0
First query of the session — reset (top of list).
Typing 1
The user edited the search box — reset.
Clear 2
The search box was cleared — reset.
Sort 3
The sort column/direction changed — reset.
Filter 4
A result filter changed — reset.
IndexChanged 5
The on-disk index changed (USN-driven refresh) — preserves the viewport.
VolumeReady 6
A volume finished indexing and joined the results — preserves the viewport.
Stale 7
The held result went stale and was re-issued — preserves the viewport.
FindMyFiles
FindMyFiles.ViewModels
RequeryOriginExtensions Class
Helpers over RequeryOrigin.
public static class RequeryOriginExtensions
Inheritance System.Object → RequeryOriginExtensions
Methods
RequeryOriginExtensions.PreservesPosition(this RequeryOrigin) Method
True for origins that restore the previous viewport instead of scrolling to the top (IndexChanged, VolumeReady, Stale) — the background refreshes the user did not initiate.
public static bool PreservesPosition(this FindMyFiles.ViewModels.RequeryOrigin origin);
Parameters
origin RequeryOrigin
The requery origin to classify.
Returns
System.Boolean
True when the origin preserves the viewport; false when it resets to the top.
FindMyFiles
FindMyFiles.ViewModels
ResultRow Class
Supports all classes in the .NET Framework class hierarchy and provides low-level services to derived classes. This is the ultimate base class of all classes in the .NET Framework; it is the root of the type hierarchy.
public sealed class ResultRow : CommunityToolkit.Mvvm.ComponentModel.ObservableObject
Inheritance System.Object → CommunityToolkit.Mvvm.ComponentModel.ObservableObject → ResultRow
Properties
ResultRow.EntryRef Property
Engine row identity — lets the view re-find a selected row after a position-preserving requery (best effort).
public ulong EntryRef { get; }
Property Value
ResultRow.FullPath Property
Absolute path (ParentPath + Name) — what open/copy act on.
Empty until Fill(RowData, IHighlighter).
public string FullPath { get; }
Property Value
ResultRow.Index Property
Absolute position of this row in the full result set — the virtualized list's stable key, set once at placeholder creation and never changed (the same instance is refilled when its page lands).
public long Index { get; init; }
Property Value
ResultRow.IsPlaceholder Property
True while this is an unfilled placeholder (its page hasn't arrived); the row template shows a skeleton until Fill(RowData, IHighlighter).
public bool IsPlaceholder { get; }
Property Value
Methods
ResultRow.CreatePlaceholder(long) Method
Make an empty row for index — the virtualized list's only constructor, called for every slot before any data is fetched.
public static FindMyFiles.ViewModels.ResultRow CreatePlaceholder(long index);
Parameters
index System.Int64
Absolute position of the row in the full result set.
Returns
ResultRow
A new placeholder row keyed to index.
ResultRow.Fill(RowData, IHighlighter) Method
Populate this placeholder from an engine RowData page hit: copies identity (EntryRef, FullPath), formats size/date for display, picks the type glyph, and clears IsPlaceholder. In place — the bound instance is reused.
public void Fill(FindMyFiles.Engine.RowData data, FindMyFiles.Highlighting.IHighlighter? highlighter=null);
Parameters
data RowData
The engine page hit supplying this row's identity and fields.
highlighter IHighlighter
Active-query highlighter, or null when no query is set.
FindMyFiles
FindMyFiles.ViewModels
ResultsPresenter Class
Supports all classes in the .NET Framework class hierarchy and provides low-level services to derived classes. This is the ultimate base class of all classes in the .NET Framework; it is the root of the type hierarchy.
public sealed class ResultsPresenter : CommunityToolkit.Mvvm.ComponentModel.ObservableObject
Inheritance System.Object → CommunityToolkit.Mvvm.ComponentModel.ObservableObject → ResultsPresenter
Constructors
ResultsPresenter(IDispatcher) Constructor
Create the presenter and its lifetime-single VirtualResultList, both bound to dispatcher (the UI thread that publishes and fetches run on).
public ResultsPresenter(FindMyFiles.Services.IDispatcher dispatcher);
Parameters
dispatcher IDispatcher
UI-thread dispatcher that publishes and page fetches run on.
Properties
ResultsPresenter.ResultsSource Property
Lifetime-single ItemsSource — bind with x:Bind OneTime.
public FindMyFiles.Virtualization.VirtualResultList ResultsSource { get; }
Property Value
Methods
ResultsPresenter.PresentEmpty() Method
Empty search box → empty screen, idempotently.
public void PresentEmpty();
ResultsPresenter.PresentEngineFailure() Method
Engine failure: the notification carries the details.
public void PresentEngineFailure();
ResultsPresenter.PresentQueryError(string) Method
Show a query problem without touching the published results.
public void PresentQueryError(string message);
Parameters
message System.String
The query-error message to display in the status bar.
ResultsPresenter.PublishAsync(ISearchResult, QueryTraceData, RequeryOrigin, IHighlighter, Func<bool>) Method
Prefetch the viewport pages of result, then publish it. Runs on the UI thread; the page reads themselves are async, so the thread is never blocked and newer keystrokes keep flowing. When isCurrent turns false mid-flight the result is disposed unpublished — the screen keeps showing the previous result.
public System.Threading.Tasks.Task PublishAsync(FindMyFiles.Engine.ISearchResult result, FindMyFiles.Engine.QueryTraceData? trace, FindMyFiles.ViewModels.RequeryOrigin origin, FindMyFiles.Highlighting.IHighlighter highlighter, System.Func<bool> isCurrent);
Parameters
result ISearchResult
The new search result to prefetch and publish.
trace QueryTraceData
Optional query trace used to format the count text;
null when no timing is available.
origin RequeryOrigin
Why the requery ran — decides reset vs. position restore.
highlighter IHighlighter
Match highlighter applied to the published rows.
isCurrent System.Func<System.Boolean>
Predicate that returns false once a newer query has superseded this one.
Returns
System.Threading.Tasks.Task
A System.Threading.Tasks.Task representing the asynchronous publish.
Exceptions
StaleResultException
The index was structurally rebuilt while prefetching — the caller
decides whether to retry.
ResultsPresenter.RefreshInPlaceAsync(ISearchResult, QueryTraceData, RequeryOrigin, IHighlighter, Func<bool>) Method
Same-results refresh (Unchanged): swap the new handle in without a Reset, so an idle USN requery repaints nothing — only cells whose values actually changed in place (sizes/mtimes of files being written) update. The count text stays untouched on purpose: a churning ms display reads as flicker. Falls back to a full publish if the counts somehow disagree.
public System.Threading.Tasks.Task RefreshInPlaceAsync(FindMyFiles.Engine.ISearchResult result, FindMyFiles.Engine.QueryTraceData? trace, FindMyFiles.ViewModels.RequeryOrigin origin, FindMyFiles.Highlighting.IHighlighter highlighter, System.Func<bool> isCurrent);
Parameters
result ISearchResult
The refreshed search result handle to swap in.
trace QueryTraceData
Optional query trace forwarded to the publish
fallback; null when no timing is available.
origin RequeryOrigin
Why the requery ran — forwarded to the publish fallback.
highlighter IHighlighter
Match highlighter applied to the refreshed rows.
isCurrent System.Func<System.Boolean>
Predicate that returns false once a newer query has superseded this one.
Returns
System.Threading.Tasks.Task
A System.Threading.Tasks.Task representing the asynchronous refresh.
Events
ResultsPresenter.ResultsPublished Event
Raised on the UI thread right after each seeded Reset.
public event Action<ResultsPublication>? ResultsPublished;
Event Type
System.Action<ResultsPublication>
FindMyFiles
FindMyFiles.ViewModels
ResultsPublication Struct
Describes one published result set so the view can place the viewport: reset origins scroll to the top, position-preserving origins scroll to RestoreIndex. The seeded index window is where a previously selected row may be re-found.
public readonly record struct ResultsPublication : System.IEquatable<FindMyFiles.ViewModels.ResultsPublication>
Implements System.IEquatable<ResultsPublication>
Constructors
ResultsPublication(RequeryOrigin, Nullable<int>, int, int) Constructor
Describes one published result set so the view can place the viewport: reset origins scroll to the top, position-preserving origins scroll to RestoreIndex. The seeded index window is where a previously selected row may be re-found.
public ResultsPublication(FindMyFiles.ViewModels.RequeryOrigin Origin, System.Nullable<int> RestoreIndex, int FirstSeededIndex, int LastSeededIndex);
Parameters
Origin RequeryOrigin
Why the requery ran — decides reset vs. position restore.
RestoreIndex System.Nullable<System.Int32>
First visible row index to scroll back to for a
position-preserving origin; null for reset origins (scroll to top).
FirstSeededIndex System.Int32
First row index that was prefetched and is thus realizable without a fetch — lower bound of the selection re-find window.
LastSeededIndex System.Int32
Last prefetched row index — upper bound of the selection re-find window.
Properties
ResultsPublication.FirstSeededIndex Property
First row index that was prefetched and is thus realizable without a fetch — lower bound of the selection re-find window.
public int FirstSeededIndex { get; init; }
Property Value
ResultsPublication.LastSeededIndex Property
Last prefetched row index — upper bound of the selection re-find window.
public int LastSeededIndex { get; init; }
Property Value
ResultsPublication.Origin Property
Why the requery ran — decides reset vs. position restore.
public FindMyFiles.ViewModels.RequeryOrigin Origin { get; init; }
Property Value
ResultsPublication.RestoreIndex Property
First visible row index to scroll back to for a
position-preserving origin; null for reset origins (scroll to top).
public System.Nullable<int> RestoreIndex { get; init; }
Property Value
FindMyFiles
FindMyFiles.ViewModels
SearchOrchestrator Class
When and what to search: 50ms debounce on typing (clearing is instant), a generation counter that discards superseded responses, requery triggers (index changes, stale results) and exception classification. Results are handed to the ResultsPresenter; failures surface through SearchFailed so the ViewModel owns the user-facing wording. All entry points run on the UI thread.
public sealed class SearchOrchestrator
Inheritance System.Object → SearchOrchestrator
Constructors
SearchOrchestrator(IEngineClient, EngineEventMarshaler, IDispatcher, ResultsPresenter, Func<SearchRequest>) Constructor
Wires the orchestrator to its collaborators and subscribes the auto-requery triggers (stale results, index changes).
public SearchOrchestrator(FindMyFiles.Engine.IEngineClient engine, FindMyFiles.Engine.EngineEventMarshaler engineEvents, FindMyFiles.Services.IDispatcher dispatcher, FindMyFiles.ViewModels.ResultsPresenter presenter, System.Func<FindMyFiles.ViewModels.SearchRequest> request);
Parameters
engine IEngineClient
Engine the queries are issued against.
engineEvents EngineEventMarshaler
UI-thread-marshaled engine events; its
IndexChanged drives an automatic requery.
dispatcher IDispatcher
UI dispatcher — used to create the debounce timer.
presenter ResultsPresenter
Sink that publishes results and stale signals.
request System.Func<SearchRequest>
Pull of the current UI state at query time (the ViewModel stays the source of truth).
Properties
SearchOrchestrator.FocusedExcludePaths Property
Noise paths excluded in focused mode (settings-owned).
public System.Collections.Generic.IReadOnlyList<string> FocusedExcludePaths { get; set; }
Property Value
System.Collections.Generic.IReadOnlyList<System.String>
SearchOrchestrator.FocusedExtensions Property
Extension whitelist for focused mode (settings-owned).
public System.Collections.Generic.IReadOnlyList<string> FocusedExtensions { get; set; }
Property Value
System.Collections.Generic.IReadOnlyList<System.String>
SearchOrchestrator.FocusedSearch Property
Focused search: when on, the user's query is rewritten with the two lists below (FocusedQueryRewriter) right before it reaches the engine. Defaults to off here — product wiring (MainViewModel) pushes the persisted settings in; a toggle flip is a filter change, so the owner requeries with Filter (top reset).
public bool FocusedSearch { get; set; }
Property Value
Methods
SearchOrchestrator.NotifyCompositionEnded(string) Method
IME composition committed (or cancelled) — search the final text through the normal debounce.
public void NotifyCompositionEnded(string value);
Parameters
value System.String
The committed search box text after composition.
SearchOrchestrator.NotifyCompositionStarted() Method
IME composition began: hold queries so half-composed text (romaji fragments, candidate strings) never hits the engine.
public void NotifyCompositionStarted();
SearchOrchestrator.NotifyTextChanged(string) Method
Search box text changed: debounce a normal edit (50ms), requery immediately on a clear (so emptying feels instant), and ignore edits while an IME composition is in flight.
public void NotifyTextChanged(string value);
Parameters
value System.String
The current search box text after the edit.
SearchOrchestrator.Requery(RequeryOrigin) Method
Fire-and-forget a query for the current UI state, bumping the generation so any in-flight older response is discarded. origin records why (and lets the presenter decide whether to preserve scroll/selection).
public void Requery(FindMyFiles.ViewModels.RequeryOrigin origin);
Parameters
origin RequeryOrigin
Why the requery was triggered.
Events
SearchOrchestrator.SearchFailed Event
Engine or unexpected failure (never query syntax — that goes to the presenter as count text).
public event Action<Exception>? SearchFailed;
Event Type
System.Action<System.Exception>
SearchOrchestrator.TraceCaptured Event
Stage trace of the last completed query (null when the engine produced none) — perf-panel food.
public event Action<QueryTraceData?>? TraceCaptured;
Event Type
FindMyFiles
FindMyFiles.ViewModels
SearchRequest Struct
Snapshot of what to search — the ViewModel stays the single source of truth for the UI state; the orchestrator only pulls it.
public readonly record struct SearchRequest : System.IEquatable<FindMyFiles.ViewModels.SearchRequest>
Implements System.IEquatable<SearchRequest>
Constructors
SearchRequest(string, SearchOptions) Constructor
Snapshot of what to search — the ViewModel stays the single source of truth for the UI state; the orchestrator only pulls it.
public SearchRequest(string Query, FindMyFiles.Engine.SearchOptions Options);
Parameters
Query System.String
Raw user query text (before any focused-mode rewrite).
Options SearchOptions
Sort, case and hidden/system flags for this search.
Properties
SearchRequest.Options Property
Sort, case and hidden/system flags for this search.
public FindMyFiles.Engine.SearchOptions Options { get; init; }
Property Value
SearchRequest.Query Property
Raw user query text (before any focused-mode rewrite).
public string Query { get; init; }
Property Value
FindMyFiles
FindMyFiles.ViewModels
ServiceManagerViewModel Class
Supports all classes in the .NET Framework class hierarchy and provides low-level services to derived classes. This is the ultimate base class of all classes in the .NET Framework; it is the root of the type hierarchy.
public sealed class ServiceManagerViewModel : CommunityToolkit.Mvvm.ComponentModel.ObservableObject
Inheritance System.Object → CommunityToolkit.Mvvm.ComponentModel.ObservableObject → ServiceManagerViewModel
Constructors
ServiceManagerViewModel(ServiceProvisioner) Constructor
Locates fmf-service.exe once (bundle or dev tree); the
dialog should call Refresh() on open to fill the state line.
public ServiceManagerViewModel(FindMyFiles.Services.ServiceProvisioner? provisioner=null);
Parameters
provisioner ServiceProvisioner
The post-register wait+relaunch steps; defaults to Real (tests inject a fake).
Properties
ServiceManagerViewModel.HasResult Property
Whether the result InfoBar has anything to show (FindMyFiles.ViewModels.ServiceManagerViewModel.ResultText non-empty).
public bool HasResult { get; }
Property Value
ServiceManagerViewModel.NotBusy Property
Buttons stay enabled only while idle — an in-flight UAC action greys the whole row (visibility is still driven by the Is*/Can* flags).
public bool NotBusy { get; }
Property Value
Methods
ServiceManagerViewModel.Refresh() Method
Re-read the SCM state and recompute which actions apply. Cheap read-only P/Invoke (no elevation) — safe on the UI thread.
public void Refresh();
ServiceManagerViewModel.RegisterAsync() Method
install (idempotent) + restart in one elevated step (the fmf-service `setup` verb). The daily user's SID is forwarded so OTS elevation — a *different* admin account at the UAC prompt — does not lock this user out of the pipe (docs/SECURITY.md threat 1). The app is unelevated here, so CurrentUserSid is exactly that daily user.
public System.Threading.Tasks.Task RegisterAsync();
Returns
System.Threading.Tasks.Task
A task that completes when the elevated setup verb finishes.
ServiceManagerViewModel.RestartApp() Method
Plain (unelevated) relaunch so the fresh instance connects to the now-running service over the pipe.
public void RestartApp();
ServiceManagerViewModel.RestartAsync() Method
Restart the running service (one elevated restart verb).
public System.Threading.Tasks.Task RestartAsync();
Returns
System.Threading.Tasks.Task
A task that completes when the elevated restart verb finishes.
ServiceManagerViewModel.StartAsync() Method
Start the stopped service (one elevated start verb).
public System.Threading.Tasks.Task StartAsync();
Returns
System.Threading.Tasks.Task
A task that completes when the elevated start verb finishes.
ServiceManagerViewModel.StopAsync() Method
Stop the running service (one elevated stop verb).
public System.Threading.Tasks.Task StopAsync();
Returns
System.Threading.Tasks.Task
A task that completes when the elevated stop verb finishes.
ServiceManagerViewModel.UninstallAsync() Method
Uninstall the service (one elevated uninstall verb),
adding --purge-data when FindMyFiles.ViewModels.ServiceManagerViewModel.PurgeData is set.
public System.Threading.Tasks.Task UninstallAsync();
Returns
System.Threading.Tasks.Task
A task that completes when the elevated uninstall verb finishes.
FindMyFiles
FindMyFiles.ViewModels
StatusFormatter Class
All user-facing status wording in one place — keys resolve through Loc (Strings/<lang>/Resources.resw).
public static class StatusFormatter
Inheritance System.Object → StatusFormatter
Methods
StatusFormatter.Count(QueryTraceData, long) Method
Result-count line: the hits count plus the elapsed query time (ms) when a trace is present (TotalUs → ms), the bare count otherwise.
public static string Count(FindMyFiles.Engine.QueryTraceData? trace, long hits);
Parameters
trace QueryTraceData
Latest query trace, or null when timing is unavailable.
hits System.Int64
Number of matching results.
Returns
System.String
Localized count line, with elapsed time when a trace is present.
StatusFormatter.EngineMode(IEngineClient) Method
Status-bar transport badge: which engine the app talks to right now (client type + live connection state).
public static string EngineMode(FindMyFiles.Engine.IEngineClient engine);
Parameters
engine IEngineClient
Engine client whose type and connection state to describe.
Returns
System.String
Localized transport badge for the active engine.
StatusFormatter.Overall(IReadOnlyList<VolumeStatus>, IReadOnlyList<string>) Method
Startup/refresh snapshot of the overall index state — reflects whatever the engine reports right now, so an already-Ready volume never shows "indexing…". requested is the list we asked to index, used only for messaging when the engine hasn't surfaced any status yet.
public static string Overall(System.Collections.Generic.IReadOnlyList<FindMyFiles.Engine.VolumeStatus> volumes, System.Collections.Generic.IReadOnlyList<string> requested);
Parameters
volumes System.Collections.Generic.IReadOnlyList<VolumeStatus>
Per-volume status the engine reports right now.
requested System.Collections.Generic.IReadOnlyList<System.String>
Volumes we asked to index, used only for early messaging.
Returns
System.String
Localized overall index-state line.
StatusFormatter.QueryError(string) Method
Status line for a rejected query — the engine's syntax-error message behind a localized prefix.
public static string QueryError(string message);
Parameters
message System.String
Engine syntax-error message for the rejected query.
Returns
System.String
Localized error line with the engine message behind a prefix.
StatusFormatter.Volume(VolumeStatus, string) Method
Status-bar line for a volume state change; falls back to the current text for states that carry no message.
public static string Volume(FindMyFiles.Engine.VolumeStatus s, string current);
Parameters
Volume status that changed.
current System.String
Existing status text, returned for states with no message.
Returns
System.String
Localized line for the new volume state, or current.
FindMyFiles
FindMyFiles.ViewModels Namespace
| Classes | |
|---|---|
| FocusedQueryRewriter | Focused search: a pure query rewrite in the UI layer — the engine is never touched (ADR-0019). Every top-level OR group of the user's query gets the configured noise-path exclusions (!path:"…") and the extension whitelist (one ext:a;b;… term) appended, except where the user already expressed intent: a group mentioning ext:/regex: keeps its own type filter, a group mentioning path: or containing \ keeps its own location. |
| MainViewModel | Provides a mechanism for releasing unmanaged resources. |
| NotificationCenter | The InfoBar notification stack: capped at three, Info entries dissolve after five seconds. Every error path in the app funnels through here via Notifier. UI thread only (the Notifier subscription marshals). |
| PerfPanelViewModel | Supports all classes in the .NET Framework class hierarchy and provides low-level services to derived classes. This is the ultimate base class of all classes in the .NET Framework; it is the root of the type hierarchy. |
| RequeryOriginExtensions | Helpers over RequeryOrigin. |
| ResultRow | Supports all classes in the .NET Framework class hierarchy and provides low-level services to derived classes. This is the ultimate base class of all classes in the .NET Framework; it is the root of the type hierarchy. |
| ResultsPresenter | Supports all classes in the .NET Framework class hierarchy and provides low-level services to derived classes. This is the ultimate base class of all classes in the .NET Framework; it is the root of the type hierarchy. |
| SearchOrchestrator | When and what to search: 50ms debounce on typing (clearing is instant), a generation counter that discards superseded responses, requery triggers (index changes, stale results) and exception classification. Results are handed to the ResultsPresenter; failures surface through SearchFailed so the ViewModel owns the user-facing wording. All entry points run on the UI thread. |
| ServiceManagerViewModel | Supports all classes in the .NET Framework class hierarchy and provides low-level services to derived classes. This is the ultimate base class of all classes in the .NET Framework; it is the root of the type hierarchy. |
| StatusFormatter | All user-facing status wording in one place — keys resolve through Loc (Strings/<lang>/Resources.resw). |
| Structs | |
|---|---|
| ResultsPublication | Describes one published result set so the view can place the viewport: reset origins scroll to the top, position-preserving origins scroll to RestoreIndex. The seeded index window is where a previously selected row may be re-found. |
| SearchRequest | Snapshot of what to search — the ViewModel stays the single source of truth for the UI state; the orchestrator only pulls it. |
| Enums | |
|---|---|
| RequeryOrigin | Why a requery ran. Reset origins land the user at the top of the list; position-preserving origins restore the previous viewport (docs/ARCHITECTURE.md "two requery families"). |
FindMyFiles
FindMyFiles.Views
PerfPanel Class
The F12 performance panel: stage bar (proportional theme-brush segments), latency sparkline, volume/USN/error text blocks and the one-click diagnostics dump. Rendered imperatively from PerfDataChanged — it is diagnostic chrome, not app data. The host supplies ViewModel via x:Bind; the 1 Hz stats poll runs only while the panel is open. UI thread only.
public sealed class PerfPanel : Microsoft.UI.Xaml.Controls.UserControl, Microsoft.UI.Xaml.Markup.IComponentConnector
Inheritance System.Object → Microsoft.UI.Xaml.DependencyObject → Microsoft.UI.Xaml.UIElement → Microsoft.UI.Xaml.FrameworkElement → Microsoft.UI.Xaml.Controls.Control → Microsoft.UI.Xaml.Controls.UserControl → PerfPanel
Implements Microsoft.UI.Xaml.Markup.IComponentConnector
Constructors
PerfPanel() Constructor
Builds the 1 Hz stats poll timer (runs only while `ViewModel.IsOpen` is true). The timer is not started here; it is started/stopped on open/close.
public PerfPanel();
Fields
PerfPanel.ViewModelProperty Field
Backing DependencyProperty for ViewModel.
On value swap, re-routes `PerfDataChanged`/`PropertyChanged` subscriptions from old to new.
public static readonly DependencyProperty ViewModelProperty;
Field Value
Microsoft.UI.Xaml.DependencyProperty
Properties
PerfPanel.ViewModel Property
Diagnostic ViewModel supplied by the host via `x:Bind`. Source of trace/stats update notifications; drives the 1 Hz stats poll only while the panel is open.
public FindMyFiles.ViewModels.PerfPanelViewModel? ViewModel { get; set; }
Property Value
Methods
PerfPanel.Connect(int, object) Method
Connect()
public void Connect(int connectionId, object target);
Parameters
connectionId System.Int32
target System.Object
Implements Connect(int, object)
PerfPanel.GetBindingConnector(int, object) Method
GetBindingConnector(int connectionId, object target)
public Microsoft.UI.Xaml.Markup.IComponentConnector GetBindingConnector(int connectionId, object target);
Parameters
connectionId System.Int32
target System.Object
Implements GetBindingConnector(int, object)
Returns
Microsoft.UI.Xaml.Markup.IComponentConnector
PerfPanel.InitializeComponent() Method
InitializeComponent()
public void InitializeComponent();
FindMyFiles
FindMyFiles.Views
ScopeManagerDialog Class
Wiring only: the scope-folder dialog (ADR-0024). Two contexts share it — the setup screen's "no admin?" link (first-run onboarding, folders only) and the gear menu's "Change search folders…" (re-selection, folders + excludes). State and the persist/relaunch live on the shared MainViewModel; the buttons drive its actions through the sanctioned Forget(this Task, string) funnel (CLAUDE.md convention). The mirror of ServiceManagerDialog for the non-elevated path.
public sealed class ScopeManagerDialog : Microsoft.UI.Xaml.Controls.ContentDialog, Microsoft.UI.Xaml.Markup.IComponentConnector
Inheritance System.Object → Microsoft.UI.Xaml.DependencyObject → Microsoft.UI.Xaml.UIElement → Microsoft.UI.Xaml.FrameworkElement → Microsoft.UI.Xaml.Controls.Control → Microsoft.UI.Xaml.Controls.ContentControl → Microsoft.UI.Xaml.Controls.ContentDialog → ScopeManagerDialog
Implements Microsoft.UI.Xaml.Markup.IComponentConnector
Properties
ScopeManagerDialog.ShowExcludes Property
Whether the excludes section shows. False in the setup (first-run) context — excludes come later, once indexing has started, via the gear's "change search folders"; true for re-selection.
public bool ShowExcludes { get; }
Property Value
ScopeManagerDialog.VM Property
The page's ViewModel, shared so the dialog edits the same ScopeFolders the setup screen seeds.
public FindMyFiles.ViewModels.MainViewModel VM { get; }
Property Value
Methods
ScopeManagerDialog.Connect(int, object) Method
Connect()
public void Connect(int connectionId, object target);
Parameters
connectionId System.Int32
target System.Object
Implements Connect(int, object)
ScopeManagerDialog.GetBindingConnector(int, object) Method
GetBindingConnector(int connectionId, object target)
public Microsoft.UI.Xaml.Markup.IComponentConnector GetBindingConnector(int connectionId, object target);
Parameters
connectionId System.Int32
target System.Object
Implements GetBindingConnector(int, object)
Returns
Microsoft.UI.Xaml.Markup.IComponentConnector
ScopeManagerDialog.InitializeComponent() Method
InitializeComponent()
public void InitializeComponent();
ScopeManagerDialog.OpenAsync(MainViewModel, bool) Method
The single entry point (setup link / gear menu). Resolves a XamlRoot from the main window and guards against a second instance (ContentDialog allows only one open at a time). Named OpenAsync, not ShowAsync, to avoid hiding the inherited Microsoft.UI.Xaml.Controls.ContentDialog.ShowAsync.
public static System.Threading.Tasks.Task OpenAsync(FindMyFiles.ViewModels.MainViewModel vm, bool setup=false);
Parameters
The page ViewModel to edit.
setup System.Boolean
True for the first-run setup context (folders only, onboarding wording); false for re-selection (folders + excludes).
Returns
System.Threading.Tasks.Task
A System.Threading.Tasks.Task that completes when the dialog closes.
FindMyFiles
FindMyFiles.Views
ServiceManagerDialog Class
Wiring only: the gear menu's "Manage service…" dialog. State and the elevated mutations live in ServiceManagerViewModel; the buttons fire-and-forget its async actions through the sanctioned Forget(this Task, string) funnel (CLAUDE.md convention).
public sealed class ServiceManagerDialog : Microsoft.UI.Xaml.Controls.ContentDialog, Microsoft.UI.Xaml.Markup.IComponentConnector
Inheritance System.Object → Microsoft.UI.Xaml.DependencyObject → Microsoft.UI.Xaml.UIElement → Microsoft.UI.Xaml.FrameworkElement → Microsoft.UI.Xaml.Controls.Control → Microsoft.UI.Xaml.Controls.ContentControl → Microsoft.UI.Xaml.Controls.ContentDialog → ServiceManagerDialog
Implements Microsoft.UI.Xaml.Markup.IComponentConnector
Constructors
ServiceManagerDialog() Constructor
Creates the ViewModel and runs the initial state `Refresh`. The only public entry point is OpenAsync(); direct constructor calls are not expected.
public ServiceManagerDialog();
Properties
ServiceManagerDialog.VM Property
ViewModel for service state and elevation-requiring operations (register/uninstall/start/stop/restart). Each button fires this instance's async actions via `Forget`.
public FindMyFiles.ViewModels.ServiceManagerViewModel VM { get; }
Property Value
Methods
ServiceManagerDialog.Connect(int, object) Method
Connect()
public void Connect(int connectionId, object target);
Parameters
connectionId System.Int32
target System.Object
Implements Connect(int, object)
ServiceManagerDialog.GetBindingConnector(int, object) Method
GetBindingConnector(int connectionId, object target)
public Microsoft.UI.Xaml.Markup.IComponentConnector GetBindingConnector(int connectionId, object target);
Parameters
connectionId System.Int32
target System.Object
Implements GetBindingConnector(int, object)
Returns
Microsoft.UI.Xaml.Markup.IComponentConnector
ServiceManagerDialog.InitializeComponent() Method
InitializeComponent()
public void InitializeComponent();
ServiceManagerDialog.OpenAsync() Method
The single entry point that opens the manager (the gear menu). Resolves a XamlRoot from the main window and guards against a second instance (ContentDialog allows only one open at a time). Named OpenAsync, not ShowAsync, to avoid hiding the inherited Microsoft.UI.Xaml.Controls.ContentDialog.ShowAsync.
public static System.Threading.Tasks.Task OpenAsync();
Returns
System.Threading.Tasks.Task
A System.Threading.Tasks.Task that completes when the dialog closes.
FindMyFiles
FindMyFiles.Views Namespace
| Classes | |
|---|---|
| PerfPanel | The F12 performance panel: stage bar (proportional theme-brush segments), latency sparkline, volume/USN/error text blocks and the one-click diagnostics dump. Rendered imperatively from PerfDataChanged — it is diagnostic chrome, not app data. The host supplies ViewModel via x:Bind; the 1 Hz stats poll runs only while the panel is open. UI thread only. |
| ScopeManagerDialog | Wiring only: the scope-folder dialog (ADR-0024). Two contexts share it — the setup screen's "no admin?" link (first-run onboarding, folders only) and the gear menu's "Change search folders…" (re-selection, folders + excludes). State and the persist/relaunch live on the shared MainViewModel; the buttons drive its actions through the sanctioned Forget(this Task, string) funnel (CLAUDE.md convention). The mirror of ServiceManagerDialog for the non-elevated path. |
| ServiceManagerDialog | Wiring only: the gear menu's "Manage service…" dialog. State and the elevated mutations live in ServiceManagerViewModel; the buttons fire-and-forget its async actions through the sanctioned Forget(this Task, string) funnel (CLAUDE.md convention). |
FindMyFiles
FindMyFiles.Virtualization
PageSeed Struct
A page of already-fetched rows handed to Reassign(ISearchResult, IReadOnlyList<PageSeed>, IHighlighter), so the viewport is filled the instant a new result is published — never a placeholder flash.
public readonly record struct PageSeed : System.IEquatable<FindMyFiles.Virtualization.PageSeed>
Implements System.IEquatable<PageSeed>
Constructors
PageSeed(long, IReadOnlyList<RowData>) Constructor
A page of already-fetched rows handed to Reassign(ISearchResult, IReadOnlyList<PageSeed>, IHighlighter), so the viewport is filled the instant a new result is published — never a placeholder flash.
public PageSeed(long Page, System.Collections.Generic.IReadOnlyList<FindMyFiles.Engine.RowData> Rows);
Parameters
Page System.Int64
Page index (row index ÷ FindMyFiles.Virtualization.VirtualResultList.PageSize) these rows belong to.
Rows System.Collections.Generic.IReadOnlyList<RowData>
The page's rows in slot order, as fetched from the engine.
Properties
PageSeed.Page Property
Page index (row index ÷ FindMyFiles.Virtualization.VirtualResultList.PageSize) these rows belong to.
public long Page { get; init; }
Property Value
PageSeed.Rows Property
The page's rows in slot order, as fetched from the engine.
public System.Collections.Generic.IReadOnlyList<FindMyFiles.Engine.RowData> Rows { get; init; }
Property Value
System.Collections.Generic.IReadOnlyList<RowData>
FindMyFiles
FindMyFiles.Virtualization
VirtualResultList Class
Random-access data virtualization for ListView: non-generic IList + INotifyCollectionChanged + IItemsRangeInfo (the only combination that works — microsoft-ui-xaml#1809, ADR-0015). The indexer hands out stable placeholder instances and never fetches; RangesChanged drives 64-row page fetches on a background task, and arriving data fills those same instances in place.
The instance lives as long as the page: new query results arrive through Reassign(ISearchResult, IReadOnlyList<PageSeed>, IHighlighter) (seeded pages + one Reset), never by swapping the ItemsSource (ADR-0015). An epoch counter makes fetches started against a previous result fall on the floor.
Membership invariant — the WinRT IList adapter trusts these answers blindly: **never vouch for membership falsely.** A false "absent" merely re-realizes a container; a false "present" sends the ListView to GetAt(staleIndex) and dies deep inside XAML (ADR-0015). A row is a member iff its index is inside Count AND the current page cache holds that exact instance in that slot; rows from previous results, evicted pages or transient enumeration answer absent. Mutating entry points enforce the UI thread (always, not just in Debug).
public sealed class VirtualResultList : System.Collections.IList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.Specialized.INotifyCollectionChanged, Microsoft.UI.Xaml.Data.IItemsRangeInfo, System.IDisposable
Inheritance System.Object → VirtualResultList
Implements System.Collections.IList, System.Collections.ICollection, System.Collections.IEnumerable, System.Collections.Specialized.INotifyCollectionChanged, Microsoft.UI.Xaml.Data.IItemsRangeInfo, System.IDisposable
Constructors
VirtualResultList(IDispatcher) Constructor
Bind the list to dispatcher, the UI-thread gate every mutation is checked against (FindMyFiles.Virtualization.VirtualResultList.EnsureUiThread(System.String)) and the queue background fetch completions marshal back through.
public VirtualResultList(FindMyFiles.Services.IDispatcher dispatcher);
Parameters
dispatcher IDispatcher
The UI-thread dispatcher mutations are gated on and fetch completions are marshaled back through.
Properties
VirtualResultList.Count Property
Row count of the published result, clamped to System.Int32.MaxValue — the fixed size the ListView virtualizes against. Out-of-range indexers throw rather than fetch.
public int Count { get; }
Implements Count
Property Value
VirtualResultList.IsFixedSize Property
Gets a value indicating whether the System.Collections.IList has a fixed size.
public bool IsFixedSize { get; }
Implements IsFixedSize
Property Value
VirtualResultList.IsReadOnly Property
Gets a value indicating whether the System.Collections.IList is read-only.
public bool IsReadOnly { get; }
Implements IsReadOnly
Property Value
VirtualResultList.IsSynchronized Property
Gets a value indicating whether access to the System.Collections.ICollection is synchronized (thread safe).
public bool IsSynchronized { get; }
Implements IsSynchronized
Property Value
VirtualResultList.LastVisibleRange Property
Visible (first, last) indexes from the most recent RangesChanged — what position-preserving requeries prefetch before publishing.
public System.Nullable<(int First,int Last)> LastVisibleRange { get; }
Property Value
System.Nullable<<System.Int32,System.Int32>>
VirtualResultList.SyncRoot Property
Gets an object that can be used to synchronize access to the System.Collections.ICollection.
public object SyncRoot { get; }
Implements SyncRoot
Property Value
VirtualResultList.this[int] Property
Hands out the stable ResultRow instance for index (creating the placeholder page on demand) — it never fetches, so realization stays cheap; arriving data fills these same instances in place. The setter is unsupported (read-only list).
public object? this[int index] { get; set; }
Parameters
index System.Int32
Zero-based row index; must be inside Count or it throws (an out-of-range slot is never fabricated into the LRU — ADR-0015).
Implements this[int]
Property Value
Exceptions
System.ArgumentOutOfRangeException
index
is negative or ≥ Count.
System.NotSupportedException
On set.
Methods
VirtualResultList.Add(object) Method
Adds an item to the System.Collections.IList.
public int Add(object? value);
Parameters
value System.Object
The object to add to the System.Collections.IList.
Implements Add(object)
Returns
System.Int32
The position into which the new element was inserted, or -1 to indicate that the item was not inserted into the collection.
Exceptions
System.NotSupportedException
The System.Collections.IList is read-only.
-or-
The System.Collections.IList has a fixed size.
VirtualResultList.Clear() Method
Removes all items from the System.Collections.IList.
public void Clear();
Implements Clear()
Exceptions
System.NotSupportedException
The System.Collections.IList is read-only.
VirtualResultList.Contains(object) Method
True only for a row whose slot still holds that exact instance. After a Reset the ListView re-locates its selected/focused item through Contains/IndexOf; vouching for a row of a previous result would send XAML to GetAt(staleIndex) and crash (ADR-0015), so membership is never faked.
public bool Contains(object? value);
Parameters
value System.Object
The candidate item to test for membership.
Implements Contains(object)
Returns
System.Boolean
True only when the current cache holds that exact instance in its slot.
VirtualResultList.CopyTo(Array, int) Method
Read surface stays landmine-free: copy what is cached, hand out transient placeholders for the rest (never cached — see GetEnumerator()).
public void CopyTo(System.Array array, int index);
Parameters
array System.Array
Destination array the rows are copied into.
index System.Int32
Start offset in array to copy from.
Implements CopyTo(Array, int)
VirtualResultList.Dispose() Method
Tear the list down at page end: cancel in-flight fetches, dispose the
fetch token source, and dispose the owned result. Idempotent in effect —
the _disposed guard makes any late fetch continuation bail before
it touches the now-freed source.
public void Dispose();
Implements Dispose()
VirtualResultList.GetEnumerator() Method
Enumeration must not disturb the virtualization state: walking a million-row result through the cache would evict every realized viewport page (placeholder flash + refetch). Cached slots yield their live instances; everything else yields transient placeholders, which by the membership invariant safely answer "absent".
public System.Collections.IEnumerator GetEnumerator();
Implements GetEnumerator()
Returns
System.Collections.IEnumerator
An enumerator yielding cached instances and transient placeholders.
VirtualResultList.IndexOf(object) Method
Index of value, or -1, under the same membership invariant as Contains(object): a ResultRow matches only when its Index is inside Count AND the current page cache holds that exact instance in that slot. Rows from previous results or evicted pages answer absent.
public int IndexOf(object? value);
Parameters
value System.Object
The candidate item to locate.
Implements IndexOf(object)
Returns
System.Int32
The row's index, or -1 when it is not a current cached member.
VirtualResultList.Insert(int, object) Method
Inserts an item to the System.Collections.IList at the specified index.
public void Insert(int index, object? value);
Parameters
index System.Int32
The zero-based index at which value should be inserted.
value System.Object
The object to insert into the System.Collections.IList.
Implements Insert(int, object)
Exceptions
System.ArgumentOutOfRangeException
index is not a valid index in the System.Collections.IList.
System.NotSupportedException
The System.Collections.IList is read-only.
-or-
The System.Collections.IList has a fixed size.
System.NullReferenceException
value is null reference in the System.Collections.IList.
VirtualResultList.RangesChanged(ItemIndexRange, IReadOnlyList<ItemIndexRange>) Method
ListView callback whenever the realized viewport moves; records the range and kicks page fetches. Delegates to the WinRT-free FindMyFiles.Virtualization.VirtualResultList.NotifyVisibleRange(System.Int32,System.Int32) seam; trackedItems (the pinned/selected items) is unused — only the visible window drives prefetch.
public void RangesChanged(Microsoft.UI.Xaml.Data.ItemIndexRange visibleRange, System.Collections.Generic.IReadOnlyList<Microsoft.UI.Xaml.Data.ItemIndexRange> trackedItems);
Parameters
visibleRange Microsoft.UI.Xaml.Data.ItemIndexRange
First/last realized item indexes.
trackedItems System.Collections.Generic.IReadOnlyList<Microsoft.UI.Xaml.Data.ItemIndexRange>
Items the host asked to keep tracked; ignored.
Implements RangesChanged(ItemIndexRange, IReadOnlyList<ItemIndexRange>)
VirtualResultList.Reassign(ISearchResult, IReadOnlyList<PageSeed>, IHighlighter) Method
Atomically replace the backing result: bump the epoch (in-flight fetches for the old result are cancelled, and their completions drop their data either way), drop the page cache, apply the pre-fetched seeds, then raise one Reset.
Contract: UI thread only (a cross-thread CollectionChanged crashes XAML); seeds must be pages of result within its count; ownership of result transfers to this list (it is disposed by the next Reassign/RefreshInPlace or by Dispose()).
public void Reassign(FindMyFiles.Engine.ISearchResult? result, System.Collections.Generic.IReadOnlyList<FindMyFiles.Virtualization.PageSeed> seeds, FindMyFiles.Highlighting.IHighlighter? highlighter=null);
Parameters
result ISearchResult
The new backing result whose ownership transfers to this list; null clears the list to empty.
seeds System.Collections.Generic.IReadOnlyList<PageSeed>
Pre-fetched pages of result used to fill the viewport before the Reset is raised.
highlighter IHighlighter
Compiled highlighter for the active query; null falls back to Empty.
VirtualResultList.RefreshInPlace(ISearchResult, IReadOnlyList<PageSeed>, IHighlighter) Method
Swap to a result the engine verified to contain the same rows (Unchanged) without raising Reset: realized rows keep their instances and re-fill from the seeds (the MVVM setters only notify on actual value changes, so an idle USN requery repaints nothing). Cached pages are marked unloaded so later scrolling re-fetches from the new handle, and the visible range is re-ensured immediately for pages the seeds missed.
Contract: UI thread only; the engine must have verified result holds the same rows as the published one — same Count required, a mismatch falls back to a full seeded Reassign(ISearchResult, IReadOnlyList<PageSeed>, IHighlighter) (Reset) rather than lying about membership; seeds must be pages of result; ownership of result transfers to this list. In-flight fetches of the previous epoch are cancelled here too.
public void RefreshInPlace(FindMyFiles.Engine.ISearchResult result, System.Collections.Generic.IReadOnlyList<FindMyFiles.Virtualization.PageSeed> seeds, FindMyFiles.Highlighting.IHighlighter? highlighter=null);
Parameters
result ISearchResult
The verified-identical result to swap in; ownership transfers to this list. A Count mismatch falls back to Reassign(ISearchResult, IReadOnlyList<PageSeed>, IHighlighter).
seeds System.Collections.Generic.IReadOnlyList<PageSeed>
Pre-fetched pages of result that re-fill realized rows in place without a Reset.
highlighter IHighlighter
Compiled highlighter for the active query; null falls back to Empty.
VirtualResultList.Remove(object) Method
Removes the first occurrence of a specific object from the System.Collections.IList.
public void Remove(object? value);
Parameters
value System.Object
The object to remove from the System.Collections.IList.
Implements Remove(object)
Exceptions
System.NotSupportedException
The System.Collections.IList is read-only.
-or-
The System.Collections.IList has a fixed size.
VirtualResultList.RemoveAt(int) Method
Removes the System.Collections.IList item at the specified index.
public void RemoveAt(int index);
Parameters
index System.Int32
The zero-based index of the item to remove.
Implements RemoveAt(int)
Exceptions
System.ArgumentOutOfRangeException
index is not a valid index in the System.Collections.IList.
System.NotSupportedException
The System.Collections.IList is read-only.
-or-
The System.Collections.IList has a fixed size.
Events
VirtualResultList.BecameStale Event
Raised on the UI thread when a fetch reported staleness.
public event Action? BecameStale;
Event Type
VirtualResultList.CollectionChanged Event
Raised (Reset) on the UI thread by Reassign(ISearchResult, IReadOnlyList<PageSeed>, IHighlighter).
public event NotifyCollectionChangedEventHandler? CollectionChanged;
Implements CollectionChanged
Event Type
System.Collections.Specialized.NotifyCollectionChangedEventHandler
FindMyFiles
FindMyFiles.Virtualization Namespace
| Classes | |
|---|---|
| VirtualResultList | Random-access data virtualization for ListView: non-generic IList + INotifyCollectionChanged + IItemsRangeInfo (the only combination that works — microsoft-ui-xaml#1809, ADR-0015). The indexer hands out stable placeholder instances and never fetches; RangesChanged drives 64-row page fetches on a background task, and arriving data fills those same instances in place. The instance lives as long as the page: new query results arrive through Reassign(ISearchResult, IReadOnlyList<PageSeed>, IHighlighter) (seeded pages + one Reset), never by swapping the ItemsSource (ADR-0015). An epoch counter makes fetches started against a previous result fall on the floor. Membership invariant — the WinRT IList adapter trusts these answers blindly: **never vouch for membership falsely.** A false "absent" merely re-realizes a container; a false "present" sends the ListView to GetAt(staleIndex) and dies deep inside XAML (ADR-0015). A row is a member iff its index is inside Count AND the current page cache holds that exact instance in that slot; rows from previous results, evicted pages or transient enumeration answer absent. Mutating entry points enforce the UI thread (always, not just in Debug). |
| Structs | |
|---|---|
| PageSeed | A page of already-fetched rows handed to Reassign(ISearchResult, IReadOnlyList<PageSeed>, IHighlighter), so the viewport is filled the instant a new result is published — never a placeholder flash. |
FindMyFiles
FindMyFiles Namespace
| Classes | |
|---|---|
| App | Application entry point and process-wide composition root. `OnLaunched` resolves the engine boundary (EngineClient) and stands up the single MainWindow. On fatal init failure it falls back to `FakeEngineClient` to avoid crashing silently. |
| MainPage | Wiring only: builds the ViewModel graph and connects view events to it. Imperative ListView work (viewport/selection restore, row actions) lives in ResultsViewportManager; the F12 panel chrome in PerfPanel; converters in UiConverters. |
| MainWindow | The application window: hosts the root Frame; app UI lives in MainPage. |
| Program | Program class |