support moving all dlls to the dll directory by adding assembly binding resolve redirection

This commit is contained in:
zeromus 2012-10-29 08:37:22 +00:00
parent 223de0609c
commit e19f39e08c
5 changed files with 83 additions and 41 deletions

View File

@ -1,4 +1,7 @@
using System;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
#if WINDOWS
using SlimDX.Direct3D9;
@ -13,33 +16,19 @@ namespace BizHawk.MultiClient
[STAThread]
unsafe static void Main(string[] args)
{
//string test = BizHawk.Emulation.Consoles.Nintendo.SNES.LibsnesDll.snes_library_revision_minor().ToString();
#if WINDOWS
// this will look in subdirectory "dll" to load pinvoked stuff
SetDllDirectory(System.IO.Path.Combine(PathManager.GetExeDirectoryAbsolute(), "dll"));
//BizHawk.Emulation.Consoles.Nintendo.SNES.LibsnesDll.snes_init();
//in case assembly resolution fails, such as if we moved them into the dll subdiretory, this event handler can reroute to them
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
#endif
//BizHawk.Emulation.Consoles.Nintendo.SNES.LibsnesDll.snes_video_refresh_t myvidproc =
// (ushort* data, int width, int height) =>
// {
// };
//System.Runtime.InteropServices.GCHandle handle = System.Runtime.InteropServices.GCHandle.Alloc(myvidproc);
////IntPtr ip = System.Runtime.InteropServices.Marshal.GetFunctionPointerForDelegate(myvidproc);
//BizHawk.Emulation.Consoles.Nintendo.SNES.LibsnesDll.snes_set_video_refresh(myvidproc);
//byte[] rom = System.IO.File.ReadAllBytes("d:\\Super Mario World (US).smc");
//BizHawk.Emulation.Consoles.Nintendo.SNES.LibsnesDll.snes_load_cartridge_normal(null, rom, rom.Length);
//BizHawk.Emulation.Consoles.Nintendo.SNES.LibsnesDll.snes_power();
//int framectr = 0;
//for (; ; )
//{
// framectr++;
// BizHawk.Emulation.Consoles.Nintendo.SNES.LibsnesDll.snes_run();
//}
SubMain(args);
}
static void SubMain(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
@ -47,9 +36,6 @@ namespace BizHawk.MultiClient
Global.Config = ConfigService.Load<Config>(PathManager.DefaultIniPath, new Config());
#if WINDOWS
// this will look in subdirectory "dll" to load pinvoked stuff
Win32.SetDllDirectory(System.IO.Path.Combine(PathManager.GetExeDirectoryAbsolute(),"dll"));
try { Global.DSound = new DirectSound(); }
catch
{
@ -102,6 +88,24 @@ namespace BizHawk.MultiClient
#endif
}
//declared here instead of a more usual place to avoid dependencies on the more usual place
#if WINDOWS
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetDllDirectory(string lpPathName);
#endif
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
//load missing assemblies by trying to find them in the dll directory
string dllname = new AssemblyName(args.Name).Name + ".dll";
string directory = System.IO.Path.Combine(PathManager.GetExeDirectoryAbsolute(), "dll");
string fname = Path.Combine(directory, dllname);
if (!File.Exists(fname)) return null;
//it is important that we use LoadFile here and not load from a byte array; otherwise mixed (managed/unamanged) assemblies can't load
return Assembly.LoadFile(fname);
}
#if WINDOWS
public class SingleInstanceController : WindowsFormsApplicationBase
{

View File

@ -1,3 +1,12 @@
del /s BizHawk.zip
rem slimdx has a way of not making it into the output directory, so this is a good time to make sure
copy ..\..\SlimDx.dll
zip -X -9 -r BizHawk.zip BizHawk.MultiClient.exe DiscoHawk.exe *.dll dll ffmpeg.exe gamedb NES\Palettes Lua Gameboy\Palettes
rem at the present we support moving all these dlls into the dll subdirectory
rem that might be troublesome some day..... if it does get troublesome, then we'll have to
rem explicitly list the OK ones here as individual copies. until then....
copy *.dll dll
zip -X -9 -r BizHawk.zip BizHawk.MultiClient.exe DiscoHawk.exe dll gamedb NES\Palettes Lua Gameboy\Palettes

View File

@ -439,9 +439,6 @@ namespace BizHawk
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(IntPtr hWnd, int msg, int wParam, int lParam);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool SetDllDirectory(string lpPathName);
}
}

View File

@ -1,4 +1,5 @@
using System;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Collections.Generic;
using System.IO;
@ -17,19 +18,49 @@ namespace BizHawk
public static string GetExeDirectoryAbsolute()
{
string p = Path.GetDirectoryName(Assembly.GetEntryAssembly().GetName().CodeBase);
if (p.Substring(0, 6) == "file:\\")
p = p.Remove(0, 6);
string z = p;
return p;
var uri = new Uri(Assembly.GetEntryAssembly().GetName().CodeBase);
string module = uri.LocalPath + System.Web.HttpUtility.UrlDecode(uri.Fragment);
return Path.GetDirectoryName(module);
}
static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
//load missing assemblies by trying to find them in the dll directory
string dllname = new AssemblyName(args.Name).Name + ".dll";
string directory = System.IO.Path.Combine(GetExeDirectoryAbsolute(), "dll");
string fname = Path.Combine(directory, dllname);
if (!File.Exists(fname)) return null;
//it is important that we use LoadFile here and not load from a byte array; otherwise mixed (managed/unamanged) assemblies can't load
return Assembly.LoadFile(fname);
}
//declared here instead of a more usual place to avoid dependencies on the more usual place
#if WINDOWS
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool SetDllDirectory(string lpPathName);
#endif
[STAThread]
static void Main(string[] args)
{
var ffmpegPath = Path.Combine(GetExeDirectoryAbsolute(), "ffmpeg.exe");
DiscSystem.FFMpeg.FFMpegPath = ffmpegPath;
AudioExtractor.FFmpegPath = ffmpegPath;
#if WINDOWS
// this will look in subdirectory "dll" to load pinvoked stuff
SetDllDirectory(System.IO.Path.Combine(GetExeDirectoryAbsolute(), "dll"));
//in case assembly resolution fails, such as if we moved them into the dll subdiretory, this event handler can reroute to them
AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
#endif
SubMain(args);
}
static void SubMain(string[] args)
{
var ffmpegPath = Path.Combine(GetExeDirectoryAbsolute(), "ffmpeg.exe");
if(!File.Exists(ffmpegPath))
ffmpegPath = Path.Combine(Path.Combine(GetExeDirectoryAbsolute(), "dll"), "ffmpeg.exe");
DiscSystem.FFMpeg.FFMpegPath = ffmpegPath;
AudioExtractor.FFmpegPath = ffmpegPath;
new DiscoHawk().Run(args);
}

View File

@ -38,7 +38,7 @@
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\BizHawk.MultiClient\output\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DefineConstants>TRACE;DEBUG;WINDOWS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
@ -49,7 +49,7 @@
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\BizHawk.MultiClient\output\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DefineConstants>TRACE;WINDOWS</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<UseVSHostingProcess>false</UseVSHostingProcess>
@ -110,6 +110,7 @@
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Drawing" />
<Reference Include="System.Web" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>