using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; using System.Globalization; using System.Threading; using System.Runtime.InteropServices; using System.Reflection; using Microsoft.VisualBasic.ApplicationServices; using Toolbox.Library; namespace Toolbox { static class Program { /// /// The main entry point for the application. /// [STAThread] static void Main() { AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve; Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Toolbox.Library.Runtime.ExecutableDir = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetEntryAssembly().Location); string[] args = Environment.GetCommandLineArgs(); List Files = new List(); foreach (var arg in args) { if (arg != Application.ExecutablePath) Files.Add(arg); } try { Config.StartupFromFile(Runtime.ExecutableDir + "\\config.xml"); Config.GamePathsFromFile(Runtime.ExecutableDir + "\\config_paths.xml"); } catch (Exception ex) { MessageBox.Show($"Failed to load config file! {ex}"); } var domain = AppDomain.CurrentDomain; domain.AssemblyResolve += LoadAssembly; bool LoadedDX = TryLoadDirectXTex(); if (!LoadedDX && !Toolbox.Library.Runtime.UseDirectXTexDecoder) { var result = MessageBox.Show("Direct X Tex Failed to load! Make sure to install Visual C++ and Direct X Tex. Do you want to go to the install sites?", "", MessageBoxButtons.YesNo); if (result == DialogResult.Yes) { System.Diagnostics.Process.Start("https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads"); System.Diagnostics.Process.Start("https://www.microsoft.com/en-us/download/details.aspx?id=35"); } } MainForm.LoadConfig(); if (Toolbox.Library.Runtime.UseSingleInstance) { SingleInstanceController controller = new SingleInstanceController(); controller.Run(args); } else { MainForm form = new MainForm(); form.OpenedFiles = Files; Application.Run(form); } } [ComVisible(true), ComImport, Guid("000214eb-0000-0000-c000-000000000046"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] public interface IExtractIcon { [PreserveSig] uint GetIconLocation(int uFlags, IntPtr szIconFile, int cchMax, IntPtr piIndex, UIntPtr pwFlags); [PreserveSig] uint Extract(string pszFile, uint nIconIndex, ref IntPtr phiconLarge, ref IntPtr phiconSmall, uint nIconSize); } public class SingleInstanceController : WindowsFormsApplicationBase { public SingleInstanceController() { IsSingleInstance = true; Startup += OnStart; StartupNextInstance += Program_StartupNextInstance; } private void OnStart(object sender, StartupEventArgs e) { List args = new List(); foreach (string arg in e.CommandLine) args.Add(arg); args.RemoveAt(0); Toolbox.MainForm.Instance.OpenedFiles = args; } void Program_StartupNextInstance(object sender, StartupNextInstanceEventArgs e) { e.BringToForeground = true; MainForm form = MainForm as MainForm; form.OpenedFiles = e.CommandLine.ToList(); form.OpenFiles(); } protected override void OnCreateMainForm() { MainForm = Toolbox.MainForm.Instance; } } private static bool TryLoadZSTD() { try { String folder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); String filePath = Path.Combine(folder, Environment.Is64BitProcess ? "x64" : "x86", "libzstd.dll"); if (File.Exists(filePath)) { Assembly assembly = Assembly.LoadFile(filePath); return true; } } catch (Exception ex) { } return false; } private static bool TryLoadDirectXTex() { try { String folder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); String filePath = Path.Combine(folder, Environment.Is64BitProcess ? "x64" : "x86", "DirectXTexNetImpl.dll"); String filePathLib = Path.Combine(folder, "Lib", Environment.Is64BitProcess ? "x64" : "x86", "DirectXTexNetImpl.dll"); if (File.Exists(filePath)) { Assembly assembly = Assembly.LoadFile(filePath); return true; } if (File.Exists(filePathLib)) { Assembly assembly = Assembly.LoadFile(filePathLib); return true; } } catch (Exception ex) { MessageBox.Show(ex.ToString()); } return false; } /// /// Include externals dlls /// private static Assembly LoadAssembly(object sender, ResolveEventArgs args) { Assembly result = null; if (args != null && !string.IsNullOrEmpty(args.Name)) { //Get current exe fullpath FileInfo info = new FileInfo(Assembly.GetExecutingAssembly().Location); //Get folder of the executing .exe var folderPath = Path.Combine(info.Directory.FullName, "Lib"); //Build potential fullpath to the loading assembly var assemblyName = args.Name.Split(new string[] { "," }, StringSplitOptions.None)[0]; var assemblyExtension = "dll"; var assemblyPath = Path.Combine(folderPath, string.Format("{0}.{1}", assemblyName, assemblyExtension)); //Check if the assembly exists in our "Libs" directory if (File.Exists(assemblyPath)) { Console.WriteLine("Loading .dll " + assemblyPath); //Load the required assembly using our custom path result = Assembly.LoadFrom(assemblyPath); } else { //Keep default loading return args.RequestingAssembly; } } return result; } // Custom assembly resolver to find the architecture-specific implementation assembly. private static Assembly AssemblyResolve(object sender, ResolveEventArgs args) { if (args.Name.StartsWith("DirectXTexNetImpl", StringComparison.OrdinalIgnoreCase)) { var assembly = Assembly.GetExecutingAssembly(); var path = GetAssemblyPath(Path.GetDirectoryName(assembly.Location)); if (!File.Exists(path)) { // If we can't find the file, try using the CodeBase instead (which can // be different if using shadow copy). // CodeBase is a uri, so must parse out the filename. path = GetAssemblyPath(Path.GetDirectoryName(new Uri(assembly.CodeBase).AbsolutePath)); } return Assembly.LoadFile(path); } return null; } private static string GetAssemblyPath(string dir) => Path.Combine(dir,"Lib", ArchitectureMoniker, "DirectXTexNetImpl.dll"); // Note: currently no support for ARM. // Don't use %PROCESSOR_ARCHITECTURE% as it calls x64 'AMD64'. private static string ArchitectureMoniker => Environment.Is64BitProcess ? "x64" : "x86"; } }