├── DeckyInstaller ├── app.manifest ├── DeckyInstaller.csproj ├── Program.cs ├── MainForm.Designer.cs └── MainForm.cs ├── Decky-Loader-For-Windows.sln ├── README.md └── PythonSetup.bat /DeckyInstaller/app.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /DeckyInstaller/DeckyInstaller.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | WinExe 6 | net7.0-windows 7 | enable 8 | true 9 | enable 10 | app.manifest 11 | Decky Loader Installer 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /DeckyInstaller/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Principal; 3 | using System.Windows.Forms; 4 | 5 | namespace DeckyInstaller 6 | { 7 | internal static class Program 8 | { 9 | [STAThread] 10 | static void Main() 11 | { 12 | // Check for admin privileges 13 | if (!IsAdministrator()) 14 | { 15 | MessageBox.Show( 16 | "This application requires administrator privileges to create the required files.", 17 | "Administrator Rights Required", 18 | MessageBoxButtons.OK, 19 | MessageBoxIcon.Warning 20 | ); 21 | return; 22 | } 23 | 24 | ApplicationConfiguration.Initialize(); 25 | Application.Run(new MainForm()); 26 | } 27 | 28 | private static bool IsAdministrator() 29 | { 30 | var identity = WindowsIdentity.GetCurrent(); 31 | var principal = new WindowsPrincipal(identity); 32 | return principal.IsInRole(WindowsBuiltInRole.Administrator); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /Decky-Loader-For-Windows.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.5.002.0 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DeckyInstaller", "DeckyInstaller\DeckyInstaller.csproj", "{6D87E13D-7D09-473A-938D-F625D91AB709}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {6D87E13D-7D09-473A-938D-F625D91AB709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {6D87E13D-7D09-473A-938D-F625D91AB709}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {6D87E13D-7D09-473A-938D-F625D91AB709}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {6D87E13D-7D09-473A-938D-F625D91AB709}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {500B9C03-87F3-41AE-BB6D-A061C5BA77AC} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Decky Loader for Windows 2 | 3 | A Work-in-progress installer for Decky Loader on Windows. This tool automates the process of downloading and configuring Decky Loader - bringing the Steam Deck's popular plugin system to Windows. 4 | 5 | ## ⚠️ Disclaimer 6 | 7 | **This is an unofficial project and is not affiliated with, endorsed, or supported by the official Decky Loader team.** 8 | **No support will be provided by the Decky Loader team for any Windows Decky installations or Decky installations performed using this installer.** 9 | 10 | ## Featurer 11 | 12 | - 🚀 1-Click installation 13 | - 🔧 Configures Steam for plugin development (-dev arg) 14 | - 🏃‍♂️ Sets up autostart for PluginLoader 15 | - 📁 Creates proper homebrew directory structure 16 | - 💻 Installs console and GUI executables 17 | 18 | ## Working Plugins on Windows 19 | 20 | - Audio Loader 21 | - CSS Loader 22 | - IsThereAnyDeal For Deck 23 | - PlayCount 24 | - PlayTime 25 | - ProtonDB Badges 26 | - SteamGridDB 27 | - TabMaster 28 | - Web Browser 29 | 30 | ## Requirements 31 | 32 | - Windows 10/11 33 | - Steam installation 34 | - Internet connection 35 | 36 | ## Usage 37 | 38 | Download the latest release and run "Decky Loader Installer.exe", 39 | 40 | ## Millennium Project 41 | 42 | 43 | 44 | The `millennium` project is progressing nicely and works in conjunction with Decky Loader. It's definitely a project to keep an eye on! 45 | -------------------------------------------------------------------------------- /PythonSetup.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | echo Checking dependencies for Decky Loader... 3 | echo. 4 | 5 | :: Check if Python is installed 6 | python --version >nul 2>&1 7 | if %errorlevel% neq 0 ( 8 | echo Python is not installed. Downloading Python installer... 9 | curl -L "https://www.python.org/ftp/python/3.11.8/python-3.11.8-amd64.exe" --output "%temp%\python-installer.exe" 10 | 11 | :: Check if download was successful 12 | if not exist "%temp%\python-installer.exe" ( 13 | echo Failed to download Python installer. Please check your internet connection and try again. 14 | pause 15 | exit /b 1 16 | ) 17 | 18 | :: Check file size to ensure proper download 19 | for %%I in ("%temp%\python-installer.exe") do if %%~zI LSS 1000000 ( 20 | echo Downloaded file seems too small. Download may have failed. 21 | del "%temp%\python-installer.exe" 22 | pause 23 | exit /b 1 24 | ) 25 | 26 | echo Installing Python... 27 | "%temp%\python-installer.exe" /quiet InstallAllUsers=1 PrependPath=1 Include_test=0 Include_pip=1 28 | 29 | :: Wait a moment for installation to complete 30 | timeout /t 5 /nobreak > nul 31 | 32 | :: Clean up 33 | del "%temp%\python-installer.exe" 34 | 35 | :: Refresh environment variables using PowerShell 36 | echo Refreshing environment variables... 37 | powershell -Command "$env:Path = [System.Environment]::GetEnvironmentVariable('Path','Machine') + ';' + [System.Environment]::GetEnvironmentVariable('Path','User')" 38 | 39 | :: Also set for current session 40 | for /f "tokens=*" %%a in ('powershell -Command "[System.Environment]::GetEnvironmentVariable('Path','Machine') + ';' + [System.Environment]::GetEnvironmentVariable('Path','User')"') do set "PATH=%%a" 41 | ) else ( 42 | echo Python is already installed. 43 | ) 44 | 45 | :: Verify installations 46 | echo. 47 | echo Verifying installations... 48 | python --version 49 | if errorlevel 1 ( 50 | echo Python installation may have failed or PATH is not updated. 51 | echo Please restart your computer and run this script again. 52 | ) else ( 53 | echo Python installation successful! 54 | ) 55 | echo. 56 | echo Setup complete! You can now run the Decky Loader installer. 57 | pause -------------------------------------------------------------------------------- /DeckyInstaller/MainForm.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace DeckyInstaller 2 | { 3 | partial class MainForm 4 | { 5 | private System.ComponentModel.IContainer components = null; 6 | 7 | protected override void Dispose(bool disposing) 8 | { 9 | if (disposing && (components != null)) 10 | { 11 | components.Dispose(); 12 | } 13 | base.Dispose(disposing); 14 | } 15 | 16 | private void InitializeComponent() 17 | { 18 | components = new System.ComponentModel.Container(); 19 | btnInstall = new Button(); 20 | progressBar = new ProgressBar(); 21 | lblStatus = new Label(); 22 | txtOutput = new TextBox(); 23 | SuspendLayout(); 24 | 25 | // Form-wide styles 26 | this.BackColor = Color.FromArgb(24, 24, 24); 27 | this.ForeColor = Color.FromArgb(240, 240, 240); 28 | this.Font = new Font("Segoe UI", 9.75F, FontStyle.Regular, GraphicsUnit.Point); 29 | 30 | // btnInstall 31 | btnInstall.BackColor = Color.FromArgb(0, 120, 215); 32 | btnInstall.FlatStyle = FlatStyle.Flat; 33 | btnInstall.FlatAppearance.BorderSize = 0; 34 | btnInstall.Font = new Font("Segoe UI", 10.2F, FontStyle.Bold, GraphicsUnit.Point); 35 | btnInstall.ForeColor = Color.White; 36 | btnInstall.Location = new Point(20, 20); 37 | btnInstall.Name = "btnInstall"; 38 | btnInstall.Size = new Size(460, 45); 39 | btnInstall.TabIndex = 0; 40 | btnInstall.Text = "Install Decky Loader"; 41 | btnInstall.UseVisualStyleBackColor = false; 42 | btnInstall.Cursor = Cursors.Hand; 43 | btnInstall.Click += btnInstall_Click; 44 | 45 | // progressBar 46 | progressBar.Location = new Point(20, 75); 47 | progressBar.Name = "progressBar"; 48 | progressBar.Size = new Size(460, 5); 49 | progressBar.Style = ProgressBarStyle.Continuous; 50 | progressBar.TabIndex = 1; 51 | progressBar.ForeColor = Color.FromArgb(0, 120, 215); 52 | progressBar.BackColor = Color.FromArgb(45, 45, 45); 53 | 54 | // lblStatus 55 | lblStatus.AutoSize = true; 56 | lblStatus.Location = new Point(20, 90); 57 | lblStatus.Name = "lblStatus"; 58 | lblStatus.Size = new Size(89, 17); 59 | lblStatus.TabIndex = 2; 60 | lblStatus.Text = "Ready to install..."; 61 | lblStatus.ForeColor = Color.FromArgb(200, 200, 200); 62 | 63 | // txtOutput 64 | txtOutput.BackColor = Color.FromArgb(30, 30, 30); 65 | txtOutput.ForeColor = Color.FromArgb(220, 220, 220); 66 | txtOutput.Font = new Font("Cascadia Code", 9F, FontStyle.Regular, GraphicsUnit.Point); 67 | txtOutput.Location = new Point(20, 115); 68 | txtOutput.Multiline = true; 69 | txtOutput.Name = "txtOutput"; 70 | txtOutput.ReadOnly = true; 71 | txtOutput.ScrollBars = ScrollBars.Both; 72 | txtOutput.Size = new Size(460, 215); 73 | txtOutput.TabIndex = 3; 74 | txtOutput.WordWrap = false; 75 | txtOutput.BorderStyle = BorderStyle.None; 76 | txtOutput.Padding = new Padding(5); 77 | 78 | // MainForm 79 | AutoScaleDimensions = new SizeF(7F, 17F); 80 | AutoScaleMode = AutoScaleMode.Font; 81 | ClientSize = new Size(500, 350); 82 | Controls.Add(txtOutput); 83 | Controls.Add(lblStatus); 84 | Controls.Add(progressBar); 85 | Controls.Add(btnInstall); 86 | FormBorderStyle = FormBorderStyle.FixedSingle; 87 | MaximizeBox = false; 88 | Name = "MainForm"; 89 | StartPosition = FormStartPosition.CenterScreen; 90 | Text = "Decky Loader Installer"; 91 | Load += MainForm_Load; 92 | Padding = new Padding(20); 93 | ResumeLayout(false); 94 | PerformLayout(); 95 | } 96 | 97 | protected Button btnInstall; 98 | protected ProgressBar progressBar; 99 | protected Label lblStatus; 100 | protected TextBox txtOutput; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /DeckyInstaller/MainForm.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using System.Net.Http; 3 | using Microsoft.Win32; 4 | using System.IO.Compression; 5 | using System.Text.RegularExpressions; 6 | 7 | namespace DeckyInstaller 8 | { 9 | public partial class MainForm : Form 10 | { 11 | private bool _isInstalling = false; 12 | private const string DOWNLOAD_URL = "https://nightly.link/SteamDeckHomebrew/decky-loader/workflows/build-win/main/PluginLoader%20Win.zip"; 13 | 14 | private readonly HttpClient _httpClient; 15 | 16 | public MainForm() 17 | { 18 | InitializeComponent(); 19 | _httpClient = new HttpClient(); 20 | _httpClient.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"); 21 | } 22 | 23 | private void MainForm_Load(object sender, EventArgs e) 24 | { 25 | txtOutput.AppendText("Ready to install Decky Loader...\r\n"); 26 | } 27 | 28 | private async void btnInstall_Click(object sender, EventArgs e) 29 | { 30 | if (_isInstalling) return; 31 | await StartInstallation(); 32 | } 33 | 34 | public async Task StartInstallation() 35 | { 36 | _isInstalling = true; 37 | btnInstall.Enabled = false; 38 | progressBar.Value = 0; 39 | progressBar.Maximum = 6; 40 | txtOutput.Clear(); 41 | 42 | try 43 | { 44 | // Kill any existing PluginLoader processes 45 | KillExistingPluginLoaders(); 46 | 47 | // Step 1: Create .cef-enable-remote-debugging file 48 | UpdateStatus("Setting up Steam CEF debugging..."); 49 | if (!await SetupSteamDebug()) 50 | { 51 | throw new Exception("Failed to setup Steam CEF debugging"); 52 | } 53 | progressBar.Value++; 54 | 55 | // Step 2: Create homebrew directories 56 | UpdateStatus("Creating homebrew directories..."); 57 | if (!await CreateHomebrewDirectories()) 58 | { 59 | throw new Exception("Failed to create homebrew directories"); 60 | } 61 | progressBar.Value++; 62 | 63 | // Step 3: Download and extract 64 | UpdateStatus("Downloading latest build..."); 65 | string zipPath = Path.Combine(Path.GetTempPath(), "PluginLoader.zip"); 66 | 67 | // Download the zip file 68 | var zipBytes = await _httpClient.GetByteArrayAsync(DOWNLOAD_URL); 69 | await File.WriteAllBytesAsync(zipPath, zipBytes); 70 | progressBar.Value++; 71 | 72 | // Step 4: Extract files 73 | UpdateStatus("Extracting files..."); 74 | string servicesDir = Path.Combine( 75 | Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), 76 | "homebrew", 77 | "services" 78 | ); 79 | ZipFile.ExtractToDirectory(zipPath, servicesDir, true); 80 | progressBar.Value++; 81 | 82 | // Step 5: Create Steam shortcut 83 | UpdateStatus("Creating Steam shortcut..."); 84 | if (!CreateSteamShortcut()) 85 | { 86 | throw new Exception("Failed to create Steam shortcut"); 87 | } 88 | progressBar.Value++; 89 | 90 | // Step 6: Setup autostart 91 | UpdateStatus("Setting up autostart..."); 92 | if (!SetupAutostart()) 93 | { 94 | throw new Exception("Failed to setup autostart"); 95 | } 96 | progressBar.Value++; 97 | 98 | // Cleanup 99 | try { File.Delete(zipPath); } catch { } 100 | 101 | UpdateStatus("Installation complete!"); 102 | MessageBox.Show( 103 | "Decky Loader has been installed successfully!\n\n" + 104 | "1. Close Steam if it's running\n" + 105 | "2. Use the new Steam shortcut on your desktop to launch Steam\n" + 106 | "3. In Big Picture Mode, press the STEAM button + A to access the Decky menu", 107 | "Installation Complete", 108 | MessageBoxButtons.OK, 109 | MessageBoxIcon.Information 110 | ); 111 | } 112 | catch (Exception ex) 113 | { 114 | UpdateStatus($"Error: {ex.Message}"); 115 | MessageBox.Show( 116 | $"An error occurred: {ex.Message}", 117 | "Error", 118 | MessageBoxButtons.OK, 119 | MessageBoxIcon.Error 120 | ); 121 | } 122 | finally 123 | { 124 | _isInstalling = false; 125 | btnInstall.Enabled = true; 126 | } 127 | } 128 | 129 | private bool CreateSteamShortcut() 130 | { 131 | try 132 | { 133 | string? steamPath = null; 134 | string steamExe; 135 | 136 | // Try to find Steam installation path from registry 137 | try 138 | { 139 | using var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\Valve\Steam"); 140 | steamPath = key?.GetValue("InstallPath") as string; 141 | } 142 | catch 143 | { 144 | try 145 | { 146 | using var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Valve\Steam"); 147 | steamPath = key?.GetValue("InstallPath") as string; 148 | } 149 | catch { } 150 | } 151 | 152 | if (string.IsNullOrEmpty(steamPath)) 153 | { 154 | steamPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Steam"); 155 | } 156 | 157 | steamExe = Path.Combine(steamPath, "steam.exe"); 158 | if (!File.Exists(steamExe)) 159 | { 160 | throw new Exception("Steam executable not found"); 161 | } 162 | 163 | // Create desktop shortcut using PowerShell 164 | string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); 165 | string shortcutPath = Path.Combine(desktopPath, "Steam (Decky).lnk"); 166 | 167 | string psCommand = $@"$WshShell = New-Object -ComObject WScript.Shell; " + 168 | $@"$Shortcut = $WshShell.CreateShortcut('{shortcutPath}'); " + 169 | $@"$Shortcut.TargetPath = '{steamExe}'; " + 170 | $@"$Shortcut.Arguments = '-dev'; " + 171 | $@"$Shortcut.WorkingDirectory = '{steamPath}'; " + 172 | $@"$Shortcut.Description = 'Launch Steam with Decky Loader'; " + 173 | "$Shortcut.Save()"; 174 | 175 | var startInfo = new ProcessStartInfo 176 | { 177 | FileName = "powershell.exe", 178 | Arguments = $"-Command \"{psCommand}\"", 179 | UseShellExecute = false, 180 | RedirectStandardOutput = true, 181 | RedirectStandardError = true, 182 | CreateNoWindow = true 183 | }; 184 | 185 | using var process = Process.Start(startInfo); 186 | process?.WaitForExit(); 187 | 188 | if (process?.ExitCode == 0) 189 | { 190 | AppendOutput("Created Steam shortcut with -dev parameter"); 191 | return true; 192 | } 193 | else 194 | { 195 | throw new Exception("Failed to create shortcut"); 196 | } 197 | } 198 | catch (Exception ex) 199 | { 200 | AppendOutput($"Error creating Steam shortcut: {ex.Message}"); 201 | return false; 202 | } 203 | } 204 | 205 | private bool SetupAutostart() 206 | { 207 | try 208 | { 209 | string servicesDir = Path.Combine( 210 | Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), 211 | "homebrew", 212 | "services" 213 | ); 214 | string pluginLoader = Path.Combine(servicesDir, "PluginLoader_noconsole.exe"); 215 | 216 | if (!File.Exists(pluginLoader)) 217 | { 218 | throw new Exception("PluginLoader_noconsole.exe not found"); 219 | } 220 | 221 | // Create startup shortcut 222 | string startupFolder = Path.Combine( 223 | Environment.GetFolderPath(Environment.SpecialFolder.Startup) 224 | ); 225 | string shortcutPath = Path.Combine(startupFolder, "Decky Loader.lnk"); 226 | 227 | string psCommand = $@"$WshShell = New-Object -ComObject WScript.Shell; " + 228 | $@"$Shortcut = $WshShell.CreateShortcut('{shortcutPath}'); " + 229 | $@"$Shortcut.TargetPath = '{pluginLoader}'; " + 230 | $@"$Shortcut.WorkingDirectory = '{servicesDir}'; " + 231 | $@"$Shortcut.Description = 'Decky Loader Autostart'; " + 232 | "$Shortcut.Save()"; 233 | 234 | var startInfo = new ProcessStartInfo 235 | { 236 | FileName = "powershell.exe", 237 | Arguments = $"-Command \"{psCommand}\"", 238 | UseShellExecute = false, 239 | RedirectStandardOutput = true, 240 | RedirectStandardError = true, 241 | CreateNoWindow = true 242 | }; 243 | 244 | using var process = Process.Start(startInfo); 245 | process?.WaitForExit(); 246 | 247 | if (process?.ExitCode == 0) 248 | { 249 | AppendOutput("Created autostart entry"); 250 | 251 | // Start the process immediately 252 | var pluginLoaderProcess = new ProcessStartInfo 253 | { 254 | FileName = pluginLoader, 255 | WorkingDirectory = servicesDir, 256 | UseShellExecute = true 257 | }; 258 | Process.Start(pluginLoaderProcess); 259 | AppendOutput("Started PluginLoader_noconsole.exe"); 260 | 261 | return true; 262 | } 263 | else 264 | { 265 | throw new Exception("Failed to create autostart entry"); 266 | } 267 | } 268 | catch (Exception ex) 269 | { 270 | AppendOutput($"Error setting up autostart: {ex.Message}"); 271 | return false; 272 | } 273 | } 274 | 275 | private async Task SetupSteamDebug() 276 | { 277 | try 278 | { 279 | string? steamPath = null; 280 | 281 | // Try to find Steam installation path from registry 282 | try 283 | { 284 | using var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\Valve\Steam"); 285 | steamPath = key?.GetValue("InstallPath") as string; 286 | } 287 | catch 288 | { 289 | try 290 | { 291 | using var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Valve\Steam"); 292 | steamPath = key?.GetValue("InstallPath") as string; 293 | } 294 | catch 295 | { 296 | AppendOutput("Steam installation not found in registry"); 297 | } 298 | } 299 | 300 | if (string.IsNullOrEmpty(steamPath)) 301 | { 302 | steamPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Steam"); 303 | } 304 | 305 | if (!Directory.Exists(steamPath)) 306 | { 307 | throw new Exception("Steam installation directory not found"); 308 | } 309 | 310 | string debugFile = Path.Combine(steamPath, ".cef-enable-remote-debugging"); 311 | File.WriteAllText(debugFile, ""); 312 | AppendOutput("Created .cef-enable-remote-debugging file"); 313 | 314 | return true; 315 | } 316 | catch (Exception ex) 317 | { 318 | AppendOutput($"Error setting up Steam debug: {ex.Message}"); 319 | return false; 320 | } 321 | } 322 | 323 | private async Task CreateHomebrewDirectories() 324 | { 325 | try 326 | { 327 | string homebrewDir = Path.Combine( 328 | Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), 329 | "homebrew" 330 | ); 331 | string servicesDir = Path.Combine(homebrewDir, "services"); 332 | 333 | Directory.CreateDirectory(homebrewDir); 334 | Directory.CreateDirectory(servicesDir); 335 | 336 | AppendOutput($"Created directory: {homebrewDir}"); 337 | AppendOutput($"Created directory: {servicesDir}"); 338 | 339 | return true; 340 | } 341 | catch (Exception ex) 342 | { 343 | AppendOutput($"Error creating directories: {ex.Message}"); 344 | return false; 345 | } 346 | } 347 | 348 | private void KillExistingPluginLoaders() 349 | { 350 | try 351 | { 352 | foreach (var process in Process.GetProcessesByName("PluginLoader")) 353 | { 354 | try 355 | { 356 | process.Kill(); 357 | AppendOutput("Terminated PluginLoader.exe process"); 358 | } 359 | catch (Exception ex) 360 | { 361 | AppendOutput($"Warning: Could not terminate PluginLoader.exe: {ex.Message}"); 362 | } 363 | } 364 | 365 | foreach (var process in Process.GetProcessesByName("PluginLoader_noconsole")) 366 | { 367 | try 368 | { 369 | process.Kill(); 370 | AppendOutput("Terminated PluginLoader_noconsole.exe process"); 371 | } 372 | catch (Exception ex) 373 | { 374 | AppendOutput($"Warning: Could not terminate PluginLoader_noconsole.exe: {ex.Message}"); 375 | } 376 | } 377 | } 378 | catch (Exception ex) 379 | { 380 | AppendOutput($"Warning: Error while checking for existing processes: {ex.Message}"); 381 | } 382 | } 383 | 384 | private void UpdateStatus(string message) 385 | { 386 | if (InvokeRequired) 387 | { 388 | Invoke(new Action(() => UpdateStatus(message))); 389 | return; 390 | } 391 | 392 | lblStatus.Text = message; 393 | lblStatus.Refresh(); 394 | } 395 | 396 | private void AppendOutput(string text) 397 | { 398 | if (txtOutput.InvokeRequired) 399 | { 400 | txtOutput.Invoke(new Action(() => AppendOutput(text))); 401 | } 402 | else 403 | { 404 | txtOutput.AppendText($"{text}\r\n"); 405 | txtOutput.SelectionStart = txtOutput.TextLength; 406 | txtOutput.ScrollToCaret(); 407 | } 408 | } 409 | } 410 | } 411 | --------------------------------------------------------------------------------