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

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

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

@ -67,8 +67,7 @@ namespace XDM.Core
public void StartBrowserMonitoring()
{
BrowserMonitor.RunNativeHostHandler();
BrowserMonitor.RunHttpIpcHandler();
BrowserMonitor.Run();
}
public string? StartDownload(
@ -120,11 +119,12 @@ namespace XDM.Core
}
http.SetFileName(FileHelper.SanitizeFileName(fileName), fileNameFetchMode);
http.SetTargetDirectory(targetFolder);
StartDownload(http, startImmediately, authentication, proxyInfo);
StartDownload(http, targetFolder, startImmediately, authentication, proxyInfo);
return http.Id;
}
private void StartDownload(IBaseDownloader download,
string? targetDir,
bool startImmediately,
AuthenticationInfo? authentication,
ProxyInfo? proxyInfo)
@ -147,7 +147,7 @@ namespace XDM.Core
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.PrimaryUrl?.ToString(), startType, authentication,
proxyInfo);

@ -8,8 +8,9 @@ namespace XDM.Core
{
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"))
{
var url = args["-u"];
@ -18,9 +19,28 @@ namespace XDM.Core
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 key = string.Empty;

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

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

@ -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);
}
}
}
}

@ -7,9 +7,9 @@ using XDM.Core.Util;
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);
if (envelop.MessageType == "videoIds")
@ -32,10 +32,9 @@ namespace XDM.Core.BrowserMonitoring
return;
}
if (envelop.MessageType == "custom")
if (envelop.MessageType == "custom" && envelop.CustomData != null)
{
var args = ArgsProcessor.ParseArgs(envelop.CustomData.Split('\r'));
ArgsProcessor.Process(args);
ArgsProcessor.Process(envelop.CustomData.Split('\r'));
return;
}

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

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

@ -48,7 +48,8 @@ namespace XDM.Core
/// <param name="startType"></param>
/// <param name="authentication"></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,
string primaryUrl, DownloadStartType startType,
AuthenticationInfo? authentication, ProxyInfo? proxyInfo);

@ -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)
{
}
}
}

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

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

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

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

@ -70,30 +70,13 @@ namespace XDM.Wpf.UI
.RegisterPlatformUIService(new WpfPlatformUIService())
.Configure();
var args = Environment.GetCommandLineArgs();
var commandOptions = ArgsProcessor.ParseArgs(args, 1);
ArgsProcessor.Process(Environment.GetCommandLineArgs(), 1);
AppTrayIcon.AttachToSystemTray();
AppTrayIcon.TrayClick += (_, _) =>
{
win.Show();
if (win.WindowState == WindowState.Minimized)
{
win.WindowState = WindowState.Normal;
}
win.Activate();
win.ShowAndActivate();
};
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)

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

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

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