diff --git a/src/MSCFixer.sln b/src/MSCFixer.sln new file mode 100644 index 0000000..2959ccd --- /dev/null +++ b/src/MSCFixer.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.10.34928.147 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MSCFixer", "MSCFixer\MSCFixer.csproj", "{FA7D5C89-63D3-4AF0-80C2-D650D35E575B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FA7D5C89-63D3-4AF0-80C2-D650D35E575B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FA7D5C89-63D3-4AF0-80C2-D650D35E575B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FA7D5C89-63D3-4AF0-80C2-D650D35E575B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FA7D5C89-63D3-4AF0-80C2-D650D35E575B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {2071364D-7643-47BA-922C-79B33CCDCCA1} + EndGlobalSection +EndGlobal diff --git a/src/MSCFixer/AppManagerService.cs b/src/MSCFixer/AppManagerService.cs index f6b801a..bebe70f 100644 --- a/src/MSCFixer/AppManagerService.cs +++ b/src/MSCFixer/AppManagerService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -40,7 +41,37 @@ namespace Crapfixer Logger.Log($"(Checked against {_appDirectory.Count} apps from the system)"); } - // Aanalyzes the apps based on predefined apps (from resources) and returns matching apps + /// + /// Analyzes the apps based on predefined apps (from resources) and logs the results in MainForm. + /// + /// + /// + public async Task> AnalyzeAndLogAppsAsync(string[] predefinedApps) + { + var apps = await AnalyzeAppsAsync(predefinedApps); + + if (apps.Count > 0) + { + Logger.Log("Bloatware apps detected:", LogLevel.Info); + foreach (var app in apps) + { + Logger.Log($"❌ {app.AppName} [{app.FullName}]", LogLevel.Warning); + } + } + else + { + Logger.Log("✅ No Microsoft Store bloatware apps found.", LogLevel.Info); + } + + return apps; + } + + + /// + /// Analyzes the apps based on predefined apps (from resources) and returns matching apps. + /// + /// + /// public async Task> AnalyzeAppsAsync(string[] predefinedApps) { Logger.Log("\n🧩 APPS ANALYSIS", LogLevel.Info); @@ -100,7 +131,11 @@ namespace Crapfixer } } - // Uninstall selected apps and log the results + /// + /// Uninstalls the selected apps and logs the results. + /// + /// + /// public async Task> UninstallSelectedAppsAsync(List selectedApps) { List removedApps = new List(); @@ -134,5 +169,50 @@ namespace Crapfixer return removedApps; // Return removed apps to update the UI } + + /// + /// Loads an external bloatware list from the CFEnhancer text file (comma-separated). + /// Falls back to an empty array if the file doesn't exist or fails to load. + /// + public string[] LoadExternalBloatwareList(string fileName = "CFEnhancer.txt") + { + try + { + string exeDir = AppDomain.CurrentDomain.BaseDirectory; + string fullPath = Path.Combine(exeDir, fileName); + + if (!File.Exists(fullPath)) + { + Logger.Log($"⚠️ The bloatware radar stays basic for now 🧠. Get the enhanced detection list from the GitHub releases (Assets).", LogLevel.Warning); + return Array.Empty(); + } + + var content = File.ReadAllText(fullPath); + return content.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) + .Select(s => s.Trim()) + .ToArray(); + } + catch (Exception ex) + { + Logger.Log($"Error reading external bloatware file: {ex.Message}", LogLevel.Warning); + return Array.Empty(); + } + } + + + /// + /// OPTIONALLY!Returns all installed apps in the system. + /// + /// + public async Task> GetAllInstalledAppsAsync() + { + await LoadAppsAsync(); + + return _appDirectory.Select(kvp => new AppAnalysisResult + { + AppName = kvp.Key, + FullName = kvp.Value + }).ToList(); + } } } \ No newline at end of file diff --git a/src/MSCFixer/FeatureManager.cs b/src/MSCFixer/FeatureManager.cs index 52c605e..1de83ba 100644 --- a/src/MSCFixer/FeatureManager.cs +++ b/src/MSCFixer/FeatureManager.cs @@ -1,4 +1,5 @@ using Features; +using System; using System.Drawing; using System.Threading.Tasks; using System.Windows.Forms; @@ -123,26 +124,6 @@ namespace Crapfixer } } - /// - /// Analyzes a selected feature and logs its status. - /// - public static async void AnalyzeFeature(TreeNode node) - { - if (node.Tag is FeatureNode fn && !fn.IsCategory && node.Checked && fn.Feature != null) - { - bool isOk = await fn.Feature.CheckFeature(); - node.ForeColor = isOk ? Color.Gray : Color.Red; - - Logger.Log(isOk - ? $"✅ Feature: {fn.Name} is properly configured." - : $"❌ Feature: {fn.Name} requires attention.\n ➤ {fn.Feature.GetFeatureDetails()}", - isOk ? LogLevel.Info : LogLevel.Warning); - - if (!isOk) - Logger.Log(new string('-', 50), LogLevel.Info); - } - } - /// /// Fixes all checked features recursively. /// @@ -186,12 +167,36 @@ namespace Crapfixer } } + + /// + /// Analyzes a selected feature and logs its status. + /// + public static async void AnalyzeFeature(TreeNode node) + { + // no && node.Checked + if (node.Tag is FeatureNode fn && !fn.IsCategory && fn.Feature != null) + { + bool isOk = await fn.Feature.CheckFeature(); + node.ForeColor = isOk ? Color.Gray : Color.Red; + + Logger.Log(isOk + ? $"✅ Feature: {fn.Name} is properly configured." + : $"❌ Feature: {fn.Name} requires attention.\n ➤ {fn.Feature.GetFeatureDetails()}", + isOk ? LogLevel.Info : LogLevel.Warning); + + if (!isOk) + Logger.Log(new string('-', 50), LogLevel.Info); + } + } + + /// /// Attempts to fix the selected feature and logs the result. /// public static async Task FixFeature(TreeNode node) { - if (node.Tag is FeatureNode fn && !fn.IsCategory && node.Checked && fn.Feature != null) + // no && node.Checked + if (node.Tag is FeatureNode fn && !fn.IsCategory && fn.Feature != null) { bool result = await fn.Feature.DoFeature(); Logger.Log(result @@ -206,7 +211,8 @@ namespace Crapfixer /// public static void RestoreFeature(TreeNode node) { - if (node.Tag is FeatureNode fn && !fn.IsCategory && node.Checked && fn.Feature != null) + // no && node.Checked + if (node.Tag is FeatureNode fn && !fn.IsCategory && fn.Feature != null) { bool ok = fn.Feature.UndoFeature(); Logger.Log(ok @@ -235,5 +241,21 @@ namespace Crapfixer MessageBox.Show("⚠️ No feature selected or feature is invalid.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } + + /// + /// Opens the default web browser to search for help online for the selected feature (Extended ShowHelp). + /// + /// + public static void ShowHelpOnline(TreeNode node) + { + if (node?.Tag is FeatureNode fn) + { + string searchQuery = Uri.EscapeDataString( fn.Feature.GetFeatureDetails()); + string webUrl = $"microsoft-edge:https://www.google.com/search?q={searchQuery}"; + + System.Diagnostics.Process.Start(webUrl); + } + } + } } \ No newline at end of file diff --git a/src/MSCFixer/MSCFixer.csproj b/src/MSCFixer/MSCFixer.csproj new file mode 100644 index 0000000..2753731 --- /dev/null +++ b/src/MSCFixer/MSCFixer.csproj @@ -0,0 +1,170 @@ + + + + + Debug + AnyCPU + {FA7D5C89-63D3-4AF0-80C2-D650D35E575B} + WinExe + MSCFixer + MSCFixer + v4.8 + 512 + true + true + + + x64 + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + app.manifest + + + AppIcon.ico + + + + + + False + ..\..\..\..\Windows\Microsoft.NET\assembly\GAC_MSIL\System.Management.Automation\v4.0_3.0.0.0__31bf3856ad364e35\System.Management.Automation.dll + + + + + + + + ..\..\..\..\..\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral\Annotated\Windows.winmd + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Form + + + MainForm.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + UserControl + + + SettingsView.cs + + + MainForm.cs + + + ResXFileCodeGenerator + Designer + Resources.Designer.cs + + + SettingsView.cs + + + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + True + Resources.resx + + + True + Settings.settings + True + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/MSCFixer/MainForm.Designer.cs b/src/MSCFixer/MainForm.Designer.cs new file mode 100644 index 0000000..95d584f --- /dev/null +++ b/src/MSCFixer/MainForm.Designer.cs @@ -0,0 +1,479 @@ +namespace Crapfixer +{ + partial class MainForm + { + /// + /// Erforderliche Designervariable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Verwendete Ressourcen bereinigen. + /// + /// True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Vom Windows Form-Designer generierter Code + + /// + /// Erforderliche Methode für die Designerunterstützung. + /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.panelContainer = new System.Windows.Forms.Panel(); + this.panelContent = new System.Windows.Forms.Panel(); + this.btnAnalyze = new System.Windows.Forms.Button(); + this.tabControl = new System.Windows.Forms.TabControl(); + this.Windows = new System.Windows.Forms.TabPage(); + this.treeFeatures = new System.Windows.Forms.TreeView(); + this.contextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); + this.analyzeMarkedFeatureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.fixMarkedFeatureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.seperatorToolStripMenuItem = new System.Windows.Forms.ToolStripSeparator(); + this.restoreMarkedFeatureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.helpMarkedFeatureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.Apps = new System.Windows.Forms.TabPage(); + this.checkedListBoxApps = new System.Windows.Forms.CheckedListBox(); + this.groupBox = new System.Windows.Forms.GroupBox(); + this.rtbLogger = new System.Windows.Forms.RichTextBox(); + this.btnFix = new System.Windows.Forms.Button(); + this.panelHeader = new System.Windows.Forms.Panel(); + this.lblOSInfo = new System.Windows.Forms.Label(); + this.lblVersionInfo = new System.Windows.Forms.Label(); + this.lblHeader = new System.Windows.Forms.Label(); + this.pictureHeader = new System.Windows.Forms.PictureBox(); + this.btnRestore = new System.Windows.Forms.Button(); + this.linkHelp = new System.Windows.Forms.LinkLabel(); + this.btnSettings = new System.Windows.Forms.Button(); + this.btnHome = new System.Windows.Forms.Button(); + this.linkSelection = new System.Windows.Forms.LinkLabel(); + this.panelContainer.SuspendLayout(); + this.panelContent.SuspendLayout(); + this.tabControl.SuspendLayout(); + this.Windows.SuspendLayout(); + this.contextMenuStrip.SuspendLayout(); + this.Apps.SuspendLayout(); + this.groupBox.SuspendLayout(); + this.panelHeader.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureHeader)).BeginInit(); + this.SuspendLayout(); + // + // panelContainer + // + this.panelContainer.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.panelContainer.BackColor = System.Drawing.SystemColors.Control; + this.panelContainer.Controls.Add(this.panelContent); + this.panelContainer.Location = new System.Drawing.Point(99, 62); + this.panelContainer.Name = "panelContainer"; + this.panelContainer.Size = new System.Drawing.Size(611, 382); + this.panelContainer.TabIndex = 198; + // + // panelContent + // + this.panelContent.AutoScroll = true; + this.panelContent.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(252)))), ((int)(((byte)(252)))), ((int)(((byte)(252))))); + this.panelContent.Controls.Add(this.btnAnalyze); + this.panelContent.Controls.Add(this.tabControl); + this.panelContent.Controls.Add(this.groupBox); + this.panelContent.Controls.Add(this.btnFix); + this.panelContent.Dock = System.Windows.Forms.DockStyle.Fill; + this.panelContent.Location = new System.Drawing.Point(0, 0); + this.panelContent.Name = "panelContent"; + this.panelContent.Size = new System.Drawing.Size(611, 382); + this.panelContent.TabIndex = 205; + // + // btnAnalyze + // + this.btnAnalyze.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.btnAnalyze.AutoEllipsis = true; + this.btnAnalyze.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.btnAnalyze.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.btnAnalyze.Location = new System.Drawing.Point(280, 346); + this.btnAnalyze.Name = "btnAnalyze"; + this.btnAnalyze.Size = new System.Drawing.Size(121, 29); + this.btnAnalyze.TabIndex = 1; + this.btnAnalyze.Text = "&Analyze"; + this.btnAnalyze.UseVisualStyleBackColor = false; + this.btnAnalyze.Click += new System.EventHandler(this.btnAnalyze_Click); + // + // tabControl + // + this.tabControl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left))); + this.tabControl.Controls.Add(this.Windows); + this.tabControl.Controls.Add(this.Apps); + this.tabControl.HotTrack = true; + this.tabControl.Location = new System.Drawing.Point(0, 0); + this.tabControl.Name = "tabControl"; + this.tabControl.Padding = new System.Drawing.Point(20, 8); + this.tabControl.SelectedIndex = 0; + this.tabControl.ShowToolTips = true; + this.tabControl.Size = new System.Drawing.Size(270, 376); + this.tabControl.SizeMode = System.Windows.Forms.TabSizeMode.Fixed; + this.tabControl.TabIndex = 199; + // + // Windows + // + this.Windows.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240))))); + this.Windows.Controls.Add(this.treeFeatures); + this.Windows.Location = new System.Drawing.Point(4, 32); + this.Windows.Name = "Windows"; + this.Windows.Padding = new System.Windows.Forms.Padding(3); + this.Windows.Size = new System.Drawing.Size(262, 340); + this.Windows.TabIndex = 0; + this.Windows.Text = "Windows"; + // + // treeFeatures + // + this.treeFeatures.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(242)))), ((int)(((byte)(242)))), ((int)(((byte)(242))))); + this.treeFeatures.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.treeFeatures.CheckBoxes = true; + this.treeFeatures.ContextMenuStrip = this.contextMenuStrip; + this.treeFeatures.Dock = System.Windows.Forms.DockStyle.Fill; + this.treeFeatures.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.treeFeatures.Indent = 20; + this.treeFeatures.ItemHeight = 23; + this.treeFeatures.Location = new System.Drawing.Point(3, 3); + this.treeFeatures.Name = "treeFeatures"; + this.treeFeatures.ShowLines = false; + this.treeFeatures.ShowNodeToolTips = true; + this.treeFeatures.ShowPlusMinus = false; + this.treeFeatures.ShowRootLines = false; + this.treeFeatures.Size = new System.Drawing.Size(256, 334); + this.treeFeatures.TabIndex = 196; + this.treeFeatures.AfterCheck += new System.Windows.Forms.TreeViewEventHandler(this.treeFeatures_AfterCheck); + this.treeFeatures.MouseDown += new System.Windows.Forms.MouseEventHandler(this.treeFeatures_MouseDown); + // + // contextMenuStrip + // + this.contextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.analyzeMarkedFeatureToolStripMenuItem, + this.fixMarkedFeatureToolStripMenuItem, + this.seperatorToolStripMenuItem, + this.restoreMarkedFeatureToolStripMenuItem, + this.helpMarkedFeatureToolStripMenuItem}); + this.contextMenuStrip.Name = "contextManualMenu"; + this.contextMenuStrip.RenderMode = System.Windows.Forms.ToolStripRenderMode.System; + this.contextMenuStrip.Size = new System.Drawing.Size(119, 98); + // + // analyzeMarkedFeatureToolStripMenuItem + // + this.analyzeMarkedFeatureToolStripMenuItem.Name = "analyzeMarkedFeatureToolStripMenuItem"; + this.analyzeMarkedFeatureToolStripMenuItem.Size = new System.Drawing.Size(118, 22); + this.analyzeMarkedFeatureToolStripMenuItem.Text = "Analyze"; + this.analyzeMarkedFeatureToolStripMenuItem.Click += new System.EventHandler(this.analyzeMarkedFeatureToolStripMenuItem_Click); + // + // fixMarkedFeatureToolStripMenuItem + // + this.fixMarkedFeatureToolStripMenuItem.Name = "fixMarkedFeatureToolStripMenuItem"; + this.fixMarkedFeatureToolStripMenuItem.Size = new System.Drawing.Size(118, 22); + this.fixMarkedFeatureToolStripMenuItem.Text = "Fix"; + this.fixMarkedFeatureToolStripMenuItem.Click += new System.EventHandler(this.fixMarkedFeatureToolStripMenuItem_Click); + // + // seperatorToolStripMenuItem + // + this.seperatorToolStripMenuItem.Name = "seperatorToolStripMenuItem"; + this.seperatorToolStripMenuItem.Size = new System.Drawing.Size(115, 6); + // + // restoreMarkedFeatureToolStripMenuItem + // + this.restoreMarkedFeatureToolStripMenuItem.Name = "restoreMarkedFeatureToolStripMenuItem"; + this.restoreMarkedFeatureToolStripMenuItem.Size = new System.Drawing.Size(118, 22); + this.restoreMarkedFeatureToolStripMenuItem.Text = "Restore"; + this.restoreMarkedFeatureToolStripMenuItem.Click += new System.EventHandler(this.restoreMarkedFeatureToolStripMenuItem_Click); + // + // helpMarkedFeatureToolStripMenuItem + // + this.helpMarkedFeatureToolStripMenuItem.Name = "helpMarkedFeatureToolStripMenuItem"; + this.helpMarkedFeatureToolStripMenuItem.ShortcutKeys = System.Windows.Forms.Keys.F1; + this.helpMarkedFeatureToolStripMenuItem.Size = new System.Drawing.Size(118, 22); + this.helpMarkedFeatureToolStripMenuItem.Text = "Help"; + this.helpMarkedFeatureToolStripMenuItem.Click += new System.EventHandler(this.helpMarkedFeatureToolStripMenuItem_Click); + // + // Apps + // + this.Apps.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(242)))), ((int)(((byte)(242)))), ((int)(((byte)(242))))); + this.Apps.Controls.Add(this.checkedListBoxApps); + this.Apps.Location = new System.Drawing.Point(4, 32); + this.Apps.Name = "Apps"; + this.Apps.Padding = new System.Windows.Forms.Padding(3); + this.Apps.Size = new System.Drawing.Size(262, 340); + this.Apps.TabIndex = 1; + this.Apps.Text = "Apps"; + // + // checkedListBoxApps + // + this.checkedListBoxApps.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(242)))), ((int)(((byte)(242)))), ((int)(((byte)(242))))); + this.checkedListBoxApps.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.checkedListBoxApps.Dock = System.Windows.Forms.DockStyle.Fill; + this.checkedListBoxApps.Font = new System.Drawing.Font("Tahoma", 8F); + this.checkedListBoxApps.FormattingEnabled = true; + this.checkedListBoxApps.Items.AddRange(new object[] { + "No analysis yet"}); + this.checkedListBoxApps.Location = new System.Drawing.Point(3, 3); + this.checkedListBoxApps.Name = "checkedListBoxApps"; + this.checkedListBoxApps.Size = new System.Drawing.Size(256, 334); + this.checkedListBoxApps.Sorted = true; + this.checkedListBoxApps.TabIndex = 336; + this.checkedListBoxApps.ThreeDCheckBoxes = true; + // + // groupBox + // + this.groupBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(252)))), ((int)(((byte)(252)))), ((int)(((byte)(252))))); + this.groupBox.Controls.Add(this.rtbLogger); + this.groupBox.Location = new System.Drawing.Point(280, 21); + this.groupBox.Name = "groupBox"; + this.groupBox.Size = new System.Drawing.Size(320, 317); + this.groupBox.TabIndex = 200; + this.groupBox.TabStop = false; + // + // rtbLogger + // + this.rtbLogger.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.rtbLogger.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(252)))), ((int)(((byte)(252)))), ((int)(((byte)(252))))); + this.rtbLogger.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.rtbLogger.Font = new System.Drawing.Font("Consolas", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.rtbLogger.Location = new System.Drawing.Point(7, 12); + this.rtbLogger.Name = "rtbLogger"; + this.rtbLogger.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Vertical; + this.rtbLogger.Size = new System.Drawing.Size(305, 297); + this.rtbLogger.TabIndex = 195; + this.rtbLogger.Text = ""; + // + // btnFix + // + this.btnFix.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.btnFix.AutoEllipsis = true; + this.btnFix.FlatStyle = System.Windows.Forms.FlatStyle.System; + this.btnFix.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.btnFix.Location = new System.Drawing.Point(480, 346); + this.btnFix.Name = "btnFix"; + this.btnFix.Size = new System.Drawing.Size(121, 29); + this.btnFix.TabIndex = 2; + this.btnFix.Text = "Run &CFixer"; + this.btnFix.UseVisualStyleBackColor = false; + this.btnFix.Click += new System.EventHandler(this.btnFix_Click); + // + // panelHeader + // + this.panelHeader.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(77)))), ((int)(((byte)(77)))), ((int)(((byte)(77))))); + this.panelHeader.Controls.Add(this.lblOSInfo); + this.panelHeader.Controls.Add(this.lblVersionInfo); + this.panelHeader.Controls.Add(this.lblHeader); + this.panelHeader.Controls.Add(this.pictureHeader); + this.panelHeader.Dock = System.Windows.Forms.DockStyle.Top; + this.panelHeader.Location = new System.Drawing.Point(0, 0); + this.panelHeader.Name = "panelHeader"; + this.panelHeader.Size = new System.Drawing.Size(710, 61); + this.panelHeader.TabIndex = 204; + this.panelHeader.Paint += new System.Windows.Forms.PaintEventHandler(this.panelHeader_Paint); + // + // lblOSInfo + // + this.lblOSInfo.AutoSize = true; + this.lblOSInfo.Font = new System.Drawing.Font("Microsoft Sans Serif", 8F); + this.lblOSInfo.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(230)))), ((int)(((byte)(230)))), ((int)(((byte)(230))))); + this.lblOSInfo.Location = new System.Drawing.Point(90, 37); + this.lblOSInfo.Name = "lblOSInfo"; + this.lblOSInfo.Size = new System.Drawing.Size(116, 13); + this.lblOSInfo.TabIndex = 200; + this.lblOSInfo.Text = "Checking your system.."; + // + // lblVersionInfo + // + this.lblVersionInfo.AutoSize = true; + this.lblVersionInfo.Font = new System.Drawing.Font("Microsoft Sans Serif", 7.5F); + this.lblVersionInfo.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(230)))), ((int)(((byte)(230)))), ((int)(((byte)(230))))); + this.lblVersionInfo.Location = new System.Drawing.Point(195, 15); + this.lblVersionInfo.Name = "lblVersionInfo"; + this.lblVersionInfo.Size = new System.Drawing.Size(13, 13); + this.lblVersionInfo.TabIndex = 2; + this.lblVersionInfo.Text = "v"; + // + // lblHeader + // + this.lblHeader.AutoEllipsis = true; + this.lblHeader.Font = new System.Drawing.Font("Tahoma", 15F, System.Drawing.FontStyle.Bold); + this.lblHeader.ForeColor = System.Drawing.Color.White; + this.lblHeader.Location = new System.Drawing.Point(89, 9); + this.lblHeader.Name = "lblHeader"; + this.lblHeader.Size = new System.Drawing.Size(105, 25); + this.lblHeader.TabIndex = 1; + this.lblHeader.Text = "Crapfixer"; + this.lblHeader.UseCompatibleTextRendering = true; + // + // pictureHeader + // + this.pictureHeader.Image = global::MSCFixer.Properties.Resources.AppIcon32; + this.pictureHeader.Location = new System.Drawing.Point(30, 9); + this.pictureHeader.Name = "pictureHeader"; + this.pictureHeader.Size = new System.Drawing.Size(44, 41); + this.pictureHeader.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom; + this.pictureHeader.TabIndex = 0; + this.pictureHeader.TabStop = false; + // + // btnRestore + // + this.btnRestore.AutoEllipsis = true; + this.btnRestore.Cursor = System.Windows.Forms.Cursors.Hand; + this.btnRestore.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(114)))), ((int)(((byte)(114)))), ((int)(((byte)(114))))); + this.btnRestore.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.btnRestore.Font = new System.Drawing.Font("Tahoma", 8.25F); + this.btnRestore.ForeColor = System.Drawing.Color.White; + this.btnRestore.Location = new System.Drawing.Point(0, 129); + this.btnRestore.Name = "btnRestore"; + this.btnRestore.Size = new System.Drawing.Size(99, 69); + this.btnRestore.TabIndex = 198; + this.btnRestore.TabStop = false; + this.btnRestore.Text = "&Restore"; + this.btnRestore.UseVisualStyleBackColor = true; + this.btnRestore.Click += new System.EventHandler(this.btnRestore_Click); + // + // linkHelp + // + this.linkHelp.ActiveLinkColor = System.Drawing.Color.Blue; + this.linkHelp.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.linkHelp.AutoEllipsis = true; + this.linkHelp.AutoSize = true; + this.linkHelp.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.linkHelp.LinkColor = System.Drawing.Color.White; + this.linkHelp.Location = new System.Drawing.Point(620, 447); + this.linkHelp.Name = "linkHelp"; + this.linkHelp.Size = new System.Drawing.Size(63, 13); + this.linkHelp.TabIndex = 203; + this.linkHelp.TabStop = true; + this.linkHelp.Text = "GitHub Help"; + this.linkHelp.TextAlign = System.Drawing.ContentAlignment.TopCenter; + // + // btnSettings + // + this.btnSettings.AutoEllipsis = true; + this.btnSettings.Cursor = System.Windows.Forms.Cursors.Hand; + this.btnSettings.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(114)))), ((int)(((byte)(114)))), ((int)(((byte)(114))))); + this.btnSettings.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.btnSettings.Font = new System.Drawing.Font("Tahoma", 8.25F); + this.btnSettings.ForeColor = System.Drawing.Color.White; + this.btnSettings.Location = new System.Drawing.Point(0, 197); + this.btnSettings.Name = "btnSettings"; + this.btnSettings.Size = new System.Drawing.Size(99, 69); + this.btnSettings.TabIndex = 205; + this.btnSettings.TabStop = false; + this.btnSettings.Text = "&Options"; + this.btnSettings.UseVisualStyleBackColor = true; + // + // btnHome + // + this.btnHome.AutoEllipsis = true; + this.btnHome.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(76)))), ((int)(((byte)(145)))), ((int)(((byte)(235))))); + this.btnHome.Cursor = System.Windows.Forms.Cursors.Hand; + this.btnHome.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(66)))), ((int)(((byte)(131)))), ((int)(((byte)(222))))); + this.btnHome.FlatStyle = System.Windows.Forms.FlatStyle.Flat; + this.btnHome.Font = new System.Drawing.Font("Tahoma", 8.25F); + this.btnHome.ForeColor = System.Drawing.Color.White; + this.btnHome.Location = new System.Drawing.Point(0, 61); + this.btnHome.Name = "btnHome"; + this.btnHome.Size = new System.Drawing.Size(99, 69); + this.btnHome.TabIndex = 206; + this.btnHome.TabStop = false; + this.btnHome.Text = "&Home"; + this.btnHome.UseVisualStyleBackColor = false; + // + // linkSelection + // + this.linkSelection.ActiveLinkColor = System.Drawing.Color.Blue; + this.linkSelection.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.linkSelection.AutoEllipsis = true; + this.linkSelection.AutoSize = true; + this.linkSelection.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.linkSelection.LinkColor = System.Drawing.Color.White; + this.linkSelection.Location = new System.Drawing.Point(10, 447); + this.linkSelection.Name = "linkSelection"; + this.linkSelection.Size = new System.Drawing.Size(49, 13); + this.linkSelection.TabIndex = 207; + this.linkSelection.TabStop = true; + this.linkSelection.Text = "Select all"; + this.linkSelection.TextAlign = System.Drawing.ContentAlignment.TopCenter; + this.linkSelection.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkSelection_LinkClicked); + // + // MainForm + // + this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; + this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(104)))), ((int)(((byte)(104)))), ((int)(((byte)(104))))); + this.ClientSize = new System.Drawing.Size(710, 466); + this.Controls.Add(this.linkSelection); + this.Controls.Add(this.btnHome); + this.Controls.Add(this.btnSettings); + this.Controls.Add(this.panelHeader); + this.Controls.Add(this.btnRestore); + this.Controls.Add(this.linkHelp); + this.Controls.Add(this.panelContainer); + this.Name = "MainForm"; + this.ShowIcon = false; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; + this.Text = "Crapfixer"; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing); + this.Shown += new System.EventHandler(this.MainForm_Shown); + this.panelContainer.ResumeLayout(false); + this.panelContent.ResumeLayout(false); + this.tabControl.ResumeLayout(false); + this.Windows.ResumeLayout(false); + this.contextMenuStrip.ResumeLayout(false); + this.Apps.ResumeLayout(false); + this.groupBox.ResumeLayout(false); + this.panelHeader.ResumeLayout(false); + this.panelHeader.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.pictureHeader)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private System.Windows.Forms.ContextMenuStrip contextMenuStrip; + private System.Windows.Forms.ToolStripMenuItem fixMarkedFeatureToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem analyzeMarkedFeatureToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem restoreMarkedFeatureToolStripMenuItem; + private System.Windows.Forms.Panel panelContainer; + private System.Windows.Forms.TabControl tabControl; + private System.Windows.Forms.TabPage Windows; + private System.Windows.Forms.TabPage Apps; + private System.Windows.Forms.GroupBox groupBox; + public System.Windows.Forms.RichTextBox rtbLogger; + private System.Windows.Forms.Button btnFix; + private System.Windows.Forms.Panel panelHeader; + private System.Windows.Forms.PictureBox pictureHeader; + private System.Windows.Forms.Label lblVersionInfo; + private System.Windows.Forms.Label lblHeader; + private System.Windows.Forms.Button btnAnalyze; + private System.Windows.Forms.Button btnRestore; + private System.Windows.Forms.CheckedListBox checkedListBoxApps; + private System.Windows.Forms.ToolStripSeparator seperatorToolStripMenuItem; + private System.Windows.Forms.Panel panelContent; + private System.Windows.Forms.LinkLabel linkHelp; + private System.Windows.Forms.ToolStripMenuItem helpMarkedFeatureToolStripMenuItem; + private System.Windows.Forms.TreeView treeFeatures; + private System.Windows.Forms.Label lblOSInfo; + private System.Windows.Forms.Button btnSettings; + private System.Windows.Forms.Button btnHome; + private System.Windows.Forms.LinkLabel linkSelection; + } +} + diff --git a/src/MSCFixer/MainForm.cs b/src/MSCFixer/MainForm.cs new file mode 100644 index 0000000..98c8622 --- /dev/null +++ b/src/MSCFixer/MainForm.cs @@ -0,0 +1,322 @@ +using MSCFixer; +using MSCFixer.Properties; +using System; +using System.Diagnostics; +using System.Drawing; +using System.IO; +using System.Linq; +using System.Threading.Tasks; +using System.Windows.Forms; +using Views; + +namespace Crapfixer +{ + public partial class MainForm : Form + { + private NavigationManager navigationManager; + private NavigationHandler navigationHandler; + private readonly AppManagerService appManager = new AppManagerService(); + private readonly string iniPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Crapfixer.ini"); + + public MainForm() + { + InitializeComponent(); + navigationManager = new NavigationManager(panelContainer); + Logger.OutputBox = rtbLogger; + FeatureNodeManager.LoadFeatures(treeFeatures); + PluginManager.LoadPlugins(treeFeatures); + + } + + private void MainForm_Shown(object sender, EventArgs e) + { + InitializeUI(); + IniStateManager.Load(treeFeatures, iniPath); + } + + private void InitializeUI() + { + navigationHandler = new NavigationHandler(btnHome, btnRestore, btnSettings); + + btnHome.Click += (s, e) => + { + navigationManager.GoToMain(); + navigationHandler.SetActive(btnHome); + }; + + btnRestore.Click += (s, e) => + { + navigationHandler.SetActive(btnRestore); + }; + + btnSettings.Click += (s, e) => + { + navigationManager.SwitchView(new SettingsView(navigationManager)); + navigationHandler.SetActive(btnSettings); + }; + + linkHelp.Click += (s, e) => + + { + Process.Start("https://github.com/builtbybel/Crapfixer/issues"); + }; + + UpdateTitleWithOSVersion(); // Update OS version label + this.lblVersionInfo.Text = $"v{Program.GetCurrentVersionTostring()} "; // Update version label + } + + private async void UpdateTitleWithOSVersion() + { + string osVersion = await OSHelper.OSHelper.GetWindowsVersion(); + this.lblOSInfo.Text = osVersion; + } + + private async void btnAnalyze_Click(object sender, EventArgs e) + { + rtbLogger.Clear(); + + // Analyze features + await FeatureNodeManager.AnalyzeAll(treeFeatures.Nodes); + + // Analyze plugins + foreach (TreeNode node in treeFeatures.Nodes) + { + PluginManager.AnalyzeAll(node); + } + + // Analyze apps + await AnalyzeApps(); + } + + /// + /// Analyzes the apps and logs the results. + /// + /// + private async Task AnalyzeApps() + { + checkedListBoxApps.Items.Clear(); + + // Try loading external bloatware list from file + string[] predefined = appManager.LoadExternalBloatwareList(); + + if (predefined.Length == 0) + { + // Fallback to internal resource if external file not found or empty + predefined = Resources.PredefinedApps? + .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) + .Select(s => s.Trim()).ToArray() ?? Array.Empty(); + + // Logger.Log("Using built-in bloatware list.", LogLevel.Info); + } + else + { + Logger.Log("Using external bloatware list via CFEnhancer", LogLevel.Info); + } + + // Analyze installed apps against the predefined list + var apps = await appManager.AnalyzeAndLogAppsAsync(predefined); + + foreach (var app in apps) + { + checkedListBoxApps.Items.Add(app.FullName); + } + + if (!apps.Any()) + { + Logger.Log("✅ No bloatware apps found.", LogLevel.Info); + } + } + + + private async void btnFix_Click(object sender, EventArgs e) + { + rtbLogger.Clear(); + + // Fix all features + foreach (TreeNode node in treeFeatures.Nodes) + await FeatureNodeManager.FixChecked(node); + + // Fix all plugins + foreach (TreeNode node in treeFeatures.Nodes) + await PluginManager.FixChecked(node); + + // Fix selected Store apps + var selectedApps = checkedListBoxApps.CheckedItems.Cast().ToList(); + if (selectedApps.Count == 0) + return; + + var appService = new AppManagerService(); + var removedApps = await appService.UninstallSelectedAppsAsync(selectedApps); + + // Update UI after uninstall + foreach (var app in removedApps) + { + checkedListBoxApps.Items.Remove(app); + } + } + + private void btnRestore_Click(object sender, EventArgs e) + { + var result = MessageBox.Show( + "⚠️ This will restore all selected features to their original state.\n" + + "Changes made by previous configurations may be reverted.\n\n" + + "Are you sure you want to proceed?", + "Restore Selected Features", + MessageBoxButtons.YesNo, + MessageBoxIcon.Warning); + + if (result == DialogResult.Yes) + { + rtbLogger.Clear(); + foreach (TreeNode node in treeFeatures.Nodes) + FeatureNodeManager.RestoreChecked(node); + + Logger.Log("↩️ All selected features have been restored.", LogLevel.Info); + } + } + + private async void analyzeMarkedFeatureToolStripMenuItem_Click(object sender, EventArgs e) + { + if (treeFeatures.SelectedNode is TreeNode selectedNode) + { + if (PluginManager.IsPluginNode(selectedNode)) + await PluginManager.AnalyzePlugin(selectedNode); + else + Logger.Log($"🔎 Analyzing Feature: {selectedNode.Text}", LogLevel.Info); + FeatureNodeManager.AnalyzeFeature(selectedNode); + } + } + + private async void fixMarkedFeatureToolStripMenuItem_Click(object sender, EventArgs e) + { + if (treeFeatures.SelectedNode is TreeNode selectedNode) + { + if (PluginManager.IsPluginNode(selectedNode)) + await PluginManager.FixPlugin(selectedNode); + else + Logger.Log($"🔧 Fixing Feature: {selectedNode.Text}", LogLevel.Info); + await FeatureNodeManager.FixFeature(selectedNode); + } + } + + private void restoreMarkedFeatureToolStripMenuItem_Click(object sender, EventArgs e) + { + if (treeFeatures.SelectedNode is TreeNode selectedNode) + { + if (PluginManager.IsPluginNode(selectedNode)) + PluginManager.RestorePlugin(selectedNode); + else + Logger.Log($"↩️ Restoring Feature: {selectedNode.Text}", LogLevel.Info); + FeatureNodeManager.RestoreFeature(selectedNode); + } + } + + private void helpMarkedFeatureToolStripMenuItem_Click(object sender, EventArgs e) + { + if (treeFeatures.SelectedNode is TreeNode selectedNode) + { + FeatureNodeManager.ShowHelp(selectedNode); + + // Prompt for online search + var result = MessageBox.Show( + "Would you like to search online for more information about this feature?", + "Online Help", + MessageBoxButtons.YesNo, + MessageBoxIcon.Question); + + if (result == DialogResult.Yes) + { + FeatureNodeManager.ShowHelpOnline(selectedNode); + } + } + } + + /// + /// Checks or unchecks all child nodes when a parent node is checked/unchecked. + /// + /// + /// + private void treeFeatures_AfterCheck(object sender, TreeViewEventArgs e) + { + if (e.Action != TreeViewAction.Unknown) + { + foreach (TreeNode child in e.Node.Nodes) + child.Checked = e.Node.Checked; + } + } + + private void treeFeatures_MouseDown(object sender, MouseEventArgs e) + { + if (e.Button == MouseButtons.Right) + { + // Get the node under the mouse cursor + TreeNode nodeUnderMouse = treeFeatures.GetNodeAt(e.X, e.Y); + + if (nodeUnderMouse != null) + { + treeFeatures.SelectedNode = nodeUnderMouse; + + // Show the context menu at the mouse position + contextMenuStrip.Show(treeFeatures, e.Location); + } + } + } + + /// + /// Handles the link click event for selecting or deselecting all items in the list. + /// + /// + /// + private bool treeChecked = false; + + private void linkSelection_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + if (tabControl.SelectedTab == Windows) + { + foreach (TreeNode node in treeFeatures.Nodes) + { + node.Checked = treeChecked; + foreach (TreeNode child in node.Nodes) + { + child.Checked = treeChecked; + foreach (TreeNode grandChild in child.Nodes) + grandChild.Checked = treeChecked; + } + } + + treeChecked = !treeChecked; + } + else if (tabControl.SelectedTab == Apps) + { + bool shouldCheck = checkedListBoxApps.Items.Cast() + .Any(item => checkedListBoxApps.GetItemChecked(checkedListBoxApps.Items.IndexOf(item)) == false); + + for (int i = 0; i < checkedListBoxApps.Items.Count; i++) + { + checkedListBoxApps.SetItemChecked(i, shouldCheck); + } + } + } + + private void panelHeader_Paint(object sender, PaintEventArgs e) + { + Panel panel = sender as Panel; + Graphics g = e.Graphics; + + // Fill background + g.Clear(Color.FromArgb(77, 77, 77)); + + // Draw a single magenta line at the bottom + using (Pen pen = new Pen(Color.FromArgb(100, 255, 0, 255))) // Magenta with transparency + { + int y = panel.Height - 1; // Bottom-most pixel + g.DrawLine(pen, 0, y, panel.Width, y); + } + } + + private void MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + IniStateManager.Save(treeFeatures, iniPath); + } + } +} \ No newline at end of file diff --git a/src/MSCFixer/MainForm.resx b/src/MSCFixer/MainForm.resx new file mode 100644 index 0000000..fbd28e5 --- /dev/null +++ b/src/MSCFixer/MainForm.resx @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + 23, 15 + + \ No newline at end of file diff --git a/src/MSCFixer/PluginManager.cs b/src/MSCFixer/PluginManager.cs new file mode 100644 index 0000000..18e4a8c --- /dev/null +++ b/src/MSCFixer/PluginManager.cs @@ -0,0 +1,198 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.Drawing; + +public static class PluginManager +{ + public static async Task ExecutePlugin(string pluginPath) + { + try + { + using (var process = new Process()) + { + process.StartInfo.FileName = "powershell.exe"; + process.StartInfo.Arguments = $"-NoProfile -ExecutionPolicy Bypass -File \"{pluginPath}\""; + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.RedirectStandardError = true; + process.StartInfo.UseShellExecute = false; + process.StartInfo.CreateNoWindow = true; + + var outputBuilder = new StringBuilder(); + var errorBuilder = new StringBuilder(); + + process.OutputDataReceived += (s, e) => + { + if (!string.IsNullOrEmpty(e.Data)) + Logger.Log($"[PS Output] {e.Data}"); + }; + + process.ErrorDataReceived += (s, e) => + { + if (!string.IsNullOrEmpty(e.Data)) + Logger.Log($"[PS Error] {e.Data}", LogLevel.Error); + }; + + process.Start(); + process.BeginOutputReadLine(); + process.BeginErrorReadLine(); + + await Task.Run(() => process.WaitForExit()); + Logger.Log($"✅ Script executed: {Path.GetFileName(pluginPath)}"); + } + } + catch (Exception ex) + { + Logger.Log($"❌ Error executing script: {ex.Message}", LogLevel.Error); + } + } + + public static void LoadPlugins(TreeView treeView) + { + string pluginsFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "plugins"); + + if (!Directory.Exists(pluginsFolder)) + { + Directory.CreateDirectory(pluginsFolder); + // Logger.Log("No Plugins found.\nGet it on https://github.com/builtbybel/Crapfixer"); + return; + } + + var pluginsNode = new TreeNode("Plugins") + { + // NodeFont = new Font(treeView.Font, FontStyle.Bold), + BackColor = Color.Magenta, + ForeColor = Color.White + }; + + foreach (var scriptPath in Directory.GetFiles(pluginsFolder, "*.ps1")) + { + var scriptName = Path.GetFileNameWithoutExtension(scriptPath); + var scriptNode = new TreeNode + { + Text = $"{scriptName} [PS]", + ToolTipText = scriptPath, + Tag = scriptPath, + Checked = false + }; + pluginsNode.Nodes.Add(scriptNode); + } + + treeView.Nodes.Add(pluginsNode); + treeView.ExpandAll(); // expand all nodes + } + + public static void AnalyzeAll(TreeNode node) + { + if (node.Tag is string path && node.Checked) + { + Logger.Log($"🔎 Plugin ready: {Path.GetFileName(path)}"); + } + + foreach (TreeNode child in node.Nodes) + AnalyzeAll(child); + } + + /// + /// Executes all checked plugins in the tree view. + /// + /// + /// + public static async Task FixChecked(TreeNode node) + { + if (node.Checked) + { + // Show a warning for each checked plugin + if (node.Tag is string pluginPath) + { + var pluginName = Path.GetFileName(pluginPath); // get the plugin name + var proceed = ShowPluginWarning(pluginName); // the warning message box + if (!proceed) return; // If user chooses not to proceed, exit the method + } + } + + if (node.Tag is string path && node.Checked) + { + await ExecutePlugin(path); + } + + // Recursively process all child nodes + foreach (TreeNode child in node.Nodes) + await FixChecked(child); + } + + /// + /// Analyzes individual plugin files. + /// + /// + /// + public static async Task AnalyzePlugin(TreeNode node) + { + if (node?.Tag is string path && File.Exists(path)) + { + string content = File.ReadAllText(path); + Logger.Log(new string('=', 50), LogLevel.Custom); + Logger.Log($"📄 Script content:{node.Text}\n{content}", LogLevel.Info); + + await Task.CompletedTask; + } + else + { + Logger.Log($"❌ Script file not found for plugin: {node?.Text}", LogLevel.Error); + } + } + + /// + /// Executes individual plugin files. + /// + /// + /// + public static async Task FixPlugin(TreeNode node) + { + if (node?.Tag is string path && File.Exists(path)) + { + Logger.Log($"🔧 Executing Plugin: {node.Text}", LogLevel.Info); + await ExecutePlugin(path); + } + else + { + Logger.Log($"❌ Script file not found for plugin: {node?.Text}", LogLevel.Error); + } + } + + public static void RestorePlugin(TreeNode node) + { + Logger.Log($"⚠️ Restore is not available for Plugins: {node?.Text}", LogLevel.Warning); + MessageBox.Show("Restore is not possible for Plugins.", "Information", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); + } + + /// + /// Checks if the node is a plugin node. + /// + /// + /// + public static bool IsPluginNode(TreeNode node) + { + return node?.Tag is string path && path.EndsWith(".ps1", StringComparison.OrdinalIgnoreCase); + } + + /// + /// Shows a warning message box when the root plugin node is checked. + /// + /// True if the user confirmed, otherwise false. + public static bool ShowPluginWarning(string pluginName) + { + var result = MessageBox.Show( + $"⚠️ WARNING: The plugin '{pluginName}' is an external script. Its execution is outside this apps responsibility and at your own risk.\n" + + "Proceed only if you trust the source of this plugin. Do you want to continue?", + "Plugin Activation Warning", + MessageBoxButtons.YesNo, + MessageBoxIcon.Warning + ); + + return result == DialogResult.Yes; // Return true if "Yes" was clicked + } +} \ No newline at end of file diff --git a/src/MSCFixer/Properties/AssemblyInfo.cs b/src/MSCFixer/Properties/AssemblyInfo.cs index 1e5d46b..f815d86 100644 --- a/src/MSCFixer/Properties/AssemblyInfo.cs +++ b/src/MSCFixer/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ using System.Runtime.InteropServices; // Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden, // indem Sie "*" wie unten gezeigt eingeben: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.40.124")] -[assembly: AssemblyFileVersion("0.40.124")] +[assembly: AssemblyVersion("0.50.135")] +[assembly: AssemblyFileVersion("0.50.135")] diff --git a/src/MSCFixer/Views/SettingsView.Designer.cs b/src/MSCFixer/Views/SettingsView.Designer.cs index b067e48..dd781cf 100644 --- a/src/MSCFixer/Views/SettingsView.Designer.cs +++ b/src/MSCFixer/Views/SettingsView.Designer.cs @@ -107,9 +107,9 @@ this.btnDonate.ForeColor = System.Drawing.Color.White; this.btnDonate.Location = new System.Drawing.Point(194, 65); this.btnDonate.Name = "btnDonate"; - this.btnDonate.Size = new System.Drawing.Size(179, 31); + this.btnDonate.Size = new System.Drawing.Size(207, 39); this.btnDonate.TabIndex = 240; - this.btnDonate.Text = "Help me Launch Version 1.0 🚀"; + this.btnDonate.Text = "Like Crapfixer? Support future updates on Ko-fi or PayPal"; this.btnDonate.UseVisualStyleBackColor = false; this.btnDonate.Click += new System.EventHandler(this.btnDonate_Click); // @@ -133,31 +133,27 @@ // this.button1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(242)))), ((int)(((byte)(242)))), ((int)(((byte)(242))))); this.button1.Enabled = false; - this.button1.FlatAppearance.BorderColor = System.Drawing.Color.Gainsboro; + this.button1.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(153)))), ((int)(((byte)(180)))), ((int)(((byte)(209))))); this.button1.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.button1.Font = new System.Drawing.Font("Tahoma", 8F); - this.button1.Location = new System.Drawing.Point(10, 49); + this.button1.Location = new System.Drawing.Point(10, 53); this.button1.Name = "button1"; - this.button1.Padding = new System.Windows.Forms.Padding(20, 0, 0, 0); - this.button1.Size = new System.Drawing.Size(127, 30); + this.button1.Size = new System.Drawing.Size(107, 34); this.button1.TabIndex = 241; this.button1.Text = "Settings"; - this.button1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; this.button1.UseVisualStyleBackColor = false; // // button2 // this.button2.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(242)))), ((int)(((byte)(242)))), ((int)(((byte)(242))))); - this.button2.FlatAppearance.BorderColor = System.Drawing.Color.Gainsboro; + this.button2.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(153)))), ((int)(((byte)(180)))), ((int)(((byte)(209))))); this.button2.FlatStyle = System.Windows.Forms.FlatStyle.Flat; this.button2.Font = new System.Drawing.Font("Tahoma", 8F); this.button2.Location = new System.Drawing.Point(10, 13); this.button2.Name = "button2"; - this.button2.Padding = new System.Windows.Forms.Padding(20, 0, 0, 0); - this.button2.Size = new System.Drawing.Size(127, 30); + this.button2.Size = new System.Drawing.Size(107, 34); this.button2.TabIndex = 242; this.button2.Text = "About"; - this.button2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; this.button2.UseVisualStyleBackColor = false; // // SettingsView diff --git a/src/MSCFixer/Views/SettingsView.cs b/src/MSCFixer/Views/SettingsView.cs index 2ec54cc..6060150 100644 --- a/src/MSCFixer/Views/SettingsView.cs +++ b/src/MSCFixer/Views/SettingsView.cs @@ -38,12 +38,30 @@ namespace Views if (result == DialogResult.Yes) { - System.Diagnostics.Process.Start(new ProcessStartInfo + var donationChoice = MessageBox.Show( + "Would you like to donate via PayPal? (Click No for Ko-fi)", + "Choose Your Support Method", + MessageBoxButtons.YesNoCancel, + MessageBoxIcon.Question); + + if (donationChoice == DialogResult.Yes) { - FileName = "https://paypal.com/donate?hosted_button_id=MY7HX4QLYR4KG", - UseShellExecute = true - }); + System.Diagnostics.Process.Start(new ProcessStartInfo + { + FileName = "https://www.paypal.com/donate/?hosted_button_id=M9DW4VNKH9ECQ", + UseShellExecute = true + }); + } + else if (donationChoice == DialogResult.No) + { + System.Diagnostics.Process.Start(new ProcessStartInfo + { + FileName = "https://ko-fi.com/builtbybel", + UseShellExecute = true + }); + } } } + } } \ No newline at end of file