fixed issue with single instance and download location

This commit is contained in:
subhra74 2022-08-06 11:54:52 +05:30
parent 4b89efeda4
commit 89fbfd685b
20 changed files with 291 additions and 72 deletions

View File

@ -39,6 +39,7 @@ namespace XDM.Core
public void AddItemToTop( public void AddItemToTop(
string id, string id,
string targetFileName, string targetFileName,
string? targetDir,
DateTime date, DateTime date,
long fileSize, long fileSize,
string type, string type,
@ -57,7 +58,7 @@ namespace XDM.Core
Progress = 0, Progress = 0,
Size = fileSize, Size = fileSize,
Status = startType == DownloadStartType.Waiting ? DownloadStatus.Waiting : DownloadStatus.Stopped, Status = startType == DownloadStartType.Waiting ? DownloadStatus.Waiting : DownloadStatus.Stopped,
TargetDir = "", TargetDir = targetDir,
PrimaryUrl = primaryUrl, PrimaryUrl = primaryUrl,
Authentication = authentication, Authentication = authentication,
Proxy = proxyInfo Proxy = proxyInfo

View File

@ -167,6 +167,7 @@ namespace XDM.Core
{ {
throw new Exception("Please configure all dependecies"); throw new Exception("Please configure all dependecies");
} }
SingleInstance.Ensure();
s_Init = true; s_Init = true;
Initialized?.Invoke(null, EventArgs.Empty); Initialized?.Invoke(null, EventArgs.Empty);
} }

View File

@ -67,8 +67,7 @@ namespace XDM.Core
public void StartBrowserMonitoring() public void StartBrowserMonitoring()
{ {
BrowserMonitor.RunNativeHostHandler(); BrowserMonitor.Run();
BrowserMonitor.RunHttpIpcHandler();
} }
public string? StartDownload( public string? StartDownload(
@ -120,11 +119,12 @@ namespace XDM.Core
} }
http.SetFileName(FileHelper.SanitizeFileName(fileName), fileNameFetchMode); http.SetFileName(FileHelper.SanitizeFileName(fileName), fileNameFetchMode);
http.SetTargetDirectory(targetFolder); http.SetTargetDirectory(targetFolder);
StartDownload(http, startImmediately, authentication, proxyInfo); StartDownload(http, targetFolder, startImmediately, authentication, proxyInfo);
return http.Id; return http.Id;
} }
private void StartDownload(IBaseDownloader download, private void StartDownload(IBaseDownloader download,
string? targetDir,
bool startImmediately, bool startImmediately,
AuthenticationInfo? authentication, AuthenticationInfo? authentication,
ProxyInfo? proxyInfo) ProxyInfo? proxyInfo)
@ -147,7 +147,7 @@ namespace XDM.Core
queuedDownloads.Add(id, false); queuedDownloads.Add(id, false);
} }
ApplicationContext.Application.AddItemToTop(id, download.TargetFileName, DateTime.Now, ApplicationContext.Application.AddItemToTop(id, download.TargetFileName, targetDir, DateTime.Now,
download.FileSize, download.Type, download.FileNameFetchMode, download.FileSize, download.Type, download.FileNameFetchMode,
download.PrimaryUrl?.ToString(), startType, authentication, download.PrimaryUrl?.ToString(), startType, authentication,
proxyInfo); proxyInfo);

View File

