Compare commits

..
10 Commits
Author SHA1 Message Date
Belim 421d3b2fb2 Update Flyoobe_Profile_Community.txt 2025-09-03 12:49:13 +02:00
Belim 2f2b2b2a17 Add files via upload 2025-09-03 12:47:02 +02:00
Belim 88fa2c6efb Create Info.md 2025-09-03 12:45:06 +02:00
Belim cfed49d76d Init-Flyoobe-part 2025-08-29 18:32:23 +02:00
Belim 9c7dbaa938 Update README.md 2025-08-27 10:10:56 +02:00
Belim 8f57b0e66e Merge pull request #237 from JohnFowler58/patch-1
Update Strings.hu.resx
2025-08-26 15:36:29 +02:00
Belim 0eda51cd73 Update README.md 2025-08-10 17:58:51 +02:00
Belim 49f8b087cd Update README.md 2025-08-10 10:31:31 +02:00
Belim dee378192c Update README.md 2025-08-02 18:01:08 +02:00
John Fowler feecd81887 Update Strings.hu.resx
Translate a new string.
2025-07-28 12:56:50 +02:00
105 changed files with 9739 additions and 30 deletions

No files matched your search

+1 -1
View File
@@ -280,6 +280,6 @@
<value>Kiválasztás a számítógépről</value> <value>Kiválasztás a számítógépről</value>
</data> </data>
<data name="msgClosing" xml:space="preserve"> <data name="msgClosing" xml:space="preserve">
<value>Thank you for using my app!\n\nI developed this application in my free time to help you upgrade from Windows 10 to Windows 11 – even on PCs that, according to Microsoft's hardware requirements, would normally not be supported.\n\nMy app helps you avoid purchasing a new computer and actively contributes to reducing unnecessary electronic waste.\n\nNormally, I do not charge anything for my projects – neither for development nor for support.\nHowever, since this app is significantly more comprehensive, offers more features, and requires more support, I would be grateful if you would consider making a small voluntary donation, if you are able to.\n\nOf course, only if you want to and can afford it.\n\nWould you like to donate on PayPal now?</value> <value>Köszönöm, hogy használja az alkalmazásomat!\n\nEzt az alkalmazást a szabadidőmben fejlesztettem ki, hogy segítsek frissíteni a Windows 10-ről a Windows 11-re - még olyan számítógépeken is, amelyek a Microsoft hardverkövetelményei szerint normál esetben nem támogatottak.\n\nAz alkalmazásom segít elkerülni az új számítógép vásárlását, és aktívan hozzájárul a felesleges elektronikai hulladék csökkentéséhez. \nNormális esetben nem számítok fel semmit a projektjeimért - sem a fejlesztésért, sem a támogatásért.\nMivel azonban ez az alkalmazás lényegesen átfogóbb, több funkciót kínál, és több támogatást igényel, hálás lennék, ha fontolóra venné egy kis önkéntes adományozás lehetőségét, ha képes rá.\nTermészetesen csak akkor, ha szeretné és megengedheti magának.\n\nSzeretne most adományozni a PayPal-on?</value>
</data> </data>
</root> </root>
+216
View File
@@ -0,0 +1,216 @@
namespace Flyoobe
{
partial class AboutForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.panel1 = new System.Windows.Forms.Panel();
this.linkAppVersion = new System.Windows.Forms.LinkLabel();
this.chkDonated = new System.Windows.Forms.CheckBox();
this.btnDonate = new System.Windows.Forms.Button();
this.lblHeader = new System.Windows.Forms.Label();
this.lblCopyright = new System.Windows.Forms.Label();
this.btnGitHub = new System.Windows.Forms.Button();
this.btnClose = new System.Windows.Forms.Button();
this.panel1.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.Anchor = System.Windows.Forms.AnchorStyles.Top;
this.panel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(230)))), ((int)(((byte)(220)))));
this.panel1.Controls.Add(this.linkAppVersion);
this.panel1.Controls.Add(this.chkDonated);
this.panel1.Controls.Add(this.btnDonate);
this.panel1.Controls.Add(this.lblHeader);
this.panel1.Controls.Add(this.lblCopyright);
this.panel1.Controls.Add(this.btnGitHub);
this.panel1.Location = new System.Drawing.Point(13, 63);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(411, 274);
this.panel1.TabIndex = 322;
//
// linkAppVersion
//
this.linkAppVersion.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.linkAppVersion.AutoEllipsis = true;
this.linkAppVersion.Font = new System.Drawing.Font("Segoe UI Variable Small Semibol", 11.75F, System.Drawing.FontStyle.Bold);
this.linkAppVersion.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline;
this.linkAppVersion.LinkColor = System.Drawing.Color.Black;
this.linkAppVersion.Location = new System.Drawing.Point(3, 75);
this.linkAppVersion.Name = "linkAppVersion";
this.linkAppVersion.Size = new System.Drawing.Size(405, 46);
this.linkAppVersion.TabIndex = 334;
this.linkAppVersion.TabStop = true;
this.linkAppVersion.Text = "Version";
this.linkAppVersion.TextAlign = System.Drawing.ContentAlignment.TopCenter;
this.linkAppVersion.UseCompatibleTextRendering = true;
this.linkAppVersion.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkAppVersion_LinkClicked);
//
// chkDonated
//
this.chkDonated.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
this.chkDonated.AutoSize = true;
this.chkDonated.Font = new System.Drawing.Font("Segoe UI Variable Small Semilig", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.chkDonated.ForeColor = System.Drawing.Color.Black;
this.chkDonated.Location = new System.Drawing.Point(14, 255);
this.chkDonated.Name = "chkDonated";
this.chkDonated.Size = new System.Drawing.Size(141, 19);
this.chkDonated.TabIndex = 333;
this.chkDonated.Text = "I have already donated";
this.chkDonated.UseVisualStyleBackColor = true;
this.chkDonated.CheckedChanged += new System.EventHandler(this.chkDonated_CheckedChanged);
//
// btnDonate
//
this.btnDonate.Anchor = System.Windows.Forms.AnchorStyles.None;
this.btnDonate.AutoEllipsis = true;
this.btnDonate.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(29)))), ((int)(((byte)(27)))), ((int)(((byte)(26)))));
this.btnDonate.Cursor = System.Windows.Forms.Cursors.Hand;
this.btnDonate.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(141)))), ((int)(((byte)(141)))), ((int)(((byte)(141)))));
this.btnDonate.FlatAppearance.BorderSize = 0;
this.btnDonate.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(243)))), ((int)(((byte)(243)))), ((int)(((byte)(243)))));
this.btnDonate.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.btnDonate.Font = new System.Drawing.Font("Segoe UI Variable Display Semib", 11F, System.Drawing.FontStyle.Bold);
this.btnDonate.ForeColor = System.Drawing.Color.White;
this.btnDonate.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.btnDonate.Location = new System.Drawing.Point(12, 214);
this.btnDonate.Name = "btnDonate";
this.btnDonate.Size = new System.Drawing.Size(388, 38);
this.btnDonate.TabIndex = 331;
this.btnDonate.TabStop = false;
this.btnDonate.Text = "Donate";
this.btnDonate.UseCompatibleTextRendering = true;
this.btnDonate.UseVisualStyleBackColor = false;
this.btnDonate.Click += new System.EventHandler(this.btnDonate_Click);
//
// lblHeader
//
this.lblHeader.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.lblHeader.AutoEllipsis = true;
this.lblHeader.Font = new System.Drawing.Font("Segoe UI Variable Small Semibol", 20.75F, System.Drawing.FontStyle.Bold);
this.lblHeader.ForeColor = System.Drawing.Color.Black;
this.lblHeader.Location = new System.Drawing.Point(3, 20);
this.lblHeader.Name = "lblHeader";
this.lblHeader.Size = new System.Drawing.Size(405, 38);
this.lblHeader.TabIndex = 330;
this.lblHeader.Text = "Flyoobe";
this.lblHeader.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.lblHeader.UseCompatibleTextRendering = true;
//
// lblCopyright
//
this.lblCopyright.Anchor = System.Windows.Forms.AnchorStyles.None;
this.lblCopyright.BackColor = System.Drawing.Color.Transparent;
this.lblCopyright.Font = new System.Drawing.Font("Segoe UI Variable Small Semilig", 9.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblCopyright.ForeColor = System.Drawing.Color.Black;
this.lblCopyright.Location = new System.Drawing.Point(3, 127);
this.lblCopyright.Name = "lblCopyright";
this.lblCopyright.Size = new System.Drawing.Size(405, 21);
this.lblCopyright.TabIndex = 319;
this.lblCopyright.Text = "A Belim app creation (C) 2025";
this.lblCopyright.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.lblCopyright.UseCompatibleTextRendering = true;
//
// btnGitHub
//
this.btnGitHub.Anchor = System.Windows.Forms.AnchorStyles.None;
this.btnGitHub.AutoEllipsis = true;
this.btnGitHub.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(29)))), ((int)(((byte)(27)))), ((int)(((byte)(26)))));
this.btnGitHub.Cursor = System.Windows.Forms.Cursors.Hand;
this.btnGitHub.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(141)))), ((int)(((byte)(141)))), ((int)(((byte)(141)))));
this.btnGitHub.FlatAppearance.BorderSize = 0;
this.btnGitHub.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(243)))), ((int)(((byte)(243)))), ((int)(((byte)(243)))));
this.btnGitHub.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.btnGitHub.Font = new System.Drawing.Font("Segoe UI Variable Display Semib", 11F, System.Drawing.FontStyle.Bold);
this.btnGitHub.ForeColor = System.Drawing.Color.White;
this.btnGitHub.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.btnGitHub.Location = new System.Drawing.Point(12, 170);
this.btnGitHub.Name = "btnGitHub";
this.btnGitHub.Size = new System.Drawing.Size(388, 38);
this.btnGitHub.TabIndex = 317;
this.btnGitHub.TabStop = false;
this.btnGitHub.Text = "GitHub";
this.btnGitHub.UseCompatibleTextRendering = true;
this.btnGitHub.UseVisualStyleBackColor = false;
this.btnGitHub.Click += new System.EventHandler(this.btnGitHub_Click);
//
// btnClose
//
this.btnClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnClose.AutoSize = true;
this.btnClose.BackColor = System.Drawing.Color.Transparent;
this.btnClose.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(252)))), ((int)(((byte)(247)))), ((int)(((byte)(242)))));
this.btnClose.FlatAppearance.BorderSize = 0;
this.btnClose.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(252)))), ((int)(((byte)(247)))), ((int)(((byte)(242)))));
this.btnClose.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(252)))), ((int)(((byte)(247)))), ((int)(((byte)(242)))));
this.btnClose.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnClose.Font = new System.Drawing.Font("Segoe MDL2 Assets", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btnClose.ForeColor = System.Drawing.Color.Black;
this.btnClose.Location = new System.Drawing.Point(387, 15);
this.btnClose.Name = "btnClose";
this.btnClose.Size = new System.Drawing.Size(30, 29);
this.btnClose.TabIndex = 332;
this.btnClose.Text = "...";
this.btnClose.UseVisualStyleBackColor = false;
this.btnClose.Click += new System.EventHandler(this.btnClose_Click);
//
// AboutForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(230)))), ((int)(((byte)(220)))));
this.ClientSize = new System.Drawing.Size(436, 349);
this.Controls.Add(this.btnClose);
this.Controls.Add(this.panel1);
this.Name = "AboutForm";
this.Opacity = 0.95D;
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Load += new System.EventHandler(this.AboutForm_Load);
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Label lblCopyright;
private System.Windows.Forms.Button btnGitHub;
private System.Windows.Forms.Label lblHeader;
private System.Windows.Forms.Button btnClose;
private System.Windows.Forms.Button btnDonate;
private System.Windows.Forms.CheckBox chkDonated;
private System.Windows.Forms.LinkLabel linkAppVersion;
}
}
+211
View File
@@ -0,0 +1,211 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.Net.Http;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flyoobe
{
public partial class AboutForm : Form
{
public AboutForm()
{
InitializeComponent();
this.FormBorderStyle = FormBorderStyle.None;
this.DoubleBuffered = true;
linkAppVersion.Text = $"You have Flyoobe version {Program.GetAppVersion()}\n" +
"(Fetching updates...)";
btnClose.Text = "\uEF2C";
ApplyRoundedCorners();
chkDonated.Checked = DonationHelper.HasDonated();
}
private async void AboutForm_Load(object sender, EventArgs e)
{
await Task.Delay(1000);
// Call update check when form loads
await CheckForUpdateAsync();
}
private void ApplyRoundedCorners()
{
int radius = 60; // Corner radius
var path = new System.Drawing.Drawing2D.GraphicsPath();
path.AddArc(0, 0, radius, radius, 180, 90); // top-left
path.AddArc(this.Width - radius, 0, radius, radius, 270, 90); // top-right
path.AddArc(this.Width - radius, this.Height - radius, radius, radius, 0, 90); // bottom-right
path.AddArc(0, this.Height - radius, radius, radius, 90, 90); // bottom-left
path.CloseFigure();
this.Region = new Region(path); // Apply the rounded shape
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
ApplyRoundedCorners(); // Reapply on resize
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
int radius = 45;
int borderWidth = 1;
// Adjust drawing rectangle
var rect = new Rectangle(borderWidth / 2, borderWidth / 2, Width - borderWidth, Height - borderWidth);
radius = Math.Min(radius, Math.Min(rect.Width, rect.Height) / 2); // Clamp radius
var path = new System.Drawing.Drawing2D.GraphicsPath();
path.AddArc(rect.Left, rect.Top, radius * 2, radius * 2, 180, 90);
path.AddArc(rect.Right - radius * 2, rect.Top, radius * 2, radius * 2, 270, 90);
path.AddArc(rect.Right - radius * 2, rect.Bottom - radius * 2, radius * 2, radius * 2, 0, 90);
path.AddArc(rect.Left, rect.Bottom - radius * 2, radius * 2, radius * 2, 90, 90);
path.CloseFigure();
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.DrawPath(new Pen(Color.Gray, borderWidth), path); // Draw border
this.Region = new Region(path); // apply rounded region
}
private void btnGitHub_Click(object sender, EventArgs e)
{
Process.Start("https://github.com/builtbybel/Flyby11");
}
private void btnClose_Click(object sender, EventArgs e)
{
this.Close();
}
private void btnDonate_Click(object sender, EventArgs e)
{
System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
{
FileName = "https://www.paypal.com/donate?hosted_button_id=MY7HX4QLYR4KG",
UseShellExecute = true
});
}
private void chkDonated_CheckedChanged(object sender, EventArgs e)
{
DonationHelper.SetDonationStatus(chkDonated.Checked);
}
private Version NormalizeVersionString(string version)
{
// Split by dot
var parts = version.Split('.');
// Add missing zeros to have at least 3 parts
while (parts.Length < 3)
{
version += ".0";
parts = version.Split('.');
}
return Version.Parse(version);
}
private async Task CheckForUpdateAsync()
{
const string githubApiUrl = "https://api.github.com/repos/builtbybel/Flyby11/releases/latest";
try
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.UserAgent.ParseAdd("FlyoobeUpdateChecker");
var response = await client.GetAsync(githubApiUrl);
response.EnsureSuccessStatusCode();
string json = await response.Content.ReadAsStringAsync();
const string tagKey = "\"tag_name\":\"";
int index = json.IndexOf(tagKey);
if (index < 0)
{
UpdateLabel($"Flyoobe v{Program.GetAppVersion()}");
return;
}
int start = index + tagKey.Length;
int end = json.IndexOf("\"", start);
if (end <= start)
{
UpdateLabel($"Flyoobe version {Program.GetAppVersion()}");
return;
}
string latestTag = json.Substring(start, end - start);
if (latestTag.StartsWith("v"))
latestTag = latestTag.Substring(1);
string currentVersionString = Program.GetAppVersion();
Version latestVersion = NormalizeVersionString(latestTag);
Version currentVersion = NormalizeVersionString(currentVersionString);
if (latestVersion > currentVersion)
{
UpdateLabel($"Update available: v{latestVersion}", clickable: true);
}
else if (latestVersion == currentVersion)
{
UpdateLabel($"Flyoobe version {currentVersion} (up-to-date)");
}
else
{
// User has a dev or newer version
UpdateLabel($"Flyoobe version {currentVersion} (dev version?)");
}
}
}
catch (Exception ex)
{
UpdateLabel($"Update check failed: {ex.Message}");
}
}
// Helper method to update label safely on UI thread
private void UpdateLabel(string text, bool clickable = false)
{
// Update label text
linkAppVersion.Text = text;
// If clickable, show bold & underline and make cursor a hand
if (clickable)
{
linkAppVersion.Font = new Font(linkAppVersion.Font, FontStyle.Bold | FontStyle.Underline);
linkAppVersion.Enabled = true;
linkAppVersion.Cursor = Cursors.Hand;
}
else
{
// Otherwise normal font and default cursor
linkAppVersion.Font = new Font(linkAppVersion.Font, FontStyle.Regular);
linkAppVersion.Enabled = false;
linkAppVersion.Cursor = Cursors.Default;
}
}
private void linkAppVersion_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
Process.Start(new ProcessStartInfo
{
FileName = "https://github.com/builtbybel/Flyby11/releases/latest",
UseShellExecute = true
});
}
}
}
+120
View File
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+6
View File
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
</configuration>
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

