Refactored file download logic to use DNS fallback for 7-zip and WebView2 downloads, fixed crash craused by corrupted user.config preventing startup

Refactored all file download logic to use DNS fallback and applied it to 7-zip and WebView2 runtime downloads. Moved WebView2 runtime download logic to GetDependencies and ensures it is downloaded at startup if missing. Added robust handling for corrupted user.config files in Program.cs, including auto-repair and fallback guidance.
This commit is contained in:
jp64k
2025-12-15 00:07:54 +01:00
parent 75d22ab504
commit 6cbfdbe52c
4 changed files with 135 additions and 55 deletions

View File

@@ -4654,6 +4654,7 @@ CTRL + F4 - Instantly relaunch Rookie Sideloader");
if (webView21.CoreWebView2 != null) return;
// Check if WebView2 runtime DLLs are present
// (downloadFiles() should have already downloaded them, but check anyway)
string runtimesPath = Path.Combine(Environment.CurrentDirectory, "runtimes");
string webView2LoaderArm64 = Path.Combine(runtimesPath, "win-arm64", "native", "WebView2Loader.dll");
string webView2LoaderX86 = Path.Combine(runtimesPath, "win-x86", "native", "WebView2Loader.dll");
@@ -4663,32 +4664,11 @@ CTRL + F4 - Instantly relaunch Rookie Sideloader");
if (!runtimeExists)
{
try
{
changeTitle("Downloading Runtime...");
string archivePath = Path.Combine(Environment.CurrentDirectory, "runtimes.7z");
using (var client = new WebClient())
{
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
await Task.Run(() => client.DownloadFile("https://vrpirates.wiki/downloads/runtimes.7z", archivePath));
}
changeTitle("Extracting Runtime...");
await Task.Run(() => Utilities.Zip.ExtractFile(archivePath, Environment.CurrentDirectory));
File.Delete(archivePath);
}
catch (Exception ex)
{
Logger.Log($"Failed to download WebView2 runtime: {ex.Message}", LogLevel.ERROR);
_ = FlexibleMessageBox.Show(Program.form,
$"Unable to download WebView2 runtime: {ex.Message}\n\nTrailer playback will be disabled.",
"WebView2 Download Failed");
enviromentCreated = true;
webView21.Hide();
return;
}
// Runtime wasn't downloaded during startup - disable trailers
Logger.Log("WebView2 runtime not found, disabling trailer playback", LogLevel.WARNING);
enviromentCreated = true;
webView21.Hide();
return;
}
try
@@ -4713,14 +4693,6 @@ CTRL + F4 - Instantly relaunch Rookie Sideloader");
}
catch (Exception /* ex */)
{
/*
Logger.Log($"Failed to initialize WebView2: {ex.Message}", LogLevel.ERROR);
_ = FlexibleMessageBox.Show(Program.form,
$"WebView2 Runtime is not installed on this system.\n\n" +
"Please download from: https://go.microsoft.com/fwlink/p/?LinkId=2124703\n\n" +
"Trailer playback will be disabled.",
"WebView2 Runtime Required");
*/
enviromentCreated = true;
webView21.Hide();
}

View File

