mirror of
https://github.com/QL-Win/QuickLook.git
synced 2026-02-28 01:00:17 +08:00
Use NamedPipe, instead of second instance, to invoke preview from command line
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using QuickLook.Helpers;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace QuickLook
|
||||
{
|
||||
@@ -16,9 +16,9 @@ namespace QuickLook
|
||||
public static readonly bool Is64Bit = Environment.Is64BitProcess;
|
||||
public static readonly string AppFullPath = Assembly.GetExecutingAssembly().Location;
|
||||
public static readonly string AppPath = Path.GetDirectoryName(AppFullPath);
|
||||
public static bool RunningAsViewer;
|
||||
|
||||
private static bool _duplicated;
|
||||
private bool _isFirstInstance;
|
||||
private Mutex _isRunning;
|
||||
|
||||
protected override void OnStartup(StartupEventArgs e)
|
||||
{
|
||||
@@ -27,7 +27,7 @@ namespace QuickLook
|
||||
MessageBox.Show(((Exception) args.ExceptionObject).Message + Environment.NewLine +
|
||||
((Exception) args.ExceptionObject).StackTrace);
|
||||
|
||||
Current.Shutdown();
|
||||
Shutdown();
|
||||
};
|
||||
|
||||
base.OnStartup(e);
|
||||
@@ -35,65 +35,60 @@ namespace QuickLook
|
||||
|
||||
private void Application_Startup(object sender, StartupEventArgs e)
|
||||
{
|
||||
if (e.Args.Any())
|
||||
if (Directory.Exists(e.Args.First()) || File.Exists(e.Args.First()))
|
||||
RunAsViewer(e);
|
||||
EnsureFirstInstance();
|
||||
|
||||
if (!_isFirstInstance)
|
||||
{
|
||||
// second instance: preview this file
|
||||
if (e.Args.Any() && (Directory.Exists(e.Args.First()) || File.Exists(e.Args.First())))
|
||||
RemoteCallShowPreview(e);
|
||||
// second instance: duplicate
|
||||
else
|
||||
RunAsListener(e);
|
||||
else
|
||||
RunAsListener(e);
|
||||
}
|
||||
MessageBox.Show("QuickLook is already running in the background.");
|
||||
|
||||
private void RunAsViewer(StartupEventArgs e)
|
||||
{
|
||||
RunningAsViewer = true;
|
||||
|
||||
var runningPid = PidHelper.GetRunningInstance();
|
||||
if (runningPid != -1)
|
||||
{
|
||||
Process.GetProcessById(runningPid).Kill();
|
||||
|
||||
Current.Shutdown();
|
||||
Shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
PidHelper.WritePid();
|
||||
RunListener(e);
|
||||
|
||||
ViewWindowManager.GetInstance().InvokeViewer(e.Args.First());
|
||||
// second instance: run and preview this file
|
||||
if (e.Args.Any() && (Directory.Exists(e.Args.First()) || File.Exists(e.Args.First())))
|
||||
RemoteCallShowPreview(e);
|
||||
}
|
||||
|
||||
private void RunAsListener(StartupEventArgs e)
|
||||
private void RemoteCallShowPreview(StartupEventArgs e)
|
||||
{
|
||||
RunningAsViewer = false;
|
||||
|
||||
if (PidHelper.GetRunningInstance() != -1)
|
||||
{
|
||||
_duplicated = true;
|
||||
|
||||
MessageBox.Show("QuickLook is already running in the background.");
|
||||
|
||||
Current.Shutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
PidHelper.WritePid();
|
||||
PipeServerManager.SendMessage(e.Args.First());
|
||||
}
|
||||
|
||||
private void RunListener(StartupEventArgs e)
|
||||
{
|
||||
TrayIconManager.GetInstance();
|
||||
if (!e.Args.Contains("/autorun"))
|
||||
TrayIconManager.GetInstance().ShowNotification("", "QuickLook is running in the background.");
|
||||
|
||||
PluginManager.GetInstance();
|
||||
|
||||
BackgroundListener.GetInstance();
|
||||
PipeServerManager.GetInstance().MessageReceived +=
|
||||
(msg, ea) => Dispatcher.BeginInvoke(
|
||||
new Action(() => ViewWindowManager.GetInstance().InvokeViewer(msg as string)),
|
||||
DispatcherPriority.ApplicationIdle);
|
||||
}
|
||||
|
||||
private void App_OnExit(object sender, ExitEventArgs e)
|
||||
{
|
||||
TrayIconManager.GetInstance().Dispose();
|
||||
BackgroundListener.GetInstance().Dispose();
|
||||
if (_isFirstInstance)
|
||||
{
|
||||
PipeServerManager.GetInstance().Dispose();
|
||||
TrayIconManager.GetInstance().Dispose();
|
||||
BackgroundListener.GetInstance().Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
if (!_duplicated)
|
||||
PidHelper.DeletePid();
|
||||
private void EnsureFirstInstance()
|
||||
{
|
||||
_isRunning = new Mutex(true, "QuickLook.App.Mutex", out _isFirstInstance);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
namespace QuickLook.Helpers
|
||||
{
|
||||
internal static class PidHelper
|
||||
{
|
||||
private static FileStream _pidLocker;
|
||||
|
||||
private static readonly string PidListener =
|
||||
Path.Combine(Path.GetTempPath(), "QuickLook.App.Listener.D6EC3F8DDF6B.pid");
|
||||
|
||||
private static readonly string PidViewer =
|
||||
Path.Combine(Path.GetTempPath(), "QuickLook.App.Viewer.A6FA53E93515.pid");
|
||||
|
||||
internal static int GetRunningInstance()
|
||||
{
|
||||
var pid = App.RunningAsViewer ? PidViewer : PidListener;
|
||||
|
||||
if (!File.Exists(pid))
|
||||
return -1;
|
||||
|
||||
var ppid = -1;
|
||||
using (var file = File.Open(pid, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
||||
using (var sr = new StreamReader(file))
|
||||
{
|
||||
int.TryParse(sr.ReadToEnd(), out ppid);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Process.GetProcessById(ppid);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ppid;
|
||||
}
|
||||
|
||||
internal static void WritePid()
|
||||
{
|
||||
var pidFile = App.RunningAsViewer ? PidViewer : PidListener;
|
||||
|
||||
File.WriteAllText(pidFile, Process.GetCurrentProcess().Id.ToString());
|
||||
|
||||
_pidLocker = File.Open(pidFile, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
|
||||
}
|
||||
|
||||
internal static void DeletePid()
|
||||
{
|
||||
_pidLocker?.Close();
|
||||
_pidLocker = null;
|
||||
|
||||
File.Delete(App.RunningAsViewer ? PidViewer : PidListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
89
QuickLook/PipeServerManager.cs
Normal file
89
QuickLook/PipeServerManager.cs
Normal file
@@ -0,0 +1,89 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.IO.Pipes;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace QuickLook
|
||||
{
|
||||
internal class PipeServerManager : IDisposable
|
||||
{
|
||||
private const string PipeName = "QuickLook.App.Pipe";
|
||||
private const string PipeCloseMessage = "QuickLook.App.Pipe.QuitSingal";
|
||||
private static PipeServerManager _instance;
|
||||
|
||||
private NamedPipeServerStream _server;
|
||||
|
||||
public PipeServerManager()
|
||||
{
|
||||
_server = new NamedPipeServerStream(PipeName, PipeDirection.In);
|
||||
|
||||
new Task(() =>
|
||||
{
|
||||
using (var reader = new StreamReader(_server))
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
Debug.WriteLine("PipeManager: WaitForConnection");
|
||||
|
||||
_server.WaitForConnection();
|
||||
var msg = reader.ReadLine();
|
||||
|
||||
Debug.WriteLine($"PipeManager: {msg}");
|
||||
|
||||
if (msg == PipeCloseMessage)
|
||||
return;
|
||||
|
||||
// dispatch message
|
||||
MessageReceived?.Invoke(msg, new EventArgs());
|
||||
|
||||
_server.Disconnect();
|
||||
}
|
||||
}
|
||||
}).Start();
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
GC.SuppressFinalize(this);
|
||||
|
||||
if (_server != null)
|
||||
SendMessage(PipeCloseMessage);
|
||||
_server?.Dispose();
|
||||
_server = null;
|
||||
}
|
||||
|
||||
public event EventHandler MessageReceived;
|
||||
|
||||
public static void SendMessage(string msg)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var client = new NamedPipeClientStream(".", PipeName, PipeDirection.Out))
|
||||
{
|
||||
client.Connect();
|
||||
|
||||
using (var writer = new StreamWriter(client))
|
||||
{
|
||||
writer.WriteLine(msg);
|
||||
writer.Flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.WriteLine(e.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
~PipeServerManager()
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
|
||||
public static PipeServerManager GetInstance()
|
||||
{
|
||||
return _instance ?? (_instance = new PipeServerManager());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,7 +134,7 @@
|
||||
<Compile Include="Helpers\FileHelper.cs" />
|
||||
<Compile Include="Helpers\ProcessHelper.cs" />
|
||||
<Compile Include="MainWindowNoTransparent.cs" />
|
||||
<Compile Include="Helpers\PidHelper.cs" />
|
||||
<Compile Include="PipeServerManager.cs" />
|
||||
<Compile Include="PluginManager.cs" />
|
||||
<Compile Include="Plugin\InfoPanel\DpiHelpers.cs" />
|
||||
<Compile Include="Plugin\InfoPanel\Extensions.cs" />
|
||||
|
||||
Reference in New Issue
Block a user