+71
View File
@@ -0,0 +1,71 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.UI
{
/// <summary>
/// Disables the Click to Do feature, which also removes its entry from the right-click context menu.
/// Only available on Copilot+ PCs running Windows 11 24H2 or newer.
/// Requires a PC with an NPU (Neural Processing Unit).
/// </summary>
internal class ClickToDo : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\Shell\ClickToDo";
private const string valueName = "DisableClickToDo";
private const int recommendedValue = 1; // 1 = fully disabled, including context menu
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Set to: {recommendedValue} (disables Click to Do, removing it from context menus). " +
"Note: This setting only applies on Copilot+ PCs with Windows 11 24H2 or newer.";
}
public override string ID()
{
return "Disable Click to Do (Only Copilot+ PCs)";
}
public override string Info()
{
return "Disables Click to Do entirely, including its context menu entry which uses on-device AI to suggest actions based on screen content. Only available on Copilot+ PCs with Windows 11 24H2 or newer.";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => true;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, recommendedValue, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Error disabling Click to Do: " + ex.Message, LogLevel.Error);
return Task.FromResult(false);
}
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Error re-enabling Click to Do: " + ex.Message, LogLevel.Error);
return false;
}
}
}
}
+67
View File
@@ -0,0 +1,67 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.AI
{
internal class CopilotTaskbar : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\WindowsCopilot";
private const string valueName = "TurnOffWindowsCopilot";
private const int recommendedValue = 1;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Don't Show Copilot in Taskbar";
}
public override string Info()
{
return "This feature will disable Copilot in Taskbar.";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => true;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, 1));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, recommendedValue, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+77
View File
@@ -0,0 +1,77 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.AI
{
internal class Recall : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsAI";
private const string valueName = "AllowRecallEnablement";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended: {recommendedValue} (Recall off – protect your privacy, prevent AI from accessing personal data)";
}
public override string ID()
{
return "Turn off Recall in Windows 11";
}
public override string Info()
{
return "This will remove Recall from Windows 11 24H2";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => true;
public override Task<bool> CheckFeature()
{
// Check if reg key exists
object value = Registry.GetValue(keyName, valueName, null);
if (value == null)
{
// Key does not exist, turn off feature
return Task.FromResult(false);
}
// Key exists, check if value is desired value
return Task.FromResult((int)value == recommendedValue);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, recommendedValue, Microsoft.Win32.RegistryValueKind.DWord);
Logger.Log("You've even disabled system-wide Snapshots for all users now.", LogLevel.Info);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+69
View File
@@ -0,0 +1,69 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Ads
{
internal class FileExplorerAds : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced";
private const string valueName = "ShowSyncProviderNotifications";
private const int recommendedValue = 0;
public override string ID()
{
return "Disable File Explorer Ads";
}
public override string Info()
{
return "This feature will disable ads in File Explorer.";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => true;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord);
Logger.Log("File Explorer Ads disabled", LogLevel.Info);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, RegistryValueKind.DWord);
Logger.Log("File Explorer Ads enabled", LogLevel.Info);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+64
View File
@@ -0,0 +1,64 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Ads
{
internal class FinishSetupAds : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\UserProfileEngagement";
private const string valueName = "ScoobeSystemSettingEnabled";
private const int recommendedValue = 0;
public override string ID() => "Disable Finish Setup Ads";
public override string Info() => "This feature will disable the \"Lets finish setting up your device\" and other advertising.";
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => true;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override Task<bool> CheckFeature()
{
return
Task.FromResult(Utils.IntEquals(keyName, valueName, 0));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+68
View File
@@ -0,0 +1,68 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Ads
{
internal class LockScreenAds : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager";
private const string valueName = "RotatingLockScreenOverlayEnabled";
private const string valueName2 = "SubscribedContent-338387Enabled";
private const int recommendedValue = 0;
public override string ID() => "Disable Lock Screen Tips and Ads";
public override string Info() => "This feature will disable tips and ads on the lock screen.";
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => true;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue) &&
Utils.IntEquals(keyName, valueName2, recommendedValue)
);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
Registry.SetValue(keyName, valueName2, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
Registry.SetValue(keyName, valueName2, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+63
View File
@@ -0,0 +1,63 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Ads
{
public class PersonalizedAds : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\AdvertisingInfo";
private const string valueName = "Enabled";
private const int recommendedValue = 0;
public override string ID() => "Disable Personalized Ads";
public override string Info() => "This feature will disable personalized ads.";
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => true;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, 0));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+73
View File
@@ -0,0 +1,73 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Ads
{
internal class SettingsAds : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager";
private const string valueName = "SubscribedContent-338393Enabled";
private const string valueName2 = "SubscribedContent-353694Enabled";
private const string valueName3 = "SubscribedContent-353696Enabled";
private const int recommendedValue = 0;
public override string ID() => "Disable Settings Ads";
public override string Info() => "This feature will disable ads in settings.";
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => true;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} + {valueName2} + {valueName3} | Recommended Value: {recommendedValue}";
}
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue) &&
Utils.IntEquals(keyName, valueName2, recommendedValue) &&
Utils.IntEquals(keyName, valueName3, recommendedValue)
);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
Registry.SetValue(keyName, valueName2, 0, Microsoft.Win32.RegistryValueKind.DWord);
Registry.SetValue(keyName, valueName3, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
Registry.SetValue(keyName, valueName2, 1, Microsoft.Win32.RegistryValueKind.DWord);
Registry.SetValue(keyName, valueName3, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+69
View File
@@ -0,0 +1,69 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Ads
{
internal class StartmenuAds : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced";
private const string valueName = "Start_IrisRecommendations";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Disable Start menu Ads";
}
public override string Info()
{
return "This feature will disable ads in the start menu.";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => true;
public override Task<bool> CheckFeature()
{
return Task.FromResult(
Utils.IntEquals(keyName, valueName, recommendedValue)
);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -0,0 +1,69 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Ads
{
internal class TailoredExperiences : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Privacy";
private const string valueName = "TailoredExperiencesWithDiagnosticDataEnabled";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Disable Tailored experiences";
}
public override string Info()
{
return "Tailored Experiences allows Microsoft to get information from you to deliver personalized tips, ads, and recommendations. Many people would call this telemetry, or even spying.";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => true;
public override Task<bool> CheckFeature()
{
return Task.FromResult(
Utils.IntEquals(keyName, valueName, recommendedValue)
);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -0,0 +1,64 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Ads
{
internal class TipsAndSuggestions : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager";
private const string valueName = "SubscribedContent-338389Enabled";
private const int recommendedValue = 0;
public override string ID() => "Disable General Tips and Ads";
public override string Info() => "This feature will disable general tips and ads.";
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => true;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue)
);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -0,0 +1,63 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Ads
{
public class WelcomeExperienceAds : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager";
private const string valueName = "SubscribedContent-310093Enabled";
private const int recommendedValue = 0;
public override string ID() => "Disable Welcome Experience Ads";
public override string Info() => "This feature will disable ads in the welcome experience.";
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => true;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, 0));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+63
View File
@@ -0,0 +1,63 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Edge
{
public class BrowserSignin : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Edge";
private const string valueName = "BrowserSignin";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID() => "Disable Browser sign in and sync services";
public override string Info() => "This setting controls whether a user can sign into Microsoft Edge with an account to use services such as sync and single sign on";
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+63
View File
@@ -0,0 +1,63 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Edge
{
public class DefaultTopSites : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Edge";
private const string valueName = "NewTabPageHideDefaultTopSites";
private const int recommendedValue = 1;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID() => "Don't Show Sponsored links in new tab page";
public override string Info() => "Hide default top sites from the new tab page in Microsoft Edge";
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, recommendedValue, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -0,0 +1,63 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Edge
{
public class DefautBrowserSetting : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Edge";
private const string valueName = "DefaultBrowserSettingEnabled";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID() => "Disable Microsoft Edge as default browser";
public override string Info() => "Force Edge to stop asking to change default browser";
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+63
View File
@@ -0,0 +1,63 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Edge
{
public class EdgeCollections : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Edge";
private const string valueName = "EdgeCollectionsEnabled";
private const int recommendedValue = 0;
public override string ID() => "Disable Access to Collections feature";
public override string Info() => "Enables users to access the Collections feature, allowing them to gather, organize, share, and export content more efficiently with Office integration";
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -0,0 +1,63 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Edge
{
public class EdgeShoppingAssistant : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Edge";
private const string valueName = "EdgeShoppingAssistantEnabled";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID() => "Disable Shopping assistant";
public override string Info() => "Shopping in Microsoft Edge feature will automatically find you the best prices and coupons from across the web as you shop";
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -0,0 +1,63 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Edge
{
public class FirstRunExperience : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Edge";
private const string valueName = "HideFirstRunExperience";
private const int recommendedValue = 1;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID() => "Don't Show First Run Experience";
public override string Info() => "Hide home screen and 'Getting Started' on initial launch (from version 80 onwards)";
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => true;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+63
View File
@@ -0,0 +1,63 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Edge
{
public class GamerMode : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Edge";
private const string valueName = "GamerModeEnabled";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID() => "Disable Gamer Mode";
public override string Info() => "Microsoft Edge Gamer Mode allows gamers to personalize their browser with gaming themes and gives them the option of enabling Efficiency Mode for PC gaming, the Gaming feed on new tabs, sidebar apps for gamers, and more";
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => true;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+63
View File
@@ -0,0 +1,63 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Edge
{
public class HubsSidebar : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Policies\Microsoft\Edge";
private const string valueName = "HubsSidebarEnabled";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID() => "Disable Copilot Symbol in Edge";
public override string Info() => "This feature will disable Copilot in Microsoft Edge.";
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, 0));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -0,0 +1,63 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Edge
{
public class ImportOnEachLaunch : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Edge";
private const string valueName = "ImportOnEachLaunch";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID() => "Don't Allow to Import of data from other browsers on each launch";
public override string Info() => "Allow import of data from other browsers on each Microsoft Edge launch";
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => true;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+63
View File
@@ -0,0 +1,63 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Edge
{
public class StartupBoost : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Edge";
private const string valueName = "StartupBoostEnabled";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID() => "Disable Start Boost";
public override string Info() => "Enables Microsoft Edge processes to initialize at operating system startup and restart in the background after the last browser window has been closed";
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => true;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -0,0 +1,63 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Edge
{
public class TabPageQuickLinks : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Edge";
private const string valueName = "NewTabPageQuickLinksEnabled";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID() => "Don't Show Quick links in new tab page";
public override string Info() => "By default, when you open a new tab, you see a Bing search bar, Bing image of the day set as the page background. For supported websites, Quick Links on the New Tab page can display recent updates right in the tile";
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+63
View File
@@ -0,0 +1,63 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Edge
{
public class UserFeedback : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Edge";
private const string valueName = "UserFeedbackAllowed";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID() => "Don't Submit user feedback option";
public override string Info() => "Allow the submission of feedback, suggestions, or customer surveys, as well as reporting issues with the browser";
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => true;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+23
View File
@@ -0,0 +1,23 @@
using System.Threading.Tasks;
namespace Flyoobe
{
public abstract class FeatureBase
{
public abstract string ID();
public abstract string Info();
public abstract string GetFeatureDetails();
public abstract string SupportedOS();
public abstract Task<bool> CheckFeature();
public abstract Task<bool> DoFeature();
public abstract bool UndoFeature();
public abstract bool IsRecommended { get; }
}
}
+134
View File
@@ -0,0 +1,134 @@
using Flyoobe; // for FeatureNode
using Settings.Ads;
using Settings.AI;
using Settings.Edge;
using Settings.Gaming;
using Settings.Issues;
using Settings.Personalization;
using Settings.Privacy;
using Settings.System;
using Settings.UI;
using System.Collections.Generic;
namespace Features
{
/// <summary>
/// Loads all available feature categories and their corresponding tweak nodes.
/// Each tweak inherits from FeatureBase and represents a system setting or cleanup action.
/// </summary>
public static class FeatureLoader
{
public static List<FeatureNode> Load()
{
return new List<FeatureNode>
{
new FeatureNode("Issues")
{
Children = new List<FeatureNode>
{
new FeatureNode(new BasicCleanup()),
new FeatureNode(new WingetUpgradeAll())
}
},
new FeatureNode("System")
{
Children = new List<FeatureNode>
{
new FeatureNode(new BSODDetails()),
new FeatureNode(new VerboseStatus()),
new FeatureNode(new SpeedUpShutdown()),
new FeatureNode(new NetworkThrottling()),
new FeatureNode(new SystemResponsiveness()),
new FeatureNode(new MenuShowDelay()),
new FeatureNode(new TaskbarEndTask()),
new FeatureNode(new DisableHibernation())
}
},
new FeatureNode("MS Edge")
{
Children = new List<FeatureNode>
{
new FeatureNode(new BrowserSignin()),
new FeatureNode(new DefaultTopSites()),
new FeatureNode(new DefautBrowserSetting()),
new FeatureNode(new EdgeCollections()),
new FeatureNode(new EdgeShoppingAssistant()),
new FeatureNode(new FirstRunExperience()),
new FeatureNode(new GamerMode()),
new FeatureNode(new HubsSidebar()),
new FeatureNode(new ImportOnEachLaunch()),
new FeatureNode(new StartupBoost()),
new FeatureNode(new TabPageQuickLinks()),
new FeatureNode(new UserFeedback())
}
},
new FeatureNode("UI")
{
Children = new List<FeatureNode>
{
new FeatureNode(new FullContextMenus()),
new FeatureNode(new WLockScreen()),
new FeatureNode(new SearchboxTaskbarMode()),
new FeatureNode(new ShowOrHideMostUsedApps()),
new FeatureNode(new ShowTaskViewButton()),
new FeatureNode(new DisableSearchBoxSuggestions()),
new FeatureNode(new DisableBingSearch()),
new FeatureNode(new StartLayout()),
new FeatureNode(new Transparency()),
new FeatureNode(new DisableSnapAssistFlyout())
}
},
new FeatureNode("Gaming")
{
Children = new List<FeatureNode>
{
new FeatureNode(new GameDVR()),
new FeatureNode(new PowerThrottling()),
new FeatureNode(new VisualFX())
}
},
new FeatureNode("Privacy")
{
Children = new List<FeatureNode>
{
new FeatureNode(new ActivityHistory()),
new FeatureNode(new LocationTracking()),
new FeatureNode(new PrivacyExperience()),
new FeatureNode(new Telemetry())
}
},
new FeatureNode("Ads")
{
Children = new List<FeatureNode>
{
new FeatureNode(new FileExplorerAds()),
new FeatureNode(new FinishSetupAds()),
new FeatureNode(new LockScreenAds()),
new FeatureNode(new PersonalizedAds()),
new FeatureNode(new SettingsAds()),
new FeatureNode(new StartmenuAds()),
new FeatureNode(new TailoredExperiences()),
new FeatureNode(new TipsAndSuggestions()),
new FeatureNode(new WelcomeExperienceAds())
}
},
new FeatureNode("AI")
{
Children = new List<FeatureNode>
{
new FeatureNode(new CopilotTaskbar()),
new FeatureNode(new Recall()),
new FeatureNode(new ClickToDo())
}
}
};
}
}
}
+94
View File
@@ -0,0 +1,94 @@
using Features;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Flyoobe
{
/// <summary>
/// Manages all available features and categories.
/// Provides methods to query, apply, and undo tweaks.
/// </summary>
public class FeatureManager
{
// List of all loaded features (root nodes with category and children)
public List<FeatureNode> AllFeatures { get; private set; }
public FeatureManager()
{
// Load features from loader once during construction
AllFeatures = FeatureLoader.Load();
}
/// <summary>
/// Returns all available top-level categories.
/// </summary>
public List<string> GetCategories()
{
return AllFeatures.Select(f => f.Category).ToList();
}
/// <summary>
/// Returns all tweaks under a specific category.
/// </summary>
public List<FeatureNode> GetFeaturesByCategory(string category)
{
return AllFeatures.FirstOrDefault(f => f.Category == category)?.Children ?? new List<FeatureNode>();
}
/// <summary>
/// Applies (executes) a selected tweak asynchronously.
/// </summary>
public async Task<bool> ApplyFeature(FeatureNode node)
{
return await node.Feature.DoFeature();
}
/// <summary>
/// Undoes a tweak if supported.
/// </summary>
public bool UndoFeature(FeatureNode node)
{
return node.Feature.UndoFeature();
}
/// <summary>
/// Returns the short informational description of the feature.
/// </summary>
public string GetFeatureInfo(FeatureNode node)
{
return node.Feature?.Info() ?? "";
}
/// <summary>
/// Checks if the tweak is currently enabled (active).
/// </summary>
public async Task<bool> IsEnabled(FeatureNode node)
{
return await node.Feature.CheckFeature();
}
/// <summary>
/// Collects all features from all categories that are marked as "Recommended"
/// Use quick settings option.
/// </summary>
public List<FeatureNode> GetAllRecommendedFeatures()
{
var recommended = new List<FeatureNode>();
foreach (var categoryNode in AllFeatures)
{
foreach (var featureNode in categoryNode.Children)
{
if (featureNode.Feature.IsRecommended)
{
recommended.Add(featureNode);
}
}
}
return recommended;
}
}
}
+26
View File
@@ -0,0 +1,26 @@
using System.Collections.Generic;
namespace Flyoobe
{
public class FeatureNode
{
public string Category { get; set; }
public FeatureBase Feature { get; set; }
public List<FeatureNode> Children { get; set; } = new List<FeatureNode>();
public FeatureNode(string category)
{
Category = category;
}
public FeatureNode(FeatureBase feature)
{
Feature = feature;
}
public override string ToString()
{
return Feature?.ID() ?? Category;
}
}
}
+80
View File
@@ -0,0 +1,80 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Gaming
{
internal class GameDVR : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\System\GameConfigStore";
// 0 = Enabled, 2 = Disabled
private const string keyName2 = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\default\ApplicationManagement\AllowGameDVR";
private const string valueName = "GameDVR_Enabled";
private const string valueName2 = "GameDVR_FSEBehaviorMode";
private const string valueName3 = "value";
public override string GetFeatureDetails()
{
return $"{keyName} |Value: {valueName} | {valueName2} | {keyName2} | {valueName3} ";
}
public override string ID()
{
return "Disable Game DVR";
}
public override string Info()
{
return "This feature will disable Game DVR.";
}
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, 0) &&
Utils.IntEquals(keyName, valueName2, 2) &&
Utils.IntEquals(keyName2, valueName3, 0));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord);
Registry.SetValue(keyName, valueName2, 2, RegistryValueKind.DWord);
Registry.SetValue(keyName2, valueName3, 0, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, RegistryValueKind.DWord);
Registry.SetValue(keyName, valueName2, 0, RegistryValueKind.DWord);
Registry.SetValue(keyName2, valueName3, 1, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -0,0 +1,69 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Gaming
{
internal class PowerThrottling : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power\PowerThrottling";
private const string valueName = "PowerThrottlingOff";
private const int recommendedValue = 1;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Disable Power Throttling";
}
public override string Info()
{
return "This feature will disable Power Throttling.";
}
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, recommendedValue, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+69
View File
@@ -0,0 +1,69 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Gaming
{
internal class VisualFX : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\VisualEffects";
private const string valueName = "VisualFXSetting";
private const int recommendedValue = 2;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Disable Visual Effects";
}
public override string Info()
{
return "Turns off visual effects like animations and shadows in Windows to boost performance.";
}
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => true;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, 0));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 2, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+163
View File
@@ -0,0 +1,163 @@
using Flyoobe;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
namespace Settings.Issues
{
internal class BasicCleanup : FeatureBase
{
private readonly string tempPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Temp");
private const int cleanupSetNumber = 1;
public override string ID() => "Basic Disk Cleanup";
public override string Info() => "Deletes all temporary files from the user's Temp folder. Then, the built-in Disk Cleanup utility (cleanmgr) is run.";
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
try
{
var totalSize = GetDirectorySize(tempPath);
bool isOk = totalSize <= 50;
return Task.FromResult(isOk);
}
catch (Exception ex)
{
Logger.Log($"Error checking Temp folder: {ex.Message}", LogLevel.Error);
return Task.FromResult(false);
}
}
public override string GetFeatureDetails()
{
try
{
var totalSize = GetDirectorySize(tempPath);
return $"Temp folder size: {totalSize} MB (including cleanmgr /sagerun:1 in the next run)";
}
catch (Exception ex)
{
Logger.Log($"Error accessing Temp folder: {ex.Message}", LogLevel.Error);
return $"Temp folder not accessible: {tempPath}";
}
}
public override async Task<bool> DoFeature()
{
try
{
await CleanTempFolderAsync();
await RunDiskCleanup();
Logger.Log("Basic Cleanup completed successfully.", LogLevel.Info);
return true;
}
catch (Exception ex)
{
Logger.Log($"Error cleaning Temp folder: {ex.Message}", LogLevel.Warning);
return false;
}
}
private async Task CleanTempFolderAsync()
{
var files = await Task.Run(() => Directory.GetFiles(tempPath, "*", SearchOption.AllDirectories));
var dirs = await Task.Run(() => Directory.GetDirectories(tempPath, "*", SearchOption.AllDirectories));
foreach (var file in files)
{
try
{
await Task.Run(() => File.Delete(file));
Logger.Log($"Deleted file: {file}", LogLevel.Info);
}
catch (Exception ex)
{
Logger.Log($"Error deleting file {file}: {ex.Message}", LogLevel.Warning);
}
}
foreach (var dir in dirs)
{
try
{
await Task.Run(() => Directory.Delete(dir, true));
Logger.Log($"Deleted directory: {dir}", LogLevel.Info);
}
catch (Exception ex)
{
Logger.Log($"Error deleting directory {dir}: {ex.Message}", LogLevel.Warning);
}
}
}
// calculate the size of the directory in MB
private long GetDirectorySize(string directory)
{
try
{
var directoryInfo = new DirectoryInfo(directory);
long size = 0;
// Calculate size of all files
size += directoryInfo.GetFiles("*", SearchOption.AllDirectories).Sum(file => file.Length);
return size / (1024 * 1024); // return size in MB
}
catch (Exception ex)
{
Logger.Log($"Error calculating directory size: {ex.Message}", LogLevel.Warning);
return 0;
}
}
private async Task RunDiskCleanup()
{
try
{
Logger.Log("Running Disk Cleanup utility (cleanmgr)...", LogLevel.Info);
var sageSetCmd = $"cleanmgr.exe /sageset:{cleanupSetNumber}";
var startInfo1 = new ProcessStartInfo("cmd", $"/c {sageSetCmd}")
{
CreateNoWindow = true,
UseShellExecute = false
};
var sageRunCmd = $"cleanmgr.exe /sagerun:{cleanupSetNumber}";
var veryLowDiskCmd = $"cleanmgr.exe /verylowdisk";
var startInfo2 = new ProcessStartInfo("cmd", $"/c {sageRunCmd} {veryLowDiskCmd}")
{
CreateNoWindow = true,
UseShellExecute = false
};
using (var process1 = Process.Start(startInfo1))
{
if (process1 != null)
await Task.Run(() => process1.WaitForExit());
}
using (var process2 = Process.Start(startInfo2))
{
if (process2 != null)
await Task.Run(() => process2.WaitForExit());
}
}
catch (Exception ex)
{
Logger.Log($"Error running Disk Cleanup: {ex.Message}", LogLevel.Warning);
}
}
// Undo method: Cleanup cannot be undone, so return false
public override bool UndoFeature() => false;
}
}
+128
View File
@@ -0,0 +1,128 @@
using Flyoobe;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
namespace Settings.System
{
internal class WingetUpgradeAll : FeatureBase
{
public override string GetFeatureDetails()
{
return "winget upgrade --include-unknown";
}
public override string ID()
{
return "Winget App Updates";
}
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override string Info()
{
return "Automatically searches for available app updates using the Windows package manager 'winget' and installs them in a new Windows Terminal window. It runs 'winget upgrade --include-unknown' to list all available updates, including manually installed apps, and then 'winget upgrade --all --include-unknown' to install them. No manual interaction is required.";
}
public override async Task<bool> CheckFeature()
{
Logger.Log("📦 Checking all available updates via winget...", LogLevel.Warning);
Logger.Log("This may take a while, please be patient.", LogLevel.Warning);
try
{
string output = await ExecuteCommand("winget upgrade --include-unknown");
Logger.Log("Winget upgrade check:\n" + output, LogLevel.Info);
return output.ToLower().Contains("available");
}
catch (Exception ex)
{
Logger.Log("Winget check failed: " + ex.Message, LogLevel.Error);
return false;
}
}
public override Task<bool> DoFeature()
{
return Task.Factory.StartNew(() =>
{
try
{
LaunchInTerminal("winget upgrade --all --include-unknown");
return true;
}
catch (Exception ex)
{
Logger.Log("Failed to run winget upgrade: " + ex.Message, LogLevel.Error);
return false;
}
});
}
public override bool UndoFeature()
{
Logger.Log("Winget upgrades cannot be undone.", LogLevel.Warning);
return false;
}
private void LaunchInTerminal(string command)
{
var startInfo = new ProcessStartInfo
{
FileName = "wt.exe",
Arguments = "-w 0 nt -p \"Windows PowerShell\" powershell -NoExit -Command \"" + command + "\"",
UseShellExecute = true
};
Process.Start(startInfo);
}
private Task<string> ExecuteCommand(string command)
{
var tcs = new TaskCompletionSource<string>();
try
{
var startInfo = new ProcessStartInfo
{
FileName = "cmd.exe",
Arguments = "/c " + command,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true
};
var process = new Process();
process.StartInfo = startInfo;
string output = "";
process.OutputDataReceived += (sender, args) =>
{
if (args.Data != null)
output += args.Data + Environment.NewLine;
};
process.EnableRaisingEvents = true;
process.Exited += (sender, args) =>
{
tcs.TrySetResult(output);
process.Dispose();
};
process.Start();
process.BeginOutputReadLine();
}
catch (Exception ex)
{
tcs.TrySetException(ex);
}
return tcs.Task;
}
}
}
@@ -0,0 +1,70 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Privacy
{
internal class ActivityHistory : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\System";
private const string valueName = "PublishUserActivities";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Disable activity history";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => false;
public override string Info()
{
return "Disable activity history (prevents Windows from tracking and storing your activity)";
}
public override Task<bool> CheckFeature()
{
return Task.FromResult(
Utils.IntEquals(keyName, valueName, recommendedValue)
);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -0,0 +1,68 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Privacy
{
internal class LocationTracking : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\LocationAndSensors";
private const string valueName = "LocationEnabled";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Disable location tracking";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => true;
public override string Info()
{
return "Disable location tracking (prevents Windows from accessing your location)";
}
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -0,0 +1,64 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Privacy
{
public class PrivacyExperience : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\OOBE";
private const string valueName = "DisablePrivacyExperience";
private const int recommendedValue = 0;
public override string ID() => "Disable Privacy Settings Experience at sign-in";
public override string Info() => "This feature will disable Privacy Settings Experience at sign-in.";
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => true;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override Task<bool> CheckFeature()
{
bool result = !Utils.IntEquals(keyName, valueName, recommendedValue);
return Task.FromResult(result);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, Microsoft.Win32.RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, Microsoft.Win32.RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+67
View File
@@ -0,0 +1,67 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Privacy
{
public class Telemetry : FeatureBase
{
private const string dataCollection = @"HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\DataCollection";
private const string diagTrack = @"HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\DiagTrack";
public override string ID() => "Turn off Telemetry data collection";
public override string Info() => "This feature will turn off telemetry data collection and prevent the data from being sent to Microsoft.";
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => true;
public override string GetFeatureDetails()
{
return $"{dataCollection} | {diagTrack}";
}
public override Task<bool> CheckFeature()
{
return Task.FromResult(
Utils.IntEquals(dataCollection, "AllowTelemetry", 0) &&
Utils.IntEquals(diagTrack, "Start", 4)
);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(dataCollection, "AllowTelemetry", 0, RegistryValueKind.DWord);
Registry.SetValue(diagTrack, "Start", 4, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(dataCollection, "AllowTelemetry", 1, RegistryValueKind.DWord);
Registry.SetValue(diagTrack, "Start", 2, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+73
View File
@@ -0,0 +1,73 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.System
{
internal class BSODDetails : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\CrashControl";
private const string valueName1 = "DisplayParameters";
private const string valueName2 = "DisableEmoticon";
private const int recommendedValue = 1;
public override string GetFeatureDetails()
{
return $"{keyName} | Values: {valueName1}, {valueName2} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Show BSOD details instead of sad smiley";
}
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override string Info()
{
return "This method displays the full classic BSOD with technical error details instead of the simplified sad face version.";
}
public override Task<bool> CheckFeature()
{
return Task.FromResult(
Utils.IntEquals(keyName, valueName1, recommendedValue) &&
Utils.IntEquals(keyName, valueName2, recommendedValue)
);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName1, recommendedValue, RegistryValueKind.DWord);
Registry.SetValue(keyName, valueName2, recommendedValue, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName1, 0, RegistryValueKind.DWord);
Registry.SetValue(keyName, valueName2, 0, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+93
View File
@@ -0,0 +1,93 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
namespace Settings.System
{
internal class DisableHibernation : FeatureBase
{
private const string powerKey = @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Power";
private const string hibernateValueName = "HibernateEnabled";
private const int disabledValue = 0;
private const int enabledValue = 1;
// Key to hide/show the Hibernate option in the power menu Alt+F4 dialog
private const string flyoutMenuKey = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\FlyoutMenuSettings";
private const string showHibernateOptionName = "ShowHibernateOption";
public override string GetFeatureDetails()
{
return "Disables hibernation by setting registry values and running powercfg, and hides/shows the Hibernate option in the power menu.";
}
public override string ID()
{
return "Disable Hibernation";
}
public override string Info()
{
return "Hibernation is mostly useful for laptops to save battery by storing your session before shutdown. On desktops, it is rarely needed and uses disk space. Disabling it frees resources and avoids confusion by hiding the Hibernate option in the power menu.";
}
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
bool hibernateDisabled = Utils.IntEquals(powerKey, hibernateValueName, disabledValue);
bool optionHidden = Utils.IntEquals(flyoutMenuKey, showHibernateOptionName, 0);
return Task.FromResult(hibernateDisabled && optionHidden);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(powerKey, hibernateValueName, disabledValue, RegistryValueKind.DWord);
Registry.SetValue(flyoutMenuKey, showHibernateOptionName, 0, RegistryValueKind.DWord);
RunCommand("powercfg", "/hibernate off");
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Error disabling hibernation: " + ex.Message, LogLevel.Error);
return Task.FromResult(false);
}
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(powerKey, hibernateValueName, enabledValue, RegistryValueKind.DWord);
Registry.SetValue(flyoutMenuKey, showHibernateOptionName, 1, RegistryValueKind.DWord);
RunCommand("powercfg", "/hibernate on");
bool hibernateEnabled = Utils.IntEquals(powerKey, hibernateValueName, enabledValue);
bool optionShown = Utils.IntEquals(flyoutMenuKey, showHibernateOptionName, 1);
return hibernateEnabled && optionShown;
}
catch (Exception ex)
{
Logger.Log("Error enabling hibernation: " + ex.Message, LogLevel.Error);
return false;
}
}
private void RunCommand(string fileName, string arguments)
{
using (var process = new Process())
{
process.StartInfo.FileName = fileName;
process.StartInfo.Arguments = arguments;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.UseShellExecute = false;
process.Start();
process.WaitForExit();
}
}
}
}
+67
View File
@@ -0,0 +1,67 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.System
{
internal class MenuShowDelay : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Control Panel\Desktop";
private const string valueName = "MenuShowDelay";
private const string recommendedValue = "10";
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: \"{recommendedValue}\" (faster menu response)";
}
public override string ID()
{
return "Speed Up Menu Show Delay";
}
public override string Info()
{
return "Speeds up the appearance of menus and submenus by lowering the default delay. This improves the perceived responsiveness of the UI.";
}
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.StringEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, recommendedValue, RegistryValueKind.String);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, "400", RegistryValueKind.String); // Default is 400 on Windows 11
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -0,0 +1,67 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.System
{
internal class NetworkThrottling : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Multimedia\SystemProfile";
private const string valueName = "NetworkThrottlingIndex";
private const int recommendedValue = -1; // 0xFFFFFFFF
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: 0xFFFFFFFF (decimal: {uint.MaxValue})";
}
public override string ID()
{
return "Disable Network Throttling";
}
public override string Info()
{
return "Disables the Windows network throttling mechanism to potentially improve performance for streaming, gaming, or real-time applications.";
}
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, unchecked((int)0xFFFFFFFF)));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, unchecked((int)0xFFFFFFFF), RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 10, RegistryValueKind.DWord); // Default is 10
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -0,0 +1,69 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.System
{
internal class SpeedUpShutdown : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control";
private const string valueName = "WaitToKillServiceTimeout";
private const string recommendedValue = "1000"; // Set to 1000 ms (1 second)
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue} ms";
}
public override string ID()
{
return "Speed Up Shutdown Time";
}
public override string Info()
{
return "This feature reduces the WaitToKillServiceTimeout value, which speeds up the shutdown process by reducing the time Windows waits for services to stop.";
}
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(
Utils.StringEquals(keyName, valueName, recommendedValue)
);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, recommendedValue, RegistryValueKind.String);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Error in SpeedUpShutdown: " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, "5000", RegistryValueKind.String); // Default value
return true;
}
catch (Exception ex)
{
Logger.Log("Error in SpeedUpShutdown (Undo): " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -0,0 +1,67 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.System
{
internal class SystemResponsiveness : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Multimedia\SystemProfile";
private const string valueName = "SystemResponsiveness";
private const int recommendedValue = 10;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Optimize System Responsiveness";
}
public override string Info()
{
return "Enhances system responsiveness by prioritizing CPU resources for foreground tasks, improving performance during active use.";
}
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, recommendedValue, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 20, RegistryValueKind.DWord); // Default is typically 20 on Windows 11
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+67
View File
@@ -0,0 +1,67 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.System
{
internal class TaskbarEndTask : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced\TaskbarDeveloperSettings";
private const string valueName = "TaskbarEndTask";
private const int recommendedValue = 1;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Enable End Task";
}
public override string Info()
{
return "Adds 'End Task' to the Windows 11 taskbar context menu, allowing you to directly kill unresponsive apps.";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => true;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, recommendedValue, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Failed to enable End Task: " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Failed to disable End Task: " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+70
View File
@@ -0,0 +1,70 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.System
{
internal class VerboseStatus : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System";
private const string valueName = "VerboseStatus";
private const int recommendedValue = 1;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Enable Verbose Logon status messages";
}
public override string Info()
{
return "This method allows you to see what processes are hanging when shutting down and turning on the machine.";
}
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(
Utils.IntEquals(keyName, valueName, recommendedValue)
);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, recommendedValue, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+65
View File
@@ -0,0 +1,65 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.UI
{
internal class DisableBingSearch : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Search";
private const string valueName = "BingSearchEnabled";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Disable Bing Search";
}
public override string Info()
{
return "This feature disables Bing integration in Windows Search.";
}
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => true;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, recommendedValue, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Error in DisableBingSearch: " + ex.Message, LogLevel.Error);
return Task.FromResult(false);
}
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Error undoing DisableBingSearch: " + ex.Message, LogLevel.Error);
return false;
}
}
}
}
+72
View File
@@ -0,0 +1,72 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Personalization
{
internal class FullContextMenus : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\SOFTWARE\CLASSES\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32";
public override string GetFeatureDetails()
{
return $"{keyName}";
}
public override string ID()
{
return "Show Full context menus in Windows 11";
}
public override string Info()
{
return "This feature will enable full context menus";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
try
{
object value = Registry.GetValue(keyName, "", null);
return Task.FromResult(value != null); // Return true if value is not null
}
catch (Exception ex)
{
Logger.Log("Error occurred while checking: " + ex.Message, LogLevel.Error);
return Task.FromResult(false);
}
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, "", "", RegistryValueKind.String);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Error occurred while enabling: " + ex.Message, LogLevel.Error);
return Task.FromResult(false);
}
}
public override bool UndoFeature()
{
try
{
Registry.CurrentUser.DeleteSubKeyTree(@"Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}", false);
return true;
}
catch (Exception ex)
{
Logger.Log("Error occurred while disabling: " + ex.Message, LogLevel.Error);
return false;
}
}
}
}
@@ -0,0 +1,65 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.UI
{
internal class DisableSearchBoxSuggestions : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Policies\Microsoft\Windows\Explorer";
private const string valueName = "DisableSearchBoxSuggestions";
private const int recommendedValue = 1;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Disable Search Box Suggestions";
}
public override string Info()
{
return "This feature disables Bing search and web suggestions in the Windows Start Menu.";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => true;
public override Task<bool> CheckFeature()
{
return Task.FromResult(Utils.IntEquals(keyName, valueName, recommendedValue));
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, recommendedValue, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Error in DisableSearchBoxSuggestions: " + ex.Message, LogLevel.Error);
return Task.FromResult(false);
}
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord); // 0 = Enable suggestions
return true;
}
catch (Exception ex)
{
Logger.Log("Error undoing DisableSearchBoxSuggestions: " + ex.Message, LogLevel.Error);
return false;
}
}
}
}
@@ -0,0 +1,69 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Personalization
{
internal class SearchboxTaskbarMode : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Search";
private const string valueName = "SearchboxTaskbarMode";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Hide search box on taskbar";
}
public override string Info()
{
return "This feature will hide search box on taskbar";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(
Utils.IntEquals(keyName, valueName, recommendedValue)
);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 2, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
@@ -0,0 +1,69 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Personalization
{
internal class ShowOrHideMostUsedApps : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Explorer";
private const string valueName = "ShowOrHideMostUsedApps";
private const int recommendedValue = 2;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Hide Most used apps in start menu";
}
public override string Info()
{
return "This feature will hide Most used apps in start menu for all users";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(
Utils.IntEquals(keyName, valueName, recommendedValue)
);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, recommendedValue, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+69
View File
@@ -0,0 +1,69 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Personalization
{
internal class ShowTaskViewButton : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced";
private const string valueName = "ShowTaskViewButton";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended: {recommendedValue} (Task View off – cleaner taskbar, unless you use it often)";
}
public override string ID()
{
return "Hide Task view button on taskbar";
}
public override string Info()
{
return "This feature will hide the Task view button on taskbar";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(
Utils.IntEquals(keyName, valueName, recommendedValue)
);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+69
View File
@@ -0,0 +1,69 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Personalization
{
internal class DisableSnapAssistFlyout : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced";
private const string valueName = "EnableSnapAssistFlyout";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Disable Snap Assist Flyout";
}
public override string Info()
{
return "This feature disables the Snap Assist flyout, which appears when you snap a window.";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(
Utils.IntEquals(keyName, valueName, recommendedValue)
);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Error in DisableSnapAssistFlyout: " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Error in DisableSnapAssistFlyout (Undo): " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+69
View File
@@ -0,0 +1,69 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Personalization
{
internal class StartLayout : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced";
private const string valueName = "Start_Layout";
private const int recommendedValue = 1;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Pin more Apps on start menu";
}
public override string Info()
{
return "This feature will allow pinning more Apps on start menu";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(
Utils.IntEquals(keyName, valueName, recommendedValue)
);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+69
View File
@@ -0,0 +1,69 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Personalization
{
internal class Transparency : FeatureBase
{
private const string keyName = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize";
private const string valueName = "EnableTransparency";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Suggestion: {recommendedValue} (No transparency – smoother performance, still stylish)";
}
public override string ID()
{
return "Disable Transparency Effects";
}
public override string Info()
{
return "This feature disables transparency effects for Start menu, taskbar, and other surfaces.";
}
public override string SupportedOS() => "Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
return Task.FromResult(
Utils.IntEquals(keyName, valueName, recommendedValue)
);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Error in DisableTransparency: " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Error in DisableTransparency (Undo): " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+68
View File
@@ -0,0 +1,68 @@
using Microsoft.Win32;
using Flyoobe;
using System;
using System.Threading.Tasks;
namespace Settings.Personalization
{
internal class WLockScreen : FeatureBase
{
private const string keyName = @"HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\Personalization";
private const string valueName = "NoLockScreen";
private const int recommendedValue = 0;
public override string GetFeatureDetails()
{
return $"{keyName} | Value: {valueName} | Recommended Value: {recommendedValue}";
}
public override string ID()
{
return "Don't use personalized lock screen";
}
public override string Info()
{
return "This feature will disable the personalized lock screen.";
}
public override string SupportedOS() => "Windows 10, Windows 11";
public override bool IsRecommended => false;
public override Task<bool> CheckFeature()
{
bool result = !Utils.IntEquals(keyName, valueName, recommendedValue);
return Task.FromResult(result);
}
public override Task<bool> DoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 1, RegistryValueKind.DWord);
return Task.FromResult(true);
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return Task.FromResult(false);
}
public override bool UndoFeature()
{
try
{
Registry.SetValue(keyName, valueName, 0, RegistryValueKind.DWord);
return true;
}
catch (Exception ex)
{
Logger.Log("Code red in " + ex.Message, LogLevel.Error);
}
return false;
}
}
}
+326
View File
@@ -0,0 +1,326 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{50CA0D4D-45AD-4E03-BFC5-64FFF4CDA36C}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>Flyoobe</RootNamespace>
<AssemblyName>Flyo</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationManifest>app.manifest</ApplicationManifest>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>AppIcon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Management" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Deployment" />
<Reference Include="System.Drawing" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
<Reference Include="Windows">
<HintPath>..\..\..\..\..\..\Program Files (x86)\Windows Kits\8.1\References\CommonConfiguration\Neutral\Annotated\Windows.winmd</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="AboutForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="AboutForm.Designer.cs">
<DependentUpon>AboutForm.cs</DependentUpon>
</Compile>
<Compile Include="Helper\DonationHelper.cs" />
<Compile Include="Helper\CopilotHelper.cs" />
<Compile Include="InstallView\BackupDriversProvider.cs" />
<Compile Include="InstallView\BootMenuInfoProvider.cs" />
<Compile Include="InstallView\InPlaceRepairProvider.cs" />
<Compile Include="InstallView\InstallProviders.cs" />
<Compile Include="InstallView\MctProvider.cs" />
<Compile Include="InstallView\MountIsoProvider.cs" />
<Compile Include="InstallView\NativeResetProvider.cs" />
<Compile Include="InstallView\RebootToUefiProvider.cs" />
<Compile Include="InstallView\RufusProvider.cs" />
<Compile Include="InstallView\RunSetupFromIsoProvider.cs" />
<Compile Include="InstallView\ToolHelper.cs" />
<Compile Include="InstallView\VentoyProvider.cs" />
<Compile Include="UpgradeView\IsoHandler.cs" />
<Compile Include="LogForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="LogForm.Designer.cs">
<DependentUpon>LogForm.cs</DependentUpon>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="ToolHubView\ToolDefinition.cs" />
<Compile Include="ToolHubView\ToolHubControlView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="ToolHubView\ToolHubControlView.Designer.cs">
<DependentUpon>ToolHubControlView.cs</DependentUpon>
</Compile>
<Compile Include="ToolHubView\ToolItemControl.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="ToolHubView\ToolItemControl.Designer.cs">
<DependentUpon>ToolItemControl.cs</DependentUpon>
</Compile>
<Compile Include="Views\AccountControlView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Views\AccountControlView.Designer.cs">
<DependentUpon>AccountControlView.cs</DependentUpon>
</Compile>
<Compile Include="Views\AppsControlView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Views\AppsControlView.Designer.cs">
<DependentUpon>AppsControlView.cs</DependentUpon>
</Compile>
<Compile Include="Features\FeatureBase.cs" />
<Compile Include="Features\FeatureLoader.cs" />
<Compile Include="Features\FeatureManager.cs" />
<Compile Include="Features\FeatureNode.cs" />
<Compile Include="Features\Ads\FileExlorerAds.cs" />
<Compile Include="Features\Ads\FinishSetupAds.cs" />
<Compile Include="Features\Ads\LockScreenAds.cs" />
<Compile Include="Features\Ads\PersonalizedAds.cs" />
<Compile Include="Features\Ads\SettingsAds.cs" />
<Compile Include="Features\Ads\StartmenuAds.cs" />
<Compile Include="Features\Ads\TailoredExperiences.cs" />
<Compile Include="Features\Ads\TipsAndSuggestions.cs" />
<Compile Include="Features\Ads\WelcomeExperienceAds.cs" />
<Compile Include="Features\AI\ClickToDo.cs" />
<Compile Include="Features\AI\CopilotTaskbar.cs" />
<Compile Include="Features\AI\Recall.cs" />
<Compile Include="Features\Edge\BrowserSignin.cs" />
<Compile Include="Features\Edge\DefaultTopSites.cs" />
<Compile Include="Features\Edge\DefautBrowserSetting.cs" />
<Compile Include="Features\Edge\EdgeCollections.cs" />
<Compile Include="Features\Edge\EdgeShoppingAssistant.cs" />
<Compile Include="Features\Edge\FirstRunExperience.cs" />
<Compile Include="Features\Edge\GamerMode.cs" />
<Compile Include="Features\Edge\HubsSidebar.cs" />
<Compile Include="Features\Edge\ImportOnEachLaunch.cs" />
<Compile Include="Features\Edge\StartupBoost.cs" />
<Compile Include="Features\Edge\TabPageQuickLinks.cs" />
<Compile Include="Features\Edge\UserFeedback.cs" />
<Compile Include="Features\Gaming\GameDVR.cs" />
<Compile Include="Features\Gaming\PowerThrotteling.cs" />
<Compile Include="Features\Gaming\VisualFX.cs" />
<Compile Include="Features\Issues\BasicCleanup.cs" />
<Compile Include="Features\Issues\WingetUpgrade.cs" />
<Compile Include="Features\Privacy\ActivityHistory.cs" />
<Compile Include="Features\Privacy\LocationTracking.cs" />
<Compile Include="Features\Privacy\PrivacyExperience.cs" />
<Compile Include="Features\Privacy\Telemetry.cs" />
<Compile Include="Features\System\BSODDetails.cs" />
<Compile Include="Features\System\Hibernation.cs" />
<Compile Include="Features\System\MenuShowDelay.cs" />
<Compile Include="Features\System\NetworkThrottling.cs" />
<Compile Include="Features\System\SpeedUpShutdown.cs" />
<Compile Include="Features\System\SystemResponsiveness.cs" />
<Compile Include="Features\System\TaskbarEndTask.cs" />
<Compile Include="Features\System\VerboseStatus.cs" />
<Compile Include="Features\UI\BingSearch.cs" />
<Compile Include="Features\UI\FullContextMenus.cs" />
<Compile Include="Features\UI\WLockScreen.cs" />
<Compile Include="Features\UI\SearchBoxSuggestions.cs" />
<Compile Include="Features\UI\SearchboxTaskbarMode.cs" />
<Compile Include="Features\UI\ShowOrHideMostUsedApps.cs" />
<Compile Include="Features\UI\ShowTaskViewButton.cs" />
<Compile Include="Features\UI\SnapAssistFlyout.cs" />
<Compile Include="Features\UI\StartLayout.cs" />
<Compile Include="Features\UI\Transparency.cs" />
<Compile Include="Views\DefaultsControlView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Views\DefaultsControlView.Designer.cs">
<DependentUpon>DefaultsControlView.cs</DependentUpon>
</Compile>
<Compile Include="Views\ExperienceControlView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Views\ExperienceControlView.Designer.cs">
<DependentUpon>ExperienceControlView.cs</DependentUpon>
</Compile>
<Compile Include="Helper\Logger.cs" />
<Compile Include="Views\DeviceControlView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Views\DeviceControlView.Designer.cs">
<DependentUpon>DeviceControlView.cs</DependentUpon>
</Compile>
<Compile Include="IView.cs" />
<Compile Include="MainForm.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="MainForm.Designer.cs">
<DependentUpon>MainForm.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Helper\Utils.cs" />
<Compile Include="ViewNavigator.cs" />
<Compile Include="Views\HomeControlView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Views\InstallerControlView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Views\InstallerControlView.Designer.cs">
<DependentUpon>InstallerControlView.cs</DependentUpon>
</Compile>
<Compile Include="Views\NetworkControlView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Views\NetworkControlView.Designer.cs">
<DependentUpon>NetworkControlView.cs</DependentUpon>
</Compile>
<Compile Include="Views\PersonalizationControlView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Views\PersonalizationControlView.Designer.cs">
<DependentUpon>PersonalizationControlView.cs</DependentUpon>
</Compile>
<Compile Include="InstallView\InstallControlView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="InstallView\InstallControlView.Designer.cs">
<DependentUpon>InstallControlView.cs</DependentUpon>
</Compile>
<Compile Include="Views\UpdatesControlView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="Views\UpdatesControlView.Designer.cs">
<DependentUpon>UpdatesControlView.cs</DependentUpon>
</Compile>
<Compile Include="UpgradeView\UpgradeControlView.cs">
<SubType>UserControl</SubType>
</Compile>
<Compile Include="UpgradeView\UpgradeControlView.Designer.cs">
<DependentUpon>UpgradeControlView.cs</DependentUpon>
</Compile>
<EmbeddedResource Include="AboutForm.resx">
<DependentUpon>AboutForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="LogForm.resx">
<DependentUpon>LogForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="ToolHubView\ToolHubControlView.resx">
<DependentUpon>ToolHubControlView.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="ToolHubView\ToolItemControl.resx">
<DependentUpon>ToolItemControl.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Views\AccountControlView.resx">
<DependentUpon>AccountControlView.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Views\AppsControlView.resx">
<DependentUpon>AppsControlView.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Views\DefaultsControlView.resx">
<DependentUpon>DefaultsControlView.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Views\ExperienceControlView.resx">
<DependentUpon>ExperienceControlView.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Views\DeviceControlView.resx">
<DependentUpon>DeviceControlView.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="MainForm.resx">
<DependentUpon>MainForm.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<SubType>Designer</SubType>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<EmbeddedResource Include="Views\InstallerControlView.resx">
<DependentUpon>InstallerControlView.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Views\NetworkControlView.resx">
<DependentUpon>NetworkControlView.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Views\PersonalizationControlView.resx">
<DependentUpon>PersonalizationControlView.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="InstallView\InstallControlView.resx">
<DependentUpon>InstallControlView.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="Views\UpdatesControlView.resx">
<DependentUpon>UpdatesControlView.cs</DependentUpon>
</EmbeddedResource>
<EmbeddedResource Include="UpgradeView\UpgradeControlView.resx">
<DependentUpon>UpgradeControlView.cs</DependentUpon>
</EmbeddedResource>
<None Include="app.manifest" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<COMReference Include="WUApiLib">
<Guid>{B596CC9F-56E5-419E-A622-E01BB457431E}</Guid>
<VersionMajor>2</VersionMajor>
<VersionMinor>0</VersionMinor>
<Lcid>0</Lcid>
<WrapperTool>tlbimp</WrapperTool>
<Isolated>False</Isolated>
<EmbedInteropTypes>True</EmbedInteropTypes>
</COMReference>
</ItemGroup>
<ItemGroup>
<None Include="assetCopilot.png" />
</ItemGroup>
<ItemGroup>
<Content Include="AppIcon.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
+92
View File
@@ -0,0 +1,92 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
public static class CopilotHelper
{
// Path to the Copilot icon file
private static readonly string IconPath = Path.Combine("app", "copilot.png");
// The Shell URI to launch the Copilot app
private const string CopilotAppUri = "shell:AppsFolder\\Microsoft.Copilot_8wekyb3d8bbwe!App";
/// <summary>
/// Loads and scales the Copilot icon if available.
/// </summary>
/// <param name="baseSize">Base size for the icon</param>
/// <returns>Scaled icon image or null if icon file missing</returns>
public static Image LoadScaledIcon(int baseSize)
{
if (!File.Exists(IconPath))
return null;
using (var img = Image.FromFile(IconPath))
{
int scaledSize = GetScaledIconSize(baseSize);
return new Bitmap(img, new Size(scaledSize, scaledSize));
}
}
/// <summary>
/// Calculates the scaled icon size based on current screen DPI.
/// </summary>
public static int GetScaledIconSize(int baseSize)
{
using (Graphics g = Graphics.FromHwnd(IntPtr.Zero))
return (int)(baseSize * (g.DpiX / 96f));
}
/// <summary>
/// Attempts to launch the Copilot app.
/// </summary>
public static void LaunchCopilot()
{
string appFolder = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"Packages",
"Microsoft.Copilot_8wekyb3d8bbwe"
);
if (!Directory.Exists(appFolder))
{
MessageBox.Show(
"Copilot is currently unavailable. You're the captain now...",
"Copilot Launch Failed",
MessageBoxButtons.OK,
MessageBoxIcon.Warning
);
return;
}
Process.Start(new ProcessStartInfo
{
FileName = "explorer.exe",
Arguments = CopilotAppUri,
UseShellExecute = true
});
}
/// <summary>
/// Sets up the Copilot button with the icon and tooltip.
/// </summary>
/// <param name="btn"></param>
/// <param name="iconBaseSize"></param>
public static void SetupCopilotButton(Button btn, int iconBaseSize)
{
if (File.Exists(IconPath))
{
btn.Visible = true;
btn.Image = LoadScaledIcon(iconBaseSize);
var tooltip = new ToolTip();
tooltip.SetToolTip(btn, "Ask Copilot");
}
else
{
btn.Visible = false;
}
}
}
+68
View File
@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
namespace Flyoobe
{
public enum LogLevel
{
Info,
Warning,
Error
}
public static class Logger
{
// Event raised when a warning or error is logged
public static event Action<string, LogLevel> OnNotificationLogged;
private static readonly List<string> _logBuffer = new List<string>();
private static readonly string _logFilePath;
// Static constructor initializes the log file path
static Logger()
{
string exeDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string appDirectory = Path.Combine(exeDirectory, "app");
_logFilePath = Path.Combine(appDirectory, "log.txt");
}
/// <summary>
/// Logs a message with timestamp and log level.
/// Also appends the message to the log file.
/// </summary>
public static void Log(string message, LogLevel level = LogLevel.Info)
{
var timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
var levelStr = level.ToString().ToUpper();
var logLine = $"[{timestamp}] [{levelStr}] {message}";
_logBuffer.Add(logLine);
try
{
File.AppendAllText(_logFilePath, logLine + Environment.NewLine);
}
catch (Exception ex)
{
Debug.WriteLine($"Failed to write to log file: {ex.Message}");
}
// Fire event if level is Warning or Error
if (level == LogLevel.Warning || level == LogLevel.Error)
{
OnNotificationLogged?.Invoke(message, level);
}
}
/// <summary>
/// Returns the full log history stored in memory.
/// </summary>
public static string GetLog()
{
return string.Join(Environment.NewLine, _logBuffer);
}
}
}
+92
View File
@@ -0,0 +1,92 @@
using Microsoft.Win32;
using System;
using System.Diagnostics;
using System.Security.Principal;
namespace Flyoobe
{
internal static class Utils
{
private const string GitHubUrl = "https://github.com/builtbybel/Flyoobe";
/// <summary>
/// Checks if a registry value equals a specified integer.
/// </summary>
public static bool IntEquals(string keyName, string valueName, int expectedValue)
{
try
{
object value = Registry.GetValue(keyName, valueName, null);
return value is int intValue && intValue == expectedValue;
}
catch (Exception ex)
{
Logger.Log($"Registry check failed for {keyName}\\{valueName}: {ex.Message}", LogLevel.Error);
return false;
}
}
/// <summary>
/// Checks if a registry value equals a specified string.
/// </summary>
public static bool StringEquals(string keyName, string valueName, string expectedValue)
{
try
{
object value = Registry.GetValue(keyName, valueName, null);
return value is string strValue && strValue == expectedValue;
}
catch (Exception ex)
{
Logger.Log($"Registry check failed for {keyName}\\{valueName}: {ex.Message}", LogLevel.Error);
return false;
}
}
/// <summary>
/// Opens the GitHub project page in the default browser.
/// </summary>
public static void OpenGitHubPage(object sender, EventArgs e)
{
try
{
Process.Start(new ProcessStartInfo
{
FileName = GitHubUrl,
UseShellExecute = true
});
}
catch (Exception ex)
{
Logger.Log($"Failed to open GitHub page: {ex.Message}", LogLevel.Error);
}
}
/// <summary>
/// Checks if the application is running with administrative privileges.
/// </summary>
/// <returns></returns>
public static bool IsRunningAsAdmin()
{
using (var identity = WindowsIdentity.GetCurrent())
{
var principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
}
/// <summary>
/// Detects if the current OS is Windows 11 or newer.
/// </summary>
public static bool DetectWindows11()
{
object buildObj = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion", "CurrentBuildNumber", null);
if (buildObj != null && int.TryParse(buildObj.ToString(), out int build))
{
return build >= 22000; // Windows 11 starts at build 22000
}
return false; // If unable to detect, assume not Windows 11
}
}
}
+15
View File
@@ -0,0 +1,15 @@
/// <summary>
/// Represents a view that can be refreshed and provides a display title.
/// </summary>
public interface IView
{
/// <summary>
/// Refreshes the view to update its display or data.
/// </summary>
void RefreshView();
/// <summary>
/// Gets the title of the view for display in the UI.
/// </summary>
string ViewTitle { get; }
}
@@ -0,0 +1,100 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Windows.Forms;
namespace Flyoobe
{
// Native provider that exports all installed drivers to C:\DriversBackup using:
// pnputil.exe /export-driver * C:\DriversBackup
public sealed class BackupDriversProvider : IInstallProvider
{
public string Id => "drivers-backup";
public string DisplayName => "Backup installed drivers (exports to C:\\DriversBackup)";
public string HomepageUrl => null;
public string DirectDownloadUrl => null;
public string[] ExactExeNames => new[] { "pnputil.exe" };
public string[] WildcardExePatterns => Array.Empty<string>();
public bool TypicallyNeedsIso => false;
public bool IsExternalTool => false;
public string Hint =>
"Exports all currently installed device drivers (INF + binaries) to C:\\DriversBackup. " +
"After a clean install, point Device Manager to this folder to restore drivers even without internet.";
public string ShowOptionsAndBuildArgs(IWin32Window owner, LastSelections last)
{
const string target = @"C:\DriversBackup";
if (!ToolHelpers.Confirm(owner,
"Export all installed drivers to:\r\n\r\n" + target +
"\r\n\r\nThis runs 'pnputil /export-driver *' with administrative rights."))
return null;
try
{
Directory.CreateDirectory(target);
}
catch (Exception ex)
{
MessageBox.Show(owner,
"Could not create target folder:\r\n" + target + "\r\n\r\n" + ex.Message,
"Folder error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
try
{
// Start pnputil as elevated process
var psi = new ProcessStartInfo
{
FileName = "pnputil.exe",
Arguments = "/export-driver * \"" + target + "\"",
UseShellExecute = true,
Verb = "runas", // force elevation
CreateNoWindow = true
};
using (var proc = Process.Start(psi))
{
if (proc == null)
{
MessageBox.Show(owner, "Could not start pnputil.exe", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
proc.WaitForExit();
}
// Now export is complete > count drivers
int infCount = 0;
try
{
infCount = Directory.GetFiles(target, "*.inf", SearchOption.AllDirectories).Length;
}
catch { /* ignore */ }
MessageBox.Show(owner,
"Driver export completed.\r\n\r\n" +
$"Target: {target}\r\n" +
$"Exported driver packages: {infCount}\r\n\r\n" +
"Tip: After reinstall, in Device Manager choose 'Update driver' → 'Browse my computer' " +
"and select this folder to restore drivers.",
"Export complete",
MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show(owner,
"Failed to run pnputil:\r\n" + ex.Message,
"Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
return null;
}
}
}
+180
View File
@@ -0,0 +1,180 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Management; //HATING WMI NEEDS IMPROVEMENT!
namespace Flyoobe
{
// Just Pure info provider: shows common Boot Menu / BIOS keys by vendor.
// No tool launch; the provider only displays a small dialog with helpful hints.
public sealed class BootMenuInfoProvider : IInstallProvider
{
public string Id => "bootmenu-info";
public string DisplayName => "Boot Menu keys (info)";
public string HomepageUrl => null;
public string DirectDownloadUrl => null;
public string[] ExactExeNames => Array.Empty<string>();
public string[] WildcardExePatterns => Array.Empty<string>();
public bool TypicallyNeedsIso => false;
public bool IsExternalTool => false;
public string Hint =>
"Shows common Boot Menu and BIOS/UEFI keys for popular manufacturers. " +
"Helpful when you want to boot from a USB installer.";
public string ShowOptionsAndBuildArgs(IWin32Window owner, LastSelections last)
{
// Build and show info dialog; nothing to run afterwards.
using (var dlg = new BootMenuInfoDialog())
{
dlg.ShowDialog(owner);
}
return null;
}
// ------------------ self-contained dialog (no designer) ------------------
private sealed class BootMenuInfoDialog : Form
{
private readonly TextBox _txt;
private readonly Button _btnCopy;
private readonly Button _btnRecovery;
private readonly Button _btnClose;
public BootMenuInfoDialog()
{
Text = "Boot Menu keys (info)";
StartPosition = FormStartPosition.CenterParent;
FormBorderStyle = FormBorderStyle.FixedDialog;
MaximizeBox = false;
MinimizeBox = false;
ShowInTaskbar = false;
AutoSize = true;
AutoSizeMode = AutoSizeMode.GrowAndShrink;
Padding = new Padding(12);
// Main multiline textbox (read-only)
_txt = new TextBox
{
Multiline = true,
ReadOnly = true,
ScrollBars = ScrollBars.Vertical,
WordWrap = false,
Width = 520,
Height = 360
};
// Buttons
_btnCopy = new Button { Text = "Copy to clipboard", AutoSize = true };
_btnRecovery = new Button { Text = "Open Recovery settings", AutoSize = true };
_btnClose = new Button { Text = "Close", AutoSize = true, DialogResult = DialogResult.OK };
_btnCopy.Click += (s, e) => { try { Clipboard.SetText(_txt.Text); } catch { } };
_btnRecovery.Click += (s, e) => { ToolHelpers.OpenUri("ms-settings:recovery"); };
var btnPanel = new FlowLayoutPanel { FlowDirection = FlowDirection.RightToLeft, AutoSize = true, Dock = DockStyle.Fill, Margin = new Padding(0, 8, 0, 0) };
btnPanel.Controls.Add(_btnClose);
btnPanel.Controls.Add(_btnRecovery);
btnPanel.Controls.Add(_btnCopy);
var root = new TableLayoutPanel { ColumnCount = 1, AutoSize = true, Dock = DockStyle.Fill };
root.Controls.Add(_txt);
root.Controls.Add(btnPanel);
Controls.Add(root);
AcceptButton = _btnClose;
CancelButton = _btnClose;
// Populate content
_txt.Text = BuildContent();
}
// Returns vendor + model (if available) and a table of common keys.
private string BuildContent()
{
// Known keys by vendor (not exhaustive, but practical)
var map = new List<(string Vendor, string BootMenu, string BiosSetup)>
{
("Acer", "F12", "F2"),
("ASUS", "Esc or F8", "Del or F2"),
("Dell", "F12", "F2"),
("HP", "Esc or F9", "Esc or F10"),
("Lenovo", "F12 (Fn+F12)", "F1 or F2"),
("MSI", "F11", "Del"),
("Gigabyte", "F12", "Del"),
("ASRock", "F11", "F2 or Del"),
("Toshiba", "F12", "F2"),
("Sony", "F11 or Assist", "F2"),
("Samsung", "Esc or F12", "F2"),
("Microsoft", "Vol-Down + Power (Surface)", "Vol-Up + Power (UEFI)")
};
// Try to read Manufacturer/Model (WMI)
var (manufacturer, model) = GetSystemVendor();
var sb = new StringBuilder();
// Header
sb.AppendLine("Boot Menu & BIOS/UEFI keys");
sb.AppendLine("---------------------------");
if (!string.IsNullOrWhiteSpace(manufacturer) || !string.IsNullOrWhiteSpace(model))
{
sb.AppendLine($"Detected: {TrimOrUnknown(manufacturer)} {TrimOrUnknown(model)}");
}
else
{
sb.AppendLine("Detected: (unknown manufacturer/model)");
}
sb.AppendLine();
// If we have a known vendor, show it first
var primary = map.FirstOrDefault(x => manufacturer != null && manufacturer.IndexOf(x.Vendor, StringComparison.OrdinalIgnoreCase) >= 0);
if (!string.IsNullOrEmpty(primary.Vendor))
{
sb.AppendLine($"★ Recommended for your device ({primary.Vendor}):");
sb.AppendLine($" Boot Menu: {primary.BootMenu}");
sb.AppendLine($" BIOS/UEFI: {primary.BiosSetup}");
sb.AppendLine();
}
// Table of common keys
sb.AppendLine("Common keys by vendor:");
sb.AppendLine("Vendor | Boot Menu | BIOS/UEFI");
sb.AppendLine("--------------+-------------------+----------------");
foreach (var entry in map)
{
sb.AppendLine(
$"{entry.Vendor.PadRight(12)}| {entry.BootMenu.PadRight(18)}| {entry.BiosSetup}");
}
sb.AppendLine();
sb.AppendLine("Tips:");
sb.AppendLine("- Press and hold the key right after power-on, before the Windows logo.");
sb.AppendLine("- On some laptops you may need to hold Fn with the function key (e.g., Fn+F12).");
sb.AppendLine("- If you cannot reach the menu, use 'Open Recovery settings' and choose Advanced startup → UEFI Firmware Settings.");
return sb.ToString();
}
private static (string Manufacturer, string Model) GetSystemVendor()
{
try
{
using (var searcher = new ManagementObjectSearcher("SELECT Manufacturer, Model FROM Win32_ComputerSystem"))
{
foreach (ManagementObject mo in searcher.Get())
{
var m = (mo["Manufacturer"] as string) ?? "";
var model = (mo["Model"] as string) ?? "";
return (m.Trim(), model.Trim());
}
}
}
catch { /* WMI not available or permission issue */ }
return (null, null);
}
private static string TrimOrUnknown(string s) => string.IsNullOrWhiteSpace(s) ? "(unknown)" : s.Trim();
}
}
}
@@ -0,0 +1,57 @@
using System.IO;
using System.Windows.Forms;
namespace Flyoobe
{
// Runs setup.exe from a mounted Windows ISO with upgrade parameters.
public sealed class InPlaceRepairProvider : IInstallProvider
{
public string Id => "inplace";
public string DisplayName => "Repair upgrade (keeps apps & files)";
public string HomepageUrl => null;
public string DirectDownloadUrl => null;
public string[] ExactExeNames => new[] { "setup.exe" }; // for documentation only
public string[] WildcardExePatterns => System.Array.Empty<string>();
public bool TypicallyNeedsIso => true;
public bool IsExternalTool => false;
public string Hint =>
"Starts Windows Setup from a mounted ISO in automatic repair mode. " +
"This reinstalls Windows while keeping your apps, settings, and personal files. " +
"Recommended if your system is broken but you want to keep everything.";
public string ShowOptionsAndBuildArgs(IWin32Window owner, LastSelections last)
{
var setupPath = FindSetupExeOnMountedDrives();
if (setupPath == null)
{
MessageBox.Show(owner, "No 'setup.exe' found. Please mount a Windows ISO first.",
"Setup not found", MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
if (!ToolHelpers.Confirm(owner, "Start repair upgrade via setup.exe? The PC will restart during the process."))
return null;
// Start directly and handle here
ToolHelpers.Run(setupPath, "/auto upgrade /dynamicupdate enable", asAdmin: true);
return null; // handled > host should not run anything else
}
private static string FindSetupExeOnMountedDrives()
{
try
{
foreach (var di in DriveInfo.GetDrives())
{
if (di.DriveType == DriveType.CDRom || di.DriveType == DriveType.Removable || di.DriveType == DriveType.Fixed)
{
var p = Path.Combine(di.Name, "setup.exe");
if (File.Exists(p)) return p;
}
}
}
catch { }
return null;
}
}
}
+316
View File
@@ -0,0 +1,316 @@
namespace Flyoobe
{
partial class InstallControlView
{
/// <summary>
/// Erforderliche Designervariable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Verwendete Ressourcen bereinigen.
/// </summary>
/// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Vom Komponenten-Designer generierter Code
/// <summary>
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.panel1 = new System.Windows.Forms.Panel();
this.textProviderSearch = new System.Windows.Forms.TextBox();
this.btnQuickRepair = new System.Windows.Forms.Button();
this.btnCreateUsb = new System.Windows.Forms.Button();
this.lblOneClick = new System.Windows.Forms.Label();
this.panelInstall = new System.Windows.Forms.Panel();
this.lblBadgeDl = new System.Windows.Forms.Label();
this.lblBadgeIso = new System.Windows.Forms.Label();
this.cboSource = new System.Windows.Forms.ComboBox();
this.btnHomepage = new System.Windows.Forms.Button();
this.lblBadgeExternal = new System.Windows.Forms.Label();
this.btnDownload = new System.Windows.Forms.Button();
this.btnRun = new System.Windows.Forms.Button();
this.lblBadgeNative = new System.Windows.Forms.Label();
this.lblHint = new System.Windows.Forms.Label();
this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
this.panel1.SuspendLayout();
this.panelInstall.SuspendLayout();
this.SuspendLayout();
//
// panel1
//
this.panel1.AutoScroll = true;
this.panel1.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(242)))), ((int)(((byte)(244)))), ((int)(((byte)(244)))));
this.panel1.Controls.Add(this.textProviderSearch);
this.panel1.Controls.Add(this.btnQuickRepair);
this.panel1.Controls.Add(this.btnCreateUsb);
this.panel1.Controls.Add(this.lblOneClick);
this.panel1.Controls.Add(this.panelInstall);
this.panel1.Controls.Add(this.lblHint);
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Location = new System.Drawing.Point(0, 0);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(835, 457);
this.panel1.TabIndex = 11;
//
// textProviderSearch
//
this.textProviderSearch.AccessibleRole = System.Windows.Forms.AccessibleRole.SplitButton;
this.textProviderSearch.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.textProviderSearch.Font = new System.Drawing.Font("Segoe UI Variable Small", 9.75F);
this.textProviderSearch.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
this.textProviderSearch.Location = new System.Drawing.Point(196, 18);
this.textProviderSearch.Name = "textProviderSearch";
this.textProviderSearch.Size = new System.Drawing.Size(473, 25);
this.textProviderSearch.TabIndex = 339;
this.textProviderSearch.Text = "Search";
this.textProviderSearch.Click += new System.EventHandler(this.textProviderSearch_Click);
//
// btnQuickRepair
//
this.btnQuickRepair.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnQuickRepair.BackColor = System.Drawing.Color.Transparent;
this.btnQuickRepair.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(138)))), ((int)(((byte)(211)))));
this.btnQuickRepair.FlatAppearance.BorderSize = 2;
this.btnQuickRepair.FlatAppearance.MouseDownBackColor = System.Drawing.Color.LightGray;
this.btnQuickRepair.FlatAppearance.MouseOverBackColor = System.Drawing.Color.LightGray;
this.btnQuickRepair.Font = new System.Drawing.Font("Segoe UI Variable Small", 8.25F);
this.btnQuickRepair.ForeColor = System.Drawing.Color.Black;
this.btnQuickRepair.Location = new System.Drawing.Point(101, 422);
this.btnQuickRepair.Name = "btnQuickRepair";
this.btnQuickRepair.Size = new System.Drawing.Size(138, 27);
this.btnQuickRepair.TabIndex = 337;
this.btnQuickRepair.Text = "🪟 Quick Repair";
this.btnQuickRepair.UseVisualStyleBackColor = false;
//
// btnCreateUsb
//
this.btnCreateUsb.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.btnCreateUsb.BackColor = System.Drawing.Color.Transparent;
this.btnCreateUsb.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(138)))), ((int)(((byte)(211)))));
this.btnCreateUsb.FlatAppearance.BorderSize = 2;
this.btnCreateUsb.FlatAppearance.MouseDownBackColor = System.Drawing.Color.LightGray;
this.btnCreateUsb.FlatAppearance.MouseOverBackColor = System.Drawing.Color.LightGray;
this.btnCreateUsb.Font = new System.Drawing.Font("Segoe UI Variable Small", 8.25F);
this.btnCreateUsb.ForeColor = System.Drawing.Color.Black;
this.btnCreateUsb.Location = new System.Drawing.Point(245, 422);
this.btnCreateUsb.Name = "btnCreateUsb";
this.btnCreateUsb.Size = new System.Drawing.Size(138, 27);
this.btnCreateUsb.TabIndex = 338;
this.btnCreateUsb.Text = " 💿 Create Install USB";
this.btnCreateUsb.UseVisualStyleBackColor = false;
//
// lblOneClick
//
this.lblOneClick.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
this.lblOneClick.AutoEllipsis = true;
this.lblOneClick.Font = new System.Drawing.Font("Segoe UI Variable Small Semilig", 10.25F);
this.lblOneClick.ForeColor = System.Drawing.Color.Black;
this.lblOneClick.Location = new System.Drawing.Point(7, 425);
this.lblOneClick.Name = "lblOneClick";
this.lblOneClick.Size = new System.Drawing.Size(89, 27);
this.lblOneClick.TabIndex = 336;
this.lblOneClick.Text = "One-click:";
this.lblOneClick.UseCompatibleTextRendering = true;
//
// panelInstall
//
this.panelInstall.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panelInstall.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(249)))), ((int)(((byte)(243)))), ((int)(((byte)(240)))));
this.panelInstall.Controls.Add(this.lblBadgeDl);
this.panelInstall.Controls.Add(this.lblBadgeIso);
this.panelInstall.Controls.Add(this.cboSource);
this.panelInstall.Controls.Add(this.btnHomepage);
this.panelInstall.Controls.Add(this.lblBadgeExternal);
this.panelInstall.Controls.Add(this.btnDownload);
this.panelInstall.Controls.Add(this.btnRun);
this.panelInstall.Controls.Add(this.lblBadgeNative);
this.panelInstall.Location = new System.Drawing.Point(42, 169);
this.panelInstall.Name = "panelInstall";
this.panelInstall.Size = new System.Drawing.Size(752, 173);
this.panelInstall.TabIndex = 335;
//
// lblBadgeDl
//
this.lblBadgeDl.AutoEllipsis = true;
this.lblBadgeDl.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(249)))), ((int)(((byte)(243)))), ((int)(((byte)(240)))));
this.lblBadgeDl.Font = new System.Drawing.Font("Segoe UI Variable Small Semilig", 9.25F);
this.lblBadgeDl.ForeColor = System.Drawing.Color.Black;
this.lblBadgeDl.Location = new System.Drawing.Point(306, 13);
this.lblBadgeDl.Name = "lblBadgeDl";
this.lblBadgeDl.Size = new System.Drawing.Size(130, 26);
this.lblBadgeDl.TabIndex = 338;
this.lblBadgeDl.Text = "⬇️ Direct download";
this.lblBadgeDl.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// lblBadgeIso
//
this.lblBadgeIso.AutoEllipsis = true;
this.lblBadgeIso.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(249)))), ((int)(((byte)(243)))), ((int)(((byte)(240)))));
this.lblBadgeIso.Font = new System.Drawing.Font("Segoe UI Variable Small Semilig", 9.25F);
this.lblBadgeIso.ForeColor = System.Drawing.Color.Black;
this.lblBadgeIso.Location = new System.Drawing.Point(194, 13);
this.lblBadgeIso.Name = "lblBadgeIso";
this.lblBadgeIso.Size = new System.Drawing.Size(106, 26);
this.lblBadgeIso.TabIndex = 337;
this.lblBadgeIso.Text = "💿 Needs ISO";
this.lblBadgeIso.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// cboSource
//
this.cboSource.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.cboSource.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.cboSource.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.cboSource.Font = new System.Drawing.Font("Segoe UI Variable Small Semilig", 11.25F);
this.cboSource.FormattingEnabled = true;
this.cboSource.Location = new System.Drawing.Point(11, 61);
this.cboSource.Name = "cboSource";
this.cboSource.Size = new System.Drawing.Size(733, 28);
this.cboSource.TabIndex = 334;
//
// btnHomepage
//
this.btnHomepage.BackColor = System.Drawing.Color.Transparent;
this.btnHomepage.FlatAppearance.BorderColor = System.Drawing.Color.Silver;
this.btnHomepage.FlatAppearance.BorderSize = 2;
this.btnHomepage.FlatAppearance.MouseDownBackColor = System.Drawing.Color.LightGray;
this.btnHomepage.FlatAppearance.MouseOverBackColor = System.Drawing.Color.LightGray;
this.btnHomepage.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnHomepage.Font = new System.Drawing.Font("Segoe UI Variable Text Semiligh", 10.25F);
this.btnHomepage.ForeColor = System.Drawing.Color.Black;
this.btnHomepage.Location = new System.Drawing.Point(11, 116);
this.btnHomepage.Name = "btnHomepage";
this.btnHomepage.Size = new System.Drawing.Size(122, 31);
this.btnHomepage.TabIndex = 6;
this.btnHomepage.Text = "Web";
this.btnHomepage.UseCompatibleTextRendering = true;
this.btnHomepage.UseVisualStyleBackColor = false;
//
// lblBadgeExternal
//
this.lblBadgeExternal.AutoEllipsis = true;
this.lblBadgeExternal.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(249)))), ((int)(((byte)(243)))), ((int)(((byte)(240)))));
this.lblBadgeExternal.Font = new System.Drawing.Font("Segoe UI Variable Small Semilig", 9.25F);
this.lblBadgeExternal.ForeColor = System.Drawing.Color.Black;
this.lblBadgeExternal.Location = new System.Drawing.Point(97, 13);
this.lblBadgeExternal.Name = "lblBadgeExternal";
this.lblBadgeExternal.Size = new System.Drawing.Size(91, 26);
this.lblBadgeExternal.TabIndex = 336;
this.lblBadgeExternal.Text = "🧰 External";
this.lblBadgeExternal.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// btnDownload
//
this.btnDownload.BackColor = System.Drawing.Color.Transparent;
this.btnDownload.FlatAppearance.BorderColor = System.Drawing.Color.Silver;
this.btnDownload.FlatAppearance.BorderSize = 2;
this.btnDownload.FlatAppearance.MouseDownBackColor = System.Drawing.Color.LightGray;
this.btnDownload.FlatAppearance.MouseOverBackColor = System.Drawing.Color.LightGray;
this.btnDownload.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnDownload.Font = new System.Drawing.Font("Segoe UI Variable Text Semiligh", 10.25F);
this.btnDownload.ForeColor = System.Drawing.Color.Black;
this.btnDownload.Location = new System.Drawing.Point(139, 116);
this.btnDownload.Name = "btnDownload";
this.btnDownload.Size = new System.Drawing.Size(122, 31);
this.btnDownload.TabIndex = 11;
this.btnDownload.Text = "Download";
this.btnDownload.UseCompatibleTextRendering = true;
this.btnDownload.UseVisualStyleBackColor = false;
//
// btnRun
//
this.btnRun.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnRun.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(183)))), ((int)(((byte)(135)))));
this.btnRun.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(255)))), ((int)(((byte)(183)))), ((int)(((byte)(135)))));
this.btnRun.FlatAppearance.BorderSize = 2;
this.btnRun.FlatAppearance.MouseDownBackColor = System.Drawing.Color.LightGray;
this.btnRun.FlatAppearance.MouseOverBackColor = System.Drawing.Color.LightGray;
this.btnRun.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnRun.Font = new System.Drawing.Font("Segoe UI Variable Display Semib", 10.25F, System.Drawing.FontStyle.Bold);
this.btnRun.ForeColor = System.Drawing.Color.Black;
this.btnRun.Location = new System.Drawing.Point(530, 115);
this.btnRun.Name = "btnRun";
this.btnRun.Size = new System.Drawing.Size(214, 31);
this.btnRun.TabIndex = 10;
this.btnRun.Text = "Run";
this.btnRun.UseCompatibleTextRendering = true;
this.btnRun.UseVisualStyleBackColor = false;
//
// lblBadgeNative
//
this.lblBadgeNative.AutoEllipsis = true;
this.lblBadgeNative.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(249)))), ((int)(((byte)(243)))), ((int)(((byte)(240)))));
this.lblBadgeNative.Font = new System.Drawing.Font("Segoe UI Variable Small Semilig", 9.25F);
this.lblBadgeNative.ForeColor = System.Drawing.Color.Black;
this.lblBadgeNative.Location = new System.Drawing.Point(10, 13);
this.lblBadgeNative.Name = "lblBadgeNative";
this.lblBadgeNative.Size = new System.Drawing.Size(81, 26);
this.lblBadgeNative.TabIndex = 335;
this.lblBadgeNative.Text = "🪟 Native";
this.lblBadgeNative.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// lblHint
//
this.lblHint.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.lblHint.AutoEllipsis = true;
this.lblHint.Font = new System.Drawing.Font("Segoe UI Variable Small Semilig", 10.25F);
this.lblHint.ForeColor = System.Drawing.Color.Black;
this.lblHint.Location = new System.Drawing.Point(42, 66);
this.lblHint.Name = "lblHint";
this.lblHint.Size = new System.Drawing.Size(744, 87);
this.lblHint.TabIndex = 9;
this.lblHint.Text = "Info";
this.lblHint.UseCompatibleTextRendering = true;
//
// InstallControlView
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoScroll = true;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(247)))), ((int)(((byte)(244)))), ((int)(((byte)(242)))));
this.Controls.Add(this.panel1);
this.Name = "InstallControlView";
this.Size = new System.Drawing.Size(835, 457);
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
this.panelInstall.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Button btnHomepage;
private System.Windows.Forms.Button btnDownload;
private System.Windows.Forms.Button btnRun;
private System.Windows.Forms.Label lblHint;
private System.Windows.Forms.ToolTip toolTip1;
private System.Windows.Forms.ComboBox cboSource;
private System.Windows.Forms.Panel panelInstall;
private System.Windows.Forms.Label lblBadgeNative;
private System.Windows.Forms.Label lblBadgeDl;
private System.Windows.Forms.Label lblBadgeIso;
private System.Windows.Forms.Label lblBadgeExternal;
private System.Windows.Forms.TextBox textProviderSearch;
private System.Windows.Forms.Button btnQuickRepair;
private System.Windows.Forms.Button btnCreateUsb;
private System.Windows.Forms.Label lblOneClick;
}
}
+345
View File
@@ -0,0 +1,345 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flyoobe
{
public partial class InstallControlView : UserControl, IView
{
public string ViewTitle => "Custom: Install && Repair";
// Providers & per-provider last selections
private readonly List<IInstallProvider> _providers = new List<IInstallProvider>();
// Store last selections (ISO/exe) per provider ID
private readonly Dictionary<string, LastSelections> _lastByProvider =
new Dictionary<string, LastSelections>(StringComparer.OrdinalIgnoreCase);
public InstallControlView()
{
InitializeComponent();
InitProviderCombo();
WireUpTooltips();
HookUpEvents();
HookSearchBox();
UpdateHint();
}
private void InitProviderCombo()
{
// Register install sources
_providers.Add(new NativeResetProvider());
_providers.Add(new RufusProvider());
_providers.Add(new MctProvider());
_providers.Add(new VentoyProvider());
_providers.Add(new InPlaceRepairProvider());
_providers.Add(new RunSetupFromIsoProvider());
_providers.Add(new MountIsoProvider());
_providers.Add(new RebootToUefiProvider());
_providers.Add(new BootMenuInfoProvider());
_providers.Add(new BackupDriversProvider());
// Bind providers to dropdown
if (cboSource != null)
{
cboSource.DropDownStyle = ComboBoxStyle.DropDownList;
cboSource.DisplayMember = nameof(IInstallProvider.DisplayName);
cboSource.DataSource = _providers;
cboSource.FormattingEnabled = true;
cboSource.Format += (s, e) =>
{
var p = e.ListItem as IInstallProvider;
if (p == null) { e.Value = e.ListItem?.ToString(); return; }
var badgeTool = p.IsExternalTool ? "🧰" : "🪟";
var badgeIso = p.TypicallyNeedsIso ? " 💿" : string.Empty;
var badgeDl = !string.IsNullOrEmpty(p.DirectDownloadUrl) ? " ⬇️" : string.Empty;
e.Value = $"{badgeTool}{badgeIso}{badgeDl} {p.DisplayName}";
};
// In InitProviderCombo(): nur EIN Aufruf statt zweier
cboSource.SelectedIndexChanged += (s, e) =>
{
UpdateHint();
UpdateBadgeLegend(SelectedProvider); // update badges
};
if (cboSource.Items.Count > 0) cboSource.SelectedIndex = 0;
// Initial legend
UpdateBadgeLegend(SelectedProvider);
}
}
// Reset all badges and highlight active ones.
private void UpdateBadgeLegend(IInstallProvider p)
{
// local helper to style a "badge" label
void Style(Label lbl, System.Drawing.Color back, System.Drawing.Color fore)
{
if (lbl == null) return;
lbl.BackColor = back;
lbl.ForeColor = fore;
lbl.Padding = new Padding(6, 2, 6, 2);
}
// base (dim) + highlight colors
var dimBack = System.Drawing.Color.FromArgb(240, 240, 240);
var dimFore = System.Drawing.Color.Black;
var hiBack = System.Drawing.Color.FromArgb(204, 222, 246); // blue badge
var hiFore = System.Drawing.Color.Black;
// reset all badges
Style(lblBadgeNative, dimBack, dimFore);
Style(lblBadgeExternal, dimBack, dimFore);
Style(lblBadgeIso, dimBack, dimFore);
Style(lblBadgeDl, dimBack, dimFore);
if (p == null) return;
// highlight active badges
if (p.IsExternalTool) Style(lblBadgeExternal, hiBack, hiFore);
else Style(lblBadgeNative, hiBack, hiFore);
if (p.TypicallyNeedsIso) Style(lblBadgeIso, hiBack, hiFore);
if (!string.IsNullOrEmpty(p.DirectDownloadUrl)) Style(lblBadgeDl, hiBack, hiFore);
}
public void RefreshView()
{
// Reserved for future state refresh (e.g., detect admin etc.)
}
// --------------------------------------------------------------------------------
// Event wiring
// --------------------------------------------------------------------------------
private void HookUpEvents()
{
// Install section
if (btnRun != null) btnRun.Click += async (s, e) => await RunSelectedAsync();
if (btnHomepage != null) btnHomepage.Click += (s, e) => OpenHomepage();
if (btnDownload != null) btnDownload.Click += async (s, e) => await DownloadProviderAsync();
// One-click actions
if (btnQuickRepair != null)
btnQuickRepair.Click += async (s, e) => await RunQuickAsync("winreset"); // NativeResetProvider.Id
if (btnCreateUsb != null)
btnCreateUsb.Click += async (s, e) => await RunQuickAsync("mct"); // MctProvider.Id
}
private void WireUpTooltips()
{
if (toolTip1 == null) return;
// Install
toolTip1.SetToolTip(cboSource, "Choose the install source (Rufus, MCT, Ventoy, ...).");
toolTip1.SetToolTip(btnRun, "Open provider options (if any) and run the selected tool.");
toolTip1.SetToolTip(btnHomepage, "Open the provider's official website.");
toolTip1.SetToolTip(btnDownload, "Download the provider binary if a direct URL is available.");
}
private void UpdateHint()
{
if (lblHint == null) return;
var p = SelectedProvider;
lblHint.Text = p?.Hint ?? string.Empty;
}
// --------------------------------------------------------------------------------
// Provider selection helpers
// --------------------------------------------------------------------------------
private IInstallProvider SelectedProvider
=> cboSource?.SelectedItem as IInstallProvider;
private LastSelections GetLast(IInstallProvider p)
{
if (p == null) return null;
if (!_lastByProvider.TryGetValue(p.Id, out var last))
{
last = new LastSelections();
_lastByProvider[p.Id] = last;
}
return last;
}
// --------------------------------------------------------------------------------
// Install: run selected provider
// --------------------------------------------------------------------------------
private async System.Threading.Tasks.Task RunSelectedAsync()
{
var p = SelectedProvider;
if (p == null) return;
var last = GetLast(p);
// Let provider collect options / handle itself.
var args = p.ShowOptionsAndBuildArgs(this, last);
if (args == null) return; // canceled or fully handled inside provider
if (p.IsExternalTool)
{
// External: resolve/browse EXE as before
var exePath = ToolHelpers.ResolveToolPath(last.LastExePath, p.ExactExeNames, p.WildcardExePatterns);
if (exePath == null)
{
using (var ofd = new OpenFileDialog
{
Title = $"Select {p.DisplayName} executable",
Filter = "Executables (*.exe)|*.exe|All files (*.*)|*.*"
})
{
try
{
var downloads = System.IO.Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Downloads");
if (System.IO.Directory.Exists(downloads)) ofd.InitialDirectory = downloads;
}
catch { }
if (ofd.ShowDialog(this) != DialogResult.OK) return;
exePath = ofd.FileName;
last.LastExePath = exePath;
}
}
ToolHelpers.Run(exePath, args, asAdmin: true);
}
else
{
// Native/built-in: run by command name without file picker (UseShellExecute=true)
var cmd = (p.ExactExeNames != null && p.ExactExeNames.Length > 0)
? p.ExactExeNames[0] // e.g., "systemreset.exe"
: null;
if (string.IsNullOrEmpty(cmd))
{
MessageBox.Show(this, "No command specified for native provider.", "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
ToolHelpers.Run(cmd, args, asAdmin: true);
}
}
private void OpenHomepage()
{
var p = SelectedProvider;
if (p == null)
return;
if (string.IsNullOrEmpty(p.HomepageUrl))
{
MessageBox.Show(this,
$"No homepage is defined for {p.DisplayName}.",
"Info",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return;
}
ToolHelpers.OpenUri(p.HomepageUrl);
}
private async Task DownloadProviderAsync()
{
var p = SelectedProvider;
if (p == null) return;
if (string.IsNullOrEmpty(p.DirectDownloadUrl))
{
MessageBox.Show(this,
$"Direct download is not available for {p.DisplayName}. Please visit the homepage instead.",
"Info",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return;
}
var fileName = p.Id + ".exe"; // simple default filename
await ToolHelpers.DownloadAsync(this, p.DirectDownloadUrl, fileName);
}
// --------------------------------------------------------------------------------
// Finds a provider by its Id in the already-registered _providers list (Quick-click)
// --------------------------------------------------------------------------------
private IInstallProvider FindProviderById(string id)
{
if (string.IsNullOrEmpty(id)) return null;
foreach (var p in _providers)
if (string.Equals(p.Id, id, StringComparison.OrdinalIgnoreCase))
return p;
return null;
}
// Selects the provider in the combo (for UI consistency) and runs it via existing pipeline.
private async System.Threading.Tasks.Task RunQuickAsync(string providerId)
{
var p = FindProviderById(providerId);
if (p == null)
{
MessageBox.Show(this, $"Provider '{providerId}' not available.", "Info",
MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
// Select in UI so hint/badges update
if (cboSource != null)
cboSource.SelectedItem = p;
// Reuse your normal execution path
await RunSelectedAsync();
}
// --------------------------------------------------------------------------------
// Wires the search box to filter the providers list on-the-fly
// --------------------------------------------------------------------------------
private void HookSearchBox()
{
if (textProviderSearch == null || cboSource == null) return;
textProviderSearch.TextChanged += (s, e) =>
{
var q = textProviderSearch.Text?.Trim() ?? string.Empty;
FilterProviders(q);
};
}
// Filters the combo by DisplayName/Id/Hint (case-insensitive).
private void FilterProviders(string query)
{
if (cboSource == null) return;
// filtered view on the fly
var list = string.IsNullOrEmpty(query)
? _providers
: _providers.FindAll(p =>
(p.DisplayName ?? "").IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0
|| (p.Id ?? "").IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0
|| (p.Hint ?? "").IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0);
// Rebind
cboSource.DataSource = null;
cboSource.DataSource = list;
cboSource.DisplayMember = nameof(IInstallProvider.DisplayName);
if (cboSource.Items.Count > 0) cboSource.SelectedIndex = 0;
}
private void textProviderSearch_Click(object sender, EventArgs e)
{
textProviderSearch.Clear();
}
}
}
+123
View File
@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="toolTip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
</root>
+39
View File
@@ -0,0 +1,39 @@
using System.Windows.Forms;
namespace Flyoobe
{
/// <summary>
/// Shared "last selection" holder reused by providers (ISO/exe).
/// </summary>
public sealed class LastSelections
{
public string LastIsoPath { get; set; }
public string LastExePath { get; set; }
}
/// <summary>
/// Contract for install sources like Rufus, MCT, Ventoy, ...
/// </summary>
public interface IInstallProvider
{
string Id { get; }
string DisplayName { get; }
string HomepageUrl { get; } // may be null
string DirectDownloadUrl { get; } // may be null
string[] ExactExeNames { get; } // e.g. "rufus.exe"
string[] WildcardExePatterns { get; } // e.g. "rufus*.exe"
bool TypicallyNeedsIso { get; } // hint for UI
bool IsExternalTool { get; } // if true > resolve/browse EXE; if false > launch by command name (no file picker)
/// <summary>
/// Short hint shown in the UI.
/// </summary>
string Hint { get; }
/// <summary>
/// Show provider-specific options dialog (if any) and build CLI args.
/// Return null if user cancelled.
/// </summary>
string ShowOptionsAndBuildArgs(IWin32Window owner, LastSelections last);
}
}
+113
View File
@@ -0,0 +1,113 @@
using System.Text;
using System.Windows.Forms;
namespace Flyoobe
{
public sealed class MctProvider : IInstallProvider
{
public string Id => "mct";
public string DisplayName => "Media Creation Tool (Windows 11 Version 24H2)";
public string HomepageUrl => "https://www.microsoft.com/software-download/windows11";
public string DirectDownloadUrl => "https://go.microsoft.com/fwlink/?linkid=2156295";
public string[] ExactExeNames => new[] { "MediaCreationTool_Win11.exe" };
public string[] WildcardExePatterns => new[] { "MediaCreationTool*.exe" };
public bool IsExternalTool => true; // needs browsing/resolving
public bool TypicallyNeedsIso => false;
public string Hint => "The Media Creation Tool can download and create media itself. ISO is not mandatory.";
public string ShowOptionsAndBuildArgs(IWin32Window owner, LastSelections last)
{
using (var dlg = new MctOptionsDialog())
{
if (dlg.ShowDialog(owner) != DialogResult.OK) return null;
// Keep GUI visible: only partial switches
var sb = new StringBuilder();
if (dlg.AcceptEula) sb.Append("/Eula Accept ");
if (!string.IsNullOrWhiteSpace(dlg.SelectedArchitecture)) sb.Append("/MediaArch ").Append(dlg.SelectedArchitecture).Append(' ');
if (!string.IsNullOrWhiteSpace(dlg.LanguageCode)) sb.Append("/MediaLangCode ").Append(dlg.LanguageCode.ToLowerInvariant()).Append(' ');
if (dlg.RetailMode) sb.Append("/Retail ");
if (dlg.Selfhost) sb.Append("/Selfhost ");
return sb.ToString().Trim();
}
}
// --- Provider-local dialog (no designer) ------------------------------------------------------
private sealed class MctOptionsDialog : Form
{
private ComboBox cmbArch;
private TextBox txtLang;
private CheckBox chkEula;
private CheckBox chkRetail;
private CheckBox chkSelfhost;
private Button btnOk;
private Button btnCancel;
public string SelectedArchitecture => (cmbArch.SelectedItem as string) ?? "x64";
public string LanguageCode => string.IsNullOrWhiteSpace(txtLang.Text) ? "en-us" : txtLang.Text.Trim().ToLowerInvariant();
public bool AcceptEula => chkEula.Checked;
public bool RetailMode => chkRetail.Checked;
public bool Selfhost => chkSelfhost.Checked;
public MctOptionsDialog()
{
Text = "Media Creation Tool – Preset Options";
StartPosition = FormStartPosition.CenterParent;
FormBorderStyle = FormBorderStyle.FixedDialog;
MaximizeBox = false;
MinimizeBox = false;
ShowInTaskbar = false;
AutoSize = true;
AutoSizeMode = AutoSizeMode.GrowAndShrink;
Padding = new Padding(12);
var layout = new TableLayoutPanel
{
ColumnCount = 2,
AutoSize = true,
Dock = DockStyle.Fill
};
layout.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
layout.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100));
// Architecture
layout.Controls.Add(new Label { Text = "Architecture:", AutoSize = true, Margin = new Padding(0, 6, 8, 6) }, 0, 0);
cmbArch = new ComboBox { DropDownStyle = ComboBoxStyle.DropDownList, Width = 160 };
cmbArch.Items.AddRange(new object[] { "x64", "x86", "Both" });
cmbArch.SelectedIndex = 0;
layout.Controls.Add(cmbArch, 1, 0);
// Language
layout.Controls.Add(new Label { Text = "Language code:", AutoSize = true, Margin = new Padding(0, 6, 8, 6) }, 0, 1);
var defLang = System.Globalization.CultureInfo.CurrentUICulture?.Name?.ToLowerInvariant() ?? "en-us";
txtLang = new TextBox { Width = 200, Text = defLang };
layout.Controls.Add(txtLang, 1, 1);
// Options
chkEula = new CheckBox { Text = "Accept EULA", Checked = true, AutoSize = true };
chkRetail = new CheckBox { Text = "Retail mode", Checked = false, AutoSize = true };
chkSelfhost = new CheckBox { Text = "Selfhost", Checked = false, AutoSize = true };
var opts = new FlowLayoutPanel { FlowDirection = FlowDirection.LeftToRight, AutoSize = true };
opts.Controls.Add(chkEula);
opts.Controls.Add(chkRetail);
opts.Controls.Add(chkSelfhost);
layout.Controls.Add(new Label { Text = "Options:", AutoSize = true, Margin = new Padding(0, 6, 8, 6) }, 0, 2);
layout.Controls.Add(opts, 1, 2);
// Buttons
var pnlButtons = new FlowLayoutPanel { FlowDirection = FlowDirection.RightToLeft, AutoSize = true, Margin = new Padding(0, 12, 0, 0) };
btnOk = new Button { Text = "OK", DialogResult = DialogResult.OK, AutoSize = true };
btnCancel = new Button { Text = "Cancel", DialogResult = DialogResult.Cancel, AutoSize = true, Margin = new Padding(6, 0, 0, 0) };
pnlButtons.Controls.Add(btnOk);
pnlButtons.Controls.Add(btnCancel);
layout.Controls.Add(pnlButtons, 0, 3);
layout.SetColumnSpan(pnlButtons, 2);
Controls.Add(layout);
AcceptButton = btnOk;
CancelButton = btnCancel;
}
}
}
}
+38
View File
@@ -0,0 +1,38 @@
using System.Windows.Forms;
namespace Flyoobe
{
// Lets the user pick an ISO and mounts it via PowerShell (Mount-DiskImage).
public sealed class MountIsoProvider : IInstallProvider
{
public string Id => "mountiso";
public string DisplayName => "Mount ISO… (built-in)";
public string HomepageUrl => null;
public string DirectDownloadUrl => null;
public string[] ExactExeNames => System.Array.Empty<string>();
public string[] WildcardExePatterns => System.Array.Empty<string>();
public bool TypicallyNeedsIso => false;
public bool IsExternalTool => false;
public string Hint => "Pick a Windows ISO and mount it using PowerShell.";
public string ShowOptionsAndBuildArgs(IWin32Window owner, LastSelections last)
{
using (var ofd = new OpenFileDialog { Filter = "ISO files (*.iso)|*.iso|All files (*.*)|*.*" })
{
if (ofd.ShowDialog(owner) != DialogResult.OK) return null;
var isoPath = ofd.FileName;
var ps = "-NoProfile -Command \"Mount-DiskImage -ImagePath '" + isoPath + "' -PassThru | Out-Null\"";
if (!ToolHelpers.Run("powershell.exe", ps, asAdmin: true))
{
MessageBox.Show(owner, "Could not mount ISO. Try manual mount via Explorer (Right-click → Mount).",
"Mount failed", MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
// remember last ISO for other providers (just optional)
if (last != null) last.LastIsoPath = isoPath;
}
return null; // handled
}
}
}
+104
View File
@@ -0,0 +1,104 @@
using Flyoobe;
using System;
using System.Windows.Forms;
using static System.Net.Mime.MediaTypeNames;
public sealed class NativeResetProvider : IInstallProvider
{
public string Id => "winreset";
public string DisplayName => "Windows Reset (built-in)";
public string HomepageUrl => "ms-settings:recovery";
public string DirectDownloadUrl => null;
public string[] ExactExeNames => new[] { "systemreset.exe" }; // only Doku
public string[] WildcardExePatterns => Array.Empty<string>();
public bool TypicallyNeedsIso => false;
public bool IsExternalTool => false;
public string Hint =>
"Built-in Windows reset. Inside the wizard choose 'Keep my files' or 'Remove everything' and optionally 'Cloud download'.";
public string ShowOptionsAndBuildArgs(IWin32Window owner, LastSelections last)
{
using (var dlg = new ResetOptionsDialog())
{
if (dlg.ShowDialog(owner) != DialogResult.OK)
return null; // canceled > host does not do anything
switch (dlg.SelectedMode)
{
case ResetMode.ResetWizard:
if (!ToolHelpers.Confirm(owner,
"Start 'Reset this PC'? This may remove apps/data depending on your selection."))
return null;
if (!ToolHelpers.Run("systemreset.exe", "-factoryreset", true))
ToolHelpers.Run("systemreset.exe", "", true);
return null; //RunSelectedAsync() should not start anything else
case ResetMode.RebootToWinRE:
ToolHelpers.Run("shutdown.exe", "/r /o /t 0 /f", true);
return null;
case ResetMode.OpenSettings:
ToolHelpers.OpenUri("ms-settings:recovery");
return null;
default:
return null;
}
}
}
private enum ResetMode { ResetWizard, RebootToWinRE, OpenSettings }
private sealed class ResetOptionsDialog : Form
{
private RadioButton rbWizard, rbWinre, rbSettings;
private Button btnOk, btnCancel;
public ResetMode SelectedMode =>
rbWizard.Checked ? ResetMode.ResetWizard :
rbWinre.Checked ? ResetMode.RebootToWinRE :
ResetMode.OpenSettings;
public ResetOptionsDialog()
{
Text = "Windows Reset options";
StartPosition = FormStartPosition.CenterParent;
FormBorderStyle = FormBorderStyle.FixedDialog;
MaximizeBox = false; MinimizeBox = false;
ShowInTaskbar = false;
AutoSize = true; AutoSizeMode = AutoSizeMode.GrowAndShrink;
Padding = new Padding(12);
var root = new TableLayoutPanel { ColumnCount = 1, AutoSize = true, Dock = DockStyle.Fill };
rbWizard = new RadioButton { Text = "Open Reset wizard (systemreset.exe -factoryreset)", Checked = true, AutoSize = true };
rbWinre = new RadioButton { Text = "Reboot into Advanced Startup (WinRE)", AutoSize = true };
rbSettings = new RadioButton { Text = "Open Recovery Settings", AutoSize = true };
root.Controls.Add(rbWizard);
root.Controls.Add(rbWinre);
root.Controls.Add(rbSettings);
root.Controls.Add(new Label
{
AutoSize = true,
MaximumSize = new System.Drawing.Size(520, 0),
Margin = new Padding(0, 8, 0, 0),
Text = "Note: Windows does not provide supported CLI switches to pre-select 'Keep my files', 'Remove everything' or 'Cloud download'. Choose them in the wizard."
});
var pnlButtons = new FlowLayoutPanel { FlowDirection = FlowDirection.RightToLeft, AutoSize = true, Margin = new Padding(0, 12, 0, 0) };
btnOk = new Button { Text = "OK", DialogResult = DialogResult.OK, AutoSize = true };
btnCancel = new Button { Text = "Cancel", DialogResult = DialogResult.Cancel, AutoSize = true, Margin = new Padding(6, 0, 0, 0) };
pnlButtons.Controls.Add(btnOk);
pnlButtons.Controls.Add(btnCancel);
root.Controls.Add(pnlButtons);
Controls.Add(root);
AcceptButton = btnOk;
CancelButton = btnCancel;
}
}
}
@@ -0,0 +1,56 @@
using System;
using System.Windows.Forms;
namespace Flyoobe
{
// Native provider to reboot directly into UEFI/BIOS setup using "shutdown.exe /r /fw /t 0".
// If /fw is not supported on the machine, we offer a fallback to Recovery Settings (WinRE path to UEFI Firmware Settings).
public sealed class RebootToUefiProvider : IInstallProvider
{
public string Id => "uefi-reboot";
public string DisplayName => "Reboot into UEFI firmware (BIOS)";
public string HomepageUrl => null;
public string DirectDownloadUrl => null;
public string[] ExactExeNames => new[] { "shutdown.exe" }; // informational
public string[] WildcardExePatterns => Array.Empty<string>();
public bool TypicallyNeedsIso => false;
public bool IsExternalTool => false;
public string Hint =>
"Restarts the PC straight into UEFI/BIOS setup (if supported by the firmware). " +
"Useful to change boot order before a clean install.";
public string ShowOptionsAndBuildArgs(IWin32Window owner, LastSelections last)
{
// Confirm with the user (explicit reboot).
if (!ToolHelpers.Confirm(owner,
"Reboot into UEFI/BIOS now? The PC will restart immediately."))
{
return null; // canceled
}
// Try the native fast path first: /r /fw /t 0
var ok = ToolHelpers.Run("shutdown.exe", "/r /fw /t 0", asAdmin: true);
if (!ok)
{
// Not supported or blocked on this device > offer a fallback....
var choice = MessageBox.Show(owner,
"Direct firmware reboot was not supported on this device.\r\n\r\n" +
"Open Recovery settings so you can choose 'UEFI Firmware Settings' after a restart?",
"UEFI reboot fallback",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Information);
if (choice == DialogResult.OK)
{
// Settings > System > Recovery (so we can go to Advanced startup > UEFI Firmware Settings)
ToolHelpers.OpenUri("ms-settings:recovery");
}
}
// We handled everything here; host should not try to launch an external EXE.
return null;
}
}
}
+147
View File
@@ -0,0 +1,147 @@
using System.IO;
using System.Text;
using System.Windows.Forms;
namespace Flyoobe
{
public sealed class RufusProvider : IInstallProvider
{
public string Id => "rufus";
public string DisplayName => "Rufus (Version 4.9)";
public string HomepageUrl => "https://rufus.ie";
public string DirectDownloadUrl => "https://github.com/pbatard/rufus/releases/download/v4.9/rufus-4.9.exe"; // keep homepage
public string[] ExactExeNames => new[] { "rufus.exe" };
public string[] WildcardExePatterns => new[] { "rufus*.exe" };
public bool IsExternalTool => true; // needs browsing/resolving
public bool TypicallyNeedsIso => true;
public string Hint => "Rufus requires you to provide a Windows ISO file. It will create a bootable USB stick.";
public string ShowOptionsAndBuildArgs(IWin32Window owner, LastSelections last)
{
// Ask / ensure ISO first
var isoPath = EnsureIso(owner, last);
if (isoPath == null) return null; // user cancelled
// Show provider-local dialog and build CLI args
using (var dlg = new RufusOptionsDialog(System.Globalization.CultureInfo.CurrentUICulture?.Name ?? "en-US"))
{
if (dlg.ShowDialog(owner) != DialogResult.OK) return null;
// Build CLI: -g -i -l -f -x -w
var sb = new StringBuilder();
sb.Append("-g ");
sb.Append("-i \"").Append(isoPath).Append("\" ");
if (!string.IsNullOrWhiteSpace(dlg.SelectedLocale)) sb.Append("-l ").Append(dlg.SelectedLocale).Append(' ');
if (!string.IsNullOrWhiteSpace(dlg.SelectedFilesystem)) sb.Append("-f ").Append(dlg.SelectedFilesystem).Append(' ');
if (dlg.ExtraDevices) sb.Append("-x ");
if (dlg.WaitTensOfSeconds > 0) sb.Append("-w ").Append(dlg.WaitTensOfSeconds).Append(' ');
return sb.ToString().Trim();
}
}
private static string EnsureIso(IWin32Window owner, LastSelections last)
{
// Reuse last ISO if available
if (!string.IsNullOrEmpty(last.LastIsoPath) && File.Exists(last.LastIsoPath))
{
var res = MessageBox.Show(owner, "Use last selected ISO?\n\n" + last.LastIsoPath,
"Rufus", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (res == DialogResult.Cancel) return null;
if (res == DialogResult.Yes) return last.LastIsoPath;
}
// Ask for ISO
using (var ofd = new OpenFileDialog
{
Title = "Select Windows ISO",
Filter = "ISO (*.iso)|*.iso|All files (*.*)|*.*"
})
{
if (ofd.ShowDialog(owner) != DialogResult.OK) return null;
last.LastIsoPath = ofd.FileName;
return ofd.FileName;
}
}
// --- Provider-local dialog (no Designer needed) --------------------------------
// Keeping this dialog private to avoid leaking UI details outside the provider.
private sealed class RufusOptionsDialog : Form
{
private ComboBox cmbFilesystem;
private ComboBox cmbLocale;
private CheckBox chkExtra;
private NumericUpDown numWait;
private Button btnOk;
private Button btnCancel;
public string SelectedFilesystem => (cmbFilesystem.SelectedItem as string) ?? "ntfs";
public string SelectedLocale => string.IsNullOrWhiteSpace(cmbLocale.Text) ? "en-US" : cmbLocale.Text.Trim();
public bool ExtraDevices => chkExtra.Checked;
public int WaitTensOfSeconds => (int)numWait.Value;
public RufusOptionsDialog(string defaultLocale)
{
// Minimal, self-contained WinForms dialog
Text = "Rufus options";
StartPosition = FormStartPosition.CenterParent;
FormBorderStyle = FormBorderStyle.FixedDialog;
MaximizeBox = false;
MinimizeBox = false;
ShowInTaskbar = false;
AutoSize = true;
AutoSizeMode = AutoSizeMode.GrowAndShrink;
Padding = new Padding(12);
var layout = new TableLayoutPanel
{
ColumnCount = 2,
RowCount = 5,
AutoSize = true,
Dock = DockStyle.Fill
};
layout.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
layout.ColumnStyles.Add(new ColumnStyle(SizeType.AutoSize));
// Filesystem
layout.Controls.Add(new Label { Text = "Filesystem:", AutoSize = true, Margin = new Padding(0, 6, 8, 6) }, 0, 0);
cmbFilesystem = new ComboBox { DropDownStyle = ComboBoxStyle.DropDownList, Width = 160 };
cmbFilesystem.Items.AddRange(new object[] { "ntfs", "fat32", "exfat" });
cmbFilesystem.SelectedIndex = 0;
layout.Controls.Add(cmbFilesystem, 1, 0);
// Locale
layout.Controls.Add(new Label { Text = "Locale:", AutoSize = true, Margin = new Padding(0, 6, 8, 6) }, 0, 1);
cmbLocale = new ComboBox { DropDownStyle = ComboBoxStyle.DropDown, Width = 160 };
cmbLocale.Items.AddRange(new object[] { "en-US", "de-DE", "fr-FR", "it-IT", "es-ES" });
if (!string.IsNullOrEmpty(defaultLocale) && !cmbLocale.Items.Contains(defaultLocale))
cmbLocale.Items.Insert(0, defaultLocale);
cmbLocale.Text = string.IsNullOrEmpty(defaultLocale) ? "en-US" : defaultLocale;
layout.Controls.Add(cmbLocale, 1, 1);
// Extra devices
layout.Controls.Add(new Label { Text = "List extra devices (-x):", AutoSize = true, Margin = new Padding(0, 6, 8, 6) }, 0, 2);
chkExtra = new CheckBox { Checked = false, AutoSize = true };
layout.Controls.Add(chkExtra, 1, 2);
// Wait
layout.Controls.Add(new Label { Text = "Wait (-w) (tens of seconds):", AutoSize = true, Margin = new Padding(0, 6, 8, 6) }, 0, 3);
numWait = new NumericUpDown { Minimum = 0, Maximum = 120, Value = 0, Width = 80 };
layout.Controls.Add(numWait, 1, 3);
// Buttons
var panelButtons = new FlowLayoutPanel { FlowDirection = FlowDirection.RightToLeft, AutoSize = true, Dock = DockStyle.Fill, Margin = new Padding(0, 12, 0, 0) };
btnOk = new Button { Text = "OK", DialogResult = DialogResult.OK, AutoSize = true };
btnCancel = new Button { Text = "Cancel", DialogResult = DialogResult.Cancel, AutoSize = true, Margin = new Padding(6, 0, 0, 0) };
panelButtons.Controls.Add(btnOk);
panelButtons.Controls.Add(btnCancel);
layout.Controls.Add(panelButtons, 0, 4);
layout.SetColumnSpan(panelButtons, 2);
Controls.Add(layout);
AcceptButton = btnOk;
CancelButton = btnCancel;
}
}
}
}
@@ -0,0 +1,56 @@
using System.IO;
using System.Windows.Forms;
namespace Flyoobe
{
// Launches setup.exe from mounted ISO without parameters.
public sealed class RunSetupFromIsoProvider : IInstallProvider
{
public string Id => "setupfromiso";
public string DisplayName => "Run Windows Setup from ISO (full wizard)";
public string HomepageUrl => null;
public string DirectDownloadUrl => null;
public string[] ExactExeNames => new[] { "setup.exe" };
public string[] WildcardExePatterns => System.Array.Empty<string>();
public bool TypicallyNeedsIso => true;
public bool IsExternalTool => false;
public string Hint =>
"Opens the full Windows Setup wizard from a mounted ISO. " +
"You can choose between Upgrade or Clean install and set partitions manually. " +
"Recommended if you want complete control over the installation process.";
public string ShowOptionsAndBuildArgs(IWin32Window owner, LastSelections last)
{
var setup = FindSetupExeOnMountedDrives();
if (setup == null)
{
MessageBox.Show(owner, "No mounted Windows ISO with 'setup.exe' found.",
"Setup missing", MessageBoxButtons.OK, MessageBoxIcon.Information);
return null;
}
if (!ToolHelpers.Confirm(owner, "Run setup.exe from the mounted ISO?"))
return null;
ToolHelpers.Run(setup, "", asAdmin: true);
return null;
}
private static string FindSetupExeOnMountedDrives()
{
try
{
foreach (var di in DriveInfo.GetDrives())
{
if (di.DriveType == DriveType.CDRom || di.DriveType == DriveType.Removable || di.DriveType == DriveType.Fixed)
{
var p = Path.Combine(di.Name, "setup.exe");
if (File.Exists(p)) return p;
}
}
}
catch { }
return null;
}
}
}
+121
View File
@@ -0,0 +1,121 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flyoobe
{
internal static class ToolHelpers
{
/// <summary>Try last path, app base, CWD, then PATH (wildcards allowed).</summary>
public static string ResolveToolPath(string lastPath, string[] exactFileNames, string[] patterns)
{
try
{
if (!string.IsNullOrEmpty(lastPath) && File.Exists(lastPath)) return lastPath;
var baseDir = AppDomain.CurrentDomain.BaseDirectory;
var cwd = Environment.CurrentDirectory;
// exact files in base/cwd
if (exactFileNames != null)
{
foreach (var f in exactFileNames)
{
var p1 = Path.Combine(baseDir, f); if (File.Exists(p1)) return p1;
var p2 = Path.Combine(cwd, f); if (File.Exists(p2)) return p2;
}
}
// wildcards in base/cwd
if (patterns != null)
{
foreach (var pat in patterns)
{
var m1 = SafeGetFiles(baseDir, pat); if (m1?.Length > 0) return m1[0];
var m2 = SafeGetFiles(cwd, pat); if (m2?.Length > 0) return m2[0];
}
}
// PATH dirs (wildcards)
var env = Environment.GetEnvironmentVariable("PATH");
if (!string.IsNullOrEmpty(env) && patterns != null)
{
foreach (var dir in env.Split(Path.PathSeparator))
{
foreach (var pat in patterns)
{
var m = SafeGetFiles(dir, pat); if (m?.Length > 0) return m[0];
}
}
}
}
catch { }
return null;
}
private static string[] SafeGetFiles(string dir, string pattern)
{
try { return Directory.GetFiles(dir, pattern); } catch { return null; }
}
public static bool Confirm(IWin32Window owner, string msg)
=> MessageBox.Show(owner, msg, "Confirm", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK;
public static bool Run(string file, string args, bool asAdmin)
{
try
{
var psi = new ProcessStartInfo
{
FileName = file,
Arguments = args ?? "",
UseShellExecute = true
};
if (asAdmin) psi.Verb = "runas";
Process.Start(psi);
return true;
}
catch (Exception ex)
{
MessageBox.Show("Start failed:\n" + file + " " + args + "\n\n" + ex.Message, "Error",
MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
public static void OpenUri(string uri)
{
try { Process.Start(new ProcessStartInfo(uri) { UseShellExecute = true }); }
catch (Exception ex) { MessageBox.Show("Could not open link: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); }
}
public static async Task<bool> DownloadAsync(IWin32Window owner, string url, string defaultFileName)
{
using (var sfd = new SaveFileDialog { FileName = defaultFileName, Filter = "Programs (*.exe)|*.exe|All files (*.*)|*.*" })
{
if (sfd.ShowDialog(owner) != DialogResult.OK) return false;
try
{
try { ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12; } catch { }
using (var wc = new WebClient())
{
Cursor.Current = Cursors.WaitCursor;
await wc.DownloadFileTaskAsync(new Uri(url), sfd.FileName);
}
MessageBox.Show("Download complete: " + sfd.FileName, "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
return true;
}
catch (Exception ex)
{
MessageBox.Show("Download failed: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
finally { Cursor.Current = Cursors.Default; }
}
}
}
}
+29
View File
@@ -0,0 +1,29 @@
using System.Windows.Forms;
namespace Flyoobe
{
public sealed class VentoyProvider : IInstallProvider
{
public string Id => "ventoy";
public string DisplayName => "Ventoy";
public string HomepageUrl => "https://www.ventoy.net/en/download.html";
public string DirectDownloadUrl => null; // Ventoy ships as ZIP/installer, no stable EXE direct link
public string[] ExactExeNames => new[] { "Ventoy2Disk.exe" };
public string[] WildcardExePatterns => new[] { "Ventoy*Disk*.exe" };
public bool IsExternalTool => true; // needs browsing/resolving
public bool TypicallyNeedsIso => false;
// Custom hint for the UI
public string Hint =>
"Ventoy creates a USB drive where you can later copy multiple ISO files. " +
"You don't need to select an ISO during setup.";
// Add advanced CLI support!?
public string ShowOptionsAndBuildArgs(IWin32Window owner, LastSelections last)
{
// Ventoy doesn't really use CLI args for normal installation.
// Just launch the GUI and let the user configure inside.
return string.Empty;
}
}
}
+85
View File
@@ -0,0 +1,85 @@
namespace Flyoobe
{
partial class LogForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.richLog = new System.Windows.Forms.RichTextBox();
this.panelLogger = new System.Windows.Forms.Panel();
this.panelLogger.SuspendLayout();
this.SuspendLayout();
//
// richLog
//
this.richLog.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.richLog.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(248)))), ((int)(((byte)(248)))), ((int)(((byte)(248)))));
this.richLog.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.richLog.Font = new System.Drawing.Font("Cascadia Code", 8.75F);
this.richLog.Location = new System.Drawing.Point(14, 14);
this.richLog.Name = "richLog";
this.richLog.Size = new System.Drawing.Size(608, 290);
this.richLog.TabIndex = 0;
this.richLog.Text = "";
//
// panelLogger
//
this.panelLogger.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.panelLogger.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(252)))), ((int)(((byte)(247)))), ((int)(((byte)(242)))));
this.panelLogger.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.panelLogger.Controls.Add(this.richLog);
this.panelLogger.Location = new System.Drawing.Point(12, 12);
this.panelLogger.Name = "panelLogger";
this.panelLogger.Size = new System.Drawing.Size(637, 319);
this.panelLogger.TabIndex = 1;
//
// LogForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(232)))), ((int)(((byte)(232)))), ((int)(((byte)(232)))));
this.ClientSize = new System.Drawing.Size(661, 343);
this.Controls.Add(this.panelLogger);
this.Name = "LogForm";
this.ShowIcon = false;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Notifications";
this.panelLogger.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.RichTextBox richLog;
private System.Windows.Forms.Panel panelLogger;
}
}
+14
View File
@@ -0,0 +1,14 @@
using System.Windows.Forms;
namespace Flyoobe
{
public partial class LogForm : Form
{
public LogForm(string logText)
{
InitializeComponent();
richLog.Text = logText;
richLog.SelectionStart = richLog.Text.Length; // Scroll to the end of the log
}
}
}
+120
View File
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+294
View File
@@ -0,0 +1,294 @@
namespace Flyoobe
{
partial class MainForm
{
/// <summary>
/// Erforderliche Designervariable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Verwendete Ressourcen bereinigen.
/// </summary>
/// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Vom Windows Form-Designer generierter Code
/// <summary>
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
/// </summary>
private void InitializeComponent()
{
this.panelControls = new System.Windows.Forms.Panel();
this.linkHome = new System.Windows.Forms.LinkLabel();
this.linkSubHeader = new System.Windows.Forms.LinkLabel();
this.btnNotification = new System.Windows.Forms.Button();
this.panelHost = new System.Windows.Forms.Panel();
this.treeNavigation = new System.Windows.Forms.TreeView();
this.btnRefresh = new System.Windows.Forms.Button();
this.btnToolSpot = new System.Windows.Forms.Button();
this.panelContainer = new System.Windows.Forms.Panel();
this.lblHeader = new System.Windows.Forms.Label();
this.btnAbout = new System.Windows.Forms.Button();
this.btnAskCopilot = new System.Windows.Forms.Button();
this.panelControls.SuspendLayout();
this.panelContainer.SuspendLayout();
this.SuspendLayout();
//
// panelControls
//
this.panelControls.AutoScroll = true;
this.panelControls.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(252)))), ((int)(((byte)(247)))), ((int)(((byte)(242)))));
this.panelControls.Controls.Add(this.linkHome);
this.panelControls.Controls.Add(this.linkSubHeader);
this.panelControls.Controls.Add(this.btnNotification);
this.panelControls.Controls.Add(this.panelHost);
this.panelControls.Controls.Add(this.treeNavigation);
this.panelControls.Controls.Add(this.btnRefresh);
this.panelControls.Dock = System.Windows.Forms.DockStyle.Fill;
this.panelControls.Location = new System.Drawing.Point(0, 0);
this.panelControls.Name = "panelControls";
this.panelControls.Size = new System.Drawing.Size(883, 503);
this.panelControls.TabIndex = 3;
//
// linkHome
//
this.linkHome.ActiveLinkColor = System.Drawing.Color.DeepPink;
this.linkHome.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.linkHome.AutoSize = true;
this.linkHome.Font = new System.Drawing.Font("Segoe UI Variable Small Semibol", 11.5F, System.Drawing.FontStyle.Bold);
this.linkHome.LinkBehavior = System.Windows.Forms.LinkBehavior.HoverUnderline;
this.linkHome.LinkColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(138)))), ((int)(((byte)(211)))));
this.linkHome.Location = new System.Drawing.Point(695, 35);
this.linkHome.Name = "linkHome";
this.linkHome.Size = new System.Drawing.Size(48, 26);
this.linkHome.TabIndex = 338;
this.linkHome.TabStop = true;
this.linkHome.Text = "Setup";
this.linkHome.UseCompatibleTextRendering = true;
this.linkHome.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkHome_LinkClicked);
//
// linkSubHeader
//
this.linkSubHeader.ActiveLinkColor = System.Drawing.Color.Magenta;
this.linkSubHeader.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.linkSubHeader.AutoEllipsis = true;
this.linkSubHeader.Font = new System.Drawing.Font("Segoe UI Variable Small Semilig", 8.5F);
this.linkSubHeader.LinkBehavior = System.Windows.Forms.LinkBehavior.NeverUnderline;
this.linkSubHeader.LinkColor = System.Drawing.Color.Black;
this.linkSubHeader.Location = new System.Drawing.Point(12, 4);
this.linkSubHeader.Name = "linkSubHeader";
this.linkSubHeader.Size = new System.Drawing.Size(677, 16);
this.linkSubHeader.TabIndex = 334;
this.linkSubHeader.TabStop = true;
this.linkSubHeader.Text = "...";
//
// btnNotification
//
this.btnNotification.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnNotification.AutoEllipsis = true;
this.btnNotification.FlatAppearance.BorderSize = 0;
this.btnNotification.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(215)))), ((int)(((byte)(235)))), ((int)(((byte)(255)))));
this.btnNotification.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(215)))), ((int)(((byte)(235)))), ((int)(((byte)(255)))));
this.btnNotification.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnNotification.Font = new System.Drawing.Font("Segoe UI Variable Small Semilig", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.btnNotification.Location = new System.Drawing.Point(748, 34);
this.btnNotification.Name = "btnNotification";
this.btnNotification.Size = new System.Drawing.Size(123, 22);
this.btnNotification.TabIndex = 337;
this.btnNotification.Text = "Notifications";
this.btnNotification.TextAlign = System.Drawing.ContentAlignment.TopCenter;
this.btnNotification.UseVisualStyleBackColor = true;
this.btnNotification.Visible = false;
this.btnNotification.Click += new System.EventHandler(this.btnNotification_Click);
//
// panelHost
//
this.panelHost.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.panelHost.Location = new System.Drawing.Point(7, 22);
this.panelHost.Name = "panelHost";
this.panelHost.Size = new System.Drawing.Size(682, 468);
this.panelHost.TabIndex = 333;
//
// treeNavigation
//
this.treeNavigation.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Right)));
this.treeNavigation.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(252)))), ((int)(((byte)(247)))), ((int)(((byte)(242)))));
this.treeNavigation.BorderStyle = System.Windows.Forms.BorderStyle.None;
this.treeNavigation.Font = new System.Drawing.Font("Segoe UI Variable Text", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.treeNavigation.HideSelection = false;
this.treeNavigation.HotTracking = true;
this.treeNavigation.Location = new System.Drawing.Point(695, 75);
this.treeNavigation.Name = "treeNavigation";
this.treeNavigation.Scrollable = false;
this.treeNavigation.ShowLines = false;
this.treeNavigation.ShowNodeToolTips = true;
this.treeNavigation.ShowPlusMinus = false;
this.treeNavigation.ShowRootLines = false;
this.treeNavigation.Size = new System.Drawing.Size(186, 416);
this.treeNavigation.TabIndex = 3;
this.treeNavigation.TabStop = false;
//
// btnRefresh
//
this.btnRefresh.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnRefresh.AutoSize = true;
this.btnRefresh.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(204)))), ((int)(((byte)(222)))), ((int)(((byte)(246)))));
this.btnRefresh.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(138)))), ((int)(((byte)(211)))));
this.btnRefresh.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(215)))), ((int)(((byte)(235)))), ((int)(((byte)(255)))));
this.btnRefresh.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(215)))), ((int)(((byte)(235)))), ((int)(((byte)(255)))));
this.btnRefresh.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnRefresh.Font = new System.Drawing.Font("Segoe MDL2 Assets", 8.25F);
this.btnRefresh.ForeColor = System.Drawing.Color.Black;
this.btnRefresh.Location = new System.Drawing.Point(858, 0);
this.btnRefresh.Name = "btnRefresh";
this.btnRefresh.Size = new System.Drawing.Size(25, 23);
this.btnRefresh.TabIndex = 332;
this.btnRefresh.TabStop = false;
this.btnRefresh.Text = "...";
this.btnRefresh.UseVisualStyleBackColor = false;
this.btnRefresh.Click += new System.EventHandler(this.btnRefresh_Click);
//
// btnToolSpot
//
this.btnToolSpot.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
this.btnToolSpot.AutoSize = true;
this.btnToolSpot.BackColor = System.Drawing.Color.Transparent;
this.btnToolSpot.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(32)))), ((int)(((byte)(138)))), ((int)(((byte)(211)))));
this.btnToolSpot.FlatAppearance.BorderSize = 0;
this.btnToolSpot.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(215)))), ((int)(((byte)(235)))), ((int)(((byte)(255)))));
this.btnToolSpot.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(215)))), ((int)(((byte)(235)))), ((int)(((byte)(255)))));
this.btnToolSpot.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnToolSpot.Font = new System.Drawing.Font("Segoe MDL2 Assets", 10.25F);
this.btnToolSpot.ForeColor = System.Drawing.Color.Black;
this.btnToolSpot.Location = new System.Drawing.Point(916, 1);
this.btnToolSpot.Name = "btnToolSpot";
this.btnToolSpot.Size = new System.Drawing.Size(26, 25);
this.btnToolSpot.TabIndex = 338;
this.btnToolSpot.TabStop = false;
this.btnToolSpot.Text = "...";
this.btnToolSpot.UseVisualStyleBackColor = false;
this.btnToolSpot.Click += new System.EventHandler(this.btnToolSpot_Click);
//
// 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.AutoScroll = true;
this.panelContainer.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(247)))), ((int)(((byte)(244)))), ((int)(((byte)(242)))));
this.panelContainer.Controls.Add(this.panelControls);
this.panelContainer.Location = new System.Drawing.Point(23, 32);
this.panelContainer.Name = "panelContainer";
this.panelContainer.Size = new System.Drawing.Size(883, 503);
this.panelContainer.TabIndex = 15;
//
// lblHeader
//
this.lblHeader.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.lblHeader.AutoEllipsis = true;
this.lblHeader.Font = new System.Drawing.Font("Segoe UI Variable Display", 27.75F);
this.lblHeader.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(67)))), ((int)(((byte)(67)))), ((int)(((byte)(67)))));
this.lblHeader.Location = new System.Drawing.Point(38, 2);
this.lblHeader.Name = "lblHeader";
this.lblHeader.Size = new System.Drawing.Size(696, 32);
this.lblHeader.TabIndex = 333;
this.lblHeader.Text = "Flyoobe";
this.lblHeader.UseCompatibleTextRendering = true;
//
// btnAbout
//
this.btnAbout.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnAbout.AutoSize = true;
this.btnAbout.BackColor = System.Drawing.Color.Transparent;
this.btnAbout.FlatAppearance.BorderColor = System.Drawing.Color.Gray;
this.btnAbout.FlatAppearance.BorderSize = 0;
this.btnAbout.FlatAppearance.MouseDownBackColor = System.Drawing.Color.DarkGray;
this.btnAbout.FlatAppearance.MouseOverBackColor = System.Drawing.Color.DarkGray;
this.btnAbout.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnAbout.Font = new System.Drawing.Font("Segoe MDL2 Assets", 10.25F);
this.btnAbout.ForeColor = System.Drawing.Color.Black;
this.btnAbout.Location = new System.Drawing.Point(912, 517);
this.btnAbout.Name = "btnAbout";
this.btnAbout.Size = new System.Drawing.Size(30, 29);
this.btnAbout.TabIndex = 336;
this.btnAbout.Text = "...";
this.btnAbout.UseVisualStyleBackColor = false;
this.btnAbout.Click += new System.EventHandler(this.btnAbout_Click);
//
// btnAskCopilot
//
this.btnAskCopilot.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnAskCopilot.AutoSize = true;
this.btnAskCopilot.BackColor = System.Drawing.Color.Transparent;
this.btnAskCopilot.FlatAppearance.BorderColor = System.Drawing.Color.Gray;
this.btnAskCopilot.FlatAppearance.BorderSize = 0;
this.btnAskCopilot.FlatAppearance.MouseDownBackColor = System.Drawing.Color.DarkGray;
this.btnAskCopilot.FlatAppearance.MouseOverBackColor = System.Drawing.Color.DarkGray;
this.btnAskCopilot.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.btnAskCopilot.Font = new System.Drawing.Font("Segoe MDL2 Assets", 9.25F);
this.btnAskCopilot.ForeColor = System.Drawing.Color.Black;
this.btnAskCopilot.Location = new System.Drawing.Point(912, 477);
this.btnAskCopilot.Name = "btnAskCopilot";
this.btnAskCopilot.Size = new System.Drawing.Size(30, 29);
this.btnAskCopilot.TabIndex = 335;
this.btnAskCopilot.UseVisualStyleBackColor = false;
this.btnAskCopilot.Click += new System.EventHandler(this.btnAskCopilot_Click);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(154)))), ((int)(((byte)(154)))), ((int)(((byte)(154)))));
this.ClientSize = new System.Drawing.Size(945, 565);
this.Controls.Add(this.btnToolSpot);
this.Controls.Add(this.btnAbout);
this.Controls.Add(this.btnAskCopilot);
this.Controls.Add(this.panelContainer);
this.Controls.Add(this.lblHeader);
this.Name = "MainForm";
this.ShowIcon = false;
this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Flyoobe";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainForm_FormClosing);
this.Load += new System.EventHandler(this.MainForm_Load);
this.LocationChanged += new System.EventHandler(this.MainForm_LocationChanged);
this.panelControls.ResumeLayout(false);
this.panelControls.PerformLayout();
this.panelContainer.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Panel panelControls;
private System.Windows.Forms.Panel panelContainer;
private System.Windows.Forms.Button btnRefresh;
private System.Windows.Forms.Label lblHeader;
private System.Windows.Forms.Button btnAskCopilot;
private System.Windows.Forms.Button btnAbout;
private System.Windows.Forms.Button btnNotification;
private System.Windows.Forms.TreeView treeNavigation;
private System.Windows.Forms.Panel panelHost;
private System.Windows.Forms.LinkLabel linkSubHeader;
private System.Windows.Forms.Button btnToolSpot;
private System.Windows.Forms.LinkLabel linkHome;
}
}
+205
View File
@@ -0,0 +1,205 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Windows.Forms;
namespace Flyoobe
{
public partial class MainForm : Form
{
private ViewNavigator _navigator;
private AboutForm aboutForm;
private int _notificationCount = 0;
public MainForm()
{
InitializeComponent();
Logger.OnNotificationLogged += Logger_OnNotificationLogged; // Subscribe to log events
}
private void MainForm_Load(object sender, EventArgs e)
{
InitializeButtons();
_navigator = new ViewNavigator(panelHost, treeNavigation, title =>
{
// lblHeader.Text = title;
linkSubHeader.Text = $"Running - {title} - {Program.GetAppVersion()}";
});
// Register views
_navigator.RegisterView("Home", () => new HomeControlView(_navigator));
_navigator.RegisterView("Upgrade", () => new UpgradeControlView());
_navigator.RegisterView("Install only", () => new InstallControlView());
_navigator.RegisterView("Device", () => new DeviceControlView());
_navigator.RegisterView("Personalization", () => new PersonalizationControlView());
_navigator.RegisterView("Browser", () => new DefaultsControlView());
_navigator.RegisterView("Network", () => new NetworkControlView());
_navigator.RegisterView("Account", () => new AccountControlView());
_navigator.RegisterView("Apps", () => new AppsControlView());
_navigator.RegisterView("Experience", () => new ExperienceControlView());
_navigator.RegisterView("Installer", () => new InstallerControlView());
_navigator.RegisterView("Updates", () => new UpdatesControlView());
_navigator.RegisterView("Extensions", () => new ToolHub.ToolHubControlView());
// Load OOBE navigation with system status
_navigator.LoadDefaultNavigation();
// Show initial view
_navigator.ShowView("Home");
}
private void InitializeButtons()
{
CopilotHelper.SetupCopilotButton(btnAskCopilot, 20);
btnAbout.Text = "\uE946";
btnRefresh.Text = "\uE72C";
btnToolSpot.Text = "\uE721";
}
private void btnAbout_Click(object sender, EventArgs e)
{
if (aboutForm == null || aboutForm.IsDisposed)
{
aboutForm = new AboutForm();
aboutForm.StartPosition = FormStartPosition.Manual;
aboutForm.Owner = this;
aboutForm.Show();
}
PositionAboutForm();
}
private void PositionAboutForm()
{
if (aboutForm != null && !aboutForm.IsDisposed)
{
int x = this.Left + (this.Width - aboutForm.Width) / 2;
int y = this.Top + (this.Height - aboutForm.Height) / 2;
aboutForm.Location = new Point(x, y);
}
}
private void MainForm_LocationChanged(object sender, EventArgs e)
{
PositionAboutForm();
}
private void btnAskCopilot_Click(object sender, EventArgs e)
{
CopilotHelper.LaunchCopilot();
}
/// <summary>
/// Handles log notifications (Warnings/Errors).
/// Increments the notification counter and updates the notification button text.
/// </summary>
private void Logger_OnNotificationLogged(string message, LogLevel level)
{
_notificationCount++;
UpdateNotificationButton();
}
/// <summary>
/// Updates the notification button text based on the current notification count.
/// Ensures thread-safe UI updates.
/// </summary>
private void UpdateNotificationButton()
{
if (InvokeRequired)
{
Invoke(new Action(UpdateNotificationButton));
return;
}
if (_notificationCount > 0)
{
btnNotification.Text = $"Notifications ({_notificationCount})";
btnNotification.ForeColor = Color.Blue;
}
else
{
btnNotification.Text = "No new notifications";
btnNotification.ForeColor = Color.Black;
}
btnNotification.Visible = true;
}
/// <summary>
/// Opens the LogForm to display the complete log.
/// Resets the notification count afterwards.
/// </summary>
private void btnNotification_Click(object sender, EventArgs e)
{
new LogForm(Logger.GetLog()).ShowDialog(this);
// Reset notification count after viewing log
_notificationCount = 0;
UpdateNotificationButton();
}
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (!DonationHelper.HasDonated())
{
DonationHelper.ShowDonationPrompt();
}
}
private void btnRefresh_Click(object sender, EventArgs e)
{
// If the current view implements IView, trigger its RefreshView method
if (_navigator.CurrentView is IView view)
{
view.RefreshView();
btnNotification.Visible = false; // Hide notification button after refresh
}
}
private void btnToolSpot_Click(object sender, EventArgs e)
{
// Path: <AppBase>\app\Foobe.Toolspot.exe
string exePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "app", "spot.exe");
if (!File.Exists(exePath))
{
MessageBox.Show("Toolspot not found:\n" + exePath, "Flyoobe",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
try
{
// Make MainForm dim (semi-transparent)
this.Opacity = 0.85;
var proc = new Process();
proc.StartInfo.FileName = exePath;
proc.EnableRaisingEvents = true;
proc.Exited += (s, ev) =>
{
// Restore opacity on UI thread
if (this.IsHandleCreated)
{
this.BeginInvoke((Action)(() => this.Opacity = 1.0));
}
};
proc.Start();
}
catch (Exception ex)
{
this.Opacity = 1.0; // safety reset
MessageBox.Show("Could not start Toolspot:\n" + ex.Message, "Flyoobe",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void linkHome_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
{
_navigator.ShowView("Home");
}
}
}
+120
View File
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+33
View File
@@ -0,0 +1,33 @@
using System;
using System.Reflection;
using System.Windows.Forms;
namespace Flyoobe
{
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
private static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainForm());
}
/// <summary>
/// Retrieves the version of the app
/// </summary>
/// <returns>The application version in the format "major.minor.build"</returns>
public static string GetAppVersion()
{
// Get the version of the current executing assembly
Version version = Assembly.GetExecutingAssembly().GetName().Version;
// Return the version in the format "major.minor.build"
return $"{version.Major}.{version.Minor}.{version.Build}";
}
}
}
+32
View File
@@ -0,0 +1,32 @@
using System.Reflection;
using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die einer Assembly zugeordnet sind.
[assembly: AssemblyTitle("Flyoobe")]
[assembly: AssemblyDescription("Flyoobe")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("A Belim app creation")]
[assembly: AssemblyProduct("Flyoobe")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("Builtbybel")]
[assembly: AssemblyCulture("")]
// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
[assembly: ComVisible(false)]
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
[assembly: Guid("50ca0d4d-45ad-4e03-bfc5-64fff4cda36c")]
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
//
// Hauptversion
// Nebenversion
// Buildnummer
// Revision
//
[assembly: AssemblyVersion("1.6.246")]
[assembly: AssemblyFileVersion("1.6.246")]
+73
View File
@@ -0,0 +1,73 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion:4.0.30319.42000
//
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Flyoobe.Properties {
using System;
/// <summary>
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
/// </summary>
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Flyoobe.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap.
/// </summary>
internal static System.Drawing.Bitmap assetCopilot {
get {
object obj = ResourceManager.GetObject("assetCopilot", resourceCulture);
return ((System.Drawing.Bitmap)(obj));
}
}
}
}
+124
View File
@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Windows.Forms" name="System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
<data name="assetCopilot" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>..\assetCopilot.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</value>
</data>
</root>
+26
View File
@@ -0,0 +1,26 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion:4.0.30319.42000
//
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Flyoobe.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.14.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}
+7
View File
@@ -0,0 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>
+523
View File
@@ -0,0 +1,523 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Net.WebRequestMethods;
namespace Flyoobe
{
public class IsoHandler
{
private static readonly HttpClient httpClient = new HttpClient();
private readonly Action<string> _updateStatus;
public IsoHandler(Action<string> updateStatus)
{
_updateStatus = updateStatus;
}
public async Task HandleIso(string isoPath, bool experimentalEnabled)
{
try
{
// Block Win10 ISOs
string isoFileName = Path.GetFileName(isoPath);
if (Regex.IsMatch(isoFileName, @"(?i)(win10|windows\s*10)"))
{
_updateStatus("Error: Windows 10 ISOs are not supported.");
MessageBox.Show("Windows 10 ISOs are not supported. Please use a Windows 11 ISO.",
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
_updateStatus("Mounting the ISO...");
// Ensure the ISO path is properly quoted
string quotedIsoPath = $"\"{isoPath}\"";
// Pass the quoted path to ExecutePowerShellCommand
string driveLetter = await MountIsoAndGetDriveLetter(isoPath);
if (string.IsNullOrEmpty(driveLetter))
{
HandleException(new InvalidOperationException("ISO mounting returned no drive letter."),
"Failed to mount the ISO. Please try again.");
return;
}
_updateStatus("ISO mounted successfully! Let's get this Windows 11 ready!");
string setupPath = Path.Combine(driveLetter, "sources", "setupprep.exe");
if (System.IO.File.Exists(setupPath))
{
await RunSetupWithAdminRights(setupPath, experimentalEnabled);
}
else
{
HandleException(new FileNotFoundException($"Setup file not found in {driveLetter}."),
"The setup file could not be found on the mounted ISO.");
}
}
catch (Exception ex)
{
_updateStatus($"Oops! Something went wrong: {ex.Message}");
HandleException(ex, "An error occurred during ISO processing.");
}
}
private async Task<string> MountIsoAndGetDriveLetter(string isoPath)
{
try
{
_updateStatus("Mounting ISO...");
string script = $@"
try {{
$iso = Mount-DiskImage -ImagePath '{isoPath}' -PassThru -ErrorAction Stop
$volumes = Get-Volume -DiskImage $iso -ErrorAction Stop
# get drive letter, but only if one exists
$driveLetter = ($volumes | Where-Object {{ $_.DriveLetter }} | Select-Object -First 1).DriveLetter
if (-not $driveLetter) {{
throw 'iso mounted but no drive letter was assigned.'
}}
# return the drive letter (e.g. 'D:')
$driveLetter
}} catch {{
Write-Error $_.Exception.Message
exit 1 # indicate an error
}}
";
using (var process = new Process())
{
process.StartInfo.FileName = "powershell.exe";
process.StartInfo.Arguments = $"-NoProfile -ExecutionPolicy Bypass -Command \"{script}\"";
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.Start();
string output = await process.StandardOutput.ReadToEndAsync();
string error = await process.StandardError.ReadToEndAsync();
await process.WaitForExitAsync();
if (process.ExitCode != 0 || !string.IsNullOrWhiteSpace(error))
{
_updateStatus($"PowerShell error during mount: {error.Trim()}");
Logger.Log($"PowerShell error during mount: {error.Trim()}", LogLevel.Error);
MessageBox.Show($"PowerShell error during mount: {error.Trim()}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return null;
}
string driveLetter = output.Trim();
if (!string.IsNullOrWhiteSpace(driveLetter))
{
// Ensure the drive letter format is correct (e.g., "D:")
if (!driveLetter.EndsWith(":") && driveLetter.Length == 1)
{
driveLetter += ":";
}
_updateStatus($"ISO mounted successfully at {driveLetter}\\");
return $"{driveLetter}\\";
}
else
{
_updateStatus("Failed to retrieve drive letter after mounting ISO. Output was empty.");
Logger.Log("Failed to retrieve drive letter after mounting ISO. Output was empty.", LogLevel.Error);
return null;
}
}
}
catch (Exception ex)
{
_updateStatus("Exception during mounting: " + ex.Message);
HandleException(ex, "An error occurred while mounting the ISO.");
return null;
}
}
private async Task RunSetupWithAdminRights(string setupPath, bool experimentalEnabled)
{
try
{
_updateStatus("Starting the setup process with elevated privileges...");
// Default argument
string arguments = "/Product Server";
// If experimental mode is enabled, append additional setup parameters
if (experimentalEnabled)
{
arguments += " /Compat IgnoreWarning /MigrateDrivers All";
}
var startInfo = new ProcessStartInfo
{
FileName = "powershell.exe",
Arguments = $"-NoProfile -ExecutionPolicy Bypass -Command \"Start-Process '{setupPath}' -ArgumentList '{arguments}' -Verb runas\"",
Verb = "runas",
UseShellExecute = true,
CreateNoWindow = false
};
_updateStatus("Almost there! We're getting the setup ready...");
using (var process = Process.Start(startInfo))
{
if (process != null)
{
await process.WaitForExitAsync();
}
}
// Final status message
string finalStatus = "You're ready to install Windows 11 on unsupported hardware! Ignore the 'Windows Server' prompt; you're all set!";
if (experimentalEnabled)
{
finalStatus += " (Advanced mode enabled: Compatibility checks bypassed)";
}
_updateStatus(finalStatus);
MessageBox.Show("Windows 11 installation can now proceed. Please follow the instructions in the setup window.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
_updateStatus($"Error: {ex.Message}");
MessageBox.Show($"Error: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// Create unattend.xml file in the sources\$OEM$\$$\Panther directory
/// </summary>
/// <param name="usbDrive">The USB drive where the unattend.xml will be created.</param>
public void CreateUnattendXml(string usbDrive)
{
string unattendDir = Path.Combine(usbDrive, "sources", "$OEM$", "$$", "Panther");
Directory.CreateDirectory(unattendDir); // Create the directory if it doesn't exist
string unattendPath = Path.Combine(unattendDir, "unattend.xml");
// Check if the file already exists
if (!System.IO.File.Exists(unattendPath))
{
// Create the unattend.xml content
string xmlContent = @"<unattend xmlns='urn:schemas-microsoft-com:unattend'>
<settings pass='disabled'>
<component xmlns:wcm='http://schemas.microsoft.com/WMIConfig/2002/State' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' name='Microsoft-Windows-Setup' processorArchitecture='amd64' language='neutral' publicKeyToken='31bf3856ad364e35' versionScope='nonSxS'>
<UserData>
<ProductKey>
<Key/>
</ProductKey>
</UserData>
<RunSynchronous>
<RunSynchronousCommand wcm:action='add'>
<Order>1</Order>
<Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassTPMCheck /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action='add'>
<Order>2</Order>
<Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassSecureBootCheck /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action='add'>
<Order>3</Order>
<Path>reg add HKLM\SYSTEM\Setup\LabConfig /v BypassRAMCheck /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
</RunSynchronous>
</component>
</settings>
<settings pass='specialize'>
<component xmlns:wcm='http://schemas.microsoft.com/WMIConfig/2002/State' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' name='Microsoft-Windows-Deployment' processorArchitecture='amd64' language='neutral' publicKeyToken='31bf3856ad364e35' versionScope='nonSxS'>
<RunSynchronous>
<RunSynchronousCommand wcm:action='add'>
<Order>1</Order>
<Path>reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE /v BypassNRO /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
</RunSynchronous>
</component>
</settings>
</unattend>";
System.IO.File.WriteAllText(unattendPath, xmlContent);
_updateStatus("Created unattend.xml in the sources\\$OEM$\\$$\\Panther directory.");
}
else
{
_updateStatus("unattend.xml already exists in the sources\\$OEM$\\$$\\Panther directory.");
// Display a message box to inform the user
MessageBox.Show("The patch has already been applied. The 'unattend.xml' file already exists in the specified directory.",
"Patch Already Applied",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
}
/// <summary>
/// Handles the event for the compatibility patch.
/// </summary>
public void HandleCompatibilityPatch()
{
using (var folderDialog = new FolderBrowserDialog())
{
/* Select the USB drive containing your Windows 11 installation files. " +
"This feature adds a compatibility patch to bypass certain system requirements. " +
"Compatible with drives prepared by any tool, including Rufus. Ensure the drive is ready! */
folderDialog.Description = "Select the USB drive containing your Windows 11 installation files.\n" +
"This feature adds a compatibility patch to bypass certain system requirements.\n" +
"Compatible with drives prepared by any tool, including Rufus. Ensure the drive is ready!";
if (folderDialog.ShowDialog() == DialogResult.OK)
{
string selectedPath = folderDialog.SelectedPath;
var driveInfo = new DriveInfo(Path.GetPathRoot(selectedPath));
if (driveInfo.DriveType == DriveType.Removable && driveInfo.IsReady)
{
if (MessageBox.Show("This will apply compatibility bypass settings on the selected USB drive. Continue ?",
"Apply Bypass Patch", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
{
try
{
CreateUnattendXml(selectedPath);
MessageBox.Show("Bypass patch applied successfully!", "Apply Bypass Patch", MessageBoxButtons.OK, MessageBoxIcon.Information);
Logger.Log("Bypass patch applied successfully!");
}
catch (Exception ex)
{
Logger.Log($"{"Failed to apply bypass patch:"} {ex.Message}", LogLevel.Error);
}
}
else
{
Logger.Log("Bypass patch canceled by user.", LogLevel.Warning);
}
}
else
{
MessageBox.Show("The selected path is not a removable drive. Please select a USB drive.", "Invalid Selection", MessageBoxButtons.OK, MessageBoxIcon.Error);
Logger.Log("User attempted to select a non-removable drive.", LogLevel.Error);
}
}
else
{
Logger.Log("No USB drive selected for patching.", LogLevel.Error);
}
}
}
/// <summary>
/// Handles the process of downloading the Media Creation Tool and optionally running it.
/// </summary>
public void HandleMediaCreationToolDownload()
{
var infoResult = MessageBox.Show(
"With the Media Creation Tool, you can upgrade your PC or create an ISO.\n\nIn the 'Choose which media to use' step, select 'ISO file'.\n\nWould you like to watch a tutorial first?",
"Media Creation Tool",
MessageBoxButtons.YesNo,
MessageBoxIcon.Information);
if (infoResult == DialogResult.Yes)
{
Process.Start("https://www.youtube.com/watch?v=dNl1FHajW9w");
}
using (var saveDialog = new SaveFileDialog())
{
saveDialog.Title = "Save Media Creation Tool";
saveDialog.Filter = "Executable|*.exe";
saveDialog.FileName = "MediaCreationTool.exe";
if (saveDialog.ShowDialog() == DialogResult.OK)
{
using (var client = new WebClient())
{
try
{
client.DownloadFile("https://go.microsoft.com/fwlink/?linkid=2156295", saveDialog.FileName);
MessageBox.Show("Tool downloaded successfully!", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
var run = MessageBox.Show("Do you want to run it now?", "Run Tool", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (run == DialogResult.Yes)
{
Process.Start(saveDialog.FileName);
}
_updateStatus("Media Creation Tool downloaded and optionally launched.");
}
catch (Exception ex)
{
_updateStatus("Failed to download Media Creation Tool: " + ex.Message);
MessageBox.Show("Download failed: " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
Logger.Log($"Failed to download Media Creation Tool: {ex.Message}", LogLevel.Error);
}
}
}
else
{
_updateStatus("Media Creation Tool download canceled.");
}
}
}
/// <summary>
/// Downloads and launches the Fido PowerShell script for advanced ISO selection.
/// </summary>
public void DownloadAndRunFidoScript(string scriptUrl)
{
string tempScript = Path.Combine(Path.GetTempPath(), "Fido.ps1");
using (var client = new WebClient())
{
try
{
client.DownloadFile(scriptUrl, tempScript);
_updateStatus("Fido script downloaded successfully. Launching PowerShell...");
Process.Start(new ProcessStartInfo
{
FileName = "powershell.exe",
Arguments = $"-ExecutionPolicy Bypass -File \"{tempScript}\"",
Verb = "runas",
UseShellExecute = true
});
}
catch (Exception ex)
{
_updateStatus("Error downloading or running Fido script: " + ex.Message);
Logger.Log($"Error downloading or running Fido script: {ex.Message}", LogLevel.Error);
}
}
}
/// <summary>
/// Keep Windows 10 secure until 2026 (Enroll in ESU) using abbodi1406's ConsumerESU scripts.
/// Downloads from GitHub if missing and executes.
/// </summary>
public async void HandleEnrollInESU()
{
string repoBase = "https://raw.githubusercontent.com/abbodi1406/ConsumerESU/master/";
string cmdFile = "Consumer_ESU_Enrollment_run.cmd";
string psFile = "Consumer_ESU_Enrollment.ps1";
string appDir = AppDomain.CurrentDomain.BaseDirectory;
string cmdPath = Path.Combine(appDir, cmdFile);
string psPath = Path.Combine(appDir, psFile);
// Check if scripts exist, otherwise download
if (!System.IO.File.Exists(cmdPath) || !System.IO.File.Exists(psPath))
{
var confirm = MessageBox.Show(
"The ESU enrollment scripts are missing.\n\n" +
"They will now be downloaded directly from GitHub (abbodi1406/ConsumerESU).\n\n" +
"Do you want to continue?",
"Download Scripts",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (confirm != DialogResult.Yes)
return;
using (var wc = new System.Net.WebClient())
{
try
{
if (!System.IO.File.Exists(cmdPath))
await wc.DownloadFileTaskAsync(new Uri(repoBase + cmdFile), cmdPath);
if (!System.IO.File.Exists(psPath))
await wc.DownloadFileTaskAsync(new Uri(repoBase + psFile), psPath);
}
catch (Exception ex)
{
MessageBox.Show("Failed to download ESU scripts:\n" + ex.Message,
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
}
}
var result = MessageBox.Show(
"📦 This will now launch the Consumer ESU Enrollment Tool by abbodi1406.\n\n" +
"✔ Extends Windows 10 support until October 2026\n" +
"✔ Requires Windows 10 22H2 with KB5039299+ (19045.4598+)\n" +
"✔ Requires Microsoft Account + Internet access\n\n" +
"Do you want to continue?",
"Enroll in ESU",
MessageBoxButtons.YesNo,
MessageBoxIcon.Information);
if (result != DialogResult.Yes)
return;
// Start the .cmd (which internally calls the PowerShell)
try
{
Process.Start(new ProcessStartInfo
{
FileName = cmdPath,
Verb = "runas",
UseShellExecute = true
});
}
catch (Exception ex)
{
MessageBox.Show("Failed to run ESU enrollment script:\n" + ex.Message,
"Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
/// <summary>
/// Handle unexpected exceptions by logging the error, updating the status, and optionally launching Copilot for help.
/// </summary>
/// <param name="ex"></param>
/// <param name="userContext"></param>
private void HandleException(Exception ex, string userContext = "An unexpected error occurred.")
{
string fullMessage = $"{userContext}\n\n{ex.Message}\n\nThe error has been copied to your clipboard.";
// Clipboard sicher setzen über STA-Thread
Thread clipboardThread = new Thread(() => Clipboard.SetText(ex.ToString()));
clipboardThread.SetApartmentState(ApartmentState.STA);
clipboardThread.Start();
clipboardThread.Join();
_updateStatus(userContext);
Logger.Log($"{userContext}: {ex}", LogLevel.Error);
var result = MessageBox.Show(
fullMessage + "\n\nWould you like to ask Copilot for help?",
"Something Went Wrong",
MessageBoxButtons.YesNo,
MessageBoxIcon.Error);
if (result == DialogResult.Yes)
{
CopilotHelper.LaunchCopilot();
}
}
}
public static class ProcessExtensions
{
public static async Task WaitForExitAsync(this Process process)
{
var tcs = new TaskCompletionSource<bool>();
process.EnableRaisingEvents = true;
process.Exited += (sender, args) => tcs.TrySetResult(true);
await tcs.Task;
}
}
}
+162
View File
@@ -0,0 +1,162 @@
namespace Flyoobe
{
partial class UpgradeControlView
{
/// <summary>
/// Erforderliche Designervariable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Verwendete Ressourcen bereinigen.
/// </summary>
/// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Vom Komponenten-Designer generierter Code
/// <summary>
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
/// </summary>
private void InitializeComponent()
{
this.panelDragDrop = new System.Windows.Forms.Panel();
this.flowLayoutPanelTiles = new System.Windows.Forms.FlowLayoutPanel();
this.dropdownOptions = new System.Windows.Forms.ComboBox();
this.btnExperience = new System.Windows.Forms.Button();
this.statusLabel = new System.Windows.Forms.Label();
this.chkAdvancedMode = new System.Windows.Forms.CheckBox();
this.panelDragDrop.SuspendLayout();
this.SuspendLayout();
//
// panelDragDrop
//
this.panelDragDrop.AllowDrop = true;
this.panelDragDrop.Anchor = System.Windows.Forms.AnchorStyles.None;
this.panelDragDrop.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(247)))), ((int)(((byte)(244)))), ((int)(((byte)(242)))));
this.panelDragDrop.Controls.Add(this.flowLayoutPanelTiles);
this.panelDragDrop.Controls.Add(this.dropdownOptions);
this.panelDragDrop.Controls.Add(this.btnExperience);
this.panelDragDrop.Controls.Add(this.statusLabel);
this.panelDragDrop.Location = new System.Drawing.Point(71, 46);
this.panelDragDrop.Name = "panelDragDrop";
this.panelDragDrop.Size = new System.Drawing.Size(697, 362);
this.panelDragDrop.TabIndex = 1;
this.panelDragDrop.DragDrop += new System.Windows.Forms.DragEventHandler(this.panelDragDrop_DragDrop);
this.panelDragDrop.DragEnter += new System.Windows.Forms.DragEventHandler(this.panelDragDrop_DragEnter);
this.panelDragDrop.Paint += new System.Windows.Forms.PaintEventHandler(this.panelDragDrop_Paint);
//
// flowLayoutPanelTiles
//
this.flowLayoutPanelTiles.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.flowLayoutPanelTiles.BackColor = System.Drawing.Color.Transparent;
this.flowLayoutPanelTiles.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
this.flowLayoutPanelTiles.Location = new System.Drawing.Point(21, 96);
this.flowLayoutPanelTiles.Name = "flowLayoutPanelTiles";
this.flowLayoutPanelTiles.Size = new System.Drawing.Size(651, 173);
this.flowLayoutPanelTiles.TabIndex = 3;
//
// dropdownOptions
//
this.dropdownOptions.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.dropdownOptions.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(252)))), ((int)(((byte)(247)))), ((int)(((byte)(242)))));
this.dropdownOptions.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.dropdownOptions.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.dropdownOptions.Font = new System.Drawing.Font("Segoe UI Variable Small Semilig", 11.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.dropdownOptions.ForeColor = System.Drawing.Color.Black;
this.dropdownOptions.FormattingEnabled = true;
this.dropdownOptions.Location = new System.Drawing.Point(55, 304);
this.dropdownOptions.Name = "dropdownOptions";
this.dropdownOptions.Size = new System.Drawing.Size(601, 28);
this.dropdownOptions.TabIndex = 507;
this.dropdownOptions.SelectedIndexChanged += new System.EventHandler(this.dropdownOptions_SelectedIndexChanged);
//
// btnExperience
//
this.btnExperience.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.btnExperience.AutoEllipsis = true;
this.btnExperience.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(230)))), ((int)(((byte)(220)))));
this.btnExperience.Cursor = System.Windows.Forms.Cursors.Hand;
this.btnExperience.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(141)))), ((int)(((byte)(141)))), ((int)(((byte)(141)))));
this.btnExperience.FlatAppearance.BorderSize = 0;
this.btnExperience.FlatAppearance.MouseOverBackColor = System.Drawing.Color.Gainsboro;
this.btnExperience.Font = new System.Drawing.Font("Segoe UI Variable Display Semib", 12F, System.Drawing.FontStyle.Bold);
this.btnExperience.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(26)))), ((int)(((byte)(26)))), ((int)(((byte)(26)))));
this.btnExperience.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft;
this.btnExperience.Location = new System.Drawing.Point(21, 286);
this.btnExperience.Name = "btnExperience";
this.btnExperience.Padding = new System.Windows.Forms.Padding(30, 0, 0, 0);
this.btnExperience.Size = new System.Drawing.Size(651, 60);
this.btnExperience.TabIndex = 506;
this.btnExperience.TabStop = false;
this.btnExperience.UseCompatibleTextRendering = true;
this.btnExperience.UseVisualStyleBackColor = false;
//
// statusLabel
//
this.statusLabel.Anchor = System.Windows.Forms.AnchorStyles.None;
this.statusLabel.AutoEllipsis = true;
this.statusLabel.BackColor = System.Drawing.Color.Transparent;
this.statusLabel.Font = new System.Drawing.Font("Segoe UI Variable Text Semibold", 13F, System.Drawing.FontStyle.Bold);
this.statusLabel.ForeColor = System.Drawing.Color.Black;
this.statusLabel.Location = new System.Drawing.Point(21, 3);
this.statusLabel.Name = "statusLabel";
this.statusLabel.Size = new System.Drawing.Size(651, 90);
this.statusLabel.TabIndex = 0;
this.statusLabel.Text = "Drag && drop your Windows 11 ISO to upgrade unsupported PCs.";
this.statusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
this.statusLabel.UseCompatibleTextRendering = true;
//
// chkAdvancedMode
//
this.chkAdvancedMode.Anchor = System.Windows.Forms.AnchorStyles.Bottom;
this.chkAdvancedMode.AutoSize = true;
this.chkAdvancedMode.FlatStyle = System.Windows.Forms.FlatStyle.System;
this.chkAdvancedMode.Font = new System.Drawing.Font("Segoe UI Variable Small Semilig", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.chkAdvancedMode.ForeColor = System.Drawing.Color.Black;
this.chkAdvancedMode.Location = new System.Drawing.Point(225, 434);
this.chkAdvancedMode.Name = "chkAdvancedMode";
this.chkAdvancedMode.Size = new System.Drawing.Size(400, 20);
this.chkAdvancedMode.TabIndex = 2;
this.chkAdvancedMode.Text = "Enable advanced upgrade mode (bypass compatibility and driver checks)";
this.chkAdvancedMode.UseCompatibleTextRendering = true;
this.chkAdvancedMode.UseVisualStyleBackColor = true;
this.chkAdvancedMode.CheckedChanged += new System.EventHandler(this.chkAdvancedMode_CheckedChanged);
//
// UpgradeControlView
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.AutoScroll = true;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(247)))), ((int)(((byte)(244)))), ((int)(((byte)(242)))));
this.Controls.Add(this.chkAdvancedMode);
this.Controls.Add(this.panelDragDrop);
this.Name = "UpgradeControlView";
this.Size = new System.Drawing.Size(835, 457);
this.panelDragDrop.ResumeLayout(false);
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Panel panelDragDrop;
private System.Windows.Forms.ComboBox dropdownOptions;
private System.Windows.Forms.Button btnExperience;
private System.Windows.Forms.Label statusLabel;
private System.Windows.Forms.CheckBox chkAdvancedMode;
private System.Windows.Forms.FlowLayoutPanel flowLayoutPanelTiles;
}
}
+393
View File
@@ -0,0 +1,393 @@
using System;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Flyoobe
{
public partial class UpgradeControlView : UserControl, IView
{
public string ViewTitle => "Upgrading Assistant";
private readonly IsoHandler _isoHandler;
public UpgradeControlView()
{
InitializeComponent();
_isoHandler = new IsoHandler(UpdateStatusLabel);
InitializeOptions();
InitializeTileOptions();
}
private void UpdateStatusLabel(string message)
{
statusLabel.Text = message;
statusLabel.Refresh();
}
/// <summary>
/// Handles the selection change in the dropdown options.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void InitializeOptions()
{
dropdownOptions.Items.Add("Select an option"); // Index 0
dropdownOptions.Items.Add("Select ISO from local computer"); // Index 1
dropdownOptions.Items.Add("Apply Compatibility Patch (Advanced)"); // Index 2
dropdownOptions.Items.Add("Keep Windows 10 secure until 2026 (Enroll in ESU)"); // Index 3
dropdownOptions.SelectedIndex = 0; // Default to "Select an option"
}
private async void dropdownOptions_SelectedIndexChanged(object sender, EventArgs e)
{
var combo = sender as ComboBox;
int selectedIndex = combo.SelectedIndex;
// Let user pick ISO from local disk (compatibility check is now in HandleIsoInput)
if (selectedIndex == 1)
{
await HandleIsoInput(sender, null);
return;
}
// Handle actions based on selection
switch (selectedIndex)
{
case 2:
_isoHandler.HandleCompatibilityPatch();
break;
case 3:
_isoHandler.HandleEnrollInESU();
break;
}
}
/// <summary>
/// Handle the download of ISO files from various sources.
/// </summary>
private void InitializeTileOptions()
{
flowLayoutPanelTiles.Controls.Clear();
var options = new[]
{
Tuple.Create("Download ISO from Microsoft Website", "Official Microsoft ISO download", 1),
Tuple.Create("Download ISO via Media Creation Tool", "Beginner-friendly download", 2),
Tuple.Create("Download ISO using Fido", "Recommended automated script", 3)
};
for (int i = 0; i < options.Length; i++)
{
var option = options[i];
var tile = CreateTile(option.Item1, option.Item2, option.Item3);
flowLayoutPanelTiles.Controls.Add(tile);
}
}
private Control CreateTile(string title, string description, int optionIndex)
{
// Calculate DPI scale factor relative to standard 96 DPI
float dpiScale = this.CreateGraphics().DpiX / 96f;
// Base + hover colors for the tile
var normalColor = Color.FromArgb(245, 240, 230);
var hoverColor = Color.FromArgb(240, 230, 220);
// Accent color per tile (magenta, blue, green)
Color accent = Color.FromArgb(96, 158, 234); // default blue
if (optionIndex == 1)
accent = Color.FromArgb(208, 59, 255); // Magenta
else if (optionIndex == 2)
accent = Color.FromArgb(96, 158, 234); // Blue
else if (optionIndex == 3)
accent = Color.FromArgb(52, 199, 89); // Green
// Main tile panel
var tile = new Panel
{
Width = (int)(200 * dpiScale),
Height = (int)(140 * dpiScale),
Margin = new Padding((int)(8 * dpiScale)),
Padding = new Padding((int)(10 * dpiScale)),
BackColor = normalColor,
Cursor = Cursors.Hand,
};
// Event handlers to apply hover color on mouse enter and revert on leave
EventHandler applyHover = (s, e) =>
{
tile.BackColor = hoverColor;
tile.Invalidate(); // redraw to update
};
EventHandler removeHover = (s, e) =>
{
tile.BackColor = normalColor;
tile.Invalidate();
};
// Paint tile with rounded corners, subtle shadow and colored top stripe
tile.Paint += (s, e) =>
{
var g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
var rect = new Rectangle(0, 0, tile.Width - 1, tile.Height - 1);
var shadowRect = rect; shadowRect.Offset(3, 3);
var path = RoundedRect(rect, 12);
var shadowPath = RoundedRect(shadowRect, 12);
using (var shadow = new SolidBrush(Color.FromArgb(30, 0, 0, 0)))
g.FillPath(shadow, shadowPath);
using (var brush = new SolidBrush(tile.BackColor))
g.FillPath(brush, path);
// Draw colored top stripe (Copilot style)
int stripeHeight = (int)(2 * dpiScale); // thin stripe
using (var stripeBrush = new SolidBrush(accent))
{
g.SetClip(new Rectangle(rect.X, rect.Y, rect.Width, stripeHeight));
g.FillPath(stripeBrush, path);
g.ResetClip();
}
// Set the region to the rounded rectangle for hit testing
tile.Region = new Region(path);
path.Dispose();
shadowPath.Dispose();
};
// Title label (top)
var titleLabel = new Label
{
Text = title,
AutoEllipsis = true,
Font = new Font("Segoe UI", 11f * dpiScale, FontStyle.Bold),
Height = (int)(40 * dpiScale),
ForeColor = Color.FromArgb(80, 60, 40),
Dock = DockStyle.Top,
TextAlign = ContentAlignment.MiddleCenter,
BackColor = Color.Transparent
};
titleLabel.MouseEnter += applyHover;
titleLabel.MouseLeave += removeHover;
// Description label (fill)
var descLabel = new Label
{
Text = description,
AutoEllipsis = true,
Font = new Font("Segoe UI", 8f * dpiScale),
ForeColor = Color.FromArgb(100, 80, 60),
Dock = DockStyle.Fill,
TextAlign = ContentAlignment.TopCenter,
BackColor = Color.Transparent,
Padding = new Padding(0, 10, 0, 0) // spacing from title
};
descLabel.MouseEnter += applyHover;
descLabel.MouseLeave += removeHover;
// One-click handler for all parts
EventHandler clickHandler = (s, e) => TileClicked(optionIndex);
tile.Click += clickHandler;
titleLabel.Click += clickHandler;
descLabel.Click += clickHandler;
// Compose tile
tile.Controls.Add(descLabel);
tile.Controls.Add(titleLabel);
return tile;
}
private void TileClicked(int optionIndex)
{
switch (optionIndex)
{
case 1:
Process.Start(new ProcessStartInfo
{
FileName = "https://www.microsoft.com/software-download/windows11",
UseShellExecute = true
});
break;
case 2:
_isoHandler.HandleMediaCreationToolDownload();
break;
case 3:
_isoHandler.DownloadAndRunFidoScript("https://raw.githubusercontent.com/pbatard/Fido/refs/heads/master/Fido.ps1");
break;
}
}
/// <summary>
/// Processes the ISO input, either from drag-and-drop or file selection.
/// Also performs a CPU compatibility check (SSE4.2 / POPCNT) before proceeding.
/// </summary>
private async Task HandleIsoInput(object sender, EventArgs e)
{
string isoPath = null;
bool experimentalEnabled = chkAdvancedMode.Checked;
// Check if an ISO file was dragged and dropped
if (e is DragEventArgs dragEvent && dragEvent.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] files = (string[])dragEvent.Data.GetData(DataFormats.FileDrop);
if (files.Length == 1 && Path.GetExtension(files[0]).Equals(".iso", StringComparison.OrdinalIgnoreCase))
{
isoPath = files[0];
}
}
// If no ISO was provided via drag-and-drop, show a file picker dialog
if (isoPath == null)
{
using (OpenFileDialog openFileDialog = new OpenFileDialog())
{
openFileDialog.Filter = "ISO Files (*.iso)|*.iso";
openFileDialog.Title = "Select an ISO File";
if (openFileDialog.ShowDialog() == DialogResult.OK)
{
isoPath = openFileDialog.FileName;
}
}
}
// If a valid ISO file was selected or dropped, continue
if (!string.IsNullOrEmpty(isoPath) && File.Exists(isoPath))
{
// === Compatibility Check ===
// Before processing the ISO, verify CPU compatibility using SSE4.2 / POPCNT
bool isCompatible;
try
{
isCompatible = CpuChecker.HasPopcnt();
}
catch (DllNotFoundException)
{
MessageBox.Show(
"Required module 'Flyby11.dll' is missing.\n\n" +
"Because of this, your system's CPU compatibility (SSE4.2 / POPCNT) cannot be verified.\n" +
"You can still proceed, but upgrade issues may occur on unsupported hardware.",
"Compatibility Check Unavailable",
MessageBoxButtons.OK,
MessageBoxIcon.Warning
);
return;
}
// CPU is not compatible
if (!isCompatible)
{
var result = MessageBox.Show(
"⚠️ Your CPU does not support SSE4.2 and POPCNT — required for Windows 11 upgrade bypass.\n\n" +
"You can still proceed, but the upgrade may fail. Continue anyway?",
"Incompatible CPU",
MessageBoxButtons.YesNo,
MessageBoxIcon.Warning
);
if (result == DialogResult.No)
return;
}
else
{
UpdateStatusLabel("✅ Thinking...");
await Task.Delay(1000);
UpdateStatusLabel("✅ CPU check passed.");
await Task.Delay(2000);
}
// === ISO Processing ===
// If all checks passed, hand over the ISO to the handler for further processing
await _isoHandler.HandleIso(isoPath, experimentalEnabled);
}
}
private async void panelDragDrop_DragDrop(object sender, DragEventArgs e)
{
await HandleIsoInput(sender, e);
}
private void panelDragDrop_DragEnter(object sender, DragEventArgs e)
{
// file is an ISO?
if (e.Data.GetDataPresent(DataFormats.FileDrop))
{
string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);
e.Effect = (files.Length == 1 && Path.GetExtension(files[0]).Equals(".iso", StringComparison.OrdinalIgnoreCase))
? DragDropEffects.Copy
: DragDropEffects.None;
}
}
// Helper method to create a rounded rectangle path
private GraphicsPath RoundedRect(Rectangle bounds, int radius)
{
int d = radius * 2;
GraphicsPath path = new GraphicsPath();
path.AddArc(bounds.X, bounds.Y, d, d, 180, 90); // Top-left corner
path.AddArc(bounds.Right - d, bounds.Y, d, d, 270, 90); // Top-right corner
path.AddArc(bounds.Right - d, bounds.Bottom - d, d, d, 0, 90); // Bottom-right corner
path.AddArc(bounds.X, bounds.Bottom - d, d, d, 90, 90); // Bottom-left corner
path.CloseFigure();
return path;
}
private void chkAdvancedMode_CheckedChanged(object sender, EventArgs e)
{
if (chkAdvancedMode.Checked)
{
var result = MessageBox.Show(
"You are enabling an advanced setup mode. This option adds extra setup parameters that may improve compatibility on unsupported hardware. " +
"\r\nSuccess may vary depending on your system and drivers.\n\nDo you want to continue?",
"Advanced Mode Warning",
MessageBoxButtons.YesNo,
MessageBoxIcon.Warning);
if (result == DialogResult.No)
{
chkAdvancedMode.Checked = false;
}
}
}
public void RefreshView()
{
UpdateStatusLabel("Select an option to begin.");
}
private void panelDragDrop_Paint(object sender, PaintEventArgs e)
{
// Create gray dashed pen
using (Pen dashPen = new Pen(Color.FromArgb(100, Color.Gray), 2))
{
dashPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
dashPen.DashPattern = new float[] { 4, 12 }; // short dash, big gap
dashPen.Alignment = System.Drawing.Drawing2D.PenAlignment.Inset;
Rectangle rect = panelDragDrop.ClientRectangle;
rect.Width -= 1;
rect.Height -= 1;
e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
e.Graphics.DrawRectangle(dashPen, rect);
}
}
}
}
public static class CpuChecker
{
[DllImport("Flyby11.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern bool HasPopcnt();
}
+120
View File
@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
+143
View File
@@ -0,0 +1,143 @@
using Flyoobe;
using Microsoft.Win32;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
public class ViewNavigator
{
// Default OOBE/Workload view names
private static readonly string[] DefaultOobeViews =
{
"Upgrade",
"Device",
"Personalization",
"Browser",
"Network",
"Account",
"Apps",
"Experience",
"Installer",
"Updates",
"Extensions"
};
private readonly Panel _hostPanel; // Panel where the active UserControl is displayed
private readonly TreeView _navigationTree; // Navigation tree
private readonly Action<string> _onViewChanged; // Callback for updating the header/title in MainForm
// View factories and cache for lazy loading
private readonly Dictionary<string, Func<UserControl>> _factories;
private readonly Dictionary<string, UserControl> _cache;
public UserControl CurrentView { get; private set; }
public ViewNavigator(Panel hostPanel, TreeView navigationTree, Action<string> onViewChanged)
{
_hostPanel = hostPanel;
_navigationTree = navigationTree;
_onViewChanged = onViewChanged;
_factories = new Dictionary<string, Func<UserControl>>();
_cache = new Dictionary<string, UserControl>();
// Event: Handle navigation when a TreeView node is clicked
_navigationTree.AfterSelect += NavigationTree_AfterSelect;
}
/// <summary>
/// Registers a view with a unique name and a factory function for lazy loading.
/// </summary>
public void RegisterView(string name, Func<UserControl> factory)
{
_factories[name] = factory;
}
/// <summary>
/// Displays the specified view. Creates it if not already loaded.
/// </summary>
public void ShowView(string name)
{
if (!_factories.ContainsKey(name))
return;
_hostPanel.Controls.Clear();
// Lazy-load the view
if (!_cache.ContainsKey(name))
{
var control = _factories[name]();
control.Dock = DockStyle.Fill;
_cache[name] = control;
}
CurrentView = _cache[name];
_hostPanel.Controls.Add(CurrentView);
// Update the MainForm's header label
if (CurrentView is IView view)
_onViewChanged?.Invoke(view.ViewTitle);
else
_onViewChanged?.Invoke(name);
}
/// <summary>
/// Builds the tree: "Upgrade" category contains status + Upgrade + Repair.
/// "OOBE" category contains the rest. Special entries get a gray subtext child node.
/// Only nodes with Tag are clickable.
/// </summary>
public void LoadDefaultNavigation()
{
_navigationTree.Nodes.Clear();
bool isWindows11 = Utils.DetectWindows11();
// --- Upgrade category ---
var upgradeNode = new TreeNode("Upgrade");
// Status (info only)
var statusNode = new TreeNode(isWindows11 ? "✔ Windows 11 detected" : "❌ Upgrade required")
{
ForeColor = isWindows11 ? Color.FromArgb(97, 75, 61): Color.Red
};
upgradeNode.Nodes.Add(statusNode);
// Upgrade step
string upgradeDisplay = isWindows11 ? "✔ Upgrade (Done)" : "Upgrade";
upgradeNode.Nodes.Add(new TreeNode(upgradeDisplay) { Tag = "Upgrade" });
// Reinstall step
upgradeNode.Nodes.Add(new TreeNode("Install only (Custom)") { Tag = "Install only" });
// --- OOBE category ---
var oobeNode = new TreeNode("OOBE");
foreach (var name in DefaultOobeViews)
{
// Skip those that belong to Upgrade category
if (name == "Upgrade" || name == "Install only")
continue;
var mainNode = new TreeNode(name); // main node: not clickable by default
oobeNode.Nodes.Add(new TreeNode(name) { Tag = name });
}
_navigationTree.Nodes.Add(upgradeNode);
_navigationTree.Nodes.Add(oobeNode);
_navigationTree.ExpandAll();
}
/// <summary>
/// Handles TreeView selection changes and loads the corresponding view if registered.
/// </summary>
private void NavigationTree_AfterSelect(object sender, TreeViewEventArgs e)
{
if (e.Node?.Tag is string viewKey)
{
ShowView(viewKey); // Use the key stored in Tag
}
}
}
+199
View File
@@ -0,0 +1,199 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Flyoobe
{
public partial class HomeControlView : UserControl, IView
{
private readonly ViewNavigator _navigator;
private Label _statusLabel; // bottom info label
public string ViewTitle => "Home";
private readonly Color[] _colorPalette = new[]
{
Color.FromArgb(0, 209, 178), // teal
Color.FromArgb(91, 141, 239), // blue
Color.FromArgb(155, 93, 229), // purple
Color.FromArgb(241, 91, 181), // pink
Color.FromArgb(0, 187, 249), // cyan
Color.FromArgb(84, 220, 132), // green
};
private int _nextColorIndex = 0;
private Color NextAccent() => _colorPalette[_nextColorIndex++ % _colorPalette.Length];
public HomeControlView(ViewNavigator navigator)
{
_navigator = navigator;
BuildLayout();
}
private void BuildLayout()
{
var root = new TableLayoutPanel
{
Dock = DockStyle.Fill,
RowCount = 2,
ColumnCount = 1
};
root.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
root.RowStyles.Add(new RowStyle(SizeType.AutoSize));
var layout = new FlowLayoutPanel
{
Dock = DockStyle.Fill,
AutoScroll = true,
FlowDirection = FlowDirection.LeftToRight,
WrapContents = true,
Padding = new Padding(20)
};
// Upgrade tile: disable if already Windows 11
if (!Utils.DetectWindows11())
{
layout.Controls.Add(CreateTile(
"🚀 Upgrade Windows",
"Upgrade to Windows 11",
"Here you can apply a bypass patch and upgrade to Windows 11 even if your hardware is not officially supported.",
() => _navigator.ShowView("Upgrade")));
}
else
{
layout.Controls.Add(CreateTile(
"✔ Windows 11 Installed",
"Your system is already on Windows 11",
"No upgrade required – you're up to date.",
null, true)); // disabled tile
}
layout.Controls.Add(CreateTile("🎨 Customize OOBE", "Personalize and streamline your Out-of-Box Experience",
"On the right side you will find the OOBE section. After a Windows 11 installation you can debloat, tweak and personalize your system.",
() => _navigator.ShowView("Personalization")));
layout.Controls.Add(CreateTile("🛠 Install && Repair", "Install or repair Windows 10/11",
"Choose repair or reinstall options such as in-place upgrade, reset this PC, or custom installation media.",
() => _navigator.ShowView("Install only")));
layout.Controls.Add(CreateTile("🧩 Setup Extensions", "Enhance your Windows setup",
"Browse community-driven PowerShell scripts and extensions to automate, debloat, or customize your system after installation.",
() => _navigator.ShowView("Extensions")));
// Status bar
float dpiScale = this.CreateGraphics().DpiX / 96f;
_statusLabel = new Label
{
Dock = DockStyle.Bottom,
Height = (int)(34 * dpiScale),
AutoEllipsis = true,
Font = new Font("Segoe UI", 9, FontStyle.Regular),
ForeColor = Color.Black,
BackColor = Color.WhiteSmoke,
TextAlign = ContentAlignment.MiddleLeft,
Padding = new Padding(8),
Text = "Welcome to Flyoobe"
};
root.Controls.Add(layout, 0, 0);
root.Controls.Add(_statusLabel, 0, 1);
Controls.Add(root);
}
/// <summary>
/// Creates a tile with title, description and optional action.
/// If disabled=true, the tile is shown lighter and not clickable.
/// </summary>
private Control CreateTile(string title, string description, string detailedDescription, Action onClick, bool disabled = false)
{
// Colors: normal, hover, pressed
var baseBack = disabled ? Color.FromArgb(245, 247, 250) : Color.FromArgb(248, 250, 252);
var hoverBack = Color.FromArgb(242, 245, 255);
var downBack = Color.FromArgb(235, 240, 255);
var accent = NextAccent();
float dpiScale = this.CreateGraphics().DpiX / 96f;
// Main tile panel
var panel = new Panel
{
Width = (int)(280 * dpiScale),
Height = (int)(100 * dpiScale),
BackColor = baseBack,
Margin = new Padding(10),
Cursor = disabled ? Cursors.Default : Cursors.Hand
};
// Colored accent bar on the left
var leftBar = new Panel
{
Dock = DockStyle.Left,
Width = (int)(5 * dpiScale),
BackColor = accent
};
// Title
var lblTitle = new Label
{
Text = title,
Dock = DockStyle.Top,
Font = new Font("Segoe UI", 10.5f, FontStyle.Bold),
Height = (int)(36 * dpiScale),
TextAlign = ContentAlignment.MiddleCenter,
ForeColor = disabled ? Color.Gray : Color.Black
};
// Short description
var lblDesc = new Label
{
Text = description,
Dock = DockStyle.Fill,
Font = new Font("Segoe UI", 9, disabled ? FontStyle.Italic : FontStyle.Regular),
TextAlign = ContentAlignment.TopCenter,
Padding = new Padding(6, 4, 6, 6),
ForeColor = disabled ? Color.DarkGray : Color.Black
};
// Compose tile
panel.Controls.Add(lblDesc);
panel.Controls.Add(lblTitle);
panel.Controls.Add(leftBar);
if (!disabled)
{
// Make tile clickable
void WireClick(Control c) => c.Click += (s, e) => onClick?.Invoke();
WireClick(panel); WireClick(lblTitle); WireClick(lblDesc);
// Hover effect + update bottom label
void SetHover(bool on)
{
panel.BackColor = on ? hoverBack : baseBack;
leftBar.Width = on ? 7 : 5;
_statusLabel.Text = on ? detailedDescription : "Welcome to Flyoobe";
}
void WireHover(Control c)
{// Hover/press visual feedback (bar grows a bit on hover)
c.MouseEnter += (s, e) => SetHover(true);
c.MouseLeave += (s, e) =>
{// Only reset if pointer actually left the tile area
var inside = panel.ClientRectangle.Contains(panel.PointToClient(Cursor.Position));
if (!inside) SetHover(false);
};
c.MouseDown += (s, e) => panel.BackColor = downBack;
c.MouseUp += (s, e) =>
{
var inside = panel.ClientRectangle.Contains(panel.PointToClient(Cursor.Position));
panel.BackColor = inside ? hoverBack : baseBack;
};
}
WireHover(panel); WireHover(lblTitle); WireHover(lblDesc);
}
return panel;
}
public void RefreshView() { }
}
}
Loaded 100 of 105 files, more files were not shown because too many files have changed in this diff. Show more