Skip to content

Commit

Permalink
app: optimized single instance mode
Browse files Browse the repository at this point in the history
- passing apk with namedpipe server & client
- bring older window to front
  • Loading branch information
hariimurti committed Apr 3, 2020
1 parent af68af0 commit 697de0e
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 5 deletions.
2 changes: 2 additions & 0 deletions ApkManager/ApkManager.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="Lib\Lib.cs" />
<Compile Include="Lib\PipeClient.cs" />
<Compile Include="Lib\PipeServer.cs" />
<Compile Include="RenamerWindow.xaml.cs">
<DependentUpon>RenamerWindow.xaml</DependentUpon>
</Compile>
Expand Down
22 changes: 17 additions & 5 deletions ApkManager/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -16,17 +17,28 @@ namespace ApkManager
/// </summary>
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();
}
}
}

Expand Down
33 changes: 33 additions & 0 deletions ApkManager/Lib/PipeClient.cs
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
}
}
59 changes: 59 additions & 0 deletions ApkManager/Lib/PipeServer.cs
Original file line number Diff line number Diff line change
@@ -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;
}
}
}
32 changes: 32 additions & 0 deletions ApkManager/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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;
}
}
}

0 comments on commit 697de0e

Please sign in to comment.