DiskPart UI — Developer Documentation

This document describes how the app is put together, subsystem by subsystem. For the user-facing overview see README.md.

Contents

Overview

DiskPart UI is a single-window .NET MAUI desktop app that targets Windows only (net10.0-windows10.0.19041.0) and runs unpackaged (WindowsPackageType=None). It is a thin, transparent front-end over the diskpart command-line tool.

Architecture is textbook MVVM:

   BlazorWebView (WebView2)
     Main.razor  ──@inject──►  MainViewModel  ──►  DiskPartService ──► diskpart.exe
     (Razor UI)                (state + commands)    │  (CliWrap)
        ▲  ▲                                         ├─► DiskPartParser  (text → models)
        │  └─ PropertyChanged / CollectionChanged    ├─► IDialogService  (native MAUI dialogs)
        │     → StateHasChanged                       └─► IFileDialogService (WinRT open/save)
        └─ js/splitter.js  (drag-to-resize + localStorage)

The UI is .NET MAUI Blazor Hybrid: a native MAUI ContentPage (MainPage) hosts a BlazorWebView, which renders the Main Razor component in an embedded WebView2. The app is still a native Windows process, so diskpart execution, elevation, and the WinRT file pickers all work exactly as in a XAML MAUI app.

Design principles:

Dependencies: CliWrap (process execution), CommunityToolkit.Mvvm (ObservableObject, [ObservableProperty], [RelayCommand]), and Microsoft.AspNetCore.Components.WebView.Maui (the BlazorWebView). No other third-party packages.

Runtime & bootstrap

diskpart execution layer

Services/DiskPartService.cs is the only code that launches a process.

Output parsing

Services/DiskPartParser.cs converts diskpart's fixed-width text tables into typed models. diskpart prints tables like:

  Disk ###  Status         Size     Free     Dyn  Gpt
  --------  -------------  -------  -------  ---  ---
  Disk 0    Online          931 GB      0 B        *

The algorithm (ParseTable):

  1. Find the separator row — the first line made only of dashes and spaces (and containing at least --).
  2. Use the runs of dashes to record each column's start position.
  3. Slice every following data row at those positions until the next blank line; each field is trimmed. The last column extends to end-of-line.

ParseDisks / ParseVolumes / ParsePartitions map the sliced fields to DiskInfo, VolumeInfo, PartitionInfo by column index and skip rows without a numeric id. This position-based slicing is resilient to the differing column widths seen across Windows versions, and tolerates empty cells (a volume with no drive letter, No Media, 0 B, etc.).

Domain models

Plain immutable objects in Models/ (init-only properties):

The view-model

ViewModels/MainViewModel.cs (a partial ObservableObject) holds all state and commands.

Dialogs & file pickers

The view (Blazor UI)

Components/Main.razor is the whole UI — a two-column flex layout with a modal overlay for the popup. It renders the injected MainViewModel and forwards clicks to its commands:

Commands are invoked via the generated IAsyncRelayCommand / IRelayCommand properties (Vm.AppendCleanCommand.ExecuteAsync(null), Vm.ShowDiskActionsCommand.Execute(disk), …). Because the component subscribes to the view-model's change events, any state the commands mutate re-renders automatically. Confirm/prompt dialogs still surface as native MAUI page dialogs (via IDialogService), shown over the WebView.

Resizing & persistence are handled in the browser, not C#:

Elevation & the manifest

diskpart requires elevation, so Platforms/Windows/app.manifest requests requireAdministrator. Running unpackaged is what lets that Win32 manifest take effect, so the app self-elevates (one UAC prompt) at launch. ElevationHelper.IsElevated() reports the current state for the header badge and the "not elevated" warnings.

Testing

Unit tests live in tests/ as a separate xUnit project (DiskPartUI.Tests). Rather than reference the Windows MAUI app (which would drag in the WinUI/RID/packaging model), the test project targets plain net10.0 and compiles the files under test directly via linked <Compile Include="..\…" /> items — they are pure logic with no MAUI dependencies, so the suite is fast and portable. The app project excludes tests/** from its own compile so the two never collide.

Covered:

dotnet test

The side-effecting layers — process launch, dialogs, file pickers, elevation, and the UI — are integration concerns and are verified by running the app.

Build & run

dotnet build -c Debug
dotnet run -c Debug -f net10.0-windows10.0.19041.0

The project multi-targets nothing else — it is Windows-only because diskpart is. See README.md for the Visual Studio path and the admin-debugging note.

Packaging the release

Release builds are published self-contained so the download needs no .NET or Windows App SDK runtime installed:

dotnet publish DiskPartUI.csproj -c Release -f net10.0-windows10.0.19041.0 -r win-x64 --self-contained true -p:WindowsAppSDKSelfContained=true

The installer is an Inno Setup script, installer/DiskPartUI.iss, which packs that publish folder into bin\DiskPartUI-v<version>-setup.exe:

"C:\Program Files (x86)\Inno Setup 6\ISCC.exe" installer\DiskPartUI.iss

(winget install JRSoftware.InnoSetup puts ISCC.exe under %LOCALAPPDATA%\Programs\Inno Setup 6\ instead — adjust the path to match your install.)

MSIX is deliberately not used: a packaged app cannot request requireAdministrator, which diskpart needs. The installer therefore sets PrivilegesRequired=admin and installs per-machine into Program Files.

installer/Test-Installer.ps1 smoke-tests the result end to end. It silently installs; asserts the app files, the self-contained runtime, the Start Menu shortcut, the uninstaller and the Programs-and-Features entry all exist; launches the installed app and checks that it stays running, that WebView2 wrote its data under LocalAppData, and that nothing was written beside the executable; then silently uninstalls and confirms the cleanup.

That launch step matters: v1.0.0 shipped an installer whose app could not start at all, because the original test only exercised install and uninstall. Installing without running proves very little. The script needs an elevated shell:

powershell -ExecutionPolicy Bypass -File installer\Test-Installer.ps1