@ -8,8 +8,9 @@ namespace XDM.Core
{ {
public static class ArgsProcessor public static class ArgsProcessor
{ {
public static void Process(Dictionary<string, string?> args) public static void Process(string[] commandArgs, int start = 0)
{ {
Dictionary<string, string?> args = ParseArgs(commandArgs, start);
if (args.ContainsKey("-u")) if (args.ContainsKey("-u"))
{ {
var url = args["-u"]; var url = args["-u"];
@ -18,9 +19,28 @@ namespace XDM.Core
ApplicationContext.CoreService.AddDownload(new Message { Url = url! }); ApplicationContext.CoreService.AddDownload(new Message { Url = url! });
} }
} }
if (args.ContainsKey("-i"))
{
Config.Instance.RunOnLogon = true;
Config.SaveConfig();
ApplicationContext.Application.RunOnUiThread(() =>
{
ApplicationContext.MainWindow.ShowAndActivate();
ApplicationContext.PlatformUIService.ShowBrowserMonitoringDialog();
});
}
if (args.Count == 0|| args.ContainsKey("-r"))
{
ApplicationContext.Application.RunOnUiThread(() =>
{
ApplicationContext.MainWindow.ShowAndActivate();
});
}
} }
public static Dictionary<string, string?> ParseArgs(string[] args, int start = 0) private static Dictionary<string, string?> ParseArgs(string[] args, int start = 0)
{ {
var options = new Dictionary<string, string?>(); var options = new Dictionary<string, string?>();
var key = string.Empty; var key = string.Empty;

View File

@ -4,16 +4,12 @@ namespace XDM.Core.BrowserMonitoring
{ {
public static class BrowserMonitor public static class BrowserMonitor
{ {
public static void RunHttpIpcHandler() public static void Run()
{ {
var handler = new IpcHttpHandler(); var pipe = new IpcPipe();
handler.StartHttpIpcChannel(); pipe.Run();
} var http = new IpcHttpMessageProcessor();
http.Run();
public static void RunNativeHostHandler()
{
var handler = new NativeMessagingHostHandler();
handler.StartPipedChannel();
} }
} }
} }

View File

@ -12,11 +12,11 @@ using Translations;
namespace XDM.Core.BrowserMonitoring namespace XDM.Core.BrowserMonitoring
{ {
public class IpcHttpHandler public class IpcHttpMessageProcessor
{ {
private NanoServer server; private NanoServer server;
public IpcHttpHandler() public IpcHttpMessageProcessor()
{ {
server = new NanoServer(IPAddress.Loopback, 9614); server = new NanoServer(IPAddress.Loopback, 9614);
server.RequestReceived += (sender, args) => server.RequestReceived += (sender, args) =>
@ -25,7 +25,7 @@ namespace XDM.Core.BrowserMonitoring
}; };
} }
public void StartHttpIpcChannel() public void Run()
{ {
new Thread(() => new Thread(() =>
{ {

View File

@ -0,0 +1,172 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Pipes;
using System.IO;
using XDM.Core;
using System.Threading;
#if NET35
using XDM.Compatibility;
#else
using System.Collections.Concurrent;
#endif
using TraceLog;
namespace XDM.Core.BrowserMonitoring
{
public class IpcPipe : IDisposable
{
private int MaxPipeInstance = 254;
private static readonly string PipeName = "XDM_Ipc_Browser_Monitoring_Pipe";
private List<PipeChannel> connectedChannels = new();
private Thread listenerThread;
public static void EnsureSingleInstance()
{
}
public IpcPipe()
{
EnsureSingleInstance();
}
public void BroadcastConfig()
{
var bytes = GetSyncBytes();
lock (this)
{
foreach (var channel in connectedChannels)
{
try
{
channel.Publish(bytes);
}
catch (Exception ex)
{
Log.Debug(ex, ex.Message);
}
}
}
}
public void Run()
{
listenerThread = new Thread(() =>
{
while (true)
{
var pipe =
new NamedPipeServerStream(PipeName,
PipeDirection.InOut, NamedPipeServerStream.MaxAllowedServerInstances,
PipeTransmissionMode.Byte, PipeOptions.Asynchronous);
Log.Debug("Waiting for native host pipe...");
pipe.WaitForConnection();
Log.Debug("Pipe request received");
lock (connectedChannels)
{
var channel = CreateChannel(pipe);
connectedChannels.Add(channel);
channel.Start(GetSyncBytes());
}
}
});
listenerThread.Start();
ApplicationContext.ApplicationEvent += ApplicationContext_ApplicationEvent;
}
private void ApplicationContext_ApplicationEvent(object? sender, ApplicationEvent e)
{
if (e.EventType == "ConfigChanged")
{
BroadcastConfig();
}
}
private PipeChannel CreateChannel(NamedPipeServerStream pipe)
{
var channel = new PipeChannel(pipe);
channel.MessageReceived += (sender, args) =>
{
try
{
using var br = new BinaryReader(new MemoryStream(args.Data));
var envelop = RawBrowserMessageEnvelop.Deserialize(br);
IpcPipeMessageProcessor.Process(envelop);
}
catch (Exception ex)
{
Log.Debug(ex, ex.ToString());
}
};
channel.Disconnected += (sender, bytes) =>
{
lock (connectedChannels)
{
connectedChannels.Remove((PipeChannel)sender);
}
};
return channel;
}
public void Dispose()
{
lock (connectedChannels)
{
foreach (var channel in connectedChannels)
{
channel.Disconnect();
}
}
}
private static byte[] GetSyncBytes()
{
var msg = new SyncMessage()
{
Enabled = Config.Instance.IsBrowserMonitoringEnabled,
BlockedHosts = Config.Instance.BlockedHosts,
VideoUrls = new string[0],
FileExts = Config.Instance.FileExtensions,
VidExts = Config.Instance.VideoExtensions,
VidList = ApplicationContext.VideoTracker.GetVideoList(false).Select(a => new VideoItem
{
Id = a.ID,
Text = a.File,
Info = a.DisplayName
}).ToList(),
MimeList = new string[] { "video", "audio", "mpegurl", "f4m", "m3u8", "dash" },
BlockedMimeList = new string[] { "text/javascript", "application/javascript", "text/css", "text/html" },
VideoUrlsWithPostReq = new string[] { "ubei/v1/player?key=", "ubei/v1/next?key=" }
};
return msg.Serialize();
}
public static void SendArgsToRunningInstance(IEnumerable<string> args)
{
var arguments = args;
if (arguments == null)
{
arguments = new string[0];
}
try
{
using var npc = new NamedPipeClientStream(".", PipeName, PipeDirection.Out);
npc.Connect();
var b = new MemoryStream();
var wb = new BinaryWriter(b);
wb.Write(Int32.MaxValue);
wb.Write(string.Join("\r", arguments.ToArray()));
wb.Close();
NativeMessageSerializer.WriteMessage(npc, b.ToArray());
npc.Flush();
npc.Close();
}
catch (Exception ex)
{
Log.Debug(ex, ex.Message);
}
}
}
}

View File

@ -7,9 +7,9 @@ using XDM.Core.Util;
namespace XDM.Core.BrowserMonitoring namespace XDM.Core.BrowserMonitoring
{ {
internal static class BrowserMessageHandler internal static class IpcPipeMessageProcessor
{ {
internal static void Handle(RawBrowserMessageEnvelop envelop) internal static void Process(RawBrowserMessageEnvelop envelop)
{ {
//Log.Debug("Type: " + envelop.MessageType); //Log.Debug("Type: " + envelop.MessageType);
if (envelop.MessageType == "videoIds") if (envelop.MessageType == "videoIds")
@ -32,10 +32,9 @@ namespace XDM.Core.BrowserMonitoring
return; return;
} }
if (envelop.MessageType == "custom") if (envelop.MessageType == "custom" && envelop.CustomData != null)
{ {
var args = ArgsProcessor.ParseArgs(envelop.CustomData.Split('\r')); ArgsProcessor.Process(envelop.CustomData.Split('\r'));
ArgsProcessor.Process(args);
return; return;
} }

View File

@ -5,14 +5,14 @@ using TraceLog;
namespace XDM.Core.BrowserMonitoring namespace XDM.Core.BrowserMonitoring
{ {
internal sealed class NativeMessagingHostChannel internal sealed class PipeChannel
{ {
private NamedPipeServerStream pipe; private NamedPipeServerStream pipe;
internal event EventHandler<NativeMessageEventArgs>? MessageReceived; internal event EventHandler<NativeMessageEventArgs>? MessageReceived;
internal event EventHandler? Disconnected; internal event EventHandler? Disconnected;
private Thread readerThread; private Thread readerThread;
internal NativeMessagingHostChannel(NamedPipeServerStream pipe) internal PipeChannel(NamedPipeServerStream pipe)
{ {
this.pipe = pipe; this.pipe = pipe;
readerThread = new Thread(() => readerThread = new Thread(() =>

View File

@ -12,7 +12,7 @@ namespace XDM.Core
public long Size { get; set; } public long Size { get; set; }
public string TargetDir { get; set; } public string? TargetDir { get; set; }
public DateTime DateAdded { get; set; } public DateTime DateAdded { get; set; }

View File

@ -48,7 +48,8 @@ namespace XDM.Core
/// <param name="startType"></param> /// <param name="startType"></param>
/// <param name="authentication"></param> /// <param name="authentication"></param>
/// <param name="proxyInfo"></param> /// <param name="proxyInfo"></param>
public void AddItemToTop(string id, string targetFileName, DateTime date, public void AddItemToTop(string id, string targetFileName,
string? targetDir, DateTime date,
long fileSize, string type, FileNameFetchMode fileNameFetchMode, long fileSize, string type, FileNameFetchMode fileNameFetchMode,
string primaryUrl, DownloadStartType startType, string primaryUrl, DownloadStartType startType,
AuthenticationInfo? authentication, ProxyInfo? proxyInfo); AuthenticationInfo? authentication, ProxyInfo? proxyInfo);

View File

@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using TraceLog;
using XDM.Core.BrowserMonitoring;
namespace XDM.Core
{
public static class SingleInstance
{
public static Mutex GlobalMutex;
public static void Ensure()
{
try
{
using var mutex = Mutex.OpenExisting(@"Global\XDM_Active_Instance");
throw new InstanceAlreadyRunningException(@"XDM instance already running, Mutex exists 'Global\XDM_Active_Instance'");
}
catch (Exception ex)
{
Log.Debug(ex, "Exception in NativeMessagingHostHandler ctor");
if (ex is InstanceAlreadyRunningException)
{
var args = Environment.GetCommandLineArgs().Skip(1);
Log.Debug(ex, "Sending args to running instance");
//if no arguments, then restore ui of previously running process
IpcPipe.SendArgsToRunningInstance(args.Count() == 0 ? new string[] { "-r" } : args);
Environment.Exit(0);
}
}
GlobalMutex = new Mutex(true, @"Global\XDM_Active_Instance");
}
}
public class InstanceAlreadyRunningException : Exception
{
public InstanceAlreadyRunningException(string message) : base(message)
{
}
}
}

View File

@ -87,6 +87,8 @@ namespace XDM.Core.UI
IPlatformClipboardMonitor GetClipboardMonitor(); IPlatformClipboardMonitor GetClipboardMonitor();
void ShowAndActivate();
event EventHandler<CategoryChangedEventArgs> CategoryChanged; event EventHandler<CategoryChangedEventArgs> CategoryChanged;
event EventHandler InProgressContextMenuOpening; event EventHandler InProgressContextMenuOpening;

View File

@ -9,6 +9,7 @@
<Import_RootNamespace>XDM.Core</Import_RootNamespace> <Import_RootNamespace>XDM.Core</Import_RootNamespace>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)SingleInstance.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Updater\AppUpdater.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Updater\AppUpdater.cs" />
<Compile Include="$(MSBuildThisFileDirectory)ClipboardMonitor.cs" /> <Compile Include="$(MSBuildThisFileDirectory)ClipboardMonitor.cs" />
<Compile Include="$(MSBuildThisFileDirectory)IO\RequestDataIO.cs" /> <Compile Include="$(MSBuildThisFileDirectory)IO\RequestDataIO.cs" />
@ -28,13 +29,13 @@
<Compile Include="$(MSBuildThisFileDirectory)LinkRefresher.cs" /> <Compile Include="$(MSBuildThisFileDirectory)LinkRefresher.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Links.cs" /> <Compile Include="$(MSBuildThisFileDirectory)Links.cs" />
<Compile Include="..\XDM.Core\ApplicationContext.cs" /> <Compile Include="..\XDM.Core\ApplicationContext.cs" />
<Compile Include="$(MSBuildThisFileDirectory)BrowserMonitoring\BrowserMessageHandler.cs" /> <Compile Include="$(MSBuildThisFileDirectory)BrowserMonitoring\IpcPipeMessageProcessor.cs" />
<Compile Include="$(MSBuildThisFileDirectory)BrowserMonitoring\BrowserMonitor.cs" /> <Compile Include="$(MSBuildThisFileDirectory)BrowserMonitoring\BrowserMonitor.cs" />
<Compile Include="$(MSBuildThisFileDirectory)BrowserMonitoring\IpcHttpHandler.cs" /> <Compile Include="$(MSBuildThisFileDirectory)BrowserMonitoring\IpcHttpMessageProcessor.cs" />
<Compile Include="$(MSBuildThisFileDirectory)BrowserMonitoring\JsonMessageParser.cs" /> <Compile Include="$(MSBuildThisFileDirectory)BrowserMonitoring\JsonMessageParser.cs" />
<Compile Include="$(MSBuildThisFileDirectory)BrowserMonitoring\NativeMessagingConfigurer.cs" /> <Compile Include="$(MSBuildThisFileDirectory)BrowserMonitoring\NativeMessagingConfigurer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)BrowserMonitoring\NativeMessagingHostChannel.cs" /> <Compile Include="$(MSBuildThisFileDirectory)BrowserMonitoring\PipeChannel.cs" />
<Compile Include="$(MSBuildThisFileDirectory)BrowserMonitoring\NativeMessagingHostHandler.cs" /> <Compile Include="..\XDM.Core\BrowserMonitoring\IpcPipe.cs" />
<Compile Include="$(MSBuildThisFileDirectory)BrowserMonitoring\VideoUrlHelper.cs" /> <Compile Include="$(MSBuildThisFileDirectory)BrowserMonitoring\VideoUrlHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HttpServer\HttpParser.cs" /> <Compile Include="$(MSBuildThisFileDirectory)HttpServer\HttpParser.cs" />
<Compile Include="$(MSBuildThisFileDirectory)HttpServer\HttpServer.cs" /> <Compile Include="$(MSBuildThisFileDirectory)HttpServer\HttpServer.cs" />

View File

@ -135,12 +135,7 @@ namespace XDM.GtkUI
private void StatusIcon_Activate(object? sender, EventArgs e) private void StatusIcon_Activate(object? sender, EventArgs e)
{ {
if (!this.Visible) ShowAndActivate();
{
this.Show();
}
//this.Deiconify();
this.Present();
} }
private void CreateMenu() private void CreateMenu()
@ -1306,8 +1301,13 @@ namespace XDM.GtkUI
public IPlatformClipboardMonitor GetClipboardMonitor() => this.clipboarMonitor; public IPlatformClipboardMonitor GetClipboardMonitor() => this.clipboarMonitor;
public void ShowFloatingWidget() public void ShowAndActivate()
{ {
if (!this.Visible)
{
this.Show();
}
this.Present();
} }
} }
} }

View File

@ -101,18 +101,7 @@ namespace XDM.GtkUI
.RegisterPlatformUIService(new GtkPlatformUIService()) .RegisterPlatformUIService(new GtkPlatformUIService())
.Configure(); .Configure();
var commandOptions = ArgsProcessor.ParseArgs(args, 0); ArgsProcessor.Process(args, 0);
if (!commandOptions.ContainsKey("-m"))
{
win.Show();
if (commandOptions.ContainsKey("-i"))
{
Config.Instance.RunOnLogon = true;
Config.SaveConfig();
ApplicationContext.PlatformUIService.ShowBrowserMonitoringDialog();
}
}
//var t = new System.Threading.Thread(() => //var t = new System.Threading.Thread(() =>
// { // {

View File

@ -70,30 +70,13 @@ namespace XDM.Wpf.UI
.RegisterPlatformUIService(new WpfPlatformUIService()) .RegisterPlatformUIService(new WpfPlatformUIService())
.Configure(); .Configure();
var args = Environment.GetCommandLineArgs(); ArgsProcessor.Process(Environment.GetCommandLineArgs(), 1);
var commandOptions = ArgsProcessor.ParseArgs(args, 1);
AppTrayIcon.AttachToSystemTray(); AppTrayIcon.AttachToSystemTray();
AppTrayIcon.TrayClick += (_, _) => AppTrayIcon.TrayClick += (_, _) =>
{ {
win.Show(); win.ShowAndActivate();
if (win.WindowState == WindowState.Minimized)
{
win.WindowState = WindowState.Normal;
}
win.Activate();
}; };
if (!commandOptions.ContainsKey("-m"))
{
win.Show();
if (commandOptions.ContainsKey("-i"))
{
Config.Instance.RunOnLogon = true;
Config.SaveConfig();
ApplicationContext.PlatformUIService.ShowBrowserMonitoringDialog();
}
}
} }
private void Application_Exit(object sender, ExitEventArgs e) private void Application_Exit(object sender, ExitEventArgs e)

View File

@ -707,5 +707,15 @@ namespace XDM.Wpf.UI
} }
public IPlatformClipboardMonitor GetClipboardMonitor() => this.clipboarMonitor; public IPlatformClipboardMonitor GetClipboardMonitor() => this.clipboarMonitor;
public void ShowAndActivate()
{
this.Show();
if (this.WindowState == WindowState.Minimized)
{
this.WindowState = WindowState.Normal;
}
this.Activate();
}
} }
} }

View File

@ -1,8 +1,7 @@
{ {
"profiles": { "profiles": {
"XDM.Wpf.UI": { "XDM.Wpf.UI": {
"commandName": "Project", "commandName": "Project"
"commandLineArgs": "-u http://abc/xyz"
} }
} }
} }

View File

@ -15,10 +15,12 @@
<Description>Xtreme Download Manager</Description> <Description>Xtreme Download Manager</Description>
<AssemblyTitle>Xtreme Download Manager</AssemblyTitle> <AssemblyTitle>Xtreme Download Manager</AssemblyTitle>
<AssemblyVersion>8.0.1</AssemblyVersion> <AssemblyVersion>8.0.1</AssemblyVersion>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net4.7.2|x86'"> <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net4.7.2|x86'">
<Optimize>true</Optimize> <Optimize>true</Optimize>
<DefineConstants>DEBUG;TRACE</DefineConstants>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net4.7.2|x64'"> <PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|net4.7.2|x64'">