Initial commit: SpdUp Windows Gaming Booster v1.0.0
- .NET 8 WPF app with full MVVM architecture - One-click boost: CPU, RAM, GPU, network, services, timer resolution - Real-time system monitor (LibreHardwareMonitor) - Auto game detection (30+ games) - RAM optimizer with kernel-level cleanup - Network optimizer (TCP registry tweaks) - Service manager, process manager, shader cache cleaner - Desktop widget overlay - Debug log viewer - Custom dark gaming theme with trans pride colors - 84 unit tests (xUnit) - Inno Setup installer script - Landing page website
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
using System.IO;
|
||||
|
||||
namespace SpdUp.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Application-wide logging service with live event for UI consumption.
|
||||
/// </summary>
|
||||
public static class Logger
|
||||
{
|
||||
private static readonly object _lock = new();
|
||||
private static readonly string _logDir = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "SpdUp", "Logs");
|
||||
|
||||
/// <summary>Fired on every log write – subscribers receive the formatted line.</summary>
|
||||
public static event Action<string>? LogWritten;
|
||||
|
||||
static Logger()
|
||||
{
|
||||
Directory.CreateDirectory(_logDir);
|
||||
}
|
||||
|
||||
private static string LogFile => Path.Combine(_logDir, $"SpdUp_{DateTime.Now:yyyy-MM-dd}.log");
|
||||
|
||||
public static void Info(string message) => Write("INFO", message);
|
||||
public static void Warn(string message) => Write("WARN", message);
|
||||
public static void Error(string message, Exception? ex = null)
|
||||
{
|
||||
var msg = ex is null ? message : $"{message} | {ex.GetType().Name}: {ex.Message}\n{ex.StackTrace}";
|
||||
Write("ERROR", msg);
|
||||
}
|
||||
|
||||
private static void Write(string level, string message)
|
||||
{
|
||||
var line = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] [{level}] {message}";
|
||||
lock (_lock)
|
||||
{
|
||||
try
|
||||
{
|
||||
File.AppendAllText(LogFile, line + Environment.NewLine);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Swallow – logging must never crash the app.
|
||||
}
|
||||
}
|
||||
|
||||
// Notify UI subscribers
|
||||
try { LogWritten?.Invoke(line); } catch { }
|
||||
|
||||
#if DEBUG
|
||||
System.Diagnostics.Debug.WriteLine(line);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes log files older than the specified number of days.
|
||||
/// </summary>
|
||||
public static void PurgeOldLogs(int keepDays = 14)
|
||||
{
|
||||
try
|
||||
{
|
||||
var cutoff = DateTime.Now.AddDays(-keepDays);
|
||||
foreach (var file in Directory.GetFiles(_logDir, "SpdUp_*.log"))
|
||||
{
|
||||
if (File.GetCreationTime(file) < cutoff)
|
||||
File.Delete(file);
|
||||
}
|
||||
}
|
||||
catch { /* best-effort */ }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace SpdUp.Core;
|
||||
|
||||
/// <summary>
|
||||
/// P/Invoke declarations used across the application.
|
||||
/// </summary>
|
||||
public static class NativeMethods
|
||||
{
|
||||
// ── Memory management ──────────────────────────────────────────────
|
||||
[DllImport("psapi.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool EmptyWorkingSet(IntPtr hProcess);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern IntPtr OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool CloseHandle(IntPtr hObject);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
public static extern bool SetProcessWorkingSetSizeEx(
|
||||
IntPtr hProcess, IntPtr dwMinimumWorkingSetSize, IntPtr dwMaximumWorkingSetSize, uint flags);
|
||||
|
||||
// ── Timer resolution ───────────────────────────────────────────────
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
public static extern int NtSetTimerResolution(uint DesiredResolution, bool SetResolution, out uint CurrentResolution);
|
||||
|
||||
[DllImport("ntdll.dll", SetLastError = true)]
|
||||
public static extern int NtQueryTimerResolution(out uint MinimumResolution, out uint MaximumResolution, out uint CurrentResolution);
|
||||
|
||||
// ── System memory info ─────────────────────────────────────────────
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct MEMORYSTATUSEX
|
||||
{
|
||||
public uint dwLength;
|
||||
public uint dwMemoryLoad;
|
||||
public ulong ullTotalPhys;
|
||||
public ulong ullAvailPhys;
|
||||
public ulong ullTotalPageFile;
|
||||
public ulong ullAvailPageFile;
|
||||
public ulong ullTotalVirtual;
|
||||
public ulong ullAvailVirtual;
|
||||
public ulong ullAvailExtendedVirtual;
|
||||
}
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer);
|
||||
|
||||
// ── System cache / standby list purge ──────────────────────────────
|
||||
public enum SYSTEM_MEMORY_LIST_COMMAND
|
||||
{
|
||||
MemoryCaptureAccessedBits = 0,
|
||||
MemoryCaptureAndResetAccessedBits = 1,
|
||||
MemoryEmptyWorkingSets = 2,
|
||||
MemoryFlushModifiedList = 3,
|
||||
MemoryPurgeStandbyList = 4,
|
||||
MemoryPurgeLowPriorityStandbyList = 5,
|
||||
MemoryCommandMax = 6
|
||||
}
|
||||
|
||||
[DllImport("ntdll.dll")]
|
||||
public static extern int NtSetSystemInformation(
|
||||
int SystemInformationClass, ref int SystemInformation, int SystemInformationLength);
|
||||
|
||||
// SystemMemoryListInformation = 0x0050
|
||||
public const int SystemMemoryListInformation = 0x0050;
|
||||
|
||||
// ── Privilege ──────────────────────────────────────────────────────
|
||||
[DllImport("advapi32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool OpenProcessToken(IntPtr ProcessHandle, uint DesiredAccess, out IntPtr TokenHandle);
|
||||
|
||||
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool LookupPrivilegeValue(string? lpSystemName, string lpName, out LUID lpLuid);
|
||||
|
||||
[DllImport("advapi32.dll", SetLastError = true)]
|
||||
[return: MarshalAs(UnmanagedType.Bool)]
|
||||
public static extern bool AdjustTokenPrivileges(
|
||||
IntPtr TokenHandle, bool DisableAllPrivileges,
|
||||
ref TOKEN_PRIVILEGES NewState, uint BufferLength,
|
||||
IntPtr PreviousState, IntPtr ReturnLength);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct LUID
|
||||
{
|
||||
public uint LowPart;
|
||||
public int HighPart;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct LUID_AND_ATTRIBUTES
|
||||
{
|
||||
public LUID Luid;
|
||||
public uint Attributes;
|
||||
}
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public struct TOKEN_PRIVILEGES
|
||||
{
|
||||
public uint PrivilegeCount;
|
||||
public LUID_AND_ATTRIBUTES Privileges;
|
||||
}
|
||||
|
||||
public const uint TOKEN_ADJUST_PRIVILEGES = 0x0020;
|
||||
public const uint TOKEN_QUERY = 0x0008;
|
||||
public const uint SE_PRIVILEGE_ENABLED = 0x00000002;
|
||||
public const string SE_DEBUG_NAME = "SeDebugPrivilege";
|
||||
public const string SE_PROF_SINGLE_PROCESS_NAME = "SeProfileSingleProcessPrivilege";
|
||||
public const string SE_INC_BASE_PRIORITY_NAME = "SeIncreaseBasePriorityPrivilege";
|
||||
|
||||
public const uint PROCESS_ALL_ACCESS = 0x001F0FFF;
|
||||
public const uint PROCESS_SET_INFORMATION = 0x0200;
|
||||
public const uint PROCESS_QUERY_INFORMATION = 0x0400;
|
||||
|
||||
/// <summary>
|
||||
/// Enable a privilege on the current process token.
|
||||
/// </summary>
|
||||
public static bool EnablePrivilege(string privilege)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!OpenProcessToken(System.Diagnostics.Process.GetCurrentProcess().Handle,
|
||||
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, out var tokenHandle))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
if (!LookupPrivilegeValue(null, privilege, out var luid))
|
||||
return false;
|
||||
|
||||
var tp = new TOKEN_PRIVILEGES
|
||||
{
|
||||
PrivilegeCount = 1,
|
||||
Privileges = new LUID_AND_ATTRIBUTES { Luid = luid, Attributes = SE_PRIVILEGE_ENABLED }
|
||||
};
|
||||
|
||||
return AdjustTokenPrivileges(tokenHandle, false, ref tp, 0, IntPtr.Zero, IntPtr.Zero);
|
||||
}
|
||||
finally
|
||||
{
|
||||
CloseHandle(tokenHandle);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace SpdUp.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Base class for ViewModels implementing INotifyPropertyChanged.
|
||||
/// </summary>
|
||||
public abstract class ObservableObject : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
|
||||
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
|
||||
protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string? propertyName = null)
|
||||
{
|
||||
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
|
||||
field = value;
|
||||
OnPropertyChanged(propertyName);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace SpdUp.Core;
|
||||
|
||||
/// <summary>
|
||||
/// A basic ICommand implementation that delegates to Action/Func.
|
||||
/// </summary>
|
||||
public sealed class RelayCommand : ICommand
|
||||
{
|
||||
private readonly Action<object?> _execute;
|
||||
private readonly Func<object?, bool>? _canExecute;
|
||||
|
||||
public RelayCommand(Action<object?> execute, Func<object?, bool>? canExecute = null)
|
||||
{
|
||||
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
|
||||
_canExecute = canExecute;
|
||||
}
|
||||
|
||||
public RelayCommand(Action execute, Func<bool>? canExecute = null)
|
||||
: this(_ => execute(), canExecute is null ? null : _ => canExecute()) { }
|
||||
|
||||
public event EventHandler? CanExecuteChanged
|
||||
{
|
||||
add => CommandManager.RequerySuggested += value;
|
||||
remove => CommandManager.RequerySuggested -= value;
|
||||
}
|
||||
|
||||
public bool CanExecute(object? parameter) => _canExecute?.Invoke(parameter) ?? true;
|
||||
public void Execute(object? parameter) => _execute(parameter);
|
||||
|
||||
public void RaiseCanExecuteChanged() => CommandManager.InvalidateRequerySuggested();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Typed relay command.
|
||||
/// </summary>
|
||||
public sealed class RelayCommand<T> : ICommand
|
||||
{
|
||||
private readonly Action<T?> _execute;
|
||||
private readonly Func<T?, bool>? _canExecute;
|
||||
|
||||
public RelayCommand(Action<T?> execute, Func<T?, bool>? canExecute = null)
|
||||
{
|
||||
_execute = execute ?? throw new ArgumentNullException(nameof(execute));
|
||||
_canExecute = canExecute;
|
||||
}
|
||||
|
||||
public event EventHandler? CanExecuteChanged
|
||||
{
|
||||
add => CommandManager.RequerySuggested += value;
|
||||
remove => CommandManager.RequerySuggested -= value;
|
||||
}
|
||||
|
||||
public bool CanExecute(object? parameter) => _canExecute?.Invoke((T?)parameter) ?? true;
|
||||
public void Execute(object? parameter) => _execute((T?)parameter);
|
||||
}
|
||||
Reference in New Issue
Block a user