using PuppeteerSharp;
using PuppeteerSharp.BrowserData;
namespace GB5Shared.Export.HybridReport
{
///
/// Resolves a working Chromium executable for PuppeteerSharp, independent of OS, process working
/// directory, or deployment folder. Cache path is derived from the running assembly's own directory
/// (AppContext.BaseDirectory) rather than the process working directory PuppeteerSharp otherwise
/// assumes — this is what produced the stale "D:\...\BusinessHost\Chrome\Win64-...\chrome.exe not
/// found" error at the client site. Moves automatically with the build folder on any OS/machine.
///
public static class ChromiumResolver
{
private static readonly SemaphoreSlim _sem = new(1, 1);
private static string? _cachedExecutablePath;
public static async Task GetExecutablePathAsync()
{
if (_cachedExecutablePath != null && File.Exists(_cachedExecutablePath))
return _cachedExecutablePath;
await _sem.WaitAsync().ConfigureAwait(false);
try
{
if (_cachedExecutablePath != null && File.Exists(_cachedExecutablePath))
return _cachedExecutablePath;
var cachePath = Path.Combine(AppContext.BaseDirectory, "ChromiumCache");
var buildId = Chrome.DefaultBuildId;
var fetcher = new BrowserFetcher(new BrowserFetcherOptions { Path = cachePath });
var executablePath = fetcher.GetExecutablePath(buildId);
// A cache folder can exist with a partial download or an AV-quarantined binary —
// its presence is not proof the exe is runnable, so always verify the file itself
// and re-download if it's missing, rather than trusting the cache blindly.
if (!File.Exists(executablePath))
{
await fetcher.DownloadAsync(buildId).ConfigureAwait(false);
executablePath = fetcher.GetExecutablePath(buildId);
}
if (!File.Exists(executablePath))
{
throw new FileNotFoundException(
$"Chromium executable could not be resolved or downloaded at: {executablePath}. " +
$"Verify outbound network access to the Chromium download host and write permission on '{cachePath}'.");
}
_cachedExecutablePath = executablePath;
return executablePath;
}
finally
{
_sem.Release();
}
}
}
}