Merge pull request #8 from SlothDpal/working

Minor fix
This commit is contained in:
Vladimir
2025-09-27 22:08:58 +04:00
committed by GitHub
8 changed files with 130 additions and 27 deletions

View File

@@ -47,6 +47,9 @@
<setting name="closeFreezeProcess" serializeAs="String"> <setting name="closeFreezeProcess" serializeAs="String">
<value>True</value> <value>True</value>
</setting> </setting>
<setting name="upgradeSettings" serializeAs="String">
<value>True</value>
</setting>
</RelaunchProcess.Properties.Settings> </RelaunchProcess.Properties.Settings>
</userSettings> </userSettings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup> <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup>

View File

@@ -12,20 +12,33 @@ namespace Discord.Webhook
public class DiscordWebhook public class DiscordWebhook
{ {
public string Url { get; set; } public string Url { get; set; }
public int queueRetryCount = 3;
public int sendTimeoutSeconds = 5;
private UInt64 queueNum = 0; private UInt64 totalMessages = 0;
private readonly ConcurrentQueue<(UInt64 num, DiscordMessage message, FileInfo[] files)> _queue = new ConcurrentQueue<(UInt64 num, DiscordMessage, FileInfo[])>(); private ConcurrentQueue<(UInt64 num, DiscordMessage message, FileInfo[] files)> _queue = new ConcurrentQueue<(UInt64 num, DiscordMessage, FileInfo[])>();
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1); private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
private bool _isProcessing; private bool _isProcessing;
private CancellationTokenSource _cts = new CancellationTokenSource();
private int queueErrorCounter = 0;
private int queueSuppressedCounter = 0;
private HttpRequestException lastHpptEx = null;
public async Task SendAsync(DiscordMessage message, params FileInfo[] files) public UInt64 TotalMessages => totalMessages;
public int QueueSize => _queue.Count;
public void CancelProcessing() => _cts.Cancel();
public int ErrorCount => queueErrorCounter;
public bool IsProcessing => _isProcessing;
public HttpRequestException LastHpptEx => lastHpptEx;
public async Task<bool> SendAsync(DiscordMessage message, params FileInfo[] files)
{ {
if (string.IsNullOrEmpty(Url)) if (string.IsNullOrEmpty(Url))
throw new ArgumentNullException("Invalid Webhook URL."); throw new ArgumentNullException("Invalid Webhook URL.");
string boundary = "------------------------" + DateTime.Now.Ticks.ToString("x"); string boundary = "------------------------" + DateTime.Now.Ticks.ToString("x");
using (var client = new HttpClient() { Timeout = TimeSpan.FromSeconds(30) }) using (var client = new HttpClient() { Timeout = TimeSpan.FromSeconds(sendTimeoutSeconds) })
using (var content = new MultipartFormDataContent(boundary)) using (var content = new MultipartFormDataContent(boundary))
{ {
// Добавляем JSON payload // Добавляем JSON payload
@@ -54,48 +67,96 @@ namespace Discord.Webhook
try try
{ {
var response = await client.PostAsync(Url, content); var response = await client.PostAsync(Url, content, _cts.Token);
response.EnsureSuccessStatusCode(); response.EnsureSuccessStatusCode();
} }
catch (HttpRequestException ex) catch (HttpRequestException ex)
{ {
Debug.WriteLine($"Discord webhook request failed: {ex.Message}"); Debug.WriteLine($"SendAsync: Discord webhook request failed: {ex.Message}");
lastHpptEx = ex;
return false;
}
catch (TaskCanceledException ex)
{
Debug.WriteLine($"SendAsync: Discord webhook request cancelled: {ex.Message}");
return false;
} }
} }
return true;
} }
private async Task ProcessQueueAsync() private async Task ProcessQueueAsync()
{ {
while (_queue.TryDequeue(out var item)) queueErrorCounter = 0;
while (_queue.TryPeek(out var item))
{ {
if (_cts.Token.IsCancellationRequested)
{
Debug.WriteLine("ProcessQueueAsync: Discord queue processing cancelled.");
break;
}
await _semaphore.WaitAsync(); await _semaphore.WaitAsync();
try try
{ {
Debug.WriteLine($"Processing message {item.num}. Queue size: {_queue.Count}"); Debug.WriteLine($"ProcessQueueAsync: Processing message {item.num}. Queue size: {_queue.Count}");
await SendAsync(item.message, item.files); if (await SendAsync(item.message, item.files))
Debug.WriteLine($"Message {item.num} sent."); {
_queue.TryDequeue(out var deqItem);
queueErrorCounter = 0;
}
else
{
queueErrorCounter++;
if (queueErrorCounter == queueRetryCount)
{
_queue.TryDequeue(out var deqItem);
queueErrorCounter = 0;
queueSuppressedCounter++;
Debug.WriteLine($"ProcessQueueAsync: Message dropped. Total messages dropped:{queueSuppressedCounter}. Queue size: {_queue.Count}.");
}
}
} }
finally finally
{ {
_semaphore.Release(); _semaphore.Release();
} }
Task.Delay(500).Wait(); try
{
await Task.Delay(1000, _cts.Token); // Discord rate limit: 1 message per second
}
catch (TaskCanceledException)
{
Debug.WriteLine($"ProcessQueueAsync: Discord queue processing cancelled during delay. Was {_queue.Count} messages in queue. {totalMessages} messages in session. ");
break;
}
} }
if ( _cts.IsCancellationRequested)
{
Debug.WriteLine($"ProcessQueueAsync: Discord queue processing cancelled. Was {_queue.Count} messages in queue.");
Debug.WriteLine("Clearing queue.");
var _newqueue = new ConcurrentQueue<(UInt64 num, DiscordMessage, FileInfo[])>();
Interlocked.Exchange(ref _queue, _newqueue);
}
Debug.WriteLine($"ProcessQueueAsync: Discord queue processing finished.");
_isProcessing = false; _isProcessing = false;
} }
public void Send(DiscordMessage message, params FileInfo[] files) public void Send(DiscordMessage message, params FileInfo[] files)
{ {
_queue.Enqueue((queueNum++, message, files)); _queue.Enqueue((totalMessages++, message, files));
Debug.WriteLine($"Message {queueNum-1} added. Queue size: {_queue.Count}"); Debug.WriteLine($"Message {totalMessages-1} added. Queue size: {_queue.Count}");
if (_isProcessing) if (_isProcessing)
{ {
Debug.WriteLine("Already processing queue."); Debug.WriteLine("Already processing queue.");
return; return;
} }
Debug.WriteLine("Run ProcessQueueAsync"); Debug.WriteLine("Run ProcessQueueAsync");
_cts.Dispose();
_cts = new CancellationTokenSource();
_isProcessing = true; _isProcessing = true;
Task.Run(ProcessQueueAsync); Task.Run(ProcessQueueAsync);
return;
} }
} }
} }

