WPF
entry point
application development
software engineering
programming

Replacing the WPF entry point

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Replacing the WPF entry point is useful when startup needs custom argument parsing, dependency injection bootstrap, single-instance checks, or early logging before any window is created. The default WPF startup generated by App.xaml is convenient, but manual entry point control gives tighter lifecycle management. The key is to avoid conflicting startup definitions between XAML and code.

Core Sections

Understand default WPF startup behavior

By default, WPF uses App.xaml with StartupUri to create the main window automatically. The compiler generates an entry point behind the scenes.

xml
1<Application x:Class="Demo.App"
2             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4             StartupUri="MainWindow.xaml">
5</Application>

If you add your own Main method, remove StartupUri and take explicit control of window creation.

Define an explicit custom entry point

Set application startup object to your App.Main and implement initialization in code.

csharp
1using System;
2using System.Windows;
3
4namespace Demo
5{
6    public partial class App : Application
7    {
8        [STAThread]
9        public static void Main(string[] args)
10        {
11            var app = new App();
12            app.InitializeComponent();
13
14            // custom startup logic
15            string mode = args.Length > 0 ? args[0] : "normal";
16            var window = new MainWindow { Title = $"Mode: {mode}" };
17
18            app.Run(window);
19        }
20    }
21}

This allows startup argument handling before the window is shown.

Disable conflicting XAML startup settings

When using explicit Main, remove StartupUri from App.xaml. If both XAML and code attempt startup, behavior can be confusing and brittle.

Keep App.xaml minimal for resources only, or move global resources to merged dictionaries if startup logic is fully code-driven.

Integrate dependency injection during startup

A common reason to replace entry point is constructing a service container before creating the first window.

csharp
1var services = new ServiceCollection();
2services.AddSingleton<MainWindow>();
3services.AddSingleton<IClock, SystemClock>();
4
5using var provider = services.BuildServiceProvider();
6var mainWindow = provider.GetRequiredService<MainWindow>();
7app.Run(mainWindow);

This pattern keeps composition root in one location and improves testability.

Add global exception and logging hooks early

Custom entry points let you register exception handlers before UI initialization.

csharp
1AppDomain.CurrentDomain.UnhandledException += (s, e) =>
2{
3    // write structured crash log
4};

Early logging setup is valuable for startup crashes that happen before window event handlers are attached.

Configure project startup object correctly

In project properties, set startup object to your custom entry point if needed. In SDK-style projects, ensure only one valid [STAThread] Main exists.

Ambiguous startup object configuration can cause build-time errors or unexpected runtime paths.

Test startup paths explicitly

If entry point behavior changes based on command-line arguments, test each mode. Include at least one invalid argument test and verify graceful fallback behavior.

Startup path tests are often skipped, but they are important because these code paths are not exercised by regular UI navigation tests.

Keep startup work minimal and asynchronous

Custom entry points are powerful, but they should not perform heavy network calls or long synchronous initialization before window display. Keep critical startup fast, then defer expensive work to background tasks after UI is responsive.

This approach improves perceived performance and reduces false crash reports caused by slow launch behavior.

Profile startup duration in diagnostics so regressions are visible early. Track launch metrics in release notes when startup logic changes.

Common Pitfalls

  • Keeping StartupUri while also defining custom Main method.
  • Forgetting [STAThread] attribute on entry point.
  • Initializing UI components before required dependency setup.
  • Placing heavy blocking work in startup thread and freezing launch.
  • Skipping validation of alternate startup argument paths.

Summary

  • Replace WPF entry point when you need explicit startup control.
  • Remove conflicting XAML startup configuration when using custom Main.
  • Initialize dependency container and logging before window creation.
  • Keep startup object configuration unambiguous in project settings.
  • Test startup modes and failure paths as first-class application behavior.

Course illustration
Course illustration