public static void Run <TStartup>(string windowTitle, string hostHtmlPath, bool fullscreen = false, int x = 0, int y = 0, int width = 800, int height = 600)
        {
            DesktopSynchronizationContext.UnhandledException += (sender, exception) =>
            {
                UnhandledException(exception);
            };

            photinoWindow = new PhotinoWindow(windowTitle, options =>
            {
                var contentRootAbsolute = Path.GetDirectoryName(Path.GetFullPath(hostHtmlPath));

                options.SchemeHandlers.Add(BlazorAppScheme, (string url, out string contentType) =>
                {
                    // TODO: Only intercept for the hostname 'app' and passthrough for others
                    // TODO: Prevent directory traversal?
                    var appFile = Path.Combine(contentRootAbsolute, new Uri(url).AbsolutePath.Substring(1));
                    if (appFile == contentRootAbsolute)
                    {
                        appFile = hostHtmlPath;
                    }

                    contentType = GetContentType(appFile);
                    return(File.Exists(appFile) ? File.OpenRead(appFile) : null);
                });

                // framework:// is resolved as embedded resources
                options.SchemeHandlers.Add("framework", (string url, out string contentType) =>
                {
                    contentType = GetContentType(url);
                    return(SupplyFrameworkFile(url));
                });
            }, fullscreen, x, y, width, height);

            CancellationTokenSource appLifetimeCts = new CancellationTokenSource();

            Task.Factory.StartNew(async() =>
            {
                try
                {
                    var ipc = new IPC(photinoWindow);
                    await RunAsync <TStartup>(ipc, appLifetimeCts.Token);
                }
                catch (Exception ex)
                {
                    UnhandledException(ex);
                    throw;
                }
            });

            try
            {
                photinoWindow.NavigateToUrl(BlazorAppScheme + "://app/");
                photinoWindow.WaitForExit();
            }
            finally
            {
                appLifetimeCts.Cancel();
            }
        }