Justin Helgerson Justin Helgerson - 3 months ago 28
C# Question

How do I launch the web browser after starting my ASP.NET Core application?

I have a ASP.NET Core application that will be used as a client by multiple users. In other words, it will not be hosted on a central server and they will run the published executable anytime they need to use the application.

In the

Program.cs
file there's the following:

var host = new WebHostBuilder()
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();

host.Run();


I would like the default web browser to automatically open to avoid a redundant step of the user having to open the browser and manually put in the
http://localhost:5000
address.

What would be the best way to achieve this? Calling
Program.Start
after the call to
Run()
won't work because
Run
blocks the thread.

Answer

You have two different problems here:

Thread Blocking

host.Run() indeed blocks the main thread. Starting the browser just before host.Run() may not always work if your app is too slow to initialize. Adding a delay in the middle improves your chances.

This code spawns a new thread, and from there you can delay first and then launch the web browser.

new Thread(new ThreadStart( MyMethodName ) ).Start();
host.Run();

Or you could use a System.Threading.Task to fire and forget an async task consisting of a Delay and then ContinueWith your code

Task.Delay(1000).ContinueWith(t => System.Diagnostics.Process.Start( "blah" ) ).Start();
host.Run();

How to start the web browser

If you are using ASP.NET Core over .NET Framework 4.x, Microsoft says you can just use:

Process.Start("http://localhost:5000");

But if you are targeting multiplatform .NET Core, the above line will fail. There is no single solution using .NET Standard that works on every platform. The Windows-only solution is:

System.Diagnostics.Process.Start("cmd", "/C start http://google.com");

Edit: I created a ticket and a MS dev answered that as-of-today, if you want a multi platform version you should do it manually, like:

public static void OpenBrowser(string url)
{
    if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
    {
        Process.Start(new ProcessStartInfo("cmd", $"/c start {url}")); // Works ok on windows
    }
    else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
    {
        Process.Start("xdg-open", url);  // Works ok on linux
    }
    else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
    {
        Process.Start("open", url); // Not tested
    }
    else
    {
        ...
    }
}

All together now:

using System.Threading;

public class Program
{
    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();

        new Thread(new ThreadStart(ControlThread)).Start();

        host.Run();
    }

    static void ControlThread()
    {
        Thread.Sleep(1000);

        try
        {
            OpenBrowser("http://localhost:5000/");
        }
        catch
        { /* Handle Exception */ }
    }


    public static void OpenBrowser(string url)
    {
        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
        {
            Process.Start(new ProcessStartInfo("cmd", $"/c start {url}"));
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
        {
            Process.Start("xdg-open", url);
        }
        else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
        {
            Process.Start("open", url);
        }
        else
        {
            // throw 
        }
    }
}
Comments