commit 4267bd2a39538423d4ec0c3cb502f00270f49fae Author: msnabila Date: Wed Jul 29 14:15:27 2026 +0700 Upload file project #project Perbandingan UPSNet-2026-3 diff --git a/.vs/UPSNet-2026-3.slnx/FileContentIndex/c432e567-3dfa-43b9-8f1f-01f262887f97.vsidx b/.vs/UPSNet-2026-3.slnx/FileContentIndex/c432e567-3dfa-43b9-8f1f-01f262887f97.vsidx new file mode 100644 index 0000000..2dc227f Binary files /dev/null and b/.vs/UPSNet-2026-3.slnx/FileContentIndex/c432e567-3dfa-43b9-8f1f-01f262887f97.vsidx differ diff --git a/.vs/UPSNet-2026-3.slnx/v18/.wsuo b/.vs/UPSNet-2026-3.slnx/v18/.wsuo new file mode 100644 index 0000000..ffd1816 Binary files /dev/null and b/.vs/UPSNet-2026-3.slnx/v18/.wsuo differ diff --git a/.vs/UPSNet-2026-3.slnx/v18/DocumentLayout.backup.json b/.vs/UPSNet-2026-3.slnx/v18/DocumentLayout.backup.json new file mode 100644 index 0000000..25b7acd --- /dev/null +++ b/.vs/UPSNet-2026-3.slnx/v18/DocumentLayout.backup.json @@ -0,0 +1,12 @@ +{ + "Version": 1, + "WorkspaceRootPath": "D:\\#project\\Perbandingan\\UPSNet-2026-3\\", + "Documents": [], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [] + } + ] +} \ No newline at end of file diff --git a/.vs/UPSNet-2026-3.slnx/v18/DocumentLayout.json b/.vs/UPSNet-2026-3.slnx/v18/DocumentLayout.json new file mode 100644 index 0000000..25b7acd --- /dev/null +++ b/.vs/UPSNet-2026-3.slnx/v18/DocumentLayout.json @@ -0,0 +1,12 @@ +{ + "Version": 1, + "WorkspaceRootPath": "D:\\#project\\Perbandingan\\UPSNet-2026-3\\", + "Documents": [], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [] + } + ] +} \ No newline at end of file diff --git a/.vs/VSWorkspaceState.json b/.vs/VSWorkspaceState.json new file mode 100644 index 0000000..686c2a4 --- /dev/null +++ b/.vs/VSWorkspaceState.json @@ -0,0 +1,8 @@ +{ + "ExpandedNodes": [ + "", + "\\UPSNet" + ], + "SelectedNode": "\\UPSNet\\UPSNet.csproj", + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite new file mode 100644 index 0000000..af26555 Binary files /dev/null and b/.vs/slnx.sqlite differ diff --git a/UPSNet/.vs/UPSNet.slnx/FileContentIndex/0bfc2b56-dd91-4122-8ac2-87a1dcc2e66c.vsidx b/UPSNet/.vs/UPSNet.slnx/FileContentIndex/0bfc2b56-dd91-4122-8ac2-87a1dcc2e66c.vsidx new file mode 100644 index 0000000..e7506a9 Binary files /dev/null and b/UPSNet/.vs/UPSNet.slnx/FileContentIndex/0bfc2b56-dd91-4122-8ac2-87a1dcc2e66c.vsidx differ diff --git a/UPSNet/.vs/UPSNet.slnx/FileContentIndex/2f22c610-1595-4ab0-a3b7-2bf93a07d1d5.vsidx b/UPSNet/.vs/UPSNet.slnx/FileContentIndex/2f22c610-1595-4ab0-a3b7-2bf93a07d1d5.vsidx new file mode 100644 index 0000000..c562a5d Binary files /dev/null and b/UPSNet/.vs/UPSNet.slnx/FileContentIndex/2f22c610-1595-4ab0-a3b7-2bf93a07d1d5.vsidx differ diff --git a/UPSNet/.vs/UPSNet.slnx/v18/.wsuo b/UPSNet/.vs/UPSNet.slnx/v18/.wsuo new file mode 100644 index 0000000..9bcdff2 Binary files /dev/null and b/UPSNet/.vs/UPSNet.slnx/v18/.wsuo differ diff --git a/UPSNet/.vs/UPSNet.slnx/v18/DocumentLayout.backup.json b/UPSNet/.vs/UPSNet.slnx/v18/DocumentLayout.backup.json new file mode 100644 index 0000000..2a1c96c --- /dev/null +++ b/UPSNet/.vs/UPSNet.slnx/v18/DocumentLayout.backup.json @@ -0,0 +1,12 @@ +{ + "Version": 1, + "WorkspaceRootPath": "D:\\#project\\Perbandingan\\UPSNet-2026-3\\UPSNet\\", + "Documents": [], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [] + } + ] +} \ No newline at end of file diff --git a/UPSNet/.vs/UPSNet.slnx/v18/DocumentLayout.json b/UPSNet/.vs/UPSNet.slnx/v18/DocumentLayout.json new file mode 100644 index 0000000..2a1c96c --- /dev/null +++ b/UPSNet/.vs/UPSNet.slnx/v18/DocumentLayout.json @@ -0,0 +1,12 @@ +{ + "Version": 1, + "WorkspaceRootPath": "D:\\#project\\Perbandingan\\UPSNet-2026-3\\UPSNet\\", + "Documents": [], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [] + } + ] +} \ No newline at end of file diff --git a/UPSNet/.vs/UPSNet/FileContentIndex/4caadc99-00b9-41ec-b01d-f3bfee398a8e.vsidx b/UPSNet/.vs/UPSNet/FileContentIndex/4caadc99-00b9-41ec-b01d-f3bfee398a8e.vsidx new file mode 100644 index 0000000..4c33a61 Binary files /dev/null and b/UPSNet/.vs/UPSNet/FileContentIndex/4caadc99-00b9-41ec-b01d-f3bfee398a8e.vsidx differ diff --git a/UPSNet/.vs/UPSNet/FileContentIndex/adf74ec9-900f-4971-b94d-2daf9651ade5.vsidx b/UPSNet/.vs/UPSNet/FileContentIndex/adf74ec9-900f-4971-b94d-2daf9651ade5.vsidx new file mode 100644 index 0000000..dfbc90c Binary files /dev/null and b/UPSNet/.vs/UPSNet/FileContentIndex/adf74ec9-900f-4971-b94d-2daf9651ade5.vsidx differ diff --git a/UPSNet/.vs/UPSNet/FileContentIndex/f945b330-4983-41e9-9b54-61c3019145ea.vsidx b/UPSNet/.vs/UPSNet/FileContentIndex/f945b330-4983-41e9-9b54-61c3019145ea.vsidx new file mode 100644 index 0000000..076aad1 Binary files /dev/null and b/UPSNet/.vs/UPSNet/FileContentIndex/f945b330-4983-41e9-9b54-61c3019145ea.vsidx differ diff --git a/UPSNet/.vs/UPSNet/v18/.suo b/UPSNet/.vs/UPSNet/v18/.suo new file mode 100644 index 0000000..2820dfb Binary files /dev/null and b/UPSNet/.vs/UPSNet/v18/.suo differ diff --git a/UPSNet/.vs/UPSNet/v18/DocumentLayout.backup.json b/UPSNet/.vs/UPSNet/v18/DocumentLayout.backup.json new file mode 100644 index 0000000..2a1c96c --- /dev/null +++ b/UPSNet/.vs/UPSNet/v18/DocumentLayout.backup.json @@ -0,0 +1,12 @@ +{ + "Version": 1, + "WorkspaceRootPath": "D:\\#project\\Perbandingan\\UPSNet-2026-3\\UPSNet\\", + "Documents": [], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [] + } + ] +} \ No newline at end of file diff --git a/UPSNet/.vs/UPSNet/v18/DocumentLayout.json b/UPSNet/.vs/UPSNet/v18/DocumentLayout.json new file mode 100644 index 0000000..2a1c96c --- /dev/null +++ b/UPSNet/.vs/UPSNet/v18/DocumentLayout.json @@ -0,0 +1,12 @@ +{ + "Version": 1, + "WorkspaceRootPath": "D:\\#project\\Perbandingan\\UPSNet-2026-3\\UPSNet\\", + "Documents": [], + "DocumentGroupContainers": [ + { + "Orientation": 0, + "VerticalTabListWidth": 256, + "DocumentGroups": [] + } + ] +} \ No newline at end of file diff --git a/UPSNet/.vs/VSWorkspaceState.json b/UPSNet/.vs/VSWorkspaceState.json new file mode 100644 index 0000000..6b61141 --- /dev/null +++ b/UPSNet/.vs/VSWorkspaceState.json @@ -0,0 +1,6 @@ +{ + "ExpandedNodes": [ + "" + ], + "PreviewInSolutionExplorer": false +} \ No newline at end of file diff --git a/UPSNet/.vs/slnx.sqlite b/UPSNet/.vs/slnx.sqlite new file mode 100644 index 0000000..074331e Binary files /dev/null and b/UPSNet/.vs/slnx.sqlite differ diff --git a/UPSNet/AppConfig.cs b/UPSNet/AppConfig.cs new file mode 100644 index 0000000..347daf5 --- /dev/null +++ b/UPSNet/AppConfig.cs @@ -0,0 +1,128 @@ +//string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + // Store config in application directory +// string appData = AppDomain.CurrentDomain.BaseDirectory; + +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace UPSNet +{ + public static class AppConfig + { + private static readonly string ConfigFilePath; + private static Dictionary _settings; + + public static bool exists = false; + + static AppConfig() { + // Store config in application directory + ConfigFilePath = Path.Combine( + AppDomain.CurrentDomain.BaseDirectory, + "config.json"); + + _settings = new Dictionary(); + exists = LoadSettings(); + } + + public static string Get(string key, string defaultValue = "") + { + return _settings.ContainsKey(key) ? _settings[key] : defaultValue; + } + + public static int GetInt(string key, int defaultValue = 0) + { + int result; + return _settings.ContainsKey(key) && int.TryParse(_settings[key], out result) + ? result + : defaultValue; + } + + public static bool GetBool(string key, bool defaultValue = false) + { + bool result; + return _settings.ContainsKey(key) && bool.TryParse(_settings[key], out result) + ? result + : defaultValue; + } + + public static void Set(string key, string value) + { + _settings[key] = value; + //SaveSettings(); + } + + public static void Set(string key, int value) + { + _settings[key] = value.ToString(); + //SaveSettings(); + } + + public static void Set(string key, bool value) + { + _settings[key] = value.ToString().ToLower(); + //SaveSettings(); + } + + public static bool LoadSettings() + { + if (!File.Exists(ConfigFilePath)) return false; + + try + { + string json = File.ReadAllText(ConfigFilePath); + json = json.Trim('{', '}', ' ', '\t', '\n', '\r'); + + string[] pairs = json.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + foreach (string pair in pairs) + { + string[] parts = pair.Split(new[] { ':' }, 2); + if (parts.Length == 2) + { + string key = parts[0].Trim().Trim('"'); + string value = parts[1].Trim().Trim('"'); + _settings[key] = value; + } + } + return true; + } + catch + { + // Reset if loading fails + _settings = new Dictionary(); + return false; + } + //return false; + } + + public static void SaveSettings() + { + try + { + StringBuilder sb = new StringBuilder(); + sb.Append("{"); + + bool first = true; + foreach (KeyValuePair kvp in _settings) + { + if (!first) sb.Append(","); + first = false; + + sb.Append("\""); + sb.Append(kvp.Key); + sb.Append("\":\""); + sb.Append(kvp.Value); + sb.Append("\""); + } + + sb.Append("}"); + File.WriteAllText(ConfigFilePath, sb.ToString()); + } + catch + { + // Ignore save errors + } + } + } +} \ No newline at end of file diff --git a/UPSNet/BackgroudTimer.cs b/UPSNet/BackgroudTimer.cs new file mode 100644 index 0000000..b2fd396 --- /dev/null +++ b/UPSNet/BackgroudTimer.cs @@ -0,0 +1,108 @@ +//example of use: +//// In your UPS monitoring class +//private readonly BackgroundTimer _monitoringTimer; +// +//public UPSMonitor() +//{ +// _monitoringTimer = new BackgroundTimer(CheckUPSStatus, 1000); +//} +// +//private void CheckUPSStatus() +//{ +// var charge = GetBatteryCharge(); +// if (charge < 10) EmergencyShutdown(); +//} + +using System; +using System.Threading; + +namespace UPSNet +{ + public class BackgroundTimer : IDisposable + { + private readonly Timer _timer; + private readonly Action _callback; + private readonly int _intervalMs; + private volatile bool _isRunning; + private readonly object _lock = new object(); + + public BackgroundTimer(Action callback, int intervalMs, bool startImmediately = true) + { + if (callback == null) + { + throw new ArgumentNullException("callback"); + } + + _callback = callback; + _intervalMs = intervalMs; + _timer = new Timer(TimerCallback, null, Timeout.Infinite, Timeout.Infinite); + + if (startImmediately) + { + Start(); + } + } + + public void Start() + { + lock (_lock) + { + if (!_isRunning) + { + _isRunning = true; + _timer.Change(0, _intervalMs); + } + } + } + + public void Stop() + { + lock (_lock) + { + if (_isRunning) + { + _isRunning = false; + _timer.Change(Timeout.Infinite, Timeout.Infinite); + } + } + } + + private void TimerCallback(object state) + { + if (!_isRunning || !Monitor.TryEnter(_lock)) + return; + + try + { + if (_isRunning) + { + _callback.Invoke(); + } + } + catch + { + // Suppress errors to prevent thread crashes + } + finally + { + Monitor.Exit(_lock); + } + } + + public void Dispose() + { + Stop(); + _timer.Dispose(); + } + + public void Restart(int newIntervalMs) + { + lock (_lock) + { + Stop(); + _timer.Change(newIntervalMs, newIntervalMs); + _isRunning = true; + } + } + } +} \ No newline at end of file diff --git a/UPSNet/ConfigForm.Designer.cs b/UPSNet/ConfigForm.Designer.cs new file mode 100644 index 0000000..024fe24 --- /dev/null +++ b/UPSNet/ConfigForm.Designer.cs @@ -0,0 +1,137 @@ +/* + * Created by SharpDevelop. + * User: EVXIO + * Date: 4/4/2025 + * Time: 1:59 AM + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ +namespace UPSNet +{ + partial class ConfigForm + { + /// + /// Designer variable used to keep track of non-visual components. + /// + private System.ComponentModel.IContainer components = null; + private System.Windows.Forms.Label labelAddress; + private System.Windows.Forms.TextBox textBoxAddress; + private System.Windows.Forms.Label labelShutMode; + private System.Windows.Forms.ComboBox comboBoxShutMode; + private System.Windows.Forms.Button buttonCancel; + private System.Windows.Forms.Button buttonOk; + + /// + /// Disposes resources used by the form. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing) { + if (components != null) { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + /// + /// This method is required for Windows Forms designer support. + /// Do not change the method contents inside the source code editor. The Forms designer might + /// not be able to load this method if it was changed manually. + /// + private void InitializeComponent(){ + this.labelAddress = new System.Windows.Forms.Label(); + this.textBoxAddress = new System.Windows.Forms.TextBox(); + this.labelShutMode = new System.Windows.Forms.Label(); + this.comboBoxShutMode = new System.Windows.Forms.ComboBox(); + this.buttonCancel = new System.Windows.Forms.Button(); + this.buttonOk = new System.Windows.Forms.Button(); + this.SuspendLayout(); + // + // labelAddress + // + this.labelAddress.Location = new System.Drawing.Point(12, 9); + this.labelAddress.Name = "labelAddress"; + this.labelAddress.Size = new System.Drawing.Size(88, 20); + this.labelAddress.TabIndex = 0; + this.labelAddress.Text = "UPS Address"; + // + // textBoxAddress + // + this.textBoxAddress.Location = new System.Drawing.Point(106, 6); + this.textBoxAddress.MaxLength = 200; + this.textBoxAddress.Name = "textBoxAddress"; + this.textBoxAddress.Size = new System.Drawing.Size(146, 20); + this.textBoxAddress.TabIndex = 1; + this.textBoxAddress.Text = "192.168.0.99"; + // + // labelShutMode + // + this.labelShutMode.Location = new System.Drawing.Point(12, 43); + this.labelShutMode.Name = "labelShutMode"; + this.labelShutMode.Size = new System.Drawing.Size(88, 20); + this.labelShutMode.TabIndex = 2; + this.labelShutMode.Text = "Shutdown Mode"; + // + // comboBoxShutMode + // + this.comboBoxShutMode.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBoxShutMode.FormattingEnabled = true; + this.comboBoxShutMode.Items.AddRange(new object[] { + "Use UPS Suggestion", + "Disabled", + "On Battery (AC Loss)", + "≤75% Battery", + "≤50% Battery", + "≤25% Battery", + "Battery Critical"}); + this.comboBoxShutMode.Location = new System.Drawing.Point(106, 40); + this.comboBoxShutMode.Name = "comboBoxShutMode"; + this.comboBoxShutMode.Size = new System.Drawing.Size(146, 21); + this.comboBoxShutMode.TabIndex = 3; + // + // buttonCancel + // + this.buttonCancel.Location = new System.Drawing.Point(189, 71); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.Size = new System.Drawing.Size(63, 23); + this.buttonCancel.TabIndex = 4; + this.buttonCancel.Text = "Cancel"; + this.buttonCancel.UseVisualStyleBackColor = true; + this.buttonCancel.Click += new System.EventHandler(this.ButtonCancelClick); + // + // buttonOk + // + this.buttonOk.Location = new System.Drawing.Point(106, 70); + this.buttonOk.Name = "buttonOk"; + this.buttonOk.Size = new System.Drawing.Size(63, 23); + this.buttonOk.TabIndex = 5; + this.buttonOk.Text = "OK"; + this.buttonOk.UseVisualStyleBackColor = true; + this.buttonOk.Click += new System.EventHandler(this.ButtonOkClick); + // + // ConfigForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(278, 103); + this.Controls.Add(this.buttonOk); + this.Controls.Add(this.buttonCancel); + this.Controls.Add(this.comboBoxShutMode); + this.Controls.Add(this.labelShutMode); + this.Controls.Add(this.textBoxAddress); + this.Controls.Add(this.labelAddress); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "ConfigForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "EVXIO UPS Net - Configuration"; + this.Shown += new System.EventHandler(this.ConfigFormShown); + this.ResumeLayout(false); + this.PerformLayout(); + + } + } +} diff --git a/UPSNet/ConfigForm.cs b/UPSNet/ConfigForm.cs new file mode 100644 index 0000000..a5ab1e2 --- /dev/null +++ b/UPSNet/ConfigForm.cs @@ -0,0 +1,58 @@ +/* + * Created by SharpDevelop. + * User: EVXIO + * Date: 4/4/2025 + * Time: 1:59 AM + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace UPSNet +{ + /// + /// Description of ConfigForm. + /// + public partial class ConfigForm : Form { + public ConfigForm() { + // + // The InitializeComponent() call is required for Windows Forms designer support. + // + InitializeComponent(); + + // + // TODO: Add constructor code after the InitializeComponent() call. + // + LoadConfig(); + } + + void LoadConfig(){ + textBoxAddress.Text = UPSApp.deviceAddress; + int modeIdx = UPSApp.shutdownMode; + if (modeIdx<0) modeIdx = 0; + if (modeIdx>6) modeIdx = 6; + comboBoxShutMode.SelectedIndex = modeIdx; + } + + void ButtonCancelClick(object sender, EventArgs e) { + this.Close(); + } + + void ButtonOkClick(object sender, EventArgs e) { + UPSApp.deviceAddress = textBoxAddress.Text; + UPSApp.shutdownMode = comboBoxShutMode.SelectedIndex; + UPSApp.SaveConfig(); + UPSApp.RestartFetcher(); + UPSApp.dialogOk = true; + this.Close(); + } + + void ConfigFormShown(object sender, EventArgs e){ + LoadConfig(); + } + + + } +} diff --git a/UPSNet/ConfigForm.resx b/UPSNet/ConfigForm.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/UPSNet/ConfigForm.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/UPSNet/NotificationIcon.cs b/UPSNet/NotificationIcon.cs new file mode 100644 index 0000000..6332cab --- /dev/null +++ b/UPSNet/NotificationIcon.cs @@ -0,0 +1,241 @@ +/* + * Created by SharpDevelop. + * User: EVXIO + * Date: 4/3/2025 + * Time: 10:01 PM + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ +using System; +using System.Diagnostics; +using System.Drawing; +using System.Threading; +using System.Windows.Forms; + +using System.Text; + +namespace UPSNet { + public sealed class NotificationIcon { + private NotifyIcon notifyIcon; + private ContextMenu notificationMenu; + + private readonly BackgroundTimer _monitoringTimer; + + //UPSApp upsApp = new UPSApp(); + + private static NotificationIcon _instance; + + private static int lastState = -1; //for save cpu by checking state + + // Changed to .NET 4.0 compatible property + public static NotifyIcon NotifyIconInstance { + get { return _instance != null ? _instance.notifyIcon : null; } + } + + #region Initialize icon and menu + public NotificationIcon() { + _instance = this; + notifyIcon = new NotifyIcon(); + notificationMenu = new ContextMenu(InitializeMenu()); + + notifyIcon.BalloonTipText = "Application is running in the background"; + notifyIcon.BalloonTipTitle = "UPS Net v1.0"; + notifyIcon.BalloonTipIcon = ToolTipIcon.Info; + notifyIcon.Text = "UPS Net \nBattery: - "; // This is the regular tooltip + + notifyIcon.DoubleClick += IconDoubleClick; + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NotificationIcon)); + notifyIcon.Icon = (Icon)resources.GetObject("$this.Icon"); + notifyIcon.ContextMenu = notificationMenu; + + _monitoringTimer = new BackgroundTimer(CheckUPSStatus, 1000); + } + + private MenuItem[] InitializeMenu() { + MenuItem[] menu = new MenuItem[] + { + new MenuItem("Show", menuShowClick), + new MenuItem("-"), // Separator + new MenuItem("About", menuAboutClick), + new MenuItem("Exit", menuExitClick) + }; + + // Enable OwnerDraw for each MenuItem (except separators) + foreach (MenuItem item in menu) { + if (item.Text != "-") + { + item.OwnerDraw = true; + // Attach events to EACH MenuItem (not ContextMenu) + item.DrawItem += MenuItem_DrawItem; + item.MeasureItem += MenuItem_MeasureItem; + } + } + + return menu; + } + + // Handle drawing for EACH MenuItem + private void MenuItem_DrawItem(object sender, DrawItemEventArgs e){ + MenuItem menuItem = (MenuItem)sender; + + // Draw background + e.DrawBackground(); + + // Draw icon (if available) + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(NotificationIcon)); + Image icon = null; + switch (menuItem.Text) { + case "Show": icon = (Image) resources.GetObject("dashboard16"); break; + case "About": icon = (Image) resources.GetObject("info16"); break; + case "Exit": icon = (Image) resources.GetObject("close16"); break; + //case "About": icon = Properties.Resources.AboutIcon; break; + //case "Exit": icon = Properties.Resources.ExitIcon; break; + } + + if (icon != null){ + e.Graphics.DrawImage( + icon, + new Rectangle( + e.Bounds.X + 2, + e.Bounds.Y + (e.Bounds.Height - 16) / 2, + 16, + 16 + ) + ); + } + + // Draw text + TextRenderer.DrawText( + e.Graphics, + menuItem.Text, + SystemFonts.MenuFont, + new Rectangle(e.Bounds.X + 20, e.Bounds.Y, e.Bounds.Width - 20, e.Bounds.Height), + e.ForeColor, + TextFormatFlags.VerticalCenter | TextFormatFlags.Left + ); + } + + // Measure each MenuItem + private void MenuItem_MeasureItem(object sender, MeasureItemEventArgs e){ + MenuItem menuItem = (MenuItem)sender; + SizeF textSize = e.Graphics.MeasureString(menuItem.Text, SystemFonts.MenuFont); + e.ItemHeight = Math.Max(16, (int)textSize.Height) + 4; + e.ItemWidth = (int)textSize.Width + 20; // 16 (icon) + 4 (padding) + } + #endregion + + #region Main - Program entry point + /// Program entry point. + /// Command Line Arguments + [STAThread] + public static void Main(string[] args) { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + bool isFirstInstance; + // Please use a unique name for the mutex to prevent conflicts with other programs + using (Mutex mtx = new Mutex(true, "UPSNet", out isFirstInstance)) { + if (isFirstInstance) { + + UPSApp.Init(); + + NotificationIcon notificationIcon = new NotificationIcon(); + notificationIcon.notifyIcon.Visible = true; + + if (SynchronizationContext.Current == null) { + SynchronizationContext.SetSynchronizationContext(new System.Windows.Forms.WindowsFormsSynchronizationContext()); + } + UPSApp.uiContext = SynchronizationContext.Current; + + Application.Run(); + + notificationIcon.notifyIcon.Dispose(); + } else { + // The application is already running + // TODO: Display message box or change focus to existing application instance + } + } // releases the Mutex + } + #endregion + + #region Event Handlers + private void menuAboutClick(object sender, EventArgs e) { + MessageBox.Show( + "EVXIO UPS Net \nVersion 1.0.0 - Portable Edition \n\nCopyright ©2025 Victor Phoa. All Rights Reserved.", + "About - EVXIO UPS Net", + MessageBoxButtons.OK, + MessageBoxIcon.Information + ); + } + + private void menuExitClick(object sender, EventArgs e) { + Application.Exit(); + } + + private void IconDoubleClick(object sender, EventArgs e) { + UPSApp.ShowOrHideForm(); + //MessageBox.Show("The icon was double clicked"); + } + + private void menuShowClick(object sender, EventArgs e) { + UPSApp.ShowForm(); + //MessageBox.Show("The icon was double clicked"); + } + #endregion + + public static string RepeatString(string str, int count){ + if (count <= 0) return "";//string.Empty; + if (count == 1) return str; + + var sb = new StringBuilder(str.Length * count); + for (int i = 0; i < count; i++) { + sb.Append(str); + } + return sb.ToString(); + } + + private static void CheckUPSStatus() { + //string s = ""; + if (UPSApp.fetcher.IsReachable) { + //s += "OnShut=" + UPSApp.fetcher.OnTimedShutdown + " Remaining=" + UPSApp.fetcher.TimedShutdownRemaining; + if (NotifyIconInstance != null) { // Explicit null check + if (UPSApp.fetcher.OnState){ + int maxBars = 4; + int barCount = 0; + if (UPSApp.fetcher.BattMaxLevel > 0) { + barCount = (int)Math.Round((double)UPSApp.fetcher.ChargeLevel * maxBars / UPSApp.fetcher.BattMaxLevel); + } else { + barCount = UPSApp.fetcher.ChargeLevel > 4 ? (int)Math.Round(UPSApp.fetcher.ChargeLevel / 25.0) : UPSApp.fetcher.ChargeLevel; + } + barCount = Math.Max(0, Math.Min(maxBars, barCount)); + + if (lastState != (100 + barCount)){ + lastState = 100 + barCount; + NotifyIconInstance.Text = "UPS Net \nBattery: " + + RepeatString("■", barCount) + + RepeatString(" ", maxBars - barCount); + } + }else{ + if (lastState!=200){ + lastState = 200; + NotifyIconInstance.Text = "UPS Net \nUPS OFF"; + } + } + } + }else{ + //s = "Unreachable"; + if (NotifyIconInstance != null){ + if (lastState!=300){ + lastState = 300; + NotifyIconInstance.Text = "UPS Net \nNot Connected"; + } + } + } + //Debug.WriteLine("CheckUPSStatus: " + s); + + + //UPSApp.ManageShutdownRoutine(); //this now managed from OnStatusChanged ata UPSApp + + } + } +} diff --git a/UPSNet/NotificationIcon.resx b/UPSNet/NotificationIcon.resx new file mode 100644 index 0000000..f097bef --- /dev/null +++ b/UPSNet/NotificationIcon.resx @@ -0,0 +1,451 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAQAMDAAAAEAIACoJQAARgAAACAgAAABACAAqBAAAO4lAAAYGAAAAQAgAIgJAACWNgAAEBAAAAEA + IABoBAAAHkAAACgAAAAwAAAAYAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPSS + JAjzlSFx85YhzPOVIfjylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zlSH385YhzPOVIXL0mCIIAAAAAAAA + AAAAAAAA8pYiHfOVIdLylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/zlSDS8pUhHQAAAAD0lCAI85Ug0vKVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/85Ug0vSWIgjzlSFy8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//OXIHHzliDN8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//OXIMzyliD48pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//OW + IffylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP7ylSD68pUg+vKVIPrylSD68pUg+vKVIPrylSD68pUg+vKVIPrylSD68pUg+vKVIPrylSD+8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/85Ugr/OWHhjylSAF8pUgBfKVIAXylSAF8pUgBfKVIAXylSAF8pUgBfKVIAXylSAF8pUgBfKV + IAXzlx8Y85Ugr/KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/yliD+85cfGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA85ceGPKVIP7ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD68pUgBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pUgBfKVIPrylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD68pUgBQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pUgBfKVIPrylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD68pUgBQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pUgBfKV + IPrylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD68pUgBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA8pUgBfKVIPrylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD68pUgBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA8pUgBfKVIPrylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD68pUgBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pUgBfKVIPrylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD68pUgBQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pUgBfKVIPrylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OW + If/zliH/85Yh//OWIf/zliH/8pYh//OWIf/zliH/8pYh//OWIf/zliH/85Yh//OWIf/zliH685YhBQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pUhBfKV + IPrylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KV + IP/zlSH/85Yh//OVIf/zliH/85Yh//OVIf/zlSH/85Ug//OVIf/zlSH/85Ug//OVIf/zliH/85Yh//OW + If/zliH685YhBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA8pUgBfKVIPrylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/8pUg//OWIf/zliH/8pUg//OW + If/zliH/85Yh//OWIf/zliH685YhBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA8pUgBfKVIPrylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/8pYh//OW + If/zliH/8pYh//OWIf/zliH/85Yh//OWIf/zliH685YhBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pUhBfKVIPrylSD/8pUh//KVIP/ylSD/8pUh//KV + IP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/zlSH/85Yh//OVIf/zliH/85Yh//OV + If/zlSH/85Ug//OVIf/zlSH/85Ug//OVIf/zliH/85Yh//OWIf/zliH685YhBQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pUgBfKVIPrylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OW + If/zliH/85Yh//OWIf/zliH/8pUg//OWIf/zliH/8pUg//OWIf/zliH/85Yh//OWIf/zliH+85UfGAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA85YeGPKV + IP7ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/8pYh//OWIf/zliH/8pYh//OWIf/zliH/85Yh//OW + If/zliH/85Ygr/OWHxjzliEF85YhBfOWIQXzliEF85YhBfKVIAXylSAF8pUhBfKVIAXylSAF8pUhBfKV + IAXzlB8Y85Ugr/KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KV + IP/ylSD/8pUh//KVIP/zlSH/85Yh//OVIf/zliH/85Yh//OVIf/zlSH/85Ug//OVIf/zlSH/85Ug//OV + If/zliH/85Yh//OWIf/zliH/85Yh//OWIf7zliH685Yh+vOWIfrzliH685Yh+vKVIPrylSD68pUg+vKV + IPrylSD68pUg+vKVIPryliD+8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/8pUg//OW + If/zliH/8pUg//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OW + If/zliH/8pYh//OWIf/zliH/8pYh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OW + If/zliH/85Yh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KV + IP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/zlSH/85Yh//OV + If/zliH/85Yh//OVIf/zlSH/85Ug//OVIf/zlSH/85Ug//OVIf/zliH/85Yh//OWIf/zliH/85Yh//OW + If/zliH/85Yh//OWIf/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OW + If/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/zlSH/8pYh//OVIP/zlSH/8pYh//OVIP/zlSH/8pYh//OVIP/zlSH/8pYh//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/85Yh//KVIP/zliH/85Yh//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OW + If/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zlSH/8pYh//OVIP/zlSH/8pYh//OV + IP/zlSH/8pYh//OVIP/zlSH/8pYh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/85Yh//KVIP/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OW + If/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/yliD48pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//OVIfjzlSDN8pUg//KVIP/ylSD/8pUh//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//OXIMzzlyBy85Yh//KVIf/zliH/85Yh//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OW + If/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//OWIXH0lh8J85Ug0/KV + IP/zlSD/8pUh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OW + If/zliH/85Yh//OWIf/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/85Yg0vSW + IwgAAAAA8pYiHfOWINLyliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OW + If/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/zlSDT8pUhHQAAAAAAAAAAAAAAAPSWIAnzlyBy85YgzfKWIPjylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD485YgzfOZIHL0lSAJAAAAAAAAAADAAAAAAAMAAIAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//gAAAAAAAH/+AAAAAAAA + f/4AAAAAAAB//gAAAAAAAH/+AAAAAAAAf/4AAAAAAAB//gAAAAAAAH/+AAAAAAAAf/4AAAAAAAB//gAA + AAAAAH/+AAAAAAAAf/4AAAAAAAB//gAAAAAAAH/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAQAAwAAAAAADAAAoAAAAIAAAAEAA + AAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8ZYiA/OTIjXylSC18pUg8fGVIP/ylSD/8ZUg//KV + IP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//KVIPDylSC185YhNfKVIQPzlCA18pUg0vGVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/ylSDS85UhNfKVILXylSD/8ZUg//KV + IP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/yliC18pUg8fGV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//KV + IPDxlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KV + IP/xlSD/8pUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KV + IP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KV + IP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8pUg9vKVH8LxlSCo8pUgqPGVIKjylSCo8ZUgqPKV + IKjxlSCo8pUgqPKVH8LylSD28ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/ylR/C85YeHvGVIALxlSAC8ZUgAvGV + IALxlSAC8ZUgAvGVIALxlSAC85YeHvKVH8LxlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIKjylSACAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADxlSAC8pUgqPGVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUgqPGV + IAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPGVIALxlSCo8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KV + IP/xlSCo8pUgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8ZUgAvKVIKjxlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIKjxlSACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADxlSAC8ZUgqPGV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUgqPKVIAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPGV + IALylSCo8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//OVIf/zlSH/85Yh//OV + If/ylSD/8pUg//KVIP/ylSD/85Yh//OWIf/zliGo85YhAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA8ZUgAvGVIKjxlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/85Yh//OW + If/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OWIajzliECAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAADxlSAC8pUgqPGVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KV + IP/zlSH/85Uh//OWIf/zlSH/8pUg//KVIP/ylSD/8pUg//OWIf/zliH/85YhqPOWIQIAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPGVIALxlSCo8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//OWIf/zliH/85Yh//OWIf/ylSD/8pUg//KVIP/ylSD/85Yh//OWIf/zlSDC85UfHvOW + IQLzliEC85YhAvKVIALxlSAC8pUgAvGVIALylSAC85UeHvKVH8LxlSD/8pUg//GVIP/ylSD/8ZUg//KV + IP/xlSD/8pUg//GVIP/ylSD/85Uh//OVIf/zliH/85Uh//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OW + IPbzliDC85YhqPOWIajzliGo8pUgqPGVIKjxlSCo8ZUgqPGVIKjylR/C8pUg9vGVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/zliH/85Yh//OWIf/zliH/8pUg//KVIP/ylSD/8pUg//OW + If/zliH/85Yh//OWIf/zliH/85Yh//OWIf/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KV + IP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//OVIf/zlSH/85Yh//OVIf/ylSD/8pUg//KV + IP/ylSD/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/ylSH/8pUg//KVIf/ylSD/8pUh//KVIP/ylSH/8pUg//GVIP/ylSD/8ZUg//KV + IP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8ZUg//GVIP/xlSD/8ZUg//KVIf/ylSD/8pUh//KVIP/ylSH/8pUg//KVIf/ylSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8pUh//KVIP/ylSH/8pUg//KVIf/ylSD/8pUh//KV + IP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//GVIP/xlSD/8ZUg//GVIP/ylSH/8pUg//KVIf/ylSD/8pUh//KV + IP/ylSH/8pUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/ylSDx8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//OWIf/zliH/85Yh//OW + If/zliH/85Yh//OWIf/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg8fKWILXylSD/8pUg//KVIP/xlSD/8ZUg//GVIP/xlSD/85Yh//OW + If/zliH/85Yh//OWIf/zliH/85Yh//KVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/ylSC185UfNvKVINLylSD/8pUg//GVIP/ylSD/8ZUg//KV + IP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8pUg0vOVITXxliID85YgNvKWILXylSDx8ZUg//GV + IP/xlSD/8ZUg//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/ylSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8pUg8fKXILXzlSA28ZUhAwAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP + 8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAABgA + AAAwAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPKWIgfzlCGS8pUg8PKVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IPDzlSCT8pUhB/OUIJPylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/85UgkvKVIPHylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg8PKVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIPzylSD88pUg/PKVIPzylSD88pUg/PKVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/85YfOPKV + IALylSAC8pUgAvKVIALylSAC8pUgAvOWHzjylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD88pUgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPKV + IALylSD88pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD88pUgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPKVIALylSD88pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD88pUgAgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAPKVIALylSD88pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD88pUgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPKVIALylSD88pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//OVIf/zlSH/85Uh//KVIP/zlSH/8pUg//OWIf/zliH885YhAgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPKVIALylSD88pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//OV + If/zlSH/85Uh//KVIP/zlSH/8pUg//OWIf/zliH885YhAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPKV + IALylSD88pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//OWIf/zliH/85Yh//KVIP/zliH/8pUg//OW + If/zliH/85UfOPOWIQLzliEC8pUgAvKVIALylSAC8pUgAvOVHzjylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//OVIf/zlSH/85Uh//KVIP/zlSH/8pUg//OWIf/zliH/85Yh//OWIfzzliH88pUg/PKV + IPzylSD88pUg/PKVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//OVIf/zlSH/85Uh//KV + IP/zlSH/8pUg//OWIf/zliH/85Yh//OWIf/zliH/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIf/zlSD/8pUg//KV + If/zlSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//OWIf/zliH/85Yh//OWIf/zliH/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + If/zlSD/8pUg//KVIf/zlSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIPHylSD/8pUg//KVIP/ylSD/8pUg//OWIf/zliH/85Yh//OWIf/zliH/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg8POWIJPylSD/8pUg//KV + IP/ylSD/8pUg//OWIf/zliH/85Yh//OWIf/zliH/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/85UhkvKWIgfzliCT8pUg8fKVIP/ylSD/8pUg//OWIf/zliH/85Yh//OW + If/zliH/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIPHzliCT8pUhBwAA + AEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQB+AEEAfgBBAH4AQQB+AEEAfgBBAH4AQQAA + AEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQSgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAADzlCFQ8pUg6fGVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//KVIOnzlSBQ8pUg6fGVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8pUg6fGVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8pUfpvGV + IFXxlSBV8ZUgVfGVIFXylR+m8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IFUAAAAAAAAAAAAAAAAAAAAA8ZUgVfGVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSBVAAAAAAAAAAAAAAAAAAAAAPGVIFXxlSD/8ZUg//GVIP/xlSD/8ZUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUgVQAAAAAAAAAAAAAAAAAAAADxlSBV8ZUg//GVIP/xlSD/8ZUg//GVIP/zlSH/85Uh//KV + IP/ylSD/85Yh//OWIVUAAAAAAAAAAAAAAAAAAAAA8ZUgVfGVIP/xlSD/8ZUg//GVIP/xlSD/85Uh//OV + If/ylSD/8pUg//OWIf/zlSCm85YhVfKVIFXxlSBV8ZUgVfKVH6bxlSD/8ZUg//GVIP/xlSD/8ZUg//OV + If/zlSH/8pUg//KVIP/zliH/85Yh//OWIf/ylSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/ylSD/8pUg//GVIP/xlSD/8pUg//KVIP/ylSD/8pUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8pUg//KVIP/xlSD/8ZUg//KVIP/ylSD/8pUg//KVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//KVIOnylSD/8ZUg//GVIP/zliH/85Yh//OWIf/ylSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//KVIOnzlSBQ8pUg6fGVIP/xlSD/85Yh//OWIf/zliH/8pUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//KVIOnzlSBQAACsQQAArEEAAKxBAACsQQAArEEAAKxBA8CsQQPArEEDwKxBA8CsQQAA + rEEAAKxBAACsQQAArEEAAKxBAACsQQ== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAAHwAAAB8ARUP7eQAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwa + AAAA60lEQVQ4T4WTvQ6CMBSF+ySujg7CJS4mUH15B53EaHTQRBeNBig46r1NKxRvy0lOUtrznfQniPdi + OlISVuhcpTARA6KMypIdMcQKHGzQH+NHqETDlGnzayq4dCa8JQxMPotGwgwHRW/BKfHABbE6wJYs4Fkv + ITLw3VmToKosnmvYyrMT+n715v5hK09J137YSpdkoBi4GYRJ5sz9bZNLuhMT4+W5sNbmYk3cFQ8nTY3n + dua4ktBThZ54ENYBVLCkknByFjBIgGF/4krweEf6F/LOJAtbMSVbUabRGAcHJeNrCLYyJTf0vkyj8RdS + 2oKRiLP1uQAAAABJRU5ErkJggg== + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAAFkAAABZAaqdqYYAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwa + AAAA2ElEQVQ4T62TzQ2DMAxGGQM4gIAtyhowSUVYpBR1idJVmv5MQBYgB26hdgpUsqyGA0hPQuDvCdvE + S1p9S856YlDJaYyD4zv2hVSBkBND50GhIcEfjS58cS+Y4IJBAR/+UvqVLJngyi4CRUIrWTMcnIL0MkZQ + XFIw7MHlFNgpQxElrJ75JsGfFU1h/XC3wD1csF8CEu6dpZa9U4BtYDt4TwnrV7RJkLVDzg0aF+AUzGF2 + zYByCqAI4cKWXQSGBhfwIOGB4oIzBgUdDVpgRThlPNJQyP7uaaOvHzE3R5jKq0r7AAAAAElFTkSuQmCC + + + + + iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 + YQUAAAAJcEhZcwAAAFkAAABZAaqdqYYAAAAZdEVYdFNvZnR3YXJlAHd3dy5pbmtzY2FwZS5vcmeb7jwa + AAABQklEQVQ4T42TPU/DQAyGb4EfQ/k7zEmEyI9AJApM1V2gpagDC1NXFlbKxwSCBaFSwcTAiAQShSkt + Ol47H0ru0gRLj+Tar33nqyNM24zUuhvKvhvET26gflLgI0a5TGbbRhStQjwEv0AvYeEE6oi0WVlqWfGF + IW5AjitNEKSTLWF/dMrU5dwwHnAxz4yrWQLQ2IDH6XaEF6jDmuS/cEJ5QNefmgnibvKskyTRZ9c3Vi7H + 2VETgVf9rktuD070y+ubvn2cWrkSM7rBzAgWUHFLg6+lIxBtDXgEOD0zkdPWwAtljDfodvCj8jf6ez19 + df+g3z8+GfIpVtaAhRfFa7wLtJ7lZN4gv8El/K1dowG+DS4mS1dZjiuCBnDgue8fr2TlqXETrCcEtVtJ + oHBOJ1vFZaM3oQ2jF6YdYeCjwX4xc2FC/AEiZRgzhgGjBwAAAABJRU5ErkJggg== + + + \ No newline at end of file diff --git a/UPSNet/Program.cs b/UPSNet/Program.cs new file mode 100644 index 0000000..365f0f5 --- /dev/null +++ b/UPSNet/Program.cs @@ -0,0 +1,31 @@ +/* + * Created by SharpDevelop. + * User: EVXIO + * Date: 4/3/2025 + * Time: 9:01 PM + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ +using System; +using System.Windows.Forms; + +namespace UPSNet +{ + /// + /// Class with program entry point. + /// + internal sealed class Program + { + /// + /// Program entry point. + /// + [STAThread] + private static void Main(string[] args) + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new MainForm()); + } + + } +} diff --git a/UPSNet/Properties/AssemblyInfo.cs b/UPSNet/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..94963d9 --- /dev/null +++ b/UPSNet/Properties/AssemblyInfo.cs @@ -0,0 +1,28 @@ +#region Using directives +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +#endregion +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle ("UPSNet")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("")] +[assembly: AssemblyProduct ("UPSNet")] +[assembly: AssemblyCopyright ("Copyright ©2025 EVXIO, By Victor Phoa")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] +// This sets the default COM visibility of types in the assembly to invisible. +// If you need to expose a type to COM, use [ComVisible(true)] on that type. +[assembly: ComVisible (false)] +// The assembly version has following format : +// +// Major.Minor.Build.Revision +// +// You can specify all the values or you can use the default the Revision and +// Build Numbers by using the '*' as shown below: +[assembly: AssemblyVersion ("1.0.0.2")] +[assembly: AssemblyFileVersion ("1.0.0.2")] diff --git a/UPSNet/ShutdownCountdownForm.cs b/UPSNet/ShutdownCountdownForm.cs new file mode 100644 index 0000000..096e103 --- /dev/null +++ b/UPSNet/ShutdownCountdownForm.cs @@ -0,0 +1,162 @@ +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace UPSNet +{ + /// + /// A countdown dialog that appears before Windows shutdown is executed. + /// Allows the user to cancel the shutdown during the countdown. + /// + public class ShutdownCountdownForm : Form + { + private Label labelTitle; + private Label labelCountdown; + private Label labelMessage; + private Button buttonCancel; + private Timer countdownTimer; + private int remainingSeconds; + + /// + /// True if user cancelled the shutdown + /// + public bool WasCancelled { get; private set; } + + /// + /// True if countdown reached zero (proceed with shutdown) + /// + public bool CountdownFinished { get; private set; } + + public ShutdownCountdownForm(int seconds) + { + remainingSeconds = seconds; + WasCancelled = false; + CountdownFinished = false; + InitializeUI(); + + countdownTimer = new Timer(); + countdownTimer.Interval = 1000; + countdownTimer.Tick += CountdownTimer_Tick; + } + + private void InitializeUI() + { + this.SuspendLayout(); + + // Form settings + this.Text = "UPS Shutdown Warning"; + this.FormBorderStyle = FormBorderStyle.FixedDialog; + this.StartPosition = FormStartPosition.CenterScreen; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.TopMost = true; + this.ClientSize = new Size(340, 180); + this.ShowInTaskbar = true; + this.BackColor = Color.FromArgb(30, 30, 30); + + // Title label + labelTitle = new Label(); + labelTitle.Text = "⚠ UPS Shutdown Warning"; + labelTitle.Font = new Font("Segoe UI", 11F, FontStyle.Bold); + labelTitle.ForeColor = Color.OrangeRed; + labelTitle.Location = new Point(12, 15); + labelTitle.Size = new Size(316, 25); + labelTitle.TextAlign = ContentAlignment.MiddleCenter; + + // Message label + labelMessage = new Label(); + labelMessage.Text = "Sistem akan dimatikan dalam:"; + labelMessage.Font = new Font("Segoe UI", 9.5F); + labelMessage.ForeColor = Color.White; + labelMessage.Location = new Point(12, 50); + labelMessage.Size = new Size(316, 20); + labelMessage.TextAlign = ContentAlignment.MiddleCenter; + + // Countdown label + labelCountdown = new Label(); + labelCountdown.Text = remainingSeconds.ToString() + " detik"; + labelCountdown.Font = new Font("Segoe UI", 22F, FontStyle.Bold); + labelCountdown.ForeColor = Color.Red; + labelCountdown.Location = new Point(12, 72); + labelCountdown.Size = new Size(316, 45); + labelCountdown.TextAlign = ContentAlignment.MiddleCenter; + + // Cancel button + buttonCancel = new Button(); + buttonCancel.Text = "Cancel Shutdown"; + buttonCancel.Font = new Font("Segoe UI", 9.5F, FontStyle.Bold); + buttonCancel.Location = new Point(70, 130); + buttonCancel.Size = new Size(200, 35); + buttonCancel.BackColor = Color.FromArgb(0, 150, 200); + buttonCancel.ForeColor = Color.White; + buttonCancel.FlatStyle = FlatStyle.Flat; + buttonCancel.FlatAppearance.BorderSize = 0; + buttonCancel.Cursor = Cursors.Hand; + buttonCancel.Click += ButtonCancel_Click; + + this.Controls.Add(labelTitle); + this.Controls.Add(labelMessage); + this.Controls.Add(labelCountdown); + this.Controls.Add(buttonCancel); + + this.ResumeLayout(false); + } + + protected override void OnShown(EventArgs e) + { + base.OnShown(e); + countdownTimer.Start(); + // Play a warning sound + System.Media.SystemSounds.Exclamation.Play(); + } + + private void CountdownTimer_Tick(object sender, EventArgs e) + { + remainingSeconds--; + + if (remainingSeconds <= 0) + { + countdownTimer.Stop(); + CountdownFinished = true; + labelCountdown.Text = "0 detik"; + this.Close(); + } + else + { + labelCountdown.Text = remainingSeconds.ToString() + " detik"; + + // Flash color when critical + if (remainingSeconds <= 5) + { + labelCountdown.ForeColor = (remainingSeconds % 2 == 0) ? Color.Red : Color.Yellow; + } + } + } + + private void ButtonCancel_Click(object sender, EventArgs e) + { + countdownTimer.Stop(); + WasCancelled = true; + CountdownFinished = false; + this.Close(); + } + + protected override void OnFormClosing(FormClosingEventArgs e) + { + countdownTimer.Stop(); + base.OnFormClosing(e); + } + + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (countdownTimer != null) + { + countdownTimer.Dispose(); + } + } + base.Dispose(disposing); + } + } +} diff --git a/UPSNet/SystemUptime.cs b/UPSNet/SystemUptime.cs new file mode 100644 index 0000000..e4b8df6 --- /dev/null +++ b/UPSNet/SystemUptime.cs @@ -0,0 +1,88 @@ +//Usage Examples: +//// Get precise milliseconds since application start +//long ms = SystemUptimeTimer.ElapsedMilliseconds; +// +//// Get system uptime (even counts when PC was sleeping) +//TimeSpan uptime = SystemUptimeTimer.SystemUptime; +//Console.WriteLine($"PC has been running for {uptime.Days} days, {uptime.Hours} hours"); +// +//// Benchmark example +//long start = SystemUptimeTimer.ElapsedMilliseconds; +//// ... run some code ... +//long elapsed = SystemUptimeTimer.ElapsedMilliseconds - start; +//Key Features: +//Two Measurement Modes: +// +//ElapsedMilliseconds: High-precision timer (μs accuracy) since class initialization +// +//SystemUptime: Standard Windows uptime (ms accuracy, counts sleep time) + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace UPSNet +{ + /// + /// High-precision timer measuring time since system startup + /// + public static class SystemUptimeTimer + { + [DllImport("kernel32.dll")] + private static extern uint GetTickCount(); + + [DllImport("kernel32.dll")] + private static extern bool QueryPerformanceCounter(out long lpPerformanceCount); + + [DllImport("kernel32.dll")] + private static extern bool QueryPerformanceFrequency(out long lpFrequency); + + private static readonly long _frequency; + private static readonly long _startCount; + private static readonly Stopwatch _fallbackTimer; + + static SystemUptimeTimer() + { + if (!QueryPerformanceFrequency(out _frequency)) + { + _frequency = -1; + _fallbackTimer = Stopwatch.StartNew(); + } + + QueryPerformanceCounter(out _startCount); + } + + /// + /// Gets elapsed milliseconds since system startup + /// + public static long ElapsedMilliseconds + { + get + { + if (_frequency == -1) + { + return _fallbackTimer.ElapsedMilliseconds; + } + + long currentCount; + QueryPerformanceCounter(out currentCount); + return (1000 * (currentCount - _startCount)) / _frequency; + } + } + + /// + /// Gets elapsed seconds since system startup + /// + public static double ElapsedSeconds { + get { return ElapsedMilliseconds / 1000.0; } + } + + /// + /// Gets system uptime using native API (works even when PC enters sleep) + /// + public static TimeSpan SystemUptime + { + get { return TimeSpan.FromMilliseconds(GetTickCount()); } + } + } +} \ No newline at end of file diff --git a/UPSNet/UPSApiFetcher.cs b/UPSNet/UPSApiFetcher.cs new file mode 100644 index 0000000..9376749 --- /dev/null +++ b/UPSNet/UPSApiFetcher.cs @@ -0,0 +1,203 @@ +using System; +using System.IO; +using System.Net; +using System.Threading; + +namespace UPSNet +{ + public class UPSApiFetcher : IDisposable + { + // Configuration + private string _apiUrl; + private string _apiUrlOnce; + private int _pollingInterval; + private int _pollingIntervalOnce; + + // State tracking + private Thread _workerThread; + private bool _isRunning; + private DateTime _lastSuccessfulFetch; + private ManualResetEvent _sleepEvent = new ManualResetEvent(false); + private readonly object _syncLock = new object(); + + // API Response Data + public int Success { get; private set; } + public int ChargeLevel { get; private set; } + public int BattMaxLevel { get; private set; } + public bool OnState { get; private set; } + public int ShutdownSuggestMode { get; private set; } + public bool ShutdownSuggested { get; private set; } + public bool OnTimedShutdown { get; private set; } + public int TimedShutdownRemaining { get; private set; } + public bool BatteryCritical { get; private set; } + public int UPSLineFrom { get; private set; } + public bool IsChargingOrBlink { get; private set; } + public bool IsReachable { get; private set; } + public DateTime LastUpdateTime { get; private set; } + public bool IsOnRequestUrlOnce { get; private set; } + + private string json; + + // Event + public event Action StatusUpdated; + + public UPSApiFetcher(string apiUrl, int pollingIntervalMs = 1000) { + _apiUrl = apiUrl; + _pollingInterval = pollingIntervalMs; + } + + public void SetApiUrl(string apiUrl, int pollingIntervalMs = 1000) { + lock (_syncLock) { + _apiUrl = apiUrl; + _pollingInterval = pollingIntervalMs; + } + } + + public void SetApiUrlOnce(string apiUrl, int pollingIntervalMs = 500) { + lock (_syncLock){ + _apiUrlOnce = apiUrl; + _pollingIntervalOnce = pollingIntervalMs; + IsOnRequestUrlOnce = true; + _sleepEvent.Set(); // Wake up thread for immediate fetch + } + } + + public void Start() { + if (_isRunning) return; + + _isRunning = true; + _workerThread = new Thread(WorkerLoop){ + IsBackground = true, + Priority = ThreadPriority.Normal//ThreadPriority.BelowNormal + }; + _workerThread.Start(); + } + + public void Stop() { + _isRunning = false; + _sleepEvent.Set(); // Wake thread to exit + _workerThread.Join(1000); + } + + public void FetchNow() { + _sleepEvent.Set(); // Wake thread for immediate fetch + } + + private void WorkerLoop() { + while (_isRunning) { + FetchApiData(); + + // Wait for next interval or immediate fetch + int interval; + lock (_syncLock) { + interval = IsOnRequestUrlOnce ? _pollingIntervalOnce : _pollingInterval; + } + _sleepEvent.WaitOne(interval); + _sleepEvent.Reset(); + } + } + + private void FetchApiData() { + try { + string currentUrl; + lock (_syncLock) { + currentUrl = IsOnRequestUrlOnce ? _apiUrlOnce : _apiUrl; + } + + var request = WebRequest.Create(currentUrl); + request.Timeout = 5000; + + // Add Basic Authentication for V2 compatibility + string credentials = Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes("admin:admin123")); + request.Headers[HttpRequestHeader.Authorization] = "Basic " + credentials; + + using (var response = (HttpWebResponse)request.GetResponse()) + using (var stream = response.GetResponseStream()) + using (var reader = new StreamReader(stream)) { + string tmp = reader.ReadToEnd(); + if (json!=tmp){ + json = tmp; + ParseJsonResponse(json); + } + IsReachable = true; + _lastSuccessfulFetch = DateTime.Now; + LastUpdateTime = DateTime.Now; + lock (_syncLock) { + if (IsOnRequestUrlOnce) { + IsOnRequestUrlOnce = false; + } + } + } + }catch{ + UpdateReachability(); + }finally{ + StatusUpdated.Invoke(this); + } + } + + private void UpdateReachability(){ + if ((DateTime.Now - _lastSuccessfulFetch).TotalSeconds > 5) { + IsReachable = false; + LastUpdateTime = DateTime.Now; + } + } + + private void ParseJsonResponse(string json) { + try { + json = json.Trim('{', '}', ' ', '\n', '\r', '\t'); + string[] pairs = json.Split(','); + + foreach (string pair in pairs) { + string[] keyValue = pair.Split(':'); + if (keyValue.Length != 2) continue; + + string key = keyValue[0].Trim().Trim('"'); + string value = keyValue[1].Trim().Trim('"'); + + switch (key.ToLower()){ + case "success": + Success = int.Parse(value); + break; + case "chargelv": + ChargeLevel = int.Parse(value); + break; + case "shutdownsuggestmode": + ShutdownSuggestMode = int.Parse(value); + break; + case "shutdownsuggest": + ShutdownSuggested = int.Parse(value) > 0; + break; + case "timedshutdown": + OnTimedShutdown = int.Parse(value) > 0; + break; + case "shutdownremain": + TimedShutdownRemaining = int.Parse(value); + break; + case "battcritical": + BatteryCritical = int.Parse(value) > 0; + break; + case "line": + UPSLineFrom = int.Parse(value); + break; + case "battblink": + IsChargingOrBlink = int.Parse(value) > 0; + break; + case "state": + OnState = int.Parse(value) > 0; + break; + case "battmax": + BattMaxLevel = int.Parse(value); + break; + } + } + }catch{ + // Keep previous values on parse error + } + } + + public void Dispose(){ + Stop(); + _sleepEvent.Dispose(); + } + } +} \ No newline at end of file diff --git a/UPSNet/UPSApp.cs b/UPSNet/UPSApp.cs new file mode 100644 index 0000000..b5198ee --- /dev/null +++ b/UPSNet/UPSApp.cs @@ -0,0 +1,366 @@ +/* + * Created by SharpDevelop. + * User: EVXIO + * Date: 4/3/2025 + * Time: 10:36 PM + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ +using System; +using System.Diagnostics; +using System.Text; +using System.Windows.Forms; +using System.Runtime.InteropServices; + +namespace UPSNet { + /// + /// Static application controller for UPS management + /// + /// + + + + enum ShutdownMode{ + Disabled = 0, + OnBattery = 1, + OnBattery75 = 2, + OnBattery50 = 3, + OnBattery25 = 4, + OnBatteryCritical = 5 + }; + + public static class UPSApp { + + [DllImport("user32.dll")] + private static extern bool FlashWindow(IntPtr hWnd, bool bInvert); + + public static bool dialogOk = false; + public static UPSForm upsForm = null; + public static string deviceAddress = "192.168.0.99"; + public static int shutdownMode = 0; + public static bool initialized = false; + + public static UPSApiFetcher fetcher = new UPSApiFetcher("http://your-ups-api/status"); + + public static System.Threading.SynchronizationContext uiContext; + + public static bool isShutdownRequested = false; + public static long lastTickShutdownRequested = 0; + public static bool isShutdownCancelledByUser = false; + + public static int lastKnownLineFrom = 1; + public static bool lastKnownBatteryCritical = false; + public static int lastKnownChargeLevel = 4; + + static void OnStatusChanged(UPSApiFetcher fetcher){ + //Debug.WriteLine("Charge: " + fetcher.ChargeLevel + ", Online: " + fetcher.IsReachable); + ManageShutdownRoutine(); + } + + static UPSApp() { + Init(); + } + + public static void Init(){ + if (initialized) return; + initialized = true; + + if (AppConfig.exists){ + // Initialize default values + deviceAddress = AppConfig.Get("address", deviceAddress); + shutdownMode = AppConfig.GetInt("mode", 0); + AppConfig.Set("initialized", "true"); + SaveConfig(); + }else{ + // Load saved values + deviceAddress = AppConfig.Get("address", deviceAddress); + if (deviceAddress.Length>200) deviceAddress = deviceAddress.Substring(0,200); + shutdownMode = AppConfig.GetInt("mode", shutdownMode); + if (shutdownMode>6) shutdownMode = 6; + if (shutdownMode<0) shutdownMode = 0; + } + + fetcher.SetApiUrl("http://" + deviceAddress + "/state"); + fetcher.StatusUpdated += OnStatusChanged; + fetcher.Start(); + Debug.WriteLine("Initialized"); + } + + public static void SaveConfig(){ + AppConfig.Set("address", deviceAddress); + AppConfig.Set("mode", shutdownMode); + AppConfig.SaveSettings(); + } + + public static void ShowForm(){ + if (upsForm==null){ + upsForm = new UPSForm(); + upsForm.Show(); + return; + }else{ + if (upsForm.WindowState == FormWindowState.Minimized){ + upsForm.WindowState = FormWindowState.Normal; + }else if (upsForm.WindowState == FormWindowState.Normal){ + if (!upsForm.Visible){ + upsForm.Visible = true; + upsForm.Show(); + upsForm.Activate(); + return; + } + } + upsForm.Activate(); // First bring to foreground + FlashWindow(upsForm.Handle, true); + } + } + + public static void ShowOrHideForm(){ + if (upsForm==null){ + upsForm = new UPSForm(); + upsForm.Show(); + return; + }else{ + if (upsForm.WindowState == FormWindowState.Minimized){ + upsForm.WindowState = FormWindowState.Normal; + upsForm.Activate(); // First bring to foreground + FlashWindow(upsForm.Handle, true); + }else if (upsForm.WindowState == FormWindowState.Normal){ + if (!upsForm.Visible){ + upsForm.Visible = true; + upsForm.Show(); + upsForm.Activate(); + //upsForm.Close(); + //upsForm = null; + return; + }else{ + upsForm.Close(); + upsForm = null; + return; + } + } + } + } + + public static void PurgeUpsForm(){ + upsForm = null; + } + + public static void RestartFetcher(){ + fetcher.Stop(); + fetcher.SetApiUrl("http://" + deviceAddress + "/state"); + fetcher.Start(); + } + + public static bool IsGoingToShutdown(){ + if (isShutdownRequested){ + //timeout after 35s + if ((Environment.TickCount-lastTickShutdownRequested) >= 35000){ + isShutdownRequested = false; + }else{ + return true; + } + } + return false; + } + + public static bool IsRunningInDebuggerOrIDE(){ + // Check for attached debugger + if (System.Diagnostics.Debugger.IsAttached) + return true; + + // Check for common IDE environment variables + string[] ideVariables = { + "VisualStudioVersion", + "VSAPPIDNAME", + "SharpDevelop" // For SharpDevelop + }; + + foreach (var variable in ideVariables){ + if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable(variable))) + return true; + } + + return false; + } + + public static bool RequestForShutdown(int sec){ + if (IsGoingToShutdown()) return true; + Debug.WriteLine("Shutdown requested."); + + // Mark as requested immediately to prevent re-entry + isShutdownRequested = true; + lastTickShutdownRequested = Environment.TickCount; + + // Show countdown form on UI thread first, then execute shutdown only if not cancelled + if (uiContext != null) { + uiContext.Post(new System.Threading.SendOrPostCallback(delegate(object state) { + ShowCountdownThenShutdown(sec); + }), null); + }else{ + // Fallback: no UI context, shutdown directly + ExecuteWindowsShutdown(sec); + } + + return isShutdownRequested; + } + + private static void ShowCountdownThenShutdown(int sec){ + using (var countdownForm = new ShutdownCountdownForm(sec)){ + // Show form and also show main form behind it + ShowForm(); + countdownForm.ShowDialog(); + + if (countdownForm.WasCancelled){ + // User cancelled - abort everything + Debug.WriteLine("Shutdown cancelled by user via countdown dialog."); + WindowsShutdown.AbortShutdown(); + CancelTimedShutdown(); + isShutdownRequested = false; + MessageBox.Show("Shutdown command has been aborted.", "Cancel Shutdown", MessageBoxButtons.OK, MessageBoxIcon.Information); + }else if (countdownForm.CountdownFinished){ + // Countdown reached 0 - execute actual Windows shutdown + Debug.WriteLine("Countdown finished. Executing Windows shutdown."); + ExecuteWindowsShutdown(1); // 1 second remaining, shutdown immediately + }else{ + // Form was closed without explicit action - treat as cancelled + Debug.WriteLine("Countdown form closed. Treating as cancelled."); + WindowsShutdown.AbortShutdown(); + CancelTimedShutdown(); + isShutdownRequested = false; + } + } + } + + private static void ExecuteWindowsShutdown(int sec){ + if (IsRunningInDebuggerOrIDE()){ + Debug.WriteLine("Running from Debug/IDE. Bypassing actual OS shutdown!"); + isShutdownRequested = true; + lastTickShutdownRequested = Environment.TickCount; + MessageBox.Show("[Debug Mode] Windows shutdown would execute now.", "Debug Shutdown", MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + bool b = WindowsShutdown.TimedShutdown(false, sec, "EVXIO UPS Net shutdown activated."); + //non invasive shutdown + if (!b) b = WindowsShutdown.Shutdown(WindowsShutdown.ShutdownMode.Shutdown); + if (!b) b = WindowsShutdown.CmdShutdown(WindowsShutdown.ShutdownMode.Shutdown, sec); + if (b){ + isShutdownRequested = true; + lastTickShutdownRequested = Environment.TickCount; + }else{ + isShutdownRequested = false; + } + } + + public static void SendTimedShutdown(){ + string url = "http://" + deviceAddress + "/state?shutdown=30"; + fetcher.SetApiUrlOnce(url); + } + + public static void CancelTimedShutdown(){ + isShutdownCancelledByUser = true; + string url = "http://" + deviceAddress + "/state?shutdown=0"; + fetcher.SetApiUrlOnce(url); + } + + public static void ManageShutdownRoutine(){ + if (UPSApp.fetcher.IsReachable){ + // Update last known state + lastKnownLineFrom = UPSApp.fetcher.UPSLineFrom; + lastKnownBatteryCritical = UPSApp.fetcher.BatteryCritical; + lastKnownChargeLevel = UPSApp.fetcher.ChargeLevel; + + if (UPSApp.fetcher.OnTimedShutdown){ + Debug.WriteLine("UPS going to shutdown: " + UPSApp.fetcher.TimedShutdownRemaining); + //checking if pc already flagged to shutdown + if (!IsGoingToShutdown() && !isShutdownCancelledByUser){ + int tMax = UPSApp.fetcher.TimedShutdownRemaining - 10; // Cadangan waktu 10 detik agar PC sempat mati sebelum listrik UPS putus + if (tMax<1) tMax = 1; + + int t = UPSApp.fetcher.BatteryCritical ? 1 : tMax; + RequestForShutdown(t);//request shutdown + } + }else{ + //checking requirement + int realMode = 0; + bool isForced = UPSApp.shutdownMode>0; + if (!isForced){ + realMode = UPSApp.fetcher.ShutdownSuggestMode; + }else{ + realMode = UPSApp.shutdownMode-1; + } + + bool shutFlag = false; + + if (isForced){ + //check setting requirmenet flag before decide to shutdown + bool onBattery = (UPSApp.fetcher.UPSLineFrom == 2); + int battLv = UPSApp.fetcher.ChargeLevel; + bool isCritical = UPSApp.fetcher.BatteryCritical; + ShutdownMode mode = (ShutdownMode) realMode; + + // Calculate normalized percentage (0 to 100) + double percentage = 100.0; + if (UPSApp.fetcher.BattMaxLevel > 0) { + percentage = (double)battLv * 100.0 / UPSApp.fetcher.BattMaxLevel; + } else { + percentage = battLv > 4 ? battLv : (battLv * 25.0); + } + + if (onBattery){ + switch (mode){ + case ShutdownMode.Disabled:{ + //do nothing + }break; + case ShutdownMode.OnBattery:{ + shutFlag = true; + }break; + case ShutdownMode.OnBattery75:{ + shutFlag = percentage <= 75.0; + }break; + case ShutdownMode.OnBattery50:{ + shutFlag = percentage <= 50.0; + }break; + case ShutdownMode.OnBattery25:{ + shutFlag = percentage <= 25.0; + }break; + case ShutdownMode.OnBatteryCritical:{ + shutFlag = (percentage <= 10.0) || isCritical; + }break; + } + } + + }else{ + //follow UPS flag + if (UPSApp.fetcher.ShutdownSuggested){ + shutFlag = true; + } + } + + if (UPSApp.fetcher.UPSLineFrom == 1 || UPSApp.fetcher.IsChargingOrBlink) { + isShutdownCancelledByUser = false; + } + + if (shutFlag && !isShutdownCancelledByUser){ + Debug.WriteLine("UPS Suggest to shutdown!"); + //request timed shutdown in 120 seconds, next cycle just wait for flagged shutdown + SendTimedShutdown(); + } + } + }else{ + // Handle unreachable (offline) state: + // If the connection is lost while the UPS was on battery, or the battery was critical, or if the user's setting was triggered + double lastPercentage = 100.0; + lastPercentage = lastKnownChargeLevel > 4 ? lastKnownChargeLevel : (lastKnownChargeLevel * 25.0); + + bool wasOnBattery = (lastKnownLineFrom == 2); + bool wasCritical = lastKnownBatteryCritical || (lastPercentage <= 25.0); + + if (wasOnBattery && wasCritical){ + if (!IsGoingToShutdown() && !isShutdownCancelledByUser){ + Debug.WriteLine("UPS connection lost while on battery and battery is critical. Requesting shutdown!"); + RequestForShutdown(30); // 30 seconds warning countdown + } + } + } + } + } +} \ No newline at end of file diff --git a/UPSNet/UPSForm.Designer.cs b/UPSNet/UPSForm.Designer.cs new file mode 100644 index 0000000..368e6e4 --- /dev/null +++ b/UPSNet/UPSForm.Designer.cs @@ -0,0 +1,137 @@ +namespace UPSNet +{ + partial class UPSForm + { + /// + /// Designer variable used to keep track of non-visual components. + /// + private System.ComponentModel.IContainer components = null; + private System.Windows.Forms.Label labelConnection; + private System.Windows.Forms.Button buttonConfig; + private System.Windows.Forms.ImageList imageListMain; + private System.Windows.Forms.Label labelInfo; + private System.Windows.Forms.Timer timerUpdate; + private System.Windows.Forms.Label labelState; + private System.Windows.Forms.Label labelBattLevel; + private System.Windows.Forms.Label labelStateEx; + + + protected override void Dispose(bool disposing) + { + if (disposing) { + if (components != null) { + components.Dispose(); + } + } + base.Dispose(disposing); + } + + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UPSForm)); + this.labelConnection = new System.Windows.Forms.Label(); + this.buttonConfig = new System.Windows.Forms.Button(); + this.imageListMain = new System.Windows.Forms.ImageList(this.components); + this.timerUpdate = new System.Windows.Forms.Timer(this.components); + this.labelState = new System.Windows.Forms.Label(); + this.labelBattLevel = new System.Windows.Forms.Label(); + this.labelInfo = new System.Windows.Forms.Label(); + this.labelStateEx = new System.Windows.Forms.Label(); + + this.SuspendLayout(); + // + // labelConnection + // + this.labelConnection.Location = new System.Drawing.Point(12, 15); + this.labelConnection.Name = "labelConnection"; + this.labelConnection.Size = new System.Drawing.Size(84, 27); + this.labelConnection.TabIndex = 0; + this.labelConnection.Text = "No Connection"; + // + // buttonConfig + // + this.buttonConfig.ImageIndex = 0; + this.buttonConfig.ImageList = this.imageListMain; + this.buttonConfig.Location = new System.Drawing.Point(225, 12); + this.buttonConfig.Name = "buttonConfig"; + this.buttonConfig.Size = new System.Drawing.Size(47, 31); + this.buttonConfig.TabIndex = 1; + this.buttonConfig.UseVisualStyleBackColor = true; + this.buttonConfig.Click += new System.EventHandler(this.ButtonConfigClick); + // + // imageListMain + // + this.imageListMain.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageListMain.ImageStream"))); + this.imageListMain.TransparentColor = System.Drawing.Color.Transparent; + this.imageListMain.Images.SetKeyName(0, "ellipsis16.png"); + // + // timerUpdate + // + this.timerUpdate.Enabled = true; + this.timerUpdate.Interval = 500; + this.timerUpdate.Tick += new System.EventHandler(this.TimerUpdateTick); + // + // labelState + // + this.labelState.Location = new System.Drawing.Point(94, 43); + this.labelState.Name = "labelState"; + this.labelState.Size = new System.Drawing.Size(170, 18); + this.labelState.TabIndex = 2; + this.labelState.Text = "State"; + this.labelState.Click += new System.EventHandler(this.LabelBattClick); + // + // labelBattLevel + // + this.labelBattLevel.Font = new System.Drawing.Font("Segoe UI Emoji", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.labelBattLevel.ForeColor = System.Drawing.Color.LimeGreen; + this.labelBattLevel.Location = new System.Drawing.Point(12, 42); + this.labelBattLevel.Name = "labelBattLevel"; + this.labelBattLevel.Size = new System.Drawing.Size(76, 18); + this.labelBattLevel.TabIndex = 3; + this.labelBattLevel.Text = "⬛⬛⬛🔲"; + // + // labelInfo + // + this.labelInfo.Location = new System.Drawing.Point(12, 79); + this.labelInfo.Name = "labelInfo"; + this.labelInfo.Size = new System.Drawing.Size(260, 18); + this.labelInfo.TabIndex = 4; + this.labelInfo.Text = "Shutdown mode: Unknown"; + // + // labelStateEx + // + this.labelStateEx.Font = new System.Drawing.Font("Webdings", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(2))); + this.labelStateEx.ForeColor = System.Drawing.Color.DarkOrange; + this.labelStateEx.Location = new System.Drawing.Point(74, 41); + this.labelStateEx.Name = "labelStateEx"; + this.labelStateEx.Size = new System.Drawing.Size(19, 18); + this.labelStateEx.TabIndex = 5; + this.labelStateEx.Text = "~rU"; + + // + // UPSForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(284, 105); + this.Controls.Add(this.labelStateEx); + this.Controls.Add(this.labelInfo); + this.Controls.Add(this.labelBattLevel); + this.Controls.Add(this.labelState); + this.Controls.Add(this.buttonConfig); + this.Controls.Add(this.labelConnection); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.MaximizeBox = false; + this.Name = "UPSForm"; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "EVXIO UPS Net"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.UPSFormFormClosing); + this.Shown += new System.EventHandler(this.UPSFormShown); + this.VisibleChanged += new System.EventHandler(this.UPSFormVisibleChanged); + this.ResumeLayout(false); + + } + } +} \ No newline at end of file diff --git a/UPSNet/UPSForm.cs b/UPSNet/UPSForm.cs new file mode 100644 index 0000000..8392c92 --- /dev/null +++ b/UPSNet/UPSForm.cs @@ -0,0 +1,220 @@ +/* + * Created by SharpDevelop. + * User: EVXIO + * Date: 4/3/2025 + * Time: 10:35 PM + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ +using System; +using System.Drawing; +using System.Windows.Forms; +using System.Text; + +namespace UPSNet +{ + /// + /// Description of UPSForm. + /// + public partial class UPSForm : Form { + + ConfigForm cfgForm = new ConfigForm(); + bool isBusy = false; + bool chargeTickTock = false; + + public static bool closeJustHideForm = false; + + public UPSForm(){ + // + // The InitializeComponent() call is required for Windows Forms designer support. + // + InitializeComponent(); + + // + // TODO: Add constructor code after the InitializeComponent() call. + // + SetDefaultInfo(); + + if (UPSApp.IsRunningInDebuggerOrIDE()){ + this.Text = "EVXIO UPS Net (Debug Mode)"; + } + } + + void SetDefaultInfo(){ + labelConnection.Text = "No Connection"; + labelBattLevel.Text = RepeatString("🔲", 4); + labelBattLevel.ForeColor = Color.LimeGreen; + labelStateEx.Text = ""; + labelState.Text = ""; + if (UPSApp.shutdownMode==0){ + labelInfo.Text = "Shutdown: Use UPS Suggestion"; + }else{ + ShowShutdownMode(UPSApp.shutdownMode-1, true); + } + } + + void UPSFormFormClosing(object sender, FormClosingEventArgs e) { + if (closeJustHideForm){ + if (e.CloseReason == CloseReason.UserClosing){ + e.Cancel = true; // Cancel the close operation + this.Hide(); // Hide the form instead + //trayIcon.Visible = true; // Show the tray icon + } + }else{ + this.Hide(); + UPSApp.upsForm = null; + e.Cancel = false; //accept close + } + } + + void ButtonConfigClick(object sender, EventArgs e) { + UPSApp.dialogOk = false; + cfgForm.ShowDialog(); + if (UPSApp.dialogOk){ + if (!UPSApp.fetcher.IsReachable){ + labelConnection.Text = "Connecting..."; + labelConnection.ForeColor = Color.Black; + }else{ + SetDefaultInfo(); + } + } + } + + + + void ShowShutdownMode(int mode, bool forced){ + string s = ""; + ShutdownMode x = (ShutdownMode) mode; + switch (x){ + case ShutdownMode.Disabled: s="Disabled";break; + case ShutdownMode.OnBattery: s="When AC Loss";break; + case ShutdownMode.OnBattery75: s="When ≤75% Battery";break; + case ShutdownMode.OnBattery50: s="When ≤50% Battery";break; + case ShutdownMode.OnBattery25: s="When ≤25% Battery";break; + case ShutdownMode.OnBatteryCritical: s="When Battery Critical";break; + default:s="Mode Unknown";break; + } + labelInfo.Text = "Shutdown: " + s; + labelInfo.ForeColor = Color.Black; + } + + void UpdateView(){ + isBusy = true; + //if (UPSApp.fetcher.IsReachable && (this.WindowState == FormWindowState.Normal) && (this.Visible)){ + if (UPSApp.fetcher.IsReachable){ + if (UPSApp.fetcher.Success>0){ + labelConnection.Text = "Connected"; + labelConnection.ForeColor = Color.Green; + + + //information status: + //show information for shutdown flag + int realMode = 0; + bool isForced = UPSApp.shutdownMode>0; + if (!isForced){ + realMode = UPSApp.fetcher.ShutdownSuggestMode; + }else{ + realMode = UPSApp.shutdownMode-1; + } + ShowShutdownMode(realMode, isForced); + + //Line and state info: + if (UPSApp.fetcher.OnState){ + if (UPSApp.fetcher.UPSLineFrom==1 || UPSApp.fetcher.IsChargingOrBlink){ + labelState.Text = "AC Line" + (UPSApp.fetcher.IsChargingOrBlink?" (Charging)":""); + labelStateEx.Text = "~"; + labelStateEx.ForeColor = Color.DarkOrange; + }else if (UPSApp.fetcher.UPSLineFrom==2){ + labelState.Text = "On Battery" + (UPSApp.fetcher.BatteryCritical?" (Critical)":""); + if (UPSApp.fetcher.BatteryCritical){ + labelStateEx.Text = "r"; + labelStateEx.ForeColor = Color.Red; + }else{ + labelStateEx.Text = ""; + } + } + }else{ + labelState.Text = "OFF"; + if (UPSApp.fetcher.UPSLineFrom==1){ + labelStateEx.Text = "~"; + labelStateEx.ForeColor = Color.DarkOrange; + if (UPSApp.fetcher.IsChargingOrBlink){ + labelState.Text += " - Charging"; + }else{ + labelState.Text += " - AC Available"; + } + }else{ + labelStateEx.Text = ""; + } + } + + //batt visual meter + if (UPSApp.fetcher.IsChargingOrBlink){ + chargeTickTock = !chargeTickTock; + int bar = chargeTickTock?Math.Min(UPSApp.fetcher.ChargeLevel+1, UPSApp.fetcher.BattMaxLevel):Math.Min(UPSApp.fetcher.ChargeLevel, UPSApp.fetcher.BattMaxLevel); + labelBattLevel.ForeColor = Color.LimeGreen; + labelBattLevel.Text = RepeatString("⬛", bar) + RepeatString("🔲", UPSApp.fetcher.BattMaxLevel-bar); + }else{ + if (UPSApp.fetcher.BatteryCritical){ + chargeTickTock = !chargeTickTock; + int bar = chargeTickTock?0:1; + labelBattLevel.ForeColor = Color.Red; + labelBattLevel.Text = RepeatString("⬛", bar) + RepeatString("🔲", UPSApp.fetcher.BattMaxLevel-bar); + }else{ + chargeTickTock = false; + if (UPSApp.fetcher.BattMaxLevel==0){ + labelBattLevel.ForeColor = Color.Red; + labelBattLevel.Text = "🔲🔲🔲🔲"; + }else{ + int bar = UPSApp.fetcher.ChargeLevel; + labelBattLevel.ForeColor = Color.LimeGreen; + labelBattLevel.Text = RepeatString("⬛", bar) + RepeatString("🔲", UPSApp.fetcher.BattMaxLevel-bar); + } + } + } + + } + }else{ + labelConnection.Text = "No Connection"; + labelConnection.ForeColor = Color.Red; + } + isBusy = false; + } + + void TimerUpdateTick(object sender, EventArgs e) { + if (isBusy) return; + UpdateView(); + } + + void UPSFormShown(object sender, EventArgs e){ + UpdateView(); + timerUpdate.Enabled = true; + } + + + void LabelBattClick(object sender, EventArgs e) { + + } + + public static string RepeatString(string str, int count){ + if (count <= 0) return "";//string.Empty; + if (count == 1) return str; + + var sb = new StringBuilder(str.Length * count); + for (int i = 0; i < count; i++) { + sb.Append(str); + } + return sb.ToString(); + } + + void UPSFormVisibleChanged(object sender, EventArgs e){ + if (!this.Visible){ + timerUpdate.Enabled = false; + }else{ + UpdateView(); + timerUpdate.Enabled = true; + } + } + + } +} diff --git a/UPSNet/UPSForm.resx b/UPSNet/UPSForm.resx new file mode 100644 index 0000000..fb92ade --- /dev/null +++ b/UPSNet/UPSForm.resx @@ -0,0 +1,462 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + 17, 17 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAAAW + BwAAAk1TRnQBSQFMAwEBAAGoAQABqAEAARABAAEQAQAE/wEhAQAI/wFCAU0BNgcAATYDAAEoAwABQAMA + ARADAAEBAQABIAYAARAiAAMeASsDSwGOAVoBXQFaAdMBUQFsAU0B8wFRAWwBTQHzAVoBXQFaAdMDSgGN + Ax0BKtgAAwQBBgNMAZIBNAF8ATIB/AE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4 + Af8BPAGvATgB/wFQAYsBTAH7A0wBkAMEAQXMAAMEAQYBVgFYAVYBvAE8Aa8BOAH/ATwBrwE4Af8BPAGv + ATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ + AVYBWAFWAbsDBAEFyAADTAGTATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8 + Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/A0wBkMQA + Ax4BKwE0AXwBMgH8ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ + ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATQBfAEyAfwDHQEq + wAADTAGPATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4 + Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wNK + AYzAAAFaAV4BWgHVATwBrwE4Af8BXQG9AVkB/wG4Ad0BtwH/AZABywGNAf8BPAGvATgB/wFGAbMBQgH/ + AasB1wGpAf8BqwHXAakB/wFFAbMBQQH/ATwBrwE4Af8BkQHLAY4B/wG4Ad0BtwH/AVwBvQFZAf8BPAGv + ATgB/wFaAV0BWgHTwAABWQFoAVkB8gE8Aa8BOAH/AeQB8QHkAf8D+gH/A/oB/wFeAb4BWwH/AawB1wGq + Af8D+gH/A/oB/wGrAdcBqQH/AV8BvgFbAf8D+gH/A/oB/wHkAfAB4wH/ATwBrwE4Af8BUwFpAVMB8cAA + AVEBbAFNAfMBPAGvATgB/wHlAfEB5QH/A/oB/wP6Af8BXwG+AVsB/wGsAdcBqgH/A/oB/wP6Af8BqwHX + AakB/wFfAb8BXAH/A/oB/wP6Af8B5AHxAeQB/wE8Aa8BOAH/AVkBaAFZAfLAAAFaAV4BWgHVATwBrwE4 + Af8BXQG+AVoB/wG5Ad0BtwH/AZEBywGOAf8BPAGvATgB/wFGAbMBQgH/AawB2AGrAf8BrAHXAaoB/wFG + AbMBQgH/ATwBrwE4Af8BkgHMAY8B/wG5Ad0BtwH/AV0BvQFZAf8BPAGvATgB/wFaAV0BWgHTwAACTQFM + AZEBPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8 + Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/A0sBjsAA + Ax8BLAE0AXwBMgH8ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ + ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATQBfAEyAfwDHgEr + xAACTgFNAZUBPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGv + ATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8DTAGSyAADBAEGAVcBWgFX + Ab0BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8 + Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wFWAVgBVgG8AwQBBswAAwQBBgJOAU0BlQFAAagBQAH9ATwBrwE4 + Af8BPAGvATgB/wE8Aa8BOAH/ATwBrwE4Af8BPAGvATgB/wE8Aa8BOAH/ATQBfAEyAfwDTAGTAwQBBtgA + Ax8BLANMAZABXAFgAVwB1AFSAWcBUgH0AVIBZwFSAfQBXAFgAVwB1ANMAZADHwEs0AABQgFNAT4HAAE+ + AwABKAMAAUADAAEQAwABAQEAAQEFAAGAFwAD/wEAAfABDwYAAcABAwYAAYABAQYAAYABAUYAAYABAQYA + AYABAQYAAcABAwYAAfABDwYACw== + + + + 141, 17 + + + + AAABAAQAMDAAAAEAIACoJQAARgAAACAgAAABACAAqBAAAO4lAAAYGAAAAQAgAIgJAACWNgAAEBAAAAEA + IABoBAAAHkAAACgAAAAwAAAAYAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPSS + JAjzlSFx85YhzPOVIfjylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zlSH385YhzPOVIXL0mCIIAAAAAAAA + AAAAAAAA8pYiHfOVIdLylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/zlSDS8pUhHQAAAAD0lCAI85Ug0vKVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/85Ug0vSWIgjzlSFy8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//OXIHHzliDN8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//OXIMzyliD48pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//OW + IffylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP7ylSD68pUg+vKVIPrylSD68pUg+vKVIPrylSD68pUg+vKVIPrylSD68pUg+vKVIPrylSD+8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/85Ugr/OWHhjylSAF8pUgBfKVIAXylSAF8pUgBfKVIAXylSAF8pUgBfKVIAXylSAF8pUgBfKV + IAXzlx8Y85Ugr/KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/yliD+85cfGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA85ceGPKVIP7ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD68pUgBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pUgBfKVIPrylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD68pUgBQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pUgBfKVIPrylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD68pUgBQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pUgBfKV + IPrylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD68pUgBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA8pUgBfKVIPrylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD68pUgBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA8pUgBfKVIPrylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD68pUgBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pUgBfKVIPrylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD68pUgBQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pUgBfKVIPrylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OW + If/zliH/85Yh//OWIf/zliH/8pYh//OWIf/zliH/8pYh//OWIf/zliH/85Yh//OWIf/zliH685YhBQAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pUhBfKV + IPrylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KV + IP/zlSH/85Yh//OVIf/zliH/85Yh//OVIf/zlSH/85Ug//OVIf/zlSH/85Ug//OVIf/zliH/85Yh//OW + If/zliH685YhBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA8pUgBfKVIPrylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/8pUg//OWIf/zliH/8pUg//OW + If/zliH/85Yh//OWIf/zliH685YhBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA8pUgBfKVIPrylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/8pYh//OW + If/zliH/8pYh//OWIf/zliH/85Yh//OWIf/zliH685YhBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pUhBfKVIPrylSD/8pUh//KVIP/ylSD/8pUh//KV + IP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/zlSH/85Yh//OVIf/zliH/85Yh//OV + If/zlSH/85Ug//OVIf/zlSH/85Ug//OVIf/zliH/85Yh//OWIf/zliH685YhBQAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8pUgBfKVIPrylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OW + If/zliH/85Yh//OWIf/zliH/8pUg//OWIf/zliH/8pUg//OWIf/zliH/85Yh//OWIf/zliH+85UfGAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA85YeGPKV + IP7ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/8pYh//OWIf/zliH/8pYh//OWIf/zliH/85Yh//OW + If/zliH/85Ygr/OWHxjzliEF85YhBfOWIQXzliEF85YhBfKVIAXylSAF8pUhBfKVIAXylSAF8pUhBfKV + IAXzlB8Y85Ugr/KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KV + IP/ylSD/8pUh//KVIP/zlSH/85Yh//OVIf/zliH/85Yh//OVIf/zlSH/85Ug//OVIf/zlSH/85Ug//OV + If/zliH/85Yh//OWIf/zliH/85Yh//OWIf7zliH685Yh+vOWIfrzliH685Yh+vKVIPrylSD68pUg+vKV + IPrylSD68pUg+vKVIPryliD+8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/8pUg//OW + If/zliH/8pUg//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OW + If/zliH/8pYh//OWIf/zliH/8pYh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OW + If/zliH/85Yh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KV + IP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/ylSD/8pUh//KVIP/zlSH/85Yh//OV + If/zliH/85Yh//OVIf/zlSH/85Ug//OVIf/zlSH/85Ug//OVIf/zliH/85Yh//OWIf/zliH/85Yh//OW + If/zliH/85Yh//OWIf/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OW + If/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/zlSH/8pYh//OVIP/zlSH/8pYh//OVIP/zlSH/8pYh//OVIP/zlSH/8pYh//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/85Yh//KVIP/zliH/85Yh//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OW + If/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zlSH/8pYh//OVIP/zlSH/8pYh//OV + IP/zlSH/8pYh//OVIP/zlSH/8pYh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/85Yh//KVIP/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OW + If/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/yliD48pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//OVIfjzlSDN8pUg//KVIP/ylSD/8pUh//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//OXIMzzlyBy85Yh//KVIf/zliH/85Yh//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OW + If/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//OWIXH0lh8J85Ug0/KV + IP/zlSD/8pUh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OWIf/zliH/85Yh//OW + If/zliH/85Yh//OWIf/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/85Yg0vSW + IwgAAAAA8pYiHfOWINLyliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OW + If/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/zlSDT8pUhHQAAAAAAAAAAAAAAAPSWIAnzlyBy85YgzfKWIPjylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD485YgzfOZIHL0lSAJAAAAAAAAAADAAAAAAAMAAIAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB//gAAAAAAAH/+AAAAAAAA + f/4AAAAAAAB//gAAAAAAAH/+AAAAAAAAf/4AAAAAAAB//gAAAAAAAH/+AAAAAAAAf/4AAAAAAAB//gAA + AAAAAH/+AAAAAAAAf/4AAAAAAAB//gAAAAAAAH/+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAAAAQAAwAAAAAADAAAoAAAAIAAAAEAA + AAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8ZYiA/OTIjXylSC18pUg8fGVIP/ylSD/8ZUg//KV + IP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//KVIPDylSC185YhNfKVIQPzlCA18pUg0vGVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/ylSDS85UhNfKVILXylSD/8ZUg//KV + IP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/yliC18pUg8fGV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//KV + IPDxlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KV + IP/xlSD/8pUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KV + IP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KV + IP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8pUg9vKVH8LxlSCo8pUgqPGVIKjylSCo8ZUgqPKV + IKjxlSCo8pUgqPKVH8LylSD28ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/ylR/C85YeHvGVIALxlSAC8ZUgAvGV + IALxlSAC8ZUgAvGVIALxlSAC85YeHvKVH8LxlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIKjylSACAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADxlSAC8pUgqPGVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUgqPGV + IAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPGVIALxlSCo8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KV + IP/xlSCo8pUgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8ZUgAvKVIKjxlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIKjxlSACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADxlSAC8ZUgqPGV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUgqPKVIAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPGV + IALylSCo8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//OVIf/zlSH/85Yh//OV + If/ylSD/8pUg//KVIP/ylSD/85Yh//OWIf/zliGo85YhAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA8ZUgAvGVIKjxlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/85Yh//OW + If/zliH/85Yh//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OWIajzliECAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAADxlSAC8pUgqPGVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KV + IP/zlSH/85Uh//OWIf/zlSH/8pUg//KVIP/ylSD/8pUg//OWIf/zliH/85YhqPOWIQIAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPGVIALxlSCo8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//OWIf/zliH/85Yh//OWIf/ylSD/8pUg//KVIP/ylSD/85Yh//OWIf/zlSDC85UfHvOW + IQLzliEC85YhAvKVIALxlSAC8pUgAvGVIALylSAC85UeHvKVH8LxlSD/8pUg//GVIP/ylSD/8ZUg//KV + IP/xlSD/8pUg//GVIP/ylSD/85Uh//OVIf/zliH/85Uh//KVIP/ylSD/8pUg//KVIP/zliH/85Yh//OW + IPbzliDC85YhqPOWIajzliGo8pUgqPGVIKjxlSCo8ZUgqPGVIKjylR/C8pUg9vGVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/zliH/85Yh//OWIf/zliH/8pUg//KVIP/ylSD/8pUg//OW + If/zliH/85Yh//OWIf/zliH/85Yh//OWIf/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KV + IP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//OVIf/zlSH/85Yh//OVIf/ylSD/8pUg//KV + IP/ylSD/85Yh//OWIf/zliH/85Yh//OWIf/zliH/85Yh//KVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/ylSH/8pUg//KVIf/ylSD/8pUh//KVIP/ylSH/8pUg//GVIP/ylSD/8ZUg//KV + IP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8ZUg//GVIP/xlSD/8ZUg//KVIf/ylSD/8pUh//KVIP/ylSH/8pUg//KVIf/ylSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8pUh//KVIP/ylSH/8pUg//KVIf/ylSD/8pUh//KV + IP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//GVIP/xlSD/8ZUg//GVIP/ylSH/8pUg//KVIf/ylSD/8pUh//KV + IP/ylSH/8pUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/ylSDx8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//OWIf/zliH/85Yh//OW + If/zliH/85Yh//OWIf/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg8fKWILXylSD/8pUg//KVIP/xlSD/8ZUg//GVIP/xlSD/85Yh//OW + If/zliH/85Yh//OWIf/zliH/85Yh//KVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/ylSC185UfNvKVINLylSD/8pUg//GVIP/ylSD/8ZUg//KV + IP/zliH/85Yh//OWIf/zliH/85Yh//OWIf/zliH/8pUg//GVIP/ylSD/8ZUg//KVIP/xlSD/8pUg//GV + IP/ylSD/8ZUg//KVIP/xlSD/8pUg//GVIP/ylSD/8pUg0vOVITXxliID85YgNvKWILXylSDx8ZUg//GV + IP/xlSD/8ZUg//OWIf/zliH/85Yh//OWIf/zliH/85Yh//OWIf/ylSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8pUg8fKXILXzlSA28ZUhAwAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP + 8AAAD/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAABgA + AAAwAAAAAQAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPKWIgfzlCGS8pUg8PKVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IPDzlSCT8pUhB/OUIJPylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/85UgkvKVIPHylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg8PKVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIPzylSD88pUg/PKVIPzylSD88pUg/PKVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/85YfOPKV + IALylSAC8pUgAvKVIALylSAC8pUgAvOWHzjylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD88pUgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPKV + IALylSD88pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD88pUgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPKVIALylSD88pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD88pUgAgAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAPKVIALylSD88pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD88pUgAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPKVIALylSD88pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//OVIf/zlSH/85Uh//KVIP/zlSH/8pUg//OWIf/zliH885YhAgAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPKVIALylSD88pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//OV + If/zlSH/85Uh//KVIP/zlSH/8pUg//OWIf/zliH885YhAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPKV + IALylSD88pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//OWIf/zliH/85Yh//KVIP/zliH/8pUg//OW + If/zliH/85UfOPOWIQLzliEC8pUgAvKVIALylSAC8pUgAvOVHzjylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//OVIf/zlSH/85Uh//KVIP/zlSH/8pUg//OWIf/zliH/85Yh//OWIfzzliH88pUg/PKV + IPzylSD88pUg/PKVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//OVIf/zlSH/85Uh//KV + IP/zlSH/8pUg//OWIf/zliH/85Yh//OWIf/zliH/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIf/zlSD/8pUg//KV + If/zlSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//OWIf/zliH/85Yh//OWIf/zliH/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + If/zlSD/8pUg//KVIf/zlSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIPHylSD/8pUg//KVIP/ylSD/8pUg//OWIf/zliH/85Yh//OWIf/zliH/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg8POWIJPylSD/8pUg//KV + IP/ylSD/8pUg//OWIf/zliH/85Yh//OWIf/zliH/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUg//KVIP/ylSD/85UhkvKWIgfzliCT8pUg8fKVIP/ylSD/8pUg//OWIf/zliH/85Yh//OW + If/zliH/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIP/ylSD/8pUg//KVIPHzliCT8pUhBwAA + AEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQQB+AEEAfgBBAH4AQQB+AEEAfgBBAH4AQQAA + AEEAAABBAAAAQQAAAEEAAABBAAAAQQAAAEEAAABBAAAAQSgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAADzlCFQ8pUg6fGVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//KVIOnzlSBQ8pUg6fGVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8pUg6fGVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8pUfpvGV + IFXxlSBV8ZUgVfGVIFXylR+m8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IFUAAAAAAAAAAAAAAAAAAAAA8ZUgVfGVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSBVAAAAAAAAAAAAAAAAAAAAAPGVIFXxlSD/8ZUg//GVIP/xlSD/8ZUg//KVIP/ylSD/8pUg//KV + IP/ylSD/8pUgVQAAAAAAAAAAAAAAAAAAAADxlSBV8ZUg//GVIP/xlSD/8ZUg//GVIP/zlSH/85Uh//KV + IP/ylSD/85Yh//OWIVUAAAAAAAAAAAAAAAAAAAAA8ZUgVfGVIP/xlSD/8ZUg//GVIP/xlSD/85Uh//OV + If/ylSD/8pUg//OWIf/zlSCm85YhVfKVIFXxlSBV8ZUgVfKVH6bxlSD/8ZUg//GVIP/xlSD/8ZUg//OV + If/zlSH/8pUg//KVIP/zliH/85Yh//OWIf/ylSD/8ZUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/ylSD/8pUg//GVIP/xlSD/8pUg//KVIP/ylSD/8pUg//GVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8pUg//KVIP/xlSD/8ZUg//KVIP/ylSD/8pUg//KVIP/xlSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//KVIOnylSD/8ZUg//GVIP/zliH/85Yh//OWIf/ylSD/8ZUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//KVIOnzlSBQ8pUg6fGVIP/xlSD/85Yh//OWIf/zliH/8pUg//GVIP/xlSD/8ZUg//GV + IP/xlSD/8ZUg//KVIOnzlSBQAACsQQAArEEAAKxBAACsQQAArEEAAKxBA8CsQQPArEEDwKxBA8CsQQAA + rEEAAKxBAACsQQAArEEAAKxBAACsQQ== + + + \ No newline at end of file diff --git a/UPSNet/UPSNet.csproj b/UPSNet/UPSNet.csproj new file mode 100644 index 0000000..dc76670 --- /dev/null +++ b/UPSNet/UPSNet.csproj @@ -0,0 +1,106 @@ + + + + {C3B4FA60-BA15-49F5-A68E-8DFAA7519B27} + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Debug + AnyCPU + WinExe + UPSNet + UPSNet + v4.8 + Properties + images\stop-ico.ico + False + False + False + False + False + False + obj\$(Configuration)\ + 4 + False + + + + x86 + 4194304 + False + Auto + 4096 + + + bin\Debug\ + True + Full + False + True + DEBUG;TRACE + obj\ + + + bin\Release\ + False + None + True + False + TRACE + + + + 4.0 + + + + 3.5 + + + + 3.5 + + + + + + 3.5 + + + + + + + Form + + + ConfigForm.cs + + + + + + + + Form + + + UPSForm.cs + + + + + + + ConfigForm.Designer.cs + + + NotificationIcon.cs + + + UPSForm.Designer.cs + + + + + + + \ No newline at end of file diff --git a/UPSNet/UPSNet.sln b/UPSNet/UPSNet.sln new file mode 100644 index 0000000..e62aa97 --- /dev/null +++ b/UPSNet/UPSNet.sln @@ -0,0 +1,20 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +# SharpDevelop 5.1 +VisualStudioVersion = 12.0.20827.3 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UPSNet", "UPSNet.csproj", "{C3B4FA60-BA15-49F5-A68E-8DFAA7519B27}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C3B4FA60-BA15-49F5-A68E-8DFAA7519B27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C3B4FA60-BA15-49F5-A68E-8DFAA7519B27}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C3B4FA60-BA15-49F5-A68E-8DFAA7519B27}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C3B4FA60-BA15-49F5-A68E-8DFAA7519B27}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/UPSNet/WindowsShutdown.cs b/UPSNet/WindowsShutdown.cs new file mode 100644 index 0000000..1597c08 --- /dev/null +++ b/UPSNet/WindowsShutdown.cs @@ -0,0 +1,140 @@ +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace UPSNet +{ + public static class WindowsShutdown + { + // Import Windows API functions + [DllImport("user32.dll", SetLastError = true)] + private static extern bool ExitWindowsEx(uint uFlags, uint dwReason); + + [DllImport("advapi32.dll", SetLastError = true)] + private static extern bool AbortSystemShutdown(string lpMachineName); + + [DllImport("advapi32.dll", SetLastError = true)] + private static extern bool InitiateSystemShutdown( + string lpMachineName, + string lpMessage, + uint dwTimeout, + bool bForceAppsClosed, + bool bRebootAfterShutdown); + + // Shutdown flags + private const uint EWX_LOGOFF = 0x00; + private const uint EWX_SHUTDOWN = 0x01; + private const uint EWX_REBOOT = 0x02; + private const uint EWX_FORCE = 0x04; + private const uint EWX_POWEROFF = 0x08; + + /// + /// Shutdown modes + /// + public enum ShutdownMode + { + Shutdown, + Restart, + LogOff, + ForceShutdown, + ForceRestart, + PowerOff + } + + /// + /// Shuts down Windows with specified mode + /// + public static bool Shutdown(ShutdownMode mode) + { + uint flags = 0; + + switch (mode) + { + case ShutdownMode.Shutdown: + flags = EWX_SHUTDOWN; + break; + case ShutdownMode.Restart: + flags = EWX_REBOOT; + break; + case ShutdownMode.LogOff: + flags = EWX_LOGOFF; + break; + case ShutdownMode.ForceShutdown: + flags = EWX_SHUTDOWN | EWX_FORCE; + break; + case ShutdownMode.ForceRestart: + flags = EWX_REBOOT | EWX_FORCE; + break; + case ShutdownMode.PowerOff: + flags = EWX_POWEROFF; + break; + } + + return ExitWindowsEx(flags, 0); + } + + /// + /// Shuts down or restarts with a timeout and message + /// + public static bool TimedShutdown(bool restart, int timeoutSeconds = 30, string message = "") { + return InitiateSystemShutdown( + null, // Local computer + message, // Display message + (uint)timeoutSeconds, // Timeout period + true, // Force apps closed + restart); // Restart after shutdown + } + + /// + /// Cancel pending shutdown + /// + public static bool CancelShutdown(){ + return AbortSystemShutdown(null); // Null for local computer + } + + /// + /// Aborts a pending shutdown + /// + public static void AbortShutdown(){ + Process.Start("shutdown", "/a"); + } + + /// + /// Executes shutdown via command line (alternative method) + /// + public static bool CmdShutdown(ShutdownMode mode, int timeoutSeconds = 0) + { + string args = ""; + + switch (mode) + { + case ShutdownMode.Shutdown: + case ShutdownMode.ForceShutdown: + case ShutdownMode.PowerOff: + args = "/s"; + break; + case ShutdownMode.Restart: + case ShutdownMode.ForceRestart: + args = "/r"; + break; + case ShutdownMode.LogOff: + args = "/l"; + break; + } + + if (timeoutSeconds > 0) + { + args += " /t " + timeoutSeconds; + } + + if (mode == ShutdownMode.ForceShutdown || mode == ShutdownMode.ForceRestart) + { + args += " /f"; + } + + Process p = Process.Start("shutdown", args); + if (p==null) return false; + return true; + } + } +} \ No newline at end of file diff --git a/UPSNet/app.config b/UPSNet/app.config new file mode 100644 index 0000000..04fcaeb --- /dev/null +++ b/UPSNet/app.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/UPSNet/bin/Debug/UPSNet.exe b/UPSNet/bin/Debug/UPSNet.exe new file mode 100644 index 0000000..d3988d0 Binary files /dev/null and b/UPSNet/bin/Debug/UPSNet.exe differ diff --git a/UPSNet/bin/Debug/UPSNet.exe.config b/UPSNet/bin/Debug/UPSNet.exe.config new file mode 100644 index 0000000..04fcaeb --- /dev/null +++ b/UPSNet/bin/Debug/UPSNet.exe.config @@ -0,0 +1,6 @@ + + + + + + diff --git a/UPSNet/bin/Debug/UPSNet.pdb b/UPSNet/bin/Debug/UPSNet.pdb new file mode 100644 index 0000000..7514dec Binary files /dev/null and b/UPSNet/bin/Debug/UPSNet.pdb differ diff --git a/UPSNet/bin/Debug/config.json b/UPSNet/bin/Debug/config.json new file mode 100644 index 0000000..d0f6a33 --- /dev/null +++ b/UPSNet/bin/Debug/config.json @@ -0,0 +1 @@ +{"initialized":"true","address":"192.168.137.113","mode":"1"} \ No newline at end of file diff --git a/UPSNet/bin/Release/Cancel Shutdown.lnk b/UPSNet/bin/Release/Cancel Shutdown.lnk new file mode 100644 index 0000000..ab28a38 Binary files /dev/null and b/UPSNet/bin/Release/Cancel Shutdown.lnk differ diff --git a/UPSNet/bin/Release/UPSNet.exe b/UPSNet/bin/Release/UPSNet.exe new file mode 100644 index 0000000..0beacad Binary files /dev/null and b/UPSNet/bin/Release/UPSNet.exe differ diff --git a/UPSNet/bin/Release/UPSNet.exe.config b/UPSNet/bin/Release/UPSNet.exe.config new file mode 100644 index 0000000..52737ff --- /dev/null +++ b/UPSNet/bin/Release/UPSNet.exe.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/UPSNet/images/close.png b/UPSNet/images/close.png new file mode 100644 index 0000000..7e7d86a Binary files /dev/null and b/UPSNet/images/close.png differ diff --git a/UPSNet/images/close16.png b/UPSNet/images/close16.png new file mode 100644 index 0000000..63bef38 Binary files /dev/null and b/UPSNet/images/close16.png differ diff --git a/UPSNet/images/close24.png b/UPSNet/images/close24.png new file mode 100644 index 0000000..6847dbc Binary files /dev/null and b/UPSNet/images/close24.png differ diff --git a/UPSNet/images/dashboard.png b/UPSNet/images/dashboard.png new file mode 100644 index 0000000..eb0c28f Binary files /dev/null and b/UPSNet/images/dashboard.png differ diff --git a/UPSNet/images/dashboard16.png b/UPSNet/images/dashboard16.png new file mode 100644 index 0000000..e498c92 Binary files /dev/null and b/UPSNet/images/dashboard16.png differ diff --git a/UPSNet/images/dashboard24.png b/UPSNet/images/dashboard24.png new file mode 100644 index 0000000..4e40316 Binary files /dev/null and b/UPSNet/images/dashboard24.png differ diff --git a/UPSNet/images/ellipsis.png b/UPSNet/images/ellipsis.png new file mode 100644 index 0000000..d1b96d9 Binary files /dev/null and b/UPSNet/images/ellipsis.png differ diff --git a/UPSNet/images/ellipsis16.png b/UPSNet/images/ellipsis16.png new file mode 100644 index 0000000..1c438be Binary files /dev/null and b/UPSNet/images/ellipsis16.png differ diff --git a/UPSNet/images/ellipsis24.png b/UPSNet/images/ellipsis24.png new file mode 100644 index 0000000..3dfdc78 Binary files /dev/null and b/UPSNet/images/ellipsis24.png differ diff --git a/UPSNet/images/info.png b/UPSNet/images/info.png new file mode 100644 index 0000000..4d12f1a Binary files /dev/null and b/UPSNet/images/info.png differ diff --git a/UPSNet/images/info16.png b/UPSNet/images/info16.png new file mode 100644 index 0000000..5259bdb Binary files /dev/null and b/UPSNet/images/info16.png differ diff --git a/UPSNet/images/info24.png b/UPSNet/images/info24.png new file mode 100644 index 0000000..f1a61de Binary files /dev/null and b/UPSNet/images/info24.png differ diff --git a/UPSNet/images/stop-ico.ico b/UPSNet/images/stop-ico.ico new file mode 100644 index 0000000..5c3ecd2 Binary files /dev/null and b/UPSNet/images/stop-ico.ico differ diff --git a/UPSNet/images/stop.png b/UPSNet/images/stop.png new file mode 100644 index 0000000..6a8fc3a Binary files /dev/null and b/UPSNet/images/stop.png differ diff --git a/UPSNet/images/stop16.png b/UPSNet/images/stop16.png new file mode 100644 index 0000000..de3dbdd Binary files /dev/null and b/UPSNet/images/stop16.png differ diff --git a/UPSNet/images/stop24.png b/UPSNet/images/stop24.png new file mode 100644 index 0000000..47c1492 Binary files /dev/null and b/UPSNet/images/stop24.png differ diff --git a/UPSNet/images/stop32.png b/UPSNet/images/stop32.png new file mode 100644 index 0000000..a267686 Binary files /dev/null and b/UPSNet/images/stop32.png differ diff --git a/UPSNet/obj/Debug/.NETFramework,Version=v4.5.2.AssemblyAttributes.cs b/UPSNet/obj/Debug/.NETFramework,Version=v4.5.2.AssemblyAttributes.cs new file mode 100644 index 0000000..97d0f21 --- /dev/null +++ b/UPSNet/obj/Debug/.NETFramework,Version=v4.5.2.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.5.2", FrameworkDisplayName = "")] diff --git a/UPSNet/obj/Debug/.NETFramework,Version=v4.8.AssemblyAttributes.cs b/UPSNet/obj/Debug/.NETFramework,Version=v4.8.AssemblyAttributes.cs new file mode 100644 index 0000000..15efebf --- /dev/null +++ b/UPSNet/obj/Debug/.NETFramework,Version=v4.8.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] diff --git a/UPSNet/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache b/UPSNet/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache new file mode 100644 index 0000000..ca95a27 Binary files /dev/null and b/UPSNet/obj/Debug/DesignTimeResolveAssemblyReferencesInput.cache differ diff --git a/UPSNet/obj/Debug/UPSNet.ConfigForm.resources b/UPSNet/obj/Debug/UPSNet.ConfigForm.resources new file mode 100644 index 0000000..6c05a97 Binary files /dev/null and b/UPSNet/obj/Debug/UPSNet.ConfigForm.resources differ diff --git a/UPSNet/obj/Debug/UPSNet.NotificationIcon.resources b/UPSNet/obj/Debug/UPSNet.NotificationIcon.resources new file mode 100644 index 0000000..b19f4e3 Binary files /dev/null and b/UPSNet/obj/Debug/UPSNet.NotificationIcon.resources differ diff --git a/UPSNet/obj/Debug/UPSNet.UPSForm.resources b/UPSNet/obj/Debug/UPSNet.UPSForm.resources new file mode 100644 index 0000000..2d609f1 Binary files /dev/null and b/UPSNet/obj/Debug/UPSNet.UPSForm.resources differ diff --git a/UPSNet/obj/Debug/UPSNet.csproj.AssemblyReference.cache b/UPSNet/obj/Debug/UPSNet.csproj.AssemblyReference.cache new file mode 100644 index 0000000..8060572 Binary files /dev/null and b/UPSNet/obj/Debug/UPSNet.csproj.AssemblyReference.cache differ diff --git a/UPSNet/obj/Debug/UPSNet.csproj.CoreCompileInputs.cache b/UPSNet/obj/Debug/UPSNet.csproj.CoreCompileInputs.cache new file mode 100644 index 0000000..d85fa0b --- /dev/null +++ b/UPSNet/obj/Debug/UPSNet.csproj.CoreCompileInputs.cache @@ -0,0 +1 @@ +05d8d2c330621d8af56c6aa46870292694c3730e157ef748c26d40a50a96d2b7 diff --git a/UPSNet/obj/Debug/UPSNet.csproj.FileListAbsolute.txt b/UPSNet/obj/Debug/UPSNet.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..d45c0ce --- /dev/null +++ b/UPSNet/obj/Debug/UPSNet.csproj.FileListAbsolute.txt @@ -0,0 +1,31 @@ +D:\Projects\SharpDevelop Projects\UPSNet\bin\Debug\UPSNet.exe.config +D:\Projects\SharpDevelop Projects\UPSNet\bin\Debug\UPSNet.exe +D:\Projects\SharpDevelop Projects\UPSNet\bin\Debug\UPSNet.pdb +D:\Projects\SharpDevelop Projects\UPSNet\obj\Debug\UPSNet.csprojResolveAssemblyReference.cache +D:\Projects\SharpDevelop Projects\UPSNet\obj\Debug\UPSNet.exe +D:\Projects\SharpDevelop Projects\UPSNet\obj\Debug\UPSNet.pdb +D:\Projects\SharpDevelop Projects\UPSNet\obj\Debug\UPSNet.csproj.GenerateResource.Cache +D:\Projects\SharpDevelop Projects\UPSNet\obj\Debug\UPSNet.NotificationIcon.resources +D:\Projects\SharpDevelop Projects\UPSNet\obj\Debug\UPSNet.UPSForm.resources +D:\Projects\SharpDevelop Projects\UPSNet\obj\Debug\UPSNet.ConfigForm.resources +D:\Antigrafity\#Project\Perbandingan\UPSNet-2026-3\UPSNet\bin\Debug\UPSNet.exe.config +D:\Antigrafity\#Project\Perbandingan\UPSNet-2026-3\UPSNet\bin\Debug\UPSNet.exe +D:\Antigrafity\#Project\Perbandingan\UPSNet-2026-3\UPSNet\obj\Debug\UPSNet.csprojResolveAssemblyReference.cache +D:\Antigrafity\#Project\Perbandingan\UPSNet-2026-3\UPSNet\obj\Debug\UPSNet.ConfigForm.resources +D:\Antigrafity\#Project\Perbandingan\UPSNet-2026-3\UPSNet\obj\Debug\UPSNet.NotificationIcon.resources +D:\Antigrafity\#Project\Perbandingan\UPSNet-2026-3\UPSNet\obj\Debug\UPSNet.UPSForm.resources +D:\Antigrafity\#Project\Perbandingan\UPSNet-2026-3\UPSNet\obj\Debug\UPSNet.csproj.GenerateResource.Cache +D:\Antigrafity\#Project\Perbandingan\UPSNet-2026-3\UPSNet\obj\Debug\UPSNet.exe +D:\Antigrafity\#Project\Perbandingan\UPSNet-2026-3\UPSNet\obj\Debug\UPSNet.pdb +D:\Antigrafity\#Project\Perbandingan\UPSNet-2026-3\UPSNet\bin\Debug\UPSNet.pdb +D:\#project\Perbandingan\UPSNet-2026-3\UPSNet\bin\Debug\UPSNet.exe.config +D:\#project\Perbandingan\UPSNet-2026-3\UPSNet\bin\Debug\UPSNet.exe +D:\#project\Perbandingan\UPSNet-2026-3\UPSNet\bin\Debug\UPSNet.pdb +D:\#project\Perbandingan\UPSNet-2026-3\UPSNet\obj\Debug\UPSNet.ConfigForm.resources +D:\#project\Perbandingan\UPSNet-2026-3\UPSNet\obj\Debug\UPSNet.NotificationIcon.resources +D:\#project\Perbandingan\UPSNet-2026-3\UPSNet\obj\Debug\UPSNet.UPSForm.resources +D:\#project\Perbandingan\UPSNet-2026-3\UPSNet\obj\Debug\UPSNet.csproj.GenerateResource.Cache +D:\#project\Perbandingan\UPSNet-2026-3\UPSNet\obj\Debug\UPSNet.exe +D:\#project\Perbandingan\UPSNet-2026-3\UPSNet\obj\Debug\UPSNet.pdb +D:\#project\Perbandingan\UPSNet-2026-3\UPSNet\obj\Debug\UPSNet.csproj.AssemblyReference.cache +D:\#project\Perbandingan\UPSNet-2026-3\UPSNet\obj\Debug\UPSNet.csproj.CoreCompileInputs.cache diff --git a/UPSNet/obj/Debug/UPSNet.csproj.GenerateResource.cache b/UPSNet/obj/Debug/UPSNet.csproj.GenerateResource.cache new file mode 100644 index 0000000..6f464b9 Binary files /dev/null and b/UPSNet/obj/Debug/UPSNet.csproj.GenerateResource.cache differ diff --git a/UPSNet/obj/Debug/UPSNet.exe b/UPSNet/obj/Debug/UPSNet.exe new file mode 100644 index 0000000..d3988d0 Binary files /dev/null and b/UPSNet/obj/Debug/UPSNet.exe differ diff --git a/UPSNet/obj/Debug/UPSNet.pdb b/UPSNet/obj/Debug/UPSNet.pdb new file mode 100644 index 0000000..7514dec Binary files /dev/null and b/UPSNet/obj/Debug/UPSNet.pdb differ diff --git a/UPSNet/obj/Release/.NETFramework,Version=v4.8.AssemblyAttributes.cs b/UPSNet/obj/Release/.NETFramework,Version=v4.8.AssemblyAttributes.cs new file mode 100644 index 0000000..15efebf --- /dev/null +++ b/UPSNet/obj/Release/.NETFramework,Version=v4.8.AssemblyAttributes.cs @@ -0,0 +1,4 @@ +// +using System; +using System.Reflection; +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] diff --git a/UPSNet/obj/Release/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs b/UPSNet/obj/Release/TemporaryGeneratedFile_036C0B5B-1481-4323-8D20-8F5ADCB23D92.cs new file mode 100644 index 0000000..e69de29 diff --git a/UPSNet/obj/Release/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs b/UPSNet/obj/Release/TemporaryGeneratedFile_5937a670-0e60-4077-877b-f7221da3dda1.cs new file mode 100644 index 0000000..e69de29 diff --git a/UPSNet/obj/Release/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs b/UPSNet/obj/Release/TemporaryGeneratedFile_E7A71F73-0F8D-4B9B-B56E-8E70B10BC5D3.cs new file mode 100644 index 0000000..e69de29 diff --git a/UPSNet/obj/Release/UPSNet.ConfigForm.resources b/UPSNet/obj/Release/UPSNet.ConfigForm.resources new file mode 100644 index 0000000..6c05a97 Binary files /dev/null and b/UPSNet/obj/Release/UPSNet.ConfigForm.resources differ diff --git a/UPSNet/obj/Release/UPSNet.NotificationIcon.resources b/UPSNet/obj/Release/UPSNet.NotificationIcon.resources new file mode 100644 index 0000000..263a2ea Binary files /dev/null and b/UPSNet/obj/Release/UPSNet.NotificationIcon.resources differ diff --git a/UPSNet/obj/Release/UPSNet.UPSForm.resources b/UPSNet/obj/Release/UPSNet.UPSForm.resources new file mode 100644 index 0000000..2d609f1 Binary files /dev/null and b/UPSNet/obj/Release/UPSNet.UPSForm.resources differ diff --git a/UPSNet/obj/Release/UPSNet.csproj.AssemblyReference.cache b/UPSNet/obj/Release/UPSNet.csproj.AssemblyReference.cache new file mode 100644 index 0000000..8060572 Binary files /dev/null and b/UPSNet/obj/Release/UPSNet.csproj.AssemblyReference.cache differ diff --git a/UPSNet/obj/Release/UPSNet.csproj.FileListAbsolute.txt b/UPSNet/obj/Release/UPSNet.csproj.FileListAbsolute.txt new file mode 100644 index 0000000..4971e39 --- /dev/null +++ b/UPSNet/obj/Release/UPSNet.csproj.FileListAbsolute.txt @@ -0,0 +1,8 @@ +D:\Projects\SharpDevelop Projects\UPSNet\bin\Release\UPSNet.exe.config +D:\Projects\SharpDevelop Projects\UPSNet\bin\Release\UPSNet.exe +D:\Projects\SharpDevelop Projects\UPSNet\obj\Release\UPSNet.ConfigForm.resources +D:\Projects\SharpDevelop Projects\UPSNet\obj\Release\UPSNet.NotificationIcon.resources +D:\Projects\SharpDevelop Projects\UPSNet\obj\Release\UPSNet.UPSForm.resources +D:\Projects\SharpDevelop Projects\UPSNet\obj\Release\UPSNet.csproj.GenerateResource.Cache +D:\Projects\SharpDevelop Projects\UPSNet\obj\Release\UPSNet.exe +D:\Projects\SharpDevelop Projects\UPSNet\obj\Release\UPSNet.csprojResolveAssemblyReference.cache diff --git a/UPSNet/obj/Release/UPSNet.csproj.GenerateResource.Cache b/UPSNet/obj/Release/UPSNet.csproj.GenerateResource.Cache new file mode 100644 index 0000000..d9eb934 Binary files /dev/null and b/UPSNet/obj/Release/UPSNet.csproj.GenerateResource.Cache differ diff --git a/UPSNet/obj/Release/UPSNet.csprojResolveAssemblyReference.cache b/UPSNet/obj/Release/UPSNet.csprojResolveAssemblyReference.cache new file mode 100644 index 0000000..659124e Binary files /dev/null and b/UPSNet/obj/Release/UPSNet.csprojResolveAssemblyReference.cache differ diff --git a/UPSNet/obj/Release/UPSNet.exe b/UPSNet/obj/Release/UPSNet.exe new file mode 100644 index 0000000..0beacad Binary files /dev/null and b/UPSNet/obj/Release/UPSNet.exe differ