@@ -8,7 +8,7 @@ namespace AndroidSideloader
{
internal static class Program
{
private static readonly SettingsManager settings = SettingsManager.Instance;
private static SettingsManager settings;
/// <summary>
/// The main entry point for the application.
/// </summary>
@@ -16,7 +16,54 @@ namespace AndroidSideloader
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
private static void Main()
{
// Handle corrupted user.config files
bool configFixed = false;
Exception configException = null;
try
{
// Force settings initialization to trigger any config errors early
var test = AndroidSideloader.Properties.Settings.Default.FontStyle;
}
catch (Exception ex)
{
configException = ex;
// Delete the corrupted config file and retry
try
{
string configPath = GetUserConfigPath();
if (!string.IsNullOrEmpty(configPath) && File.Exists(configPath))
{
File.Delete(configPath);
configFixed = true;
}
}
catch
{
// If we can't delete it, try to continue anyway
}
}
if (configFixed)
{
// Restart the application after fixing config
Application.Restart();
return;
}
if (configException != null)
{
MessageBox.Show(
"Settings file is corrupted and could not be repaired automatically.\n\n" +
"Please delete this folder and restart the application:\n" +
Path.GetDirectoryName(GetUserConfigPath()),
"Configuration Error",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
return;
}
settings = SettingsManager.Instance;
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.UnhandledException += new UnhandledExceptionEventHandler(CrashHandler);
Application.EnableVisualStyles();
@@ -25,6 +72,23 @@ namespace AndroidSideloader
Application.Run(form);
//form.Show();
}
private static string GetUserConfigPath()
{
try
{
string appData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string companyName = "Rookie.AndroidSideloader";
string exeName = "AndroidSideloader.exe_Url_dkp0unsd4fjaabhwwafgfxvvbrerf10b";
string version = "2.0.0.0";
return Path.Combine(appData, companyName, exeName, version, "user.config");
}
catch
{
return null;
}
}
public static MainForm form;
private static void CrashHandler(object sender, UnhandledExceptionEventArgs args)
@@ -37,7 +101,7 @@ namespace AndroidSideloader
string date_time = DateTime.Now.ToString("dddd, MMMM dd @ hh:mmtt (UTC)");
File.WriteAllText(Sideloader.CrashLogPath, $"Date/Time of crash: {date_time}\nMessage: {e.Message}\nInner Message: {innerExceptionMessage}\nData: {e.Data}\nSource: {e.Source}\nTargetSite: {e.TargetSite}\nStack Trace: \n{e.StackTrace}\n\n\nDebuglog: \n\n\n");
// If a debuglog exists we append it to the crashlog.
if (File.Exists(settings.CurrentLogPath))
if (settings != null && File.Exists(settings.CurrentLogPath))
{
File.AppendAllText(Sideloader.CrashLogPath, File.ReadAllText($"{settings.CurrentLogPath}"));
}

View File

@@ -61,7 +61,7 @@ namespace AndroidSideloader
}
}
// Download required dependencies.
// Download required dependencies
public static void downloadFiles()
{
// Initialize DNS helper early to detect and configure fallback if needed
@@ -151,30 +151,75 @@ namespace AndroidSideloader
_ = FlexibleMessageBox.Show(Program.form, "Rclone was unable to be downloaded\nRookie will now close, please use Offline Mode for manual sideloading if needed");
Application.Exit();
}
// Download WebView2 runtime if needed
downloadWebView2Runtime();
}
// Downloads a file with DNS fallback support
private static void DownloadFileWithDnsFallback(WebClient client, string url, string localPath)
// Downloads a file using the DNS fallback proxy if active
public static void DownloadFileWithDnsFallback(WebClient client, string url, string localPath)
{
try
{
// Use DNS fallback proxy if active
if (DnsHelper.UseFallbackDns && !string.IsNullOrEmpty(DnsHelper.ProxyUrl))
{
client.Proxy = new WebProxy(DnsHelper.ProxyUrl);
}
client.DownloadFile(url, localPath);
}
catch when (DnsHelper.UseFallbackDns)
catch (Exception ex)
{
// Try with fallback DNS
var uri = new Uri(url);
var ip = DnsHelper.ResolveHostname(uri.Host);
if (ip != null)
_ = Logger.Log($"Download failed for {url}: {ex.Message}", LogLevel.ERROR);
throw;
}
finally
{
// Reset proxy to avoid affecting other operations
client.Proxy = null;
}
}
// Overload that creates its own WebClient for convenience
public static void DownloadFileWithDnsFallback(string url, string localPath)
{
using (var client = new WebClient())
{
ServicePointManager.Expect100Continue = true;
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
DownloadFileWithDnsFallback(client, url, localPath);
}
}
// Downloads WebView2 runtime if not present
private static void downloadWebView2Runtime()
{
string runtimesPath = Path.Combine(Environment.CurrentDirectory, "runtimes");
string webView2LoaderArm64 = Path.Combine(runtimesPath, "win-arm64", "native", "WebView2Loader.dll");
string webView2LoaderX86 = Path.Combine(runtimesPath, "win-x86", "native", "WebView2Loader.dll");
string webView2LoaderX64 = Path.Combine(runtimesPath, "win-x64", "native", "WebView2Loader.dll");
bool runtimeExists = File.Exists(webView2LoaderX86) || File.Exists(webView2LoaderX64) || File.Exists(webView2LoaderArm64);
if (!runtimeExists)
{
try
{
var builder = new UriBuilder(uri) { Host = ip.ToString() };
client.Headers["Host"] = uri.Host;
client.DownloadFile(builder.Uri, localPath);
client.Headers.Remove("Host");
_ = Logger.Log("Missing WebView2 runtime. Attempting to download...");
string archivePath = Path.Combine(Environment.CurrentDirectory, "runtimes.7z");
DownloadFileWithDnsFallback("https://vrpirates.wiki/downloads/runtimes.7z", archivePath);
_ = Logger.Log("Extracting WebView2 runtime...");
Utilities.Zip.ExtractFile(archivePath, Environment.CurrentDirectory);
File.Delete(archivePath);
_ = Logger.Log("WebView2 runtime download successful");
}
else
catch (Exception ex)
{
throw;
_ = Logger.Log($"Failed to download WebView2 runtime: {ex.Message}", LogLevel.ERROR);
// Don't show message box here - let CreateEnvironment handle the UI feedback
}
}
}

View File

@@ -38,12 +38,12 @@ namespace AndroidSideloader.Utilities
if (!File.Exists(Path.Combine(Environment.CurrentDirectory, "7z.exe")) || !File.Exists(Path.Combine(Environment.CurrentDirectory, "7z.dll")))
{
_ = Logger.Log("Begin download 7-zip");
WebClient client = new WebClient();
string architecture = Environment.Is64BitOperatingSystem ? "64" : "";
try
{
client.DownloadFile($"https://github.com/VRPirates/rookie/raw/master/7z{architecture}.exe", $"7z.exe");
client.DownloadFile($"https://github.com/VRPirates/rookie/raw/master/7z{architecture}.dll", $"7z.dll");
// Use DNS fallback download method from GetDependencies
GetDependencies.DownloadFileWithDnsFallback($"https://github.com/VRPirates/rookie/raw/master/7z{architecture}.exe", "7z.exe");
GetDependencies.DownloadFileWithDnsFallback($"https://github.com/VRPirates/rookie/raw/master/7z{architecture}.dll", "7z.dll");
}
catch (Exception ex)
{
@@ -127,7 +127,6 @@ namespace AndroidSideloader.Utilities
extractionError = null; // Reset the error message
throw new ExtractionException(errorMessage);
}
}
}
}