diff --git a/QuickLook.Common/Helpers/ProcessHelper.cs b/QuickLook.Common/Helpers/ProcessHelper.cs
index 2afebbb..35262cc 100644
--- a/QuickLook.Common/Helpers/ProcessHelper.cs
+++ b/QuickLook.Common/Helpers/ProcessHelper.cs
@@ -16,6 +16,7 @@
// along with this program. If not, see .
using System;
+using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Threading.Tasks;
@@ -63,6 +64,8 @@ namespace QuickLook.Common.Helpers
public static void WriteLog(string msg)
{
+ Debug.WriteLine(msg);
+
var logFilePath = Path.Combine(SettingHelper.LocalDataPath, @"QuickLook.Exception.log");
using (var writer = new StreamWriter(new FileStream(logFilePath, FileMode.OpenOrCreate,
diff --git a/QuickLook.Plugin/QuickLook.Plugin.PluginInstaller/Plugin.cs b/QuickLook.Plugin/QuickLook.Plugin.PluginInstaller/Plugin.cs
index c0d93f2..5bb906a 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.PluginInstaller/Plugin.cs
+++ b/QuickLook.Plugin/QuickLook.Plugin.PluginInstaller/Plugin.cs
@@ -33,12 +33,12 @@ namespace QuickLook.Plugin.PluginInstaller
public bool CanHandle(string path)
{
- return !Directory.Exists(path) && path.ToLower().EndsWith(".qlviewer");
+ return !Directory.Exists(path) && path.ToLower().EndsWith(".qlplugin");
}
public void Prepare(string path, ContextObject context)
{
- context.PreferredSize = new Size { Width = 400, Height = 172 };
+ context.PreferredSize = new Size { Width = 460, Height = 200 };
context.Title = "";
context.TitlebarOverlap = false;
@@ -50,7 +50,7 @@ namespace QuickLook.Plugin.PluginInstaller
public void View(string path, ContextObject context)
{
- context.ViewerContent = new PluginInfoPanel(path);
+ context.ViewerContent = new PluginInfoPanel(path, context);
context.IsBusy = false;
}
diff --git a/QuickLook.Plugin/QuickLook.Plugin.PluginInstaller/PluginInfoPanel.xaml b/QuickLook.Plugin/QuickLook.Plugin.PluginInstaller/PluginInfoPanel.xaml
index 694466c..4420267 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.PluginInstaller/PluginInfoPanel.xaml
+++ b/QuickLook.Plugin/QuickLook.Plugin.PluginInstaller/PluginInfoPanel.xaml
@@ -4,7 +4,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
FontSize="14"
- mc:Ignorable="d" Width="400" Height="172" UseLayoutRounding="True">
+ mc:Ignorable="d" Width="460" Height="200">
diff --git a/QuickLook.Plugin/QuickLook.Plugin.PluginInstaller/PluginInfoPanel.xaml.cs b/QuickLook.Plugin/QuickLook.Plugin.PluginInstaller/PluginInfoPanel.xaml.cs
index f536695..fe73360 100644
--- a/QuickLook.Plugin/QuickLook.Plugin.PluginInstaller/PluginInfoPanel.xaml.cs
+++ b/QuickLook.Plugin/QuickLook.Plugin.PluginInstaller/PluginInfoPanel.xaml.cs
@@ -16,19 +16,24 @@
// along with this program. If not, see .
using System;
-using System.Globalization;
using System.IO;
using System.IO.Compression;
+using System.Threading.Tasks;
+using System.Windows;
using System.Windows.Controls;
using System.Xml;
+using QuickLook.Common.ExtensionMethods;
+using QuickLook.Common.Plugin;
namespace QuickLook.Plugin.PluginInstaller
{
public partial class PluginInfoPanel : UserControl
{
+ private readonly ContextObject _context;
private readonly string _path;
+ private string _namespace;
- public PluginInfoPanel(string path)
+ public PluginInfoPanel(string path, ContextObject context)
{
InitializeComponent();
@@ -36,19 +41,87 @@ namespace QuickLook.Plugin.PluginInstaller
Resources.MergedDictionaries[0].Clear();
_path = path;
+ _context = context;
ReadInfo();
+
+ btnInstall.Click += BtnInstall_Click;
}
+ private void BtnInstall_Click(object sender, RoutedEventArgs e)
+ {
+ btnInstall.Content = "Installing ...";
+ btnInstall.IsEnabled = false;
+
+ var t=DoInstall();
+ t.ContinueWith(_ =>
+ Dispatcher.BeginInvoke(new Action(() => btnInstall.Content = "Done! Please restart QuickLook.")));
+ t.Start();
+ }
+
+ private Task DoInstall()
+ {
+ var targetFolder = Path.Combine(App.UserPluginPath, _namespace);
+ return new Task(() =>
+ {
+ CleanUp();
+
+ try
+ {
+ ZipFile.ExtractToDirectory(_path, targetFolder);
+ }
+ catch (Exception ex)
+ {
+ Dispatcher.BeginInvoke(new Action(() => description.Text = ex.Message));
+ CleanUp();
+ }
+ });
+
+ void CleanUp()
+ {
+ if (!Directory.Exists(targetFolder))
+ {
+ Directory.CreateDirectory(targetFolder);
+ return;
+ }
+
+ try
+ {
+ Directory.GetFiles(targetFolder, "*", SearchOption.AllDirectories)
+ .ForEach(file => File.Move(file, new Guid() + ".to_be_deleted"));
+ }
+ catch (Exception ex)
+ {
+ Dispatcher.BeginInvoke(new Action(() => description.Text = ex.Message));
+ }
+ }
+ }
+
+
private void ReadInfo()
{
filename.Text = Path.GetFileNameWithoutExtension(_path);
- var xml = LoadXml(GetFileFromZip(_path, "Metadata.config"));
+ var xml = LoadXml(GetFileFromZip(_path, "QuickLook.Plugin.Metadata.config"));
+
+ _namespace = GetString(xml, @"/Metadata/Namespace");
+
+ var okay = _namespace != null && _namespace.StartsWith("QuickLook.Plugin.");
+
+ filename.Text = okay ? _namespace : "Invalid plugin.";
+ description.Text = GetString(xml, @"/Metadata/Description", string.Empty);
+
+ btnInstall.Visibility = okay ? Visibility.Visible : Visibility.Collapsed;
}
- private XmlDocument LoadXml(Stream data)
+ private static string GetString(XmlNode xml, string xpath, string def = null)
{
+ var n = xml?.SelectSingleNode(xpath);
+ return n?.InnerText;
+ }
+
+ private static XmlDocument LoadXml(Stream data)
+ {
var doc = new XmlDocument();
try
{
@@ -61,18 +134,26 @@ namespace QuickLook.Plugin.PluginInstaller
}
}
- private Stream GetFileFromZip(string archive, string entry)
+ private static MemoryStream GetFileFromZip(string archive, string entry)
{
var ms = new MemoryStream();
- using (var zip = ZipFile.Open(archive, ZipArchiveMode.Read))
+ try
{
- using (var s = zip.GetEntry(entry)?.Open())
+ using (var zip = ZipFile.Open(archive, ZipArchiveMode.Read))
{
- s?.CopyTo(ms);
+ using (var s = zip?.GetEntry(entry)?.Open())
+ {
+ s?.CopyTo(ms);
+ }
}
}
+ catch (Exception)
+ {
+ return ms;
+ }
+ ms.Position = 0;
return ms;
}
}
diff --git a/QuickLook/App.xaml.cs b/QuickLook/App.xaml.cs
index 4b02637..2dd0efd 100644
--- a/QuickLook/App.xaml.cs
+++ b/QuickLook/App.xaml.cs
@@ -34,6 +34,7 @@ namespace QuickLook
///
public partial class App : Application
{
+ public static readonly string UserPluginPath = Path.Combine(SettingHelper.LocalDataPath, "QuickLook.Plugin\\");
public static readonly string AppFullPath = Assembly.GetExecutingAssembly().Location;
public static readonly string AppPath = Path.GetDirectoryName(AppFullPath);
public static readonly bool Is64Bit = Environment.Is64BitProcess;
diff --git a/QuickLook/PluginManager.cs b/QuickLook/PluginManager.cs
index cf174db..d465dc8 100644
--- a/QuickLook/PluginManager.cs
+++ b/QuickLook/PluginManager.cs
@@ -22,6 +22,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using QuickLook.Common.ExtensionMethods;
+using QuickLook.Common.Helpers;
using QuickLook.Common.Plugin;
namespace QuickLook
@@ -32,7 +33,10 @@ namespace QuickLook
private PluginManager()
{
- LoadPlugins();
+ CleanupOldPlugins(App.UserPluginPath);
+ LoadPlugins(App.UserPluginPath);
+ LoadPlugins(Path.Combine(App.AppPath, "QuickLook.Plugin\\"));
+ InitLoadedPlugins();
}
internal IViewer DefaultPlugin { get; } = new Plugin.InfoPanel.Plugin();
@@ -74,9 +78,12 @@ namespace QuickLook
return (matched ?? DefaultPlugin).GetType().CreateInstance();
}
- private void LoadPlugins()
+ private void LoadPlugins(string folder)
{
- Directory.GetFiles(Path.Combine(App.AppPath, "QuickLook.Plugin\\"), "QuickLook.Plugin.*.dll",
+ if (!Directory.Exists(folder))
+ return;
+
+ Directory.GetFiles(folder, "QuickLook.Plugin.*.dll",
SearchOption.AllDirectories)
.ToList()
.ForEach(
@@ -90,7 +97,10 @@ namespace QuickLook
});
LoadedPlugins = LoadedPlugins.OrderByDescending(i => i.Priority).ToList();
+ }
+ private void InitLoadedPlugins()
+ {
LoadedPlugins.ForEach(i =>
{
try
@@ -99,7 +109,25 @@ namespace QuickLook
}
catch (Exception e)
{
- Debug.WriteLine(e);
+ ProcessHelper.WriteLog(e.ToString());
+ }
+ });
+ }
+
+ private static void CleanupOldPlugins(string folder)
+ {
+ if (!Directory.Exists(folder))
+ return;
+
+ Directory.GetFiles(folder, "*.to_be_deleted", SearchOption.AllDirectories).ForEach(file =>
+ {
+ try
+ {
+ File.Delete(file);
+ }
+ catch (Exception)
+ {
+ // ignored
}
});
}