199 lines
6.3 KiB
C#
199 lines
6.3 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
|
|
using System.Windows.Forms;
|
|
using BizHawk.Client.Common;
|
|
|
|
namespace BizHawk.Client.ApiHawk
|
|
{
|
|
/// <summary>
|
|
/// This static class handle all ExternalTools
|
|
/// </summary>
|
|
public static class ExternalToolManager
|
|
{
|
|
#region Fields
|
|
|
|
private static FileSystemWatcher directoryMonitor;
|
|
private static List<ToolStripMenuItem> menuItems = new List<ToolStripMenuItem>();
|
|
|
|
#endregion
|
|
|
|
#region cTor(s)
|
|
|
|
/// <summary>
|
|
/// Initilization
|
|
/// </summary>
|
|
static ExternalToolManager()
|
|
{
|
|
if(!Directory.Exists(Global.Config.PathEntries["Global", "External Tools"].Path))
|
|
{
|
|
Directory.CreateDirectory(Global.Config.PathEntries["Global", "External Tools"].Path);
|
|
}
|
|
directoryMonitor = new FileSystemWatcher(Global.Config.PathEntries["Global", "External Tools"].Path, "*.dll");
|
|
directoryMonitor.IncludeSubdirectories = false;
|
|
directoryMonitor.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.FileName;
|
|
directoryMonitor.Filter = "*.dll";
|
|
directoryMonitor.Created += new FileSystemEventHandler(DirectoryMonitor_Created);
|
|
directoryMonitor.EnableRaisingEvents = true;
|
|
|
|
ClientApi.RomLoaded += delegate { BuildToolStrip(); };
|
|
|
|
BuildToolStrip();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Methods
|
|
|
|
/// <summary>
|
|
/// Build the toolstrip menu
|
|
/// </summary>
|
|
private static void BuildToolStrip()
|
|
{
|
|
menuItems.Clear();
|
|
if (Directory.Exists(directoryMonitor.Path))
|
|
{
|
|
DirectoryInfo dInfo = new DirectoryInfo(directoryMonitor.Path);
|
|
|
|
foreach (FileInfo fi in dInfo.GetFiles("*.dll"))
|
|
{
|
|
menuItems.Add(GenerateToolTipFromFileName(fi.FullName));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generate a <see cref="ToolStripMenuItem"/> from an
|
|
/// external tool dll.
|
|
/// The assembly must have <see cref="BizHawkExternalToolAttribute"/> in its
|
|
/// assembly attributes
|
|
/// </summary>
|
|
/// <param name="fileName">File that will be reflected</param>
|
|
/// <returns>A new <see cref="ToolStripMenuItem"/>; assembly path can be found in the Tag property</returns>
|
|
/// <remarks>For the moment, you could only load a dll that have a form (which implements <see cref="BizHawk.Client.EmuHawk.IExternalToolForm"/>)</remarks>
|
|
private static ToolStripMenuItem GenerateToolTipFromFileName(string fileName)
|
|
{
|
|
Type customFormType;
|
|
Assembly externalToolFile;
|
|
ToolStripMenuItem item = null;
|
|
|
|
try
|
|
{
|
|
BizHawk.Common.Win32Hacks.RemoveMOTW(fileName);
|
|
externalToolFile = Assembly.LoadFrom(fileName);
|
|
object[] attributes = externalToolFile.GetCustomAttributes(typeof(BizHawkExternalToolAttribute), false);
|
|
if (attributes != null && attributes.Count() == 1)
|
|
{
|
|
BizHawkExternalToolAttribute attribute = (BizHawkExternalToolAttribute)attributes[0];
|
|
item = new ToolStripMenuItem(attribute.Name);
|
|
item.ToolTipText = attribute.Description;
|
|
if (attribute.IconResourceName != "")
|
|
{
|
|
Stream s = externalToolFile.GetManifestResourceStream(string.Format("{0}.{1}", externalToolFile.GetName().Name, attribute.IconResourceName));
|
|
if (s != null)
|
|
{
|
|
item.Image = new Bitmap(s);
|
|
}
|
|
}
|
|
|
|
customFormType = externalToolFile.GetTypes().FirstOrDefault<Type>(t => t != null && t.FullName == "BizHawk.Client.EmuHawk.CustomMainForm");
|
|
if (customFormType == null)
|
|
{
|
|
item.ToolTipText = "Does not have a CustomMainForm";
|
|
item.Enabled = false;
|
|
}
|
|
item.Tag = fileName;
|
|
|
|
attributes = externalToolFile.GetCustomAttributes(typeof(BizHawkExternalToolUsageAttribute), false);
|
|
if (attributes != null && attributes.Count() == 1)
|
|
{
|
|
BizHawkExternalToolUsageAttribute attribute2 = (BizHawkExternalToolUsageAttribute)attributes[0];
|
|
if(Global.Emulator.SystemId == "NULL" && attribute2.ToolUsage != BizHawkExternalToolUsage.Global)
|
|
{
|
|
item.ToolTipText = "This tool doesn't work if nothing is loaded";
|
|
item.Enabled = false;
|
|
}
|
|
else if(attribute2.ToolUsage == BizHawkExternalToolUsage.EmulatorSpecific && Global.Emulator.SystemId != ClientApi.SystemIdConverter.ConvertBack(attribute2.System))
|
|
{
|
|
item.ToolTipText = "This tool doesn't work for current system";
|
|
item.Enabled = false;
|
|
}
|
|
else if (attribute2.ToolUsage == BizHawkExternalToolUsage.GameSpecific && Global.Game.Hash != attribute2.GameHash)
|
|
{
|
|
item.ToolTipText = "This tool doesn't work for current game";
|
|
item.Enabled = false;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
item = new ToolStripMenuItem(externalToolFile.GetName().Name);
|
|
item.ToolTipText = "BizHawkExternalTool attribute hasn't been found";
|
|
item.Enabled = false;
|
|
}
|
|
}
|
|
catch (BadImageFormatException)
|
|
{
|
|
item = new ToolStripMenuItem(fileName);
|
|
item.ToolTipText = "This is not an assembly";
|
|
item.Enabled = false;
|
|
}
|
|
|
|
#if DEBUG //I added special debug stuff to get additionnal informations. Don(t think it can be usefull for released versions
|
|
catch (ReflectionTypeLoadException ex)
|
|
{
|
|
foreach (Exception e in ex.LoaderExceptions)
|
|
{
|
|
Debug.WriteLine(e.Message);
|
|
}
|
|
item.ToolTipText = "Something goes wrong while trying to load";
|
|
item.Enabled = false;
|
|
}
|
|
#else
|
|
catch (ReflectionTypeLoadException)
|
|
{
|
|
item.ToolTipText = "Something goes wrong while trying to load";
|
|
item.Enabled = false;
|
|
}
|
|
#endif
|
|
|
|
return item;
|
|
}
|
|
|
|
/// <summary>
|
|
/// This event is raised when we add a dll file into
|
|
/// the external tools path.
|
|
/// It will automatically load the assembly and add it into the list
|
|
/// </summary>
|
|
/// <param name="sender">Object that raised the event</param>
|
|
/// <param name="e">Event arguments</param>
|
|
private static void DirectoryMonitor_Created(object sender, FileSystemEventArgs e)
|
|
{
|
|
menuItems.Add(GenerateToolTipFromFileName(e.FullPath));
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
|
|
/// <summary>
|
|
/// Gets a prebuild <see cref="ToolStripMenuItem"/>
|
|
/// This list auto-updated by the <see cref="ExternalToolManager"/> itself
|
|
/// </summary>
|
|
public static IEnumerable<ToolStripMenuItem> ToolStripMenu
|
|
{
|
|
get
|
|
{
|
|
return menuItems;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|