View File

@@ -9,15 +9,19 @@ using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Windows.Forms; using System.Windows.Forms;
using Process_Auto_Relaunch;
using RelaunchProcess.Properties; using RelaunchProcess.Properties;
namespace RelaunchProcess namespace RelaunchProcess
{ {
public partial class WebhookSettings : Form public partial class WebhookSettings : Form
{ {
public WebhookSettings() private Form1 parent;
public WebhookSettings(Form1 _parent)
{ {
InitializeComponent(); InitializeComponent();
parent = _parent;
RestoreSettings(); RestoreSettings();
} }
@@ -64,6 +68,10 @@ namespace RelaunchProcess
{ {
chbxDiscordEnabled.Checked = false; chbxDiscordEnabled.Checked = false;
} }
if (!chbxDiscordEnabled.Checked)
{
parent.dwhHook.CancelProcessing();
}
SaveSettings(); SaveSettings();
DialogResult = DialogResult.OK; DialogResult = DialogResult.OK;
Close(); Close();

View File

@@ -15,7 +15,7 @@ using RelaunchProcess;
using System.Timers; using System.Timers;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Configuration;
namespace Process_Auto_Relaunch namespace Process_Auto_Relaunch
{ {
@@ -32,7 +32,7 @@ namespace Process_Auto_Relaunch
} }
private delegate void UpdateLogDelegate(string text, NotifyLevel level = NotifyLevel.logUpdateStatus); private delegate void UpdateLogDelegate(string text, NotifyLevel level = NotifyLevel.logUpdateStatus);
private readonly UpdateLogDelegate updateLogDelegate; private readonly UpdateLogDelegate updateLogDelegate;
private DiscordWebhook dwhHook; public DiscordWebhook dwhHook;
private DiscordMessage dwhMessage; private DiscordMessage dwhMessage;
private Process WatchedProcess; private Process WatchedProcess;
private double cpuLastTime = 0; private double cpuLastTime = 0;
@@ -47,6 +47,24 @@ namespace Process_Auto_Relaunch
public Form1() public Form1()
{ {
InitializeComponent(); InitializeComponent();
if (Settings.Default.upgradeSettings)
{
Debug.WriteLine("Обновление настроек.");
try
{
Settings.Default.Upgrade();
}
catch (ConfigurationErrorsException ex)
{
Debug.WriteLine($"Ошибка обновления настроек: {ex.Message}");
Settings.Default.Reset();
}
finally
{
Settings.Default.upgradeSettings = false;
Settings.Default.Save();
}
}
this.updateLogDelegate = this.UpdateStatus; this.updateLogDelegate = this.UpdateStatus;
this.updateLogDelegate += this.SendDiscordMessage; this.updateLogDelegate += this.SendDiscordMessage;
this.updateLogDelegate += this.HistoryLog; this.updateLogDelegate += this.HistoryLog;
@@ -249,8 +267,9 @@ namespace Process_Auto_Relaunch
/// <param name="e"></param> /// <param name="e"></param>
private void Form1_FormClosing(object sender, FormClosingEventArgs e) private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{ {
Settings.Default.Save(); dwhHook.CancelProcessing();
Status("Наблюдение отменено - приложение закрыто.", NotifyLevel.logAlways); Status("Наблюдение отменено - приложение закрыто.", NotifyLevel.logAlways);
Settings.Default.Save();
} }
private bool ProcessByNameIsRuning(string name) private bool ProcessByNameIsRuning(string name)
@@ -476,7 +495,7 @@ namespace Process_Auto_Relaunch
private void webhookDiscordToolStripMenuItem_Click(object sender, EventArgs e) private void webhookDiscordToolStripMenuItem_Click(object sender, EventArgs e)
{ {
WebhookSettings discordSettings; WebhookSettings discordSettings;
discordSettings = new WebhookSettings(); discordSettings = new WebhookSettings(this);
discordSettings.ShowDialog(this); discordSettings.ShowDialog(this);
discordSettings.Dispose(); discordSettings.Dispose();
} }

View File

@@ -82,14 +82,11 @@
<Prefer32Bit>true</Prefer32Bit> <Prefer32Bit>true</Prefer32Bit>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="CSharpDiscordWebhook, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>.\CSharpDiscordWebhook.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL"> <Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>packages\Newtonsoft.Json.13.0.4\lib\net45\Newtonsoft.Json.dll</HintPath> <HintPath>packages\Newtonsoft.Json.13.0.4\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference> </Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />

View File

@@ -29,7 +29,7 @@ using System.Runtime.InteropServices;
// Номер сборки // Номер сборки
// Редакция // Редакция
// //
[assembly: AssemblyVersion("1.6.0.0")] [assembly: AssemblyVersion("1.6.1.2")]
[assembly: AssemblyFileVersion("1.6.0.0")] [assembly: AssemblyFileVersion("1.6.1.2")]
[assembly: AssemblyInformationalVersion("1.6.0.0")] [assembly: AssemblyInformationalVersion("1.6.1.2")]

View File

@@ -1,4 +1,4 @@
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// <auto-generated> // <auto-generated>
// Этот код создан программой. // Этот код создан программой.
// Исполняемая версия:4.0.30319.42000 // Исполняемая версия:4.0.30319.42000
@@ -12,7 +12,7 @@ namespace RelaunchProcess.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.10.0.0")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -179,5 +179,17 @@ namespace RelaunchProcess.Properties {
this["closeFreezeProcess"] = value; this["closeFreezeProcess"] = value;
} }
} }
[global::System.Configuration.UserScopedSettingAttribute()]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Configuration.DefaultSettingValueAttribute("True")]
public bool upgradeSettings {
get {
return ((bool)(this["upgradeSettings"]));
}
set {
this["upgradeSettings"] = value;
}
}
} }
} }

View File

@@ -41,5 +41,8 @@
<Setting Name="closeFreezeProcess" Type="System.Boolean" Scope="User"> <Setting Name="closeFreezeProcess" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value> <Value Profile="(Default)">True</Value>
</Setting> </Setting>
<Setting Name="upgradeSettings" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">True</Value>
</Setting>
</Settings> </Settings>
</SettingsFile> </SettingsFile>