using System; using System.Diagnostics; using System.IO; using System.Net; using System.Reflection; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Windows.Forms; namespace WelsonJS.Launcher { public class ResourceServer { private readonly HttpListener _listener; private CancellationTokenSource _cts; private Task _serverTask; private bool _isRunning; private string _prefix; private string _resourceName; public ResourceServer(string prefix, string resourceName) { _prefix = prefix; _listener = new HttpListener(); _listener.Prefixes.Add(prefix); _resourceName = typeof(ResourceServer).Namespace + "." + resourceName; } public void Start() { if (_isRunning) return; _isRunning = true; _cts = new CancellationTokenSource(); _listener.Start(); // Open the web browser Process.Start(_prefix); // Run a task with cancellation token _serverTask = Task.Run(() => ListenLoop(_cts.Token)); } public void Stop() { _isRunning = false; _cts.Cancel(); _listener.Stop(); MessageBox.Show("Server stopped."); } public bool IsRunning() { return _isRunning; } private async Task ListenLoop(CancellationToken token) { while (!token.IsCancellationRequested && _isRunning) { try { ProcessRequest(await _listener.GetContextAsync()); } catch (Exception ex) { if (token.IsCancellationRequested || !_isRunning) break; MessageBox.Show($"Error: {ex.Message}"); } } } private void ProcessRequest(HttpListenerContext context) { string responseString = GetEmbeddedResource(); byte[] buffer = Encoding.UTF8.GetBytes(responseString); context.Response.ContentType = "text/html"; context.Response.ContentLength64 = buffer.Length; context.Response.OutputStream.Write(buffer, 0, buffer.Length); context.Response.OutputStream.Close(); } private string GetEmbeddedResource() { var assembly = Assembly.GetExecutingAssembly(); using (Stream stream = assembly.GetManifestResourceStream(_resourceName)) { if (stream == null) { return "