From 697de0e4f711dea2cfb84f7bcd492e52aea45647 Mon Sep 17 00:00:00 2001 From: Harimurti Date: Sat, 4 Apr 2020 02:09:49 +0700 Subject: [PATCH] app: optimized single instance mode - passing apk with namedpipe server & client - bring older window to front --- ApkManager/ApkManager.csproj | 2 ++ ApkManager/App.xaml.cs | 22 ++++++++++--- ApkManager/Lib/PipeClient.cs | 33 ++++++++++++++++++++ ApkManager/Lib/PipeServer.cs | 59 +++++++++++++++++++++++++++++++++++ ApkManager/MainWindow.xaml.cs | 32 +++++++++++++++++++ 5 files changed, 143 insertions(+), 5 deletions(-) create mode 100644 ApkManager/Lib/PipeClient.cs create mode 100644 ApkManager/Lib/PipeServer.cs diff --git a/ApkManager/ApkManager.csproj b/ApkManager/ApkManager.csproj index 605ce1c..835903e 100644 --- a/ApkManager/ApkManager.csproj +++ b/ApkManager/ApkManager.csproj @@ -77,6 +77,8 @@ Designer + + RenamerWindow.xaml diff --git a/ApkManager/App.xaml.cs b/ApkManager/App.xaml.cs index 70a05ad..16ddd89 100644 --- a/ApkManager/App.xaml.cs +++ b/ApkManager/App.xaml.cs @@ -2,6 +2,7 @@ using System; using System.Data; using System.Diagnostics; +using System.IO; using System.Linq; using System.Reflection; using System.Security.Principal; @@ -16,17 +17,28 @@ namespace ApkManager /// public partial class App : Application { + public static readonly string PIPENAMESERVER = "{BB8C82B6-7851-46A0-A902-48446B59CAD6}"; + private void Application_Startup(object sender, StartupEventArgs e) { var cfg = new Config(); - using (var mutex = new Mutex(true, "{BB8C82B6-7851-46A0-A902-48446B59CAD6}", out bool isFirstInstance)) + using (var mutex = new Mutex(true, PIPENAMESERVER, out bool isFirstInstance)) { - if (!isFirstInstance && cfg.SingleInstance()) return; - - var apks = e.Args.Where(s => s.ToLower().EndsWith(".apk")).ToArray(); + // collect all args where apk & exist + var apks = e.Args.Where(s => s.ToLower().EndsWith(".apk") && File.Exists(s)).ToList(); + if (apks.Count == 0) apks.Add(""); - if (apks.Count() <= 1) + if (!isFirstInstance && cfg.SingleInstance()) + { + // send message to existed app + new PipeClient(PIPENAMESERVER).SendMessage(apks.FirstOrDefault()).GetAwaiter(); + Current.Shutdown(); + } + else + { + // open main window with null or single apk new MainWindow(apks.FirstOrDefault()).ShowDialog(); + } } } diff --git a/ApkManager/Lib/PipeClient.cs b/ApkManager/Lib/PipeClient.cs new file mode 100644 index 0000000..5bb4d2a --- /dev/null +++ b/ApkManager/Lib/PipeClient.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Pipes; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ApkManager.Lib +{ + class PipeClient + { + private string pipename; + + public PipeClient(string pipename) + { + this.pipename = pipename; + } + + public async Task SendMessage(string message) + { + using (var client = new NamedPipeClientStream(pipename)) + { + await Task.Run(()=> client.Connect(1000)); + using (var sw = new StreamWriter(client)) + { + sw.AutoFlush = true; + sw.WriteLine(message); + } + } + } + } +} diff --git a/ApkManager/Lib/PipeServer.cs b/ApkManager/Lib/PipeServer.cs new file mode 100644 index 0000000..bef3ef3 --- /dev/null +++ b/ApkManager/Lib/PipeServer.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.IO.Pipes; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ApkManager.Lib +{ + class PipeServer + { + public delegate void MessageEventHander(string message); + public event MessageEventHander OnMessageReceived; + + NamedPipeServerStream server; + private string pipename; + + public PipeServer(string pipename) + { + this.pipename = pipename; + } + + public async void StartListening() + { + if (server != null) return; + server = new NamedPipeServerStream(pipename); + + while(true) + { + try + { + await Task.Run(() => server.WaitForConnection()); + using (var sr = new StreamReader(server)) + { + OnMessageReceived?.Invoke(sr.ReadLine()); + } + server?.Disconnect(); + } + catch(Exception) + { + break; + } + finally + { + server?.Dispose(); + server = null; + } + } + } + + public void StopListening() + { + server?.Dispose(); + server = null; + } + } +} diff --git a/ApkManager/MainWindow.xaml.cs b/ApkManager/MainWindow.xaml.cs index 4213f4e..215c052 100644 --- a/ApkManager/MainWindow.xaml.cs +++ b/ApkManager/MainWindow.xaml.cs @@ -21,6 +21,7 @@ public partial class MainWindow : MetroWindow private Config cfg; private Apk loadedApk; private string pathApk; + public bool donotInterupt; #region WINDOW public MainWindow(string pathApk = null) @@ -55,8 +56,17 @@ private void OnLoaded(object sender, RoutedEventArgs e) swInstance.IsChecked = cfg.SingleInstance(); swWindow.IsChecked = cfg.GetWindowPostition(); + // open apk passes arg not null if (!string.IsNullOrWhiteSpace(pathApk)) txtPath.Text = pathApk; + + // start pip server if in one single instance + if (cfg.SingleInstance()) + { + var server = new PipeServer(App.PIPENAMESERVER); + server.OnMessageReceived += OnMessageReceived; + server.StartListening(); + } } private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e) @@ -65,6 +75,18 @@ private void OnClosing(object sender, System.ComponentModel.CancelEventArgs e) cfg.WindowPostition(new WindowPosition() { Top = this.Top, Left = this.Left }); } + private void OnMessageReceived(string message) + { + if (donotInterupt) return; + + txtPath.Text = message; + + if (this.WindowState == WindowState.Minimized) + this.WindowState = WindowState.Normal; + + this.Activate(); + } + private void OnFileDrop(object sender, DragEventArgs e) { if (!e.Data.GetDataPresent(DataFormats.FileDrop)) return; @@ -178,6 +200,8 @@ private async void ButtonRenamer_Click(object sender, RoutedEventArgs e) { try { + donotInterupt = true; + var window = new RenamerWindow(loadedApk); if (window.ShowDialog().Value == false) return; @@ -189,11 +213,19 @@ private async void ButtonRenamer_Click(object sender, RoutedEventArgs e) { await this.ShowMessageAsync("Renamer", ex.Message); } + finally + { + donotInterupt = false; + } } private void ButtonInstaller_Click(object sender, RoutedEventArgs e) { + donotInterupt = true; + new AdbWindow(loadedApk).ShowDialog(); + + donotInterupt = false; } } } \ No newline at end of file