pausedProgressBarBrush = new(() =>
33 | // This fails with HRESULT 0x80070490
34 | /*using var hTheme = Win32Error.ThrowLastErrorIfInvalid(OpenThemeData(IntPtr.Zero, "PROGRESS"));
35 | HRESULT.ThrowIfFailed(GetThemeColor(hTheme, PROGRESSPARTS.PP_FILL, FILLSTATES.PBFS_PAUSED, ThemeProperty.TMT_FILLCOLOR, out var color));
36 | return new SolidColorBrush(color.ToColor());*/
37 | new SolidColorBrush(Color.FromRgb(0xDA, 0xCB, 0x26)));
38 |
39 | public TextStyle MainInstruction => mainInstruction.Value;
40 | public Brush PausedProgressBarBrush => pausedProgressBarBrush.Value;
41 | }
--------------------------------------------------------------------------------
/README.fr.md:
--------------------------------------------------------------------------------
1 | # [🇺🇸](README.md)
2 |
3 |
4 |
9 | Utilitaire d'optimisation et de nettoyage Windows.
10 |
11 |
12 |
13 |
14 |
15 |
16 | ---
17 |
18 | Accessible aux utilisateurs moyens tout comme aux administrateurs système, WinClean permet de faire de Windows un system d'exploitation sûr, fiable et performant en quelques clics.
19 |
20 | Plus d'informations et tutoriels dispnibles sur le [wiki](https://github.com/5cover/WinClean/wiki/Home-FR-fr).
21 |
22 | 
23 |
24 | ## ~~Encore une arnaque~~
25 |
26 | ## Fonctionnalités
27 | - Exécuter 40 scripts *Batch*, *PowerShell* et *Éditeur du Registre* directement depuis l'interface utilisateur.
28 | - Ajouter des scripts personnalisés pour aller plus loin dans le nettoyage et l'optimisation.
29 |
30 | ## Spécifications
31 | - .NET 6
32 | - WPF
33 | - Architecture MVVM
34 |
35 | ## Contribuer
36 | N'hésitez pas à signaler les bugs et à proposer de nouvelles fonctionnalités.
37 |
38 | Vous pouvez également soumettre des scripts à ajouter dans la section Issues.
39 |
--------------------------------------------------------------------------------
/WinClean/Model/Serialization/IScriptMetadataDeserializer.cs:
--------------------------------------------------------------------------------
1 | using Scover.WinClean.Model.Metadatas;
2 |
3 | namespace Scover.WinClean.Model.Serialization;
4 |
5 | public interface IScriptMetadataDeserializer
6 | {
7 | /// Deserializes a collection of categories from the specified stream.
8 | /// A stream with read access.
9 | ///
10 | /// is in a invalid or incomplete format.
11 | ///
12 | /// A collection of deserialized objects.
13 | IEnumerable GetCategories(Stream stream);
14 |
15 | /// Deserializes a collection of hosts from the specified stream.
16 | /// A stream with read access.
17 | ///
18 | /// is in a invalid or incomplete format.
19 | ///
20 | /// A collection of deserialized objects.
21 | IEnumerable GetHosts(Stream stream);
22 |
23 | /// Deserializes a collection of impacts from the specified stream.
24 | /// A stream with read access.
25 | ///
26 | /// is in a invalid or incomplete format.
27 | ///
28 | /// A collection of deserialized objects.
29 | IEnumerable GetImpacts(Stream stream);
30 |
31 | /// Deserializes a collection of safety levels from the specified stream.
32 | /// A stream with read access.
33 | ///
34 | /// is in a invalid or incomplete format.
35 | ///
36 | /// A collection of deserialized objects.
37 | IEnumerable GetSafetyLevels(Stream stream);
38 | }
--------------------------------------------------------------------------------
/WinClean/ViewModel/Logging/Logger.cs:
--------------------------------------------------------------------------------
1 | using System.Runtime.CompilerServices;
2 |
3 | using Scover.WinClean.Services;
4 |
5 | namespace Scover.WinClean.ViewModel.Logging;
6 |
7 | public abstract class Logger
8 | {
9 | /// Gets or sets the minimal log level for a logging operation to occur.
10 | /// Default value is .
11 | public LogLevel MinLevel { get; set; } = LogLevel.Verbose;
12 |
13 | /// Clears the logs.
14 | public abstract Task ClearLogsAsync();
15 |
16 | /// Logs a string.
17 | /// The string to log.
18 | /// The level of the log entry.
19 | /// - Don't specify
20 | /// - Don't specify
21 | /// - Don't specify
22 | public void Log(string message,
23 | LogLevel lvl = LogLevel.Verbose,
24 | [CallerMemberName] string caller = "",
25 | [CallerLineNumber] int callLine = 0,
26 | [CallerFilePath] string callFile = "")
27 | {
28 | if (ServiceProvider.Get().IsLoggingEnabled && lvl >= MinLevel)
29 | {
30 | Log(new(lvl,
31 | DateTime.Now,
32 | message,
33 | caller,
34 | callLine,
35 | // Only keep the filename of the source file to avoid showing personal information in
36 | // file paths.
37 | Path.GetFileName(callFile)));
38 | }
39 | }
40 |
41 | protected abstract void Log(LogEntry entry);
42 |
43 | ///Topmost = leftmost.
44 | protected sealed record LogEntry(LogLevel Level,
45 | DateTime Date,
46 | string Message,
47 | string Caller,
48 | int CallLine,
49 | string CallFile);
50 | }
--------------------------------------------------------------------------------
/WinClean/Scripts/Enable Verbose status messages.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/WinClean/Services/MessageFormatter.cs:
--------------------------------------------------------------------------------
1 | using System.Globalization;
2 |
3 | using Jeffijoe.MessageFormat;
4 |
5 | namespace Scover.WinClean.Services;
6 |
7 | public sealed class MessageFormatter : IMessageFormatter
8 | {
9 | private const string HumanizeStyle = "humanize";
10 |
11 | private static readonly Jeffijoe.MessageFormat.MessageFormatter msgFormatter = new(customValueFormatter: HumanizerValueFormatter.Instance);
12 |
13 | public string Format(string message, IReadOnlyDictionary args) => Format(message, CultureInfo.CurrentCulture, args);
14 |
15 | public string Format(string message, CultureInfo culture, IReadOnlyDictionary args)
16 | {
17 | msgFormatter.Locale = culture.Name;
18 | return msgFormatter.FormatMessage(message, args);
19 | }
20 |
21 | ///
22 | /// Custom MessageFormatter.NET formatter for Humanizer interoperability with dates, times and durations.
23 | ///
24 | private sealed class HumanizerValueFormatter : CustomValueFormatter
25 | {
26 | private HumanizerValueFormatter()
27 | {
28 | }
29 |
30 | public static HumanizerValueFormatter Instance { get; } = new();
31 |
32 | public override bool TryFormatDate(CultureInfo culture, object? value, string? style, out string? formatted)
33 | // MessageFormatter.NET doesn't do type checking so value could be of any type
34 | => (formatted = value switch
35 | {
36 | _ when style != HumanizeStyle => null,
37 | DateTime dt => dt.Humanize(culture: culture),
38 | DateOnly d => d.Humanize(culture: culture),
39 | DateTimeOffset dto => dto.Humanize(culture: culture),
40 | TimeOnly t => t.Humanize(culture: culture),
41 | _ => null,
42 | }) is not null;
43 |
44 | public override bool TryFormatTime(CultureInfo culture, object? value, string? style, out string? formatted)
45 | => (formatted = value switch
46 | {
47 | _ when style != HumanizeStyle => null,
48 | TimeSpan d => d.HumanizeToSeconds(),
49 | _ => null,
50 | }) is not null;
51 | }
52 | }
--------------------------------------------------------------------------------
/WinClean/Scripts/Delete junk files.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/WinClean/Scripts/Disable Cortana.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/WinClean/Model/TypedEnumerableDictionary.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Diagnostics.CodeAnalysis;
3 |
4 | namespace Scover.WinClean.Model;
5 |
6 | ///
7 | /// Dictionary of keyed by with generic helpers.
8 | ///
9 | public sealed class TypedEnumerableDictionary : IDictionary
10 | {
11 | private readonly Dictionary _dic = new();
12 | public int Count => _dic.Count;
13 | public ICollection Keys => _dic.Keys;
14 | public ICollection Values => _dic.Values;
15 | bool ICollection>.IsReadOnly => ((ICollection>)_dic).IsReadOnly;
16 |
17 | public IEnumerable this[Type key]
18 | {
19 | get => _dic[key];
20 | set => _dic[key] = value;
21 | }
22 |
23 | public void Add(Type key, IEnumerable value) => _dic.Add(key, value);
24 |
25 | public void Add(IEnumerable value) => _dic.Add(typeof(TKey), value);
26 |
27 | public void Clear() => _dic.Clear();
28 |
29 | public bool ContainsKey(Type key) => _dic.ContainsKey(key);
30 |
31 | public IEnumerable Get() => _dic[typeof(TKey)].Cast();
32 |
33 | public bool Remove(Type key) => _dic.Remove(key);
34 |
35 | public bool TryGetValue(Type key, [MaybeNullWhen(false)] out IEnumerable value) => _dic.TryGetValue(key, out value);
36 |
37 | void ICollection>.Add(KeyValuePair item) => ((ICollection>)_dic).Add(item);
38 |
39 | bool ICollection>.Contains(KeyValuePair item) => ((ICollection>)_dic).Contains(item);
40 |
41 | void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) => ((ICollection>)_dic).CopyTo(array, arrayIndex);
42 |
43 | IEnumerator> IEnumerable>.GetEnumerator() => _dic.GetEnumerator();
44 |
45 | IEnumerator IEnumerable.GetEnumerator() => _dic.GetEnumerator();
46 |
47 | bool ICollection>.Remove(KeyValuePair item) => ((ICollection>)_dic).Remove(item);
48 | }
--------------------------------------------------------------------------------
/WinClean/Model/Metadatas/Capability.cs:
--------------------------------------------------------------------------------
1 | using Scover.WinClean.Resources;
2 |
3 | namespace Scover.WinClean.Model.Metadatas;
4 |
5 | ///
6 | /// Specifies which script selection state a capability belongs to.
7 | ///
8 | public enum CapabilityCorrespondingSelectionState
9 | {
10 | ///
11 | /// The capability corresponds to a "Selected" selection state.
12 | ///
13 | Selected,
14 |
15 | ///
16 | /// The capability corresponds to an "Unselected" selection state.
17 | ///
18 | Unselected,
19 |
20 | ///
21 | /// The capability corresponds to an unspecified selection state.
22 | ///
23 | Unspecified,
24 | }
25 |
26 | public sealed class Capability : Metadata
27 | {
28 | private Capability(string resourceName, CapabilityCorrespondingSelectionState correspondingSelectionState) : base(new ResourceTextProvider(Capabilities.ResourceManager, resourceName))
29 | => (CorrespondingSelectionState, ResourceName) = (correspondingSelectionState, resourceName);
30 |
31 | public static Capability Detect { get; } = new(nameof(Detect), CapabilityCorrespondingSelectionState.Unspecified);
32 | public static Capability Disable { get; } = new(nameof(Disable), CapabilityCorrespondingSelectionState.Unselected);
33 | public static Capability Enable { get; } = new(nameof(Enable), CapabilityCorrespondingSelectionState.Selected);
34 | public static Capability Execute { get; } = new(nameof(Execute), CapabilityCorrespondingSelectionState.Selected);
35 | public CapabilityCorrespondingSelectionState CorrespondingSelectionState { get; }
36 | public string ResourceName { get; }
37 |
38 | public static Capability? FromInteger(int number) => number switch
39 | {
40 | 0 => Disable,
41 | 1 => Enable,
42 | 2 => Execute,
43 | 3 => Detect,
44 | _ => null,
45 | };
46 |
47 | ///
48 | /// No capability exists with the specified resource name.
49 | ///
50 | public static Capability FromResourceName(string resourceName) => Multiton.GetInstance(i => i.ResourceName == resourceName);
51 |
52 | public static Capability? FromResourceNameOrDefault(string resourceName) => Multiton.GetInstanceOrDefault(i => i.ResourceName == resourceName);
53 | }
--------------------------------------------------------------------------------
/WinClean/Scripts/Remove Microsoft Edge.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/WinClean/Scripts/Run advanced disk cleanup.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/WinClean/View/App.xaml:
--------------------------------------------------------------------------------
1 |
10 |
11 |
16 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | 0.15
41 |
42 |
--------------------------------------------------------------------------------
/WinClean/Services/ScriptStorage.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.ObjectModel;
2 |
3 | using Scover.WinClean.Model;
4 | using Scover.WinClean.Model.Metadatas;
5 | using Scover.WinClean.Model.Scripts;
6 | using Scover.WinClean.Model.Serialization;
7 | using Scover.WinClean.Model.Serialization.Xml;
8 | using Scover.WinClean.Resources;
9 |
10 | namespace Scover.WinClean.Services;
11 |
12 | /// Represent the storage systems of mutable and immutable scripts.
13 | public sealed class ScriptStorage : IScriptStorage
14 | {
15 | private const string DefaultScriptsResourceNamespace = $"{nameof(Scover)}.{nameof(WinClean)}.Scripts";
16 | private static readonly IScriptSerializer serializer = new ScriptXmlSerializer();
17 | private readonly Dictionary _repos = new();
18 | private bool _loaded;
19 | public ObservableCollection
--------------------------------------------------------------------------------
/WinClean/View/Controls/ScriptListView.xaml.cs:
--------------------------------------------------------------------------------
1 | using System.Windows;
2 | using System.Windows.Controls;
3 | using System.Windows.Input;
4 |
5 | using Scover.WinClean.Model.Metadatas;
6 | using Scover.WinClean.ViewModel;
7 |
8 | namespace Scover.WinClean.View.Controls;
9 |
10 | public sealed partial class ScriptListView
11 | {
12 | public static readonly DependencyProperty DeleteCommandProperty = DependencyProperty.Register(nameof(DeleteCommand), typeof(ICommand), typeof(ScriptListView));
13 | public static readonly DependencyProperty SelectedScriptProperty = DependencyProperty.Register(nameof(SelectedScript), typeof(ScriptViewModel), typeof(ScriptListView));
14 | public static readonly DependencyProperty UsageProperty = DependencyProperty.Register(nameof(Usage), typeof(Usage), typeof(ScriptListView));
15 |
16 | public ScriptListView() => InitializeComponent();
17 |
18 | public ICommand DeleteCommand
19 | {
20 | get => (ICommand)GetValue(DeleteCommandProperty);
21 | set => SetValue(DeleteCommandProperty, value);
22 | }
23 |
24 | public ScriptViewModel SelectedScript
25 | {
26 | get => (ScriptViewModel)GetValue(SelectedScriptProperty);
27 | set => SetValue(SelectedScriptProperty, value);
28 | }
29 |
30 | public Usage Usage
31 | {
32 | get => (Usage)GetValue(UsageProperty);
33 | set => SetValue(UsageProperty, value);
34 | }
35 |
36 | private void DataGridIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
37 | {
38 | var dg = (DataGrid)sender;
39 | // This is required to make the SelectedItem binding update
40 | // Indeed, when a data grid is brought into view, the binding doesn't update when it's focused and the selected script doesn't change.
41 | // So the selected script from before this data grid became visible doesn't change.
42 | // This is a way to ensure that SelectedScript is always one of scripts displayed.
43 | if (e.NewValue is true)
44 | {
45 | dg.SelectedItem = dg.SelectedItem;
46 | }
47 | }
48 |
49 | private void DataGridRowRequestBringIntoViewSwallow(object sender, RequestBringIntoViewEventArgs e) => e.Handled = true;
50 |
51 | private void DeleteCanExecute(object sender, CanExecuteRoutedEventArgs e) => e.CanExecute = DeleteCommand.CanExecute(e.Parameter);
52 |
53 | private void DeleteExecuted(object sender, ExecutedRoutedEventArgs e)
54 | {
55 | DeleteCommand.Execute(e.Parameter);
56 | // After deletion, focus the DataGrid to allow for more deletions.
57 | _ = this.GetVisualChild()?.Focus();
58 | }
59 | }
--------------------------------------------------------------------------------
/WinClean/Model/Scripts/MutableScriptRepository.cs:
--------------------------------------------------------------------------------
1 | using Scover.WinClean.Model.Metadatas;
2 | using Scover.WinClean.Model.Serialization;
3 |
4 | namespace Scover.WinClean.Model.Scripts;
5 |
6 | public abstract class MutableScriptRepository : ScriptRepository
7 | {
8 | private bool _updatesEnabled = true;
9 |
10 | protected MutableScriptRepository(IScriptSerializer serializer, ScriptType type) : base(serializer, type)
11 | => Scripts.CollectionChanged += (s, e) =>
12 | {
13 | if (!_updatesEnabled)
14 | {
15 | return;
16 | }
17 |
18 | if (e.OldItems is not null)
19 | {
20 | foreach (Script script in e.OldItems)
21 | {
22 | _ = Remove(script);
23 | }
24 | }
25 | if (e.NewItems is not null)
26 | {
27 | foreach (Script script in e.NewItems)
28 | {
29 | Add(script);
30 | }
31 | }
32 | };
33 |
34 | /// Updates a script in a repository.
35 | /// The script to update.
36 | ///
37 | /// is not present in the repository.
38 | ///
39 | /// A filesystem exception occurred.
40 | public abstract void Commit(Script script);
41 |
42 | /// Adds a script to the repository.
43 | /// A filesystem exception occurred.
44 | ///
45 | /// The script already exists in the repository.
46 | ///
47 | protected abstract void Add(Script script);
48 |
49 | ///
50 | /// Adds an item to the script collection without triggering the CollectionChanged event handler.
51 | ///
52 | protected void AddItemInternally(Script script)
53 | {
54 | _updatesEnabled = false;
55 | Scripts.Add(script);
56 | _updatesEnabled = true;
57 | }
58 |
59 | /// Removes a script from a repository.
60 | /// The script to remove.
61 | ///
62 | /// if successfully removed otherwise, . This method also returns if
64 | /// was not found in the repository.
65 | ///
66 | protected abstract bool Remove(Script script);
67 | }
--------------------------------------------------------------------------------
/WinClean/Hosts.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Cmd
5 | Command Processor
6 | Interpréteur de commandes
7 | The Command Processor is a program that allows the entering of commands and then executes those commands to the operating system.
8 | L'Interpréteur de commandes est un programme qui permet de saisir des commandes, puis d'exécuter ces commandes sur le système d'exploitation.
9 | %COMSPEC%
10 | /d /c "{0}"
11 | .cmd
12 |
13 |
14 |
15 | PowerShell
16 | PowerShell
17 | PowerShell
18 | Microsoft PowerShell is a shell and scripting language built on top of Microsoft .NET technology.
19 | Microsoft PowerShell est un shell et un langage de script construit sur la technologie Microsoft .NET.
20 | %SYSTEMROOT%\System32\WindowsPowerShell\v1.0\powershell.exe
21 | -NoProfile -ExecutionPolicy Unrestricted -File "{0}"
22 | .ps1
23 |
24 | >=6.1.0
25 |
26 |
27 | Regedit
28 | Registry Editor
29 | Éditeur du Registre
30 | The Registry Editor is a tool that enables users to view the Windows registry and make changes.
31 | L'Éditeur du Registre est un outil qui permet aux utilisateurs d'afficher le Registre Windows et d'y apporter des modifications.
32 | %SYSTEMROOT%\regedit.exe
33 | /s {0}
34 | .reg
35 |
36 |
37 |
38 | Execute
39 | Direct execution
40 | Exécution directe
41 | Executes a script's code as a standalone program
42 | Exécute le code d'un script en tant que programme indépendant.
43 | {0}
44 |
45 |
46 |
--------------------------------------------------------------------------------
/WinClean/Properties/deploy.ps1:
--------------------------------------------------------------------------------
1 | Param (
2 | [Parameter(Mandatory=$false)]
3 | [Switch]
4 | $SkipBuild = $false,
5 | [Parameter(Mandatory=$false)]
6 | [Switch]
7 | $SkipSign = $false
8 | )
9 |
10 | $thumbprint = '1069E1903B197B71ADFCF6D2151BAF5920706A21'
11 | $name = 'WinClean'
12 | $outputDir = '..\bin\setup'
13 |
14 | $portableWin64 = '..\bin\publish\portable-win-x64'
15 | $portableWin86 = '..\bin\publish\portable-win-x86'
16 | $win64 = '..\bin\publish\win-x64'
17 | $win86 = '..\bin\publish\win-x86'
18 |
19 | # Get app info
20 | $csprojXml = [Xml] (Get-Content '..\WinClean.csproj')
21 | $version = $csprojXml.Project.PropertyGroup.Version[0].Trim()
22 | $description = $csprojXml.Project.PropertyGroup.Description[0].Trim()
23 | $repoUrl = $csprojXml.Project.PropertyGroup.RepositoryUrl[0].Trim()
24 | $authors = $csprojXml.Project.PropertyGroup.Authors[0].Trim()
25 | $copyright = $csprojXml.Project.PropertyGroup.Copyright[0].Trim()
26 |
27 | # Publish
28 | if (-Not $SkipBuild) {
29 | dotnet publish .. /p:PublishProfile=portable-win-x64 -o $portableWin64
30 | dotnet publish .. /p:PublishProfile=portable-win-x86 -o $portableWin86
31 | dotnet publish .. /p:PublishProfile=win-x64 -o $win64
32 | dotnet publish .. /p:PublishProfile=win-x86 -o $win86
33 | }
34 |
35 | # Sign if available
36 | $signFile = 'systray' # no-op dummy exe
37 | $isccArgs = @(
38 | "/D_Copyright=$copyright",
39 | "/D_Description=$description",
40 | "/D_Output=$outputDir",
41 | "/D_Publisher=$author",
42 | "/D_RepoUrl=$repoUrl",
43 | "/D_Version=$version",
44 | 'InstallerScript.iss')
45 |
46 | if ((-Not $SkipSign) -And (Test-Path Cert:\CurrentUser\My\$thumbprint)) {
47 | $signExe = 'signtool'
48 | $signArgs = @('sign', '/fd', 'SHA256', '/sha1', $thumbprint, '/t', 'http://timestamp.digicert.com')
49 | $innoSigntoolName = 'signtool'
50 | $isccArgs += @("/S$innoSigntoolName=$signExe $signArgs `$f", "/D_SignTool=$innoSigntoolName")
51 |
52 | & $signExe $signArgs "$portableWin64\$name.exe"
53 | & $signExe $signArgs "$portableWin86\$name.exe"
54 | & $signExe $signArgs "$win64\$name.dll"
55 | & $signExe $signArgs "$win64\$name.exe"
56 | & $signExe $signArgs "$win86\$name.dll"
57 | & $signExe $signArgs "$win86\$name.exe"
58 | } elseif (-Not $SkipSign) {
59 | Write-Error 'Cannot sign: certificate not found'
60 | }
61 |
62 | # Compile scripts
63 | $ISCC = 'D:\Programmes\Inno Setup 6\ISCC.exe'
64 |
65 | & $ISCC $($isccArgs + @('/D_Arch=win-x64', "/D_Path=$win64"))
66 | & $ISCC $($isccArgs + @('/D_Arch=win-x86', "/D_Path=$win86"))
67 |
68 | # Copy portable binaries
69 | Copy-Item "$portableWin64\$name.exe" "$outputDir\$name-x64.exe"
70 | Copy-Item "$portableWin86\$name.exe" "$outputDir\$name-x86.exe"
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/WinClean/View/Windows/AboutWindow.xaml:
--------------------------------------------------------------------------------
1 |
18 |
19 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
41 |
42 |
46 |
50 |
51 |
52 | GitHub
53 |
54 |
55 |
56 |
68 |
69 |
--------------------------------------------------------------------------------
/WinClean/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | .xml
7 |
8 |
9 | NaN
10 |
11 |
12 | NaN
13 |
14 |
15 | NaN
16 |
17 |
18 | NaN
19 |
20 |
21 | False
22 |
23 |
24 | True
25 |
26 |
27 | False
28 |
29 |
30 | 00:01:00
31 |
32 |
33 | *-*
34 |
35 |
36 | *-*
37 |
38 |
39 | https://github.com/5cover/WinClean/releases/latest
40 |
41 |
42 | https://github.com/5cover/WinClean/wiki/
43 |
44 |
45 | https://github.com/5cover/WinClean/issues/new
46 |
47 |
48 | 511304031
49 |
50 |
51 | False
52 |
53 |
54 |
--------------------------------------------------------------------------------
/WinClean/Impacts.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Ergonomics
5 | Ergonomie
6 | Improves system practicality, comfort and ease of use.
7 | Améliore la fonctionnalité du système, son confort et sa facilité d'utilisation.
8 |
9 |
10 | Free storage space
11 | Espace de stockage libre
12 | Frees up disk space.
13 | Libère de l'espace disque.
14 |
15 |
16 | Memory usage
17 | Utilisation mémoire
18 | Reduces idle system memory usage.
19 | Limite l'utilisation mémoire du système inactif.
20 |
21 |
22 | Network usage
23 | Utilisation réseau
24 | Reduces idle system network usage.
25 | Limite l'utilisation réseau du système inactif.
26 |
27 |
28 | Privacy
29 | Confidentialité
30 | Reduces the amout of diagnostic data and analytics sent to Microsoft.
31 | Réduit la quantitié de données de diagnostic et analyses envoyées à Microsoft.
32 |
33 |
34 | Shutdown time
35 | Temps d'arrêt
36 | Makes the shutdown process faster.
37 | Rend le processus d'arrêt plus rapide.
38 |
39 |
40 | Stability
41 | Stabilité
42 | Reduces the tendency of the system to crash, hang, or bluescreen.
43 | Réduit la tendance du système à planter, à se bloquer ou à afficher un écran bleu.
44 |
45 |
46 | Startup time
47 | Temps de démarrage
48 | Makes the startup process faster.
49 | Rend le processus de démarrage plus rapide.
50 |
51 |
52 | Storage speed
53 | Vitesse disque
54 | Improves the speed at which disk I/O operations are performed.
55 | Améliore la vitesse à laquelle les opérations d'E/S de disque sont exécutées.
56 |
57 |
--------------------------------------------------------------------------------
/WinClean/ViewModel/Logging/Logging.CsvLogger.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Globalization;
3 | using System.Text;
4 |
5 | using CsvHelper;
6 | using CsvHelper.Configuration;
7 |
8 | using Scover.WinClean.Model;
9 | using Scover.WinClean.Resources;
10 |
11 | namespace Scover.WinClean.ViewModel.Logging;
12 |
13 | public static partial class Logging
14 | {
15 | private sealed class CsvLogger : Logger, IDisposable
16 | {
17 | private const string DateTimeFilenameFormat = "yyyy-MM-dd--HH-mm-ss";
18 | private const string LogFileExtension = ".csv";
19 |
20 | private readonly Lazy _csvWriter;
21 |
22 | private readonly string _currentLogFile;
23 |
24 | public CsvLogger()
25 | {
26 | _currentLogFile = Path.Join(AppDirectory.Logs, Process.GetCurrentProcess().StartTime.ToString(DateTimeFilenameFormat, DateTimeFormatInfo.InvariantInfo) + LogFileExtension);
27 | // Defer writer creation. This prevents creating of empty log file at the start of the program.
28 | _csvWriter = new(() =>
29 | {
30 | CsvWriter writer = new(new StreamWriter(_currentLogFile, false, Encoding.Unicode), new CsvConfiguration(CultureInfo.InvariantCulture));
31 | writer.WriteHeader();
32 | return writer;
33 | });
34 | }
35 |
36 | public override Task ClearLogsAsync() => Task.Run(() =>
37 | {
38 | foreach (string logFile in Directory.EnumerateFiles(AppDirectory.Logs, $"*{LogFileExtension}").Where(CanLogFileBeDeleted))
39 | {
40 | try
41 | {
42 | File.Delete(logFile);
43 | }
44 | catch (Exception e) when (e.IsFileSystemExogenous())
45 | {
46 | Log(Logs.FailedToDeleteLogFile.FormatWith(logFile, e), LogLevel.Error);
47 | // Swallow the exception. Failing to delete a log file is not serious enough to justify
48 | // terminating the application with an unhandled exception.
49 | }
50 | }
51 | Log(Logs.ClearedLogsFolder);
52 | });
53 |
54 | public void Dispose() => _csvWriter.Value.Dispose();
55 |
56 | protected override void Log(LogEntry entry)
57 | {
58 | lock (_csvWriter)
59 | {
60 | _csvWriter.Value.NextRecord();
61 | _csvWriter.Value.WriteRecord(entry);
62 | _csvWriter.Value.Flush();
63 | }
64 | }
65 |
66 | private bool CanLogFileBeDeleted(string logFile)
67 | => DateTime.TryParseExact(Path.GetFileNameWithoutExtension(logFile), DateTimeFilenameFormat,
68 | DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None, out _) && logFile != _currentLogFile;
69 | }
70 | }
--------------------------------------------------------------------------------