Compare commits

..

27 Commits

Author SHA1 Message Date
0d9b6f3a79 Update configs.Tests.ps1 2024-08-28 16:46:18 -05:00
5d53b96553 Update configs.Tests.ps1 2024-08-28 16:43:36 -05:00
66164379c8 Update configs.Tests.ps1 2024-08-28 16:42:03 -05:00
44521776ba Update configs.Tests.ps1 2024-08-28 16:40:38 -05:00
bf56639572 Update configs.Tests.ps1 2024-08-28 16:38:02 -05:00
c79fa58500 Update configs.Tests.ps1 2024-08-28 16:34:21 -05:00
26a2b3df9b Update configs.Tests.ps1 2024-08-28 16:24:28 -05:00
e6dbc811f4 Update configs.Tests.ps1 2024-08-28 16:20:11 -05:00
97bf9520a1 Update configs.Tests.ps1 2024-08-28 16:16:30 -05:00
01f41982f6 Update configs.Tests.ps1 2024-08-28 16:08:11 -05:00
be9fae199c Update configs.Tests.ps1 2024-08-28 16:03:49 -05:00
31ec62f00b Merge branch 'main' into config-schema 2024-08-28 12:55:17 -05:00
50cb1be797 Merge branch 'main' into config-schema 2024-08-14 16:58:57 -07:00
77e5c254a5 Merge branch 'main' into config-schema 2024-08-09 08:02:01 -07:00
b9b617ea81 Merge branch 'main' into config-schema 2024-08-08 01:10:39 -07:00
14efc4f4f6 Merge branch 'main' into config-schema 2024-08-07 14:38:54 -07:00
632f295355 Merge branch 'main' into config-schema 2024-08-07 10:52:33 -07:00
e7d0637396 Merge branch 'main' into config-schema 2024-08-07 09:30:31 -07:00
e2a870f746 added json-schema for config/applications.json 2024-08-07 08:20:03 -07:00
8844b85531 json-schema adjustments 2024-08-07 08:11:07 -07:00
5e2acadee5 added json-schema for config/feature.json 2024-08-07 08:10:55 -07:00
c61b1e899b added json-schema for config/preset.json 2024-08-07 07:58:21 -07:00
6fedea17ec added json-schema for config/tweaks.json 2024-08-07 07:56:15 -07:00
483baea1a4 json-schema for config/themes.json required fields 2024-08-07 07:17:08 -07:00
5a60625553 added json-schema for config/themes.json 2024-08-07 07:11:52 -07:00
26256e14f8 [build-script]: strip $schema from config jsons before embedding 2024-08-07 07:11:52 -07:00
4d7e6ded11 added json-schema for config/dns.json 2024-08-07 07:11:52 -07:00
32 changed files with 844 additions and 272 deletions

View File

@ -7,7 +7,7 @@ assignees: ''
---
## Describe the bug
<!-- A clear and concise description of what the bug is. -->
A clear and concise description of what the bug is.
## To Reproduce
Steps to reproduce the behavior:
@ -17,10 +17,10 @@ Steps to reproduce the behavior:
4. See error
## Expected behavior
<!-- A clear and concise description of what you expected to happen. -->
A clear and concise description of what you expected to happen.
## Screenshots
<!-- If applicable, add screenshots to help explain your problem. -->
If applicable, add screenshots to help explain your problem.
## Additional context
<!-- Add any other context about the problem here. -->
Add any other context about the problem here.

View File

@ -8,13 +8,13 @@ assignees: ''
---
**Is your feature request related to a problem? Please describe.**
<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
<!-- A clear and concise description of what you want to happen. -->
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
<!-- A clear and concise description of any alternative solutions or features you've considered. -->
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
<!-- Add any other context or screenshots about the feature request here. -->
Add any other context or screenshots about the feature request here.

View File

@ -1,9 +1,7 @@
# Pull Request
<!--Before you make this PR have you followed the docs here? - https://christitustech.github.io/winutil/contribute/ -->
## Title
<!--[Provide a succinct and descriptive title for the pull request.]-->
[Provide a succinct and descriptive title for the pull request.]
## Type of Change
- [ ] New feature
@ -15,20 +13,20 @@
- [ ] UI/UX improvement
## Description
<!--[Provide a detailed explanation of the changes you have made. Include the reasons behind these changes and any relevant context. Link any related issues.]-->
[Provide a detailed explanation of the changes you have made. Include the reasons behind these changes and any relevant context. Link any related issues.]
## Testing
<!--[Detail the testing you have performed to ensure that these changes function as intended. Include information about any added tests.]-->
[Detail the testing you have performed to ensure that these changes function as intended. Include information about any added tests.]
## Impact
<!--[Discuss the impact of your changes on the project. This might include effects on performance, new dependencies, or changes in behaviour.]-->
[Discuss the impact of your changes on the project. This might include effects on performance, new dependencies, or changes in behaviour.]
## Issue related to PR
<!--[What issue/discussion is related to this PR (if any)]-->
[What issue/discussion is related to this PR (if any)]
- Resolves #
## Additional Information
<!--[Any additional information that reviewers should be aware of.]-->
[Any additional information that reviewers should be aware of.]
## Checklist
- [ ] My code adheres to the coding and style guidelines of the project.

2
.github/SECURITY.md vendored
View File

@ -1,5 +1,5 @@
# Security Policy
If you find a security issue please make post it in the issues tab. If you think it should be private you can email me at contact@christitus.com.
If you find a security issue please make post it in the issues tab. If you think it should be private you can email me at contact@christitus.com.
For immediate response check out our discord server @ [![](https://dcbadge.limes.pink/api/server/https://discord.gg/RUbZUZyByQ?theme=default-inverted&style=for-the-badge)](https://discord.gg/RUbZUZyByQ)

View File

@ -1,24 +0,0 @@
name-template: '$RESOLVED_VERSION'
tag-template: '$RESOLVED_VERSION'
tag-prefix: ""
categories:
- title: '🚀 Features'
labels:
- 'feature'
- 'enhancement'
- title: '🐛 Bug Fixes'
labels:
- 'fix'
- 'bugfix'
- 'bug'
- title: '🧰 Maintenance'
label: 'chore'
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
template: |
## Changes
$CHANGES
## Contributors
$CONTRIBUTORS

View File

@ -22,8 +22,8 @@ jobs:
exempt-issue-labels: "Keep Issue Open"
# Split it into two weeks, after one week the issue will be marked as stale,
# after another week have pasted without any update.. the issue will then be closed.
days-before-issue-stale: 90
days-before-issue-close: 365
days-before-issue-stale: 7
days-before-issue-close: 7
# NEVER mark PRs as Stale or Close + this workflow should never have write permissions on PRs, EVER!
days-before-pr-stale: -1
days-before-pr-close: -1

View File

@ -7,7 +7,6 @@ on:
- '.github/requirements.txt'
- 'docs/**'
- 'overrides/**'
- '.github/CONTRIBUTING.md'
workflow_dispatch:
jobs:

View File

@ -74,52 +74,16 @@ jobs:
name: winutil
path: ./winutil.ps1
- name: Get latest release tag
id: get_latest_release
run: |
git fetch --tags --force
$latestTag = git for-each-ref --sort=-creatordate --format '%(refname:short)' refs/tags --count 1
if ($LASTEXITCODE -ne 0 -or [string]::IsNullOrEmpty($latestTag)) {
Write-Error "Failed to get latest tag. Error code: $LASTEXITCODE"
exit 1
}
Write-Host "Latest tag: $latestTag"
echo "LATEST_TAG=$latestTag" >> $env:GITHUB_ENV
shell: pwsh
- name: Generate Release Notes
id: generate_notes
uses: release-drafter/release-drafter@v5
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
config-name: release-drafter.yml
version: ${{ env.version }}
tag: ${{ env.LATEST_TAG }}
- name: Prepare Release Body
id: prepare_body
run: |
$newChanges = @'
${{ steps.generate_notes.outputs.body }}
'@
$formattedChanges = "Changes since ${{ env.LATEST_TAG }}:`n`n$newChanges"
$encodedChanges = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($formattedChanges))
echo "body=$encodedChanges" >> $env:GITHUB_OUTPUT
shell: pwsh
- name: Create and Upload Release
id: create_release
uses: softprops/action-gh-release@v2
with:
tag_name: ${{ env.version }}
name: Pre-Release ${{ env.version }}
body: |
${{ '{{' }} fromJson(format('"{0}"', steps.prepare_body.outputs.body)) | base64decode {{ '}}' }}
![GitHub Downloads (specific asset, specific tag)](https://img.shields.io/github/downloads/ChrisTitusTech/winutil/${{ env.VERSION }}/winutil.ps1)
tag_name: ${{ env.VERSION }}
name: Pre-Release ${{ env.VERSION }}
body: "![GitHub Downloads (specific asset, specific tag)](https://img.shields.io/github/downloads/ChrisTitusTech/winutil/${{ env.VERSION }}/winutil.ps1)"
append_body: false
files: ./winutil.ps1
prerelease: true
generate_release_notes: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -65,7 +65,35 @@ Get-ChildItem "$workingdir\functions" -Recurse -File | ForEach-Object {
Update-Progress "Adding: Config *.json" 40
Get-ChildItem "$workingdir\config" | Where-Object {$psitem.extension -eq ".json"} | ForEach-Object {
$json = (Get-Content $psitem.FullName).replace("'","''")
$jsonAsObject = $json | convertfrom-json
# Replace every XML Special Character so it'll render correctly in final build
# Only do so if json files has content to be displayed (for example the applications, tweaks, features json files)
# Make an Array List containing every name at first level of Json File
[PSCustomObject]$jsonAsObject = $json | convertfrom-json
# Remove properties like $schema and such from the json object (we don't need it at this point)
@(
"`$schema"
) | ForEach-Object {
$jsonAsObject.PSObject.Properties.Remove($_) | Out-Null
}
$firstLevelJsonList = [System.Collections.ArrayList]::new()
$jsonAsObject.PSObject.Properties.Name | ForEach-Object {$null = $firstLevelJsonList.Add($_)}
# Note:
# Avoid using HTML Entity Codes, for example '&rdquo;' (stands for "Right Double Quotation Mark"),
# Use **HTML decimal/hex codes instead**, as using HTML Entity Codes will result in XML parse Error when running the compiled script.
for ($i = 0; $i -lt $firstLevelJsonList.Count; $i += 1) {
$firstLevelName = $firstLevelJsonList[$i]
if ($jsonAsObject.$firstLevelName.content -ne $null) {
$jsonAsObject.$firstLevelName.content = $jsonAsObject.$firstLevelName.content.replace('&','&#38;').replace('“','&#8220;').replace('”','&#8221;').replace("'",'&#39;').replace('<','&#60;').replace('>','&#62;').replace('—','&#8212;')
$jsonAsObject.$firstLevelName.content = $jsonAsObject.$firstLevelName.content.replace('&#39;&#39;',"&#39;") # resolves the Double Apostrophe caused by the first replace function in the main loop
}
if ($jsonAsObject.$firstLevelName.description -ne $null) {
$jsonAsObject.$firstLevelName.description = $jsonAsObject.$firstLevelName.description.replace('&','&#38;').replace('“','&#8220;').replace('”','&#8221;').replace("'",'&#39;').replace('<','&#60;').replace('>','&#62;').replace('—','&#8212;')
$jsonAsObject.$firstLevelName.description = $jsonAsObject.$firstLevelName.description.replace('&#39;&#39;',"&#39;") # resolves the Double Apostrophe caused by the first replace function in the main loop
}
}
# Add 'WPFInstall' as a prefix to every entry-name in 'applications.json' file
if ($psitem.Name -eq "applications.json") {

View File

@ -1,4 +1,5 @@
{
"$schema": "../schemas/config/applications.json",
"1password": {
"category": "Utilities",
"choco": "1password",
@ -87,6 +88,14 @@
"link": "https://anydesk.com/",
"winget": "AnyDeskSoftwareGmbH.AnyDesk"
},
"ATLauncher": {
"category": "Games",
"choco": "na",
"content": "ATLauncher",
"description": "ATLauncher is a Launcher for Minecraft which integrates multiple different ModPacks to allow you to download and install ModPacks easily and quickly.",
"link": "https://github.com/ATLauncher/ATLauncher",
"winget": "ATLauncher.ATLauncher"
},
"audacity": {
"category": "Multimedia Tools",
"choco": "audacity",
@ -503,6 +512,14 @@
"link": "https://www.epicgames.com/store/en-US/",
"winget": "EpicGames.EpicGamesLauncher"
},
"errorlookup": {
"category": "Utilities",
"choco": "na",
"content": "Windows Error Code Lookup",
"description": "ErrorLookup is a tool for looking up Windows error codes and their descriptions.",
"link": "https://github.com/HenryPP/ErrorLookup",
"winget": "Henry++.ErrorLookup"
},
"esearch": {
"category": "Utilities",
"choco": "everything",

View File

@ -1,4 +1,5 @@
{
"$schema": "../schemas/config/dns.json",
"Google":{
"Primary": "8.8.8.8",
"Secondary": "8.8.4.4",

View File

@ -1,4 +1,5 @@
{
"$schema": "../schemas/config/feature.json",
"WPFFeaturesdotnet": {
"Content": "All .Net Framework (2,3,4)",
"Description": ".NET and .NET Framework is a developer platform made up of tools, programming languages, and libraries for building many different types of applications.",

View File

@ -1,4 +1,5 @@
{
"$schema": "../schemas/config/preset.json",
"Standard": [
"WPFTweaksAH",
"WPFTweaksConsumerFeatures",

View File

@ -1,4 +1,5 @@
{
"$schema": "../schemas/config/themes.json",
"_default": {
"CustomDialogFontSize": "12",
"CustomDialogFontSizeHeader": "14",

View File

@ -1,4 +1,5 @@
{
"$schema": "../schemas/config/tweaks.json",
"WPFTweaksAH": {
"Content": "Disable Activity History",
"Description": "This erases recent docs, clipboard, and run history.",
@ -2713,9 +2714,6 @@
reg delete \"HKEY_USERS\\Default\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run\" /v \"OneDriveSetup\" /f
reg unload \"hku\\Default\"
Write-Host \"Removing autostart key\"
reg delete \"HKEY_CURRENT_USER\\Software\\Microsoft\\Windows\\CurrentVersion\\Run\" /v \"OneDrive\" /f
Write-Host \"Removing startmenu entry\"
Remove-Item -Force -ErrorAction SilentlyContinue \"$env:userprofile\\AppData\\Roaming\\Microsoft\\Windows\\Start Menu\\Programs\\OneDrive.lnk\"
@ -3402,6 +3400,22 @@
"ComboItems": "Default DHCP Google Cloudflare Cloudflare_Malware Cloudflare_Malware_Adult Open_DNS Quad9 AdGuard_Ads_Trackers AdGuard_Ads_Trackers_Malware_Adult",
"link": "https://christitustech.github.io/winutil/dev/tweaks/z--Advanced-Tweaks---CAUTION/changedns"
},
"WPFTweaksbutton": {
"Content": "Run Tweaks",
"category": "z__Advanced Tweaks - CAUTION",
"panel": "1",
"Order": "a041_",
"Type": "Button",
"link": "https://christitustech.github.io/winutil/dev/tweaks/z--Advanced-Tweaks---CAUTION/button"
},
"WPFUndoall": {
"Content": "Undo Selected Tweaks",
"category": "z__Advanced Tweaks - CAUTION",
"panel": "1",
"Order": "a042_",
"Type": "Button",
"link": "https://christitustech.github.io/winutil/dev/tweaks/z--Advanced-Tweaks---CAUTION/Undoall"
},
"WPFAddUltPerf": {
"Content": "Add and Activate Ultimate Performance Profile",
"category": "Performance Plans",

View File

@ -7,9 +7,7 @@ function Invoke-WinUtilGPU {
"*NVIDIA GeForce*Laptop*",
"*NVIDIA GeForce*GT*",
"*AMD Radeon(TM)*",
"*Intel(R) HD Graphics*",
"*UHD*"
)
foreach ($gpu in $gpuInfo) {
@ -20,4 +18,4 @@ function Invoke-WinUtilGPU {
}
}
return $true
}
}

View File

@ -248,7 +248,7 @@ function Remove-FileOrDirectory([string]$pathToDelete, [string]$mask = "", [swit
function New-Unattend {
param (
[Parameter(Mandatory, Position = 0)] [string]$userName,
[Parameter(Mandatory, Position = 0)] [string] $userName,
[Parameter(Position = 1)] [string] $userPassword
)

View File

@ -11,7 +11,7 @@ Function Update-WinUtilProgramWinget {
$host.ui.RawUI.WindowTitle = """Winget Install"""
Start-Transcript "$logdir\winget-update_$dateTime.log" -Append
Start-Transcript $ENV:TEMP\winget-update.log -Append
winget upgrade --all --accept-source-agreements --accept-package-agreements --scope=machine --silent
}

View File

@ -21,13 +21,13 @@ function Invoke-WPFButton {
Switch -Wildcard ($Button) {
"WPFTab?BT" {Invoke-WPFTab $Button}
"WPFInstall" {Invoke-WPFInstall}
"WPFUninstall" {Invoke-WPFUnInstall}
"WPFinstall" {Invoke-WPFInstall}
"WPFuninstall" {Invoke-WPFUnInstall}
"WPFInstallUpgrade" {Invoke-WPFInstallUpgrade}
"WPFStandard" {Invoke-WPFPresets "Standard" -checkboxfilterpattern "WPFTweak*"}
"WPFMinimal" {Invoke-WPFPresets "Minimal" -checkboxfilterpattern "WPFTweak*"}
"WPFClearTweaksSelection" {Invoke-WPFPresets -imported $true -checkboxfilterpattern "WPFTweak*"}
"WPFClearInstallSelection" {Invoke-WPFPresets -imported $true -checkboxfilterpattern "WPFInstall*"}
"WPFstandard" {Invoke-WPFPresets "Standard"}
"WPFminimal" {Invoke-WPFPresets "Minimal"}
"WPFclear" {Invoke-WPFPresets -preset $null -imported $true}
"WPFclearWinget" {Invoke-WPFPresets -preset $null -imported $true -CheckBox "WPFInstall"}
"WPFtweaksbutton" {Invoke-WPFtweaksbutton}
"WPFOOSUbutton" {Invoke-WPFOOSU}
"WPFAddUltPerf" {Invoke-WPFUltimatePerformance -State "Enable"}

View File

@ -10,36 +10,29 @@ function Invoke-WPFPresets {
.PARAMETER imported
If the preset is imported from a file, defaults to false
.PARAMETER checkboxfilterpattern
The Pattern to use when filtering through CheckBoxes, defaults to "**"
.PARAMETER checkbox
The checkbox to set the options to, defaults to 'WPFTweaks'
#>
param (
[Parameter(position=0)]
[string]$preset = "",
[Parameter(position=1)]
[bool]$imported = $false,
[Parameter(position=2)]
[string]$checkboxfilterpattern = "**"
param(
$preset,
[bool]$imported = $false
)
if ($imported -eq $true) {
if($imported -eq $true) {
$CheckBoxesToCheck = $preset
} else {
$CheckBoxesToCheck = $sync.configs.preset.$preset
}
$CheckBoxes = ($sync.GetEnumerator()).where{ $_.Value -is [System.Windows.Controls.CheckBox] -and $_.Name -notlike "WPFToggle*" -and $_.Name -like "$checkboxfilterpattern"}
Write-Debug "Getting checkboxes to set, number of checkboxes: $($CheckBoxes.Count)"
$CheckBoxes = $sync.GetEnumerator() | Where-Object { $_.Value -is [System.Windows.Controls.CheckBox] -and $_.Name -notlike "WPFToggle*" }
Write-Debug "Getting checkboxes to set $($CheckBoxes.Count)"
if ($CheckBoxesToCheck -ne "") {
$debugMsg = "CheckBoxes to Check are: "
$CheckBoxesToCheck | ForEach-Object { $debugMsg += "$_, " }
$debugMsg = $debugMsg -replace (',\s*$', '')
Write-Debug "$debugMsg"
$CheckBoxesToCheck | ForEach-Object {
if ($_ -ne $null) {
Write-Debug $_
}
}
foreach ($CheckBox in $CheckBoxes) {

View File

@ -186,7 +186,6 @@ function Invoke-WPFUIElements {
$label.ToolTip = $entryInfo.Description
$label.HorizontalAlignment = "Left"
$label.FontSize = $theme.FontSize
$label.Foreground = $theme.MainForegroundColor
$dockPanel.Children.Add($label) | Out-Null
$stackPanel.Children.Add($dockPanel) | Out-Null

View File

@ -1,12 +1,5 @@
{% extends "base.html" %}
{% block header %}
{{ super() }}
<div style="color: red; text-align: center; padding: 10px; font-size: 20px;">
<strong>Announcement:</strong> We are currently not adding any applications to WinUtil and any apps that will be added through a PR will be declined by the maintainer.
</div>
{% endblock %}
{% block footer %}
{# Empty block to override the footer #}
{% endblock %}

View File

@ -1,87 +1,146 @@
# Enable verbose output
$VerbosePreference = "Continue"
# Define Test-Schema function
function Test-Schema {
param (
$Object,
$Schema
)
$errors = @()
$Object.PSObject.Properties | ForEach-Object {
$propName = $_.Name
$propValue = $_.Value
$propSchema = $Schema.Properties[$propName]
if (-not $propSchema) {
$errors += "Property '$propName' is not defined in the schema"
return
}
switch ($propSchema.Type) {
"String" {
if ($propValue -isnot [string]) {
$errors += "Property '$propName' should be a string but is $($propValue.GetType())"
}
}
"Object" {
if ($propValue -isnot [PSCustomObject]) {
$errors += "Property '$propName' should be an object but is $($propValue.GetType())"
} else {
$errors += Test-Schema -Object $propValue -Schema $propSchema
}
}
}
}
foreach ($requiredProp in $Schema.Required) {
if (-not $Object.PSObject.Properties.Name.Contains($requiredProp)) {
$errors += "Required property '$requiredProp' is missing"
}
}
return $errors
}
# Import Config Files
$global:importedconfigs = @{}
Get-ChildItem .\config | Where-Object {$_.Extension -eq ".json"} | ForEach-Object {
$global:importedconfigs[$psitem.BaseName] = Get-Content $psitem.FullName | ConvertFrom-Json
}
#===========================================================================
# Tests - Application Installs
#===========================================================================
Describe "Config Files" -ForEach @(
@{
name = "applications"
config = $('{
"winget": "value",
"choco": "value",
"category": "value",
"content": "value",
"description": "value",
"link": "value"
}' | ConvertFrom-Json)
},
@{
name = "tweaks"
undo = $true
}
) {
Context "$name config file" {
It "Imports with no errors" {
$global:importedconfigs.$name | should -Not -BeNullOrEmpty
}
if ($config) {
It "Imports should be the correct structure" {
$applications = $global:importedconfigs.$name | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty name
$template = $config | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty name
$result = New-Object System.Collections.Generic.List[System.Object]
Foreach ($application in $applications) {
$compare = $global:importedconfigs.$name.$application | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty name
if (-not $compare) {
throw "Comparison object for application '$application' is null."
}
if (-not $template) {
throw "Template object for application '$application' is null."
}
if ($(Compare-Object $compare $template) -ne $null) {
$result.Add($application)
}
}
$result | Select-String "WPF*" | should -BeNullOrEmpty
}
}
if($undo) {
It "Tweaks should contain original Value" {
$tweaks = $global:importedconfigs.$name | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty name
$result = New-Object System.Collections.Generic.List[System.Object]
foreach ($tweak in $tweaks) {
$Originals = @(
@{
name = "registry"
value = "OriginalValue"
},
@{
name = "service"
value = "OriginalType"
},
@{
name = "ScheduledTask"
value = "OriginalState"
}
)
Foreach ($original in $Originals) {
$TotalCount = ($global:importedconfigs.$name.$tweak.$($original.name)).count
$OriginalCount = ($global:importedconfigs.$name.$tweak.$($original.name).$($original.value) | Where-Object {$_}).count
if($TotalCount -ne $OriginalCount) {
$result.Add("$Tweak,$($original.name)")
}
}
}
$result | Select-String "WPF*" | should -BeNullOrEmpty
}
}
$global:importedConfigs = @{}
Get-ChildItem .\config -Filter *.json | ForEach-Object {
try {
$global:importedConfigs[$_.BaseName] = Get-Content $_.FullName | ConvertFrom-Json
Write-Verbose "Successfully imported config file: $($_.FullName)"
} catch {
Write-Error "Failed to import config file: $($_.FullName). Error: $_"
}
}
Describe "Config Files Validation" {
BeforeAll {
$script:configSchemas = @{
applications = @{
Type = "Object"
Properties = @{
winget = @{ Type = "String" }
choco = @{ Type = "String" }
category = @{ Type = "String" }
content = @{ Type = "String" }
description = @{ Type = "String" }
link = @{ Type = "String" }
}
Required = @("winget", "choco", "category", "content", "description", "link")
}
tweaks = @{
Type = "Object"
Properties = @{
registry = @{
Type = "Object"
Properties = @{
Path = @{ Type = "String" }
Name = @{ Type = "String" }
Type = @{ Type = "String" }
Value = @{ Type = "String" }
OriginalValue = @{ Type = "String" }
}
Required = @("Path", "Name", "Type", "Value", "OriginalValue")
}
service = @{
Type = "Object"
Properties = @{
Name = @{ Type = "String" }
StartupType = @{ Type = "String" }
OriginalType = @{ Type = "String" }
}
Required = @("Name", "StartupType", "OriginalType")
}
ScheduledTask = @{
Type = "Object"
Properties = @{
Name = @{ Type = "String" }
State = @{ Type = "String" }
OriginalState = @{ Type = "String" }
}
Required = @("Name", "State", "OriginalState")
}
}
}
}
}
Context "Config File Structure" {
It "Should import all config files without errors" {
$global:importedConfigs | Should -Not -BeNullOrEmpty -Because "No config files were imported successfully"
}
It "Should have the correct structure for all configs" {
$testSchemaScriptBlock = ${function:Test-Schema}.ToString()
$results = $configSchemas.Keys | ForEach-Object -Parallel {
$configName = $_
$importedConfigs = $using:global:importedConfigs
$configSchemas = $using:configSchemas
$config = $importedConfigs[$configName]
$schema = $configSchemas[$configName]
if (-not $config) {
return "Config file '$configName' is missing or empty"
}
$testSchemaFunction = [ScriptBlock]::Create($using:testSchemaScriptBlock)
& $testSchemaFunction -Object $config -Schema $schema
} -ThrottleLimit 4
$results | Should -BeNullOrEmpty -Because "The following schema violations were found: $($results -join '; ')"
}
}
}
# Summarize test results
$testResults = Invoke-Pester -PassThru
if ($testResults.FailedCount -gt 0) {
Write-Error "Tests failed. $($testResults.FailedCount) out of $($testResults.TotalCount) tests failed."
exit 1
} else {
Write-Output "All tests passed successfully!"
}

View File

@ -0,0 +1,55 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"definitions": {
"url": {
"type": "string",
"format": "uri"
}
},
"patternProperties": {
"^[a-zA-Z_][a-zA-Z0-9_]*$": {
"type": "object",
"properties": {
"content": {
"type": "string"
},
"description": {
"type": "string"
},
"category": {
"type": "string",
"enum": [
"Utilities",
"Document",
"Pro Tools",
"Multimedia Tools",
"Development",
"Games",
"Microsoft Tools",
"Browsers",
"Communications"
]
},
"choco": {
"type": "string"
},
"winget": {
"type": "string"
},
"link": {
"$ref": "#/definitions/url"
}
},
"required": [
"content",
"description",
"category",
"link",
"choco",
"winget"
],
"additionalProperties": false
}
}
}

29
schemas/config/dns.json Normal file
View File

@ -0,0 +1,29 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"patternProperties": {
"^[a-zA-Z_][a-zA-Z0-9_]*$": {
"type": "object",
"properties": {
"Primary": {
"type": "string",
"format": "ipv4"
},
"Secondary": {
"type": "string",
"format": "ipv4"
},
"Primary6": {
"type": "string",
"format": "ipv6"
},
"Secondary6": {
"type": "string",
"format": "ipv6"
}
},
"required": ["Primary", "Secondary", "Primary6", "Secondary6"],
"additionalProperties": false
}
}
}

View File

@ -0,0 +1,57 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"patternProperties": {
"^[a-zA-Z_][a-zA-Z0-9_]*$": {
"type": "object",
"properties": {
"Content": {
"type": "string"
},
"Description": {
"type": "string"
},
"category": {
"type": "string",
"enum": ["Features", "Fixes", "Legacy Windows Panels"]
},
"panel": {
"type": "string",
"pattern": "^\\d+$"
},
"Order": {
"type": "string",
"pattern": "^[0-9a-f]+_$"
},
"feature": {
"type": "array",
"items": {
"type": "string"
}
},
"InvokeScript": {
"type": "array",
"items": {
"type": "string"
}
},
"UndoScript": {
"type": "array",
"items": {
"type": "string"
}
},
"Type": {
"type": "string",
"enum": ["Button"]
},
"ButtonWidth": {
"type": "string",
"pattern": "^\\d+$"
}
},
"required": ["Content", "category", "panel"],
"additionalProperties": false
}
}
}

View File

@ -0,0 +1,12 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"patternProperties": {
"^[a-zA-Z_][a-zA-Z0-9_]*$": {
"type": "array",
"items": {
"type": "string"
}
}
}
}

297
schemas/config/themes.json Normal file
View File

@ -0,0 +1,297 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"color": {
"type": "string",
"pattern": "^Transparent|(#[0-9A-Fa-f]{6})$"
},
"decimal": {
"type": "string",
"pattern": "^\\d+(\\.\\d+)?$"
}
},
"type": "object",
"patternProperties": {
"^[a-zA-Z_][a-zA-Z0-9_]*$": {
"type": "object",
"properties": {
"CustomDialogFontSize": {
"type": "string",
"pattern": "^\\d+$"
},
"CustomDialogFontSizeHeader": {
"type": "string",
"pattern": "^\\d+$"
},
"CustomDialogIconSize": {
"type": "string",
"pattern": "^\\d+$"
},
"CustomDialogWidth": {
"type": "string",
"pattern": "^\\d+$"
},
"CustomDialogHeight": {
"type": "string",
"pattern": "^\\d+$"
},
"FontSize": {
"type": "string",
"pattern": "^\\d+$"
},
"FontFamily": {
"type": "string"
},
"FontSizeHeading": {
"type": "string",
"pattern": "^\\d+$"
},
"HeaderFontFamily": {
"type": "string"
},
"CheckBoxBulletDecoratorFontSize": {
"type": "string",
"pattern": "^\\d+$"
},
"CheckBoxMargin": {
"type": "string"
},
"TabButtonFontSize": {
"type": "string",
"pattern": "^\\d+$"
},
"TabButtonWidth": {
"type": "string",
"pattern": "^\\d+$"
},
"TabButtonHeight": {
"type": "string",
"pattern": "^\\d+$"
},
"TabRowHeightInPixels": {
"type": "string",
"pattern": "^\\d+$"
},
"IconFontSize": {
"type": "string",
"pattern": "^\\d+$"
},
"IconButtonSize": {
"type": "string",
"pattern": "^\\d+$"
},
"WinUtilIconSize": {
"type": "string"
},
"SettingsIconFontSize": {
"type": "string",
"pattern": "^\\d+$"
},
"MicroWinLogoSize": {
"type": "string",
"pattern": "^\\d+$"
},
"ProgressBarForegroundColor": {
"$ref": "#/definitions/color"
},
"ProgressBarBackgroundColor": {
"$ref": "#/definitions/color"
},
"ProgressBarTextColor": {
"$ref": "#/definitions/color"
},
"ComboBoxBackgroundColor": {
"$ref": "#/definitions/color"
},
"LabelboxForegroundColor": {
"$ref": "#/definitions/color"
},
"MainForegroundColor": {
"$ref": "#/definitions/color"
},
"MainBackgroundColor": {
"$ref": "#/definitions/color"
},
"LabelBackgroundColor": {
"$ref": "#/definitions/color"
},
"LinkForegroundColor": {
"$ref": "#/definitions/color"
},
"LinkHoverForegroundColor": {
"$ref": "#/definitions/color"
},
"GroupBorderBackgroundColor": {
"$ref": "#/definitions/color"
},
"ComboBoxForegroundColor": {
"$ref": "#/definitions/color"
},
"ButtonFontSize": {
"type": "string",
"pattern": "^\\d+$"
},
"ButtonFontFamily": {
"type": "string"
},
"ButtonWidth": {
"type": "string",
"pattern": "^\\d+$"
},
"ButtonHeight": {
"type": "string",
"pattern": "^\\d+$"
},
"ConfigTabButtonFontSize": {
"type": "string",
"pattern": "^\\d+$"
},
"SearchBarWidth": {
"type": "string",
"pattern": "^\\d+$"
},
"SearchBarHeight": {
"type": "string",
"pattern": "^\\d+$"
},
"SearchBarTextBoxFontSize": {
"type": "string",
"pattern": "^\\d+$"
},
"SearchBarClearButtonFontSize": {
"type": "string",
"pattern": "^\\d+$"
},
"ButtonInstallBackgroundColor": {
"$ref": "#/definitions/color"
},
"ButtonTweaksBackgroundColor": {
"$ref": "#/definitions/color"
},
"ButtonConfigBackgroundColor": {
"$ref": "#/definitions/color"
},
"ButtonUpdatesBackgroundColor": {
"$ref": "#/definitions/color"
},
"ButtonInstallForegroundColor": {
"$ref": "#/definitions/color"
},
"ButtonTweaksForegroundColor": {
"$ref": "#/definitions/color"
},
"ButtonConfigForegroundColor": {
"$ref": "#/definitions/color"
},
"ButtonUpdatesForegroundColor": {
"$ref": "#/definitions/color"
},
"ButtonBackgroundColor": {
"$ref": "#/definitions/color"
},
"ButtonBackgroundPressedColor": {
"$ref": "#/definitions/color"
},
"CheckboxMouseOverColor": {
"$ref": "#/definitions/color"
},
"ButtonBackgroundMouseoverColor": {
"$ref": "#/definitions/color"
},
"ButtonBackgroundSelectedColor": {
"$ref": "#/definitions/color"
},
"ButtonForegroundColor": {
"$ref": "#/definitions/color"
},
"ToggleButtonOnColor": {
"$ref": "#/definitions/color"
},
"ButtonBorderThickness": {
"type": "string",
"pattern": "^\\d+$"
},
"ButtonMargin": {
"type": "string",
"pattern": "^\\d+$"
},
"ButtonCornerRadius": {
"type": "string",
"pattern": "^\\d+$"
},
"BorderColor": {
"$ref": "#/definitions/color"
},
"BorderOpacity": {
"$ref": "#/definitions/decimal"
},
"ShadowPulse": {
"type": "string"
}
},
"required": [
"CustomDialogFontSize",
"CustomDialogFontSizeHeader",
"CustomDialogIconSize",
"CustomDialogWidth",
"CustomDialogHeight",
"FontSize",
"FontFamily",
"FontSizeHeading",
"HeaderFontFamily",
"CheckBoxBulletDecoratorFontSize",
"CheckBoxMargin",
"TabButtonFontSize",
"TabButtonWidth",
"TabButtonHeight",
"TabRowHeightInPixels",
"IconFontSize",
"IconButtonSize",
"WinUtilIconSize",
"SettingsIconFontSize",
"MicroWinLogoSize",
"ProgressBarForegroundColor",
"ProgressBarBackgroundColor",
"ProgressBarTextColor",
"ComboBoxBackgroundColor",
"LabelboxForegroundColor",
"MainForegroundColor",
"MainBackgroundColor",
"LabelBackgroundColor",
"LinkForegroundColor",
"LinkHoverForegroundColor",
"ComboBoxForegroundColor",
"ButtonFontSize",
"ButtonFontFamily",
"ButtonWidth",
"ButtonHeight",
"ConfigTabButtonFontSize",
"SearchBarWidth",
"SearchBarHeight",
"SearchBarTextBoxFontSize",
"SearchBarClearButtonFontSize",
"ButtonInstallBackgroundColor",
"ButtonTweaksBackgroundColor",
"ButtonConfigBackgroundColor",
"ButtonUpdatesBackgroundColor",
"ButtonInstallForegroundColor",
"ButtonTweaksForegroundColor",
"ButtonConfigForegroundColor",
"ButtonUpdatesForegroundColor",
"ButtonBackgroundColor",
"ButtonBackgroundPressedColor",
"ButtonBackgroundMouseoverColor",
"ButtonBackgroundSelectedColor",
"ButtonForegroundColor",
"ToggleButtonOnColor",
"ButtonBorderThickness",
"ButtonMargin",
"ButtonCornerRadius",
"BorderColor",
"BorderOpacity",
"ShadowPulse"
],
"additionalProperties": false
}
}
}

121
schemas/config/tweaks.json Normal file
View File

@ -0,0 +1,121 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"type": "object",
"definitions": {
"toggle-state": {
"type": "string",
"enum": ["Enabled", "Disabled"]
}
},
"patternProperties": {
"^[a-zA-Z_][a-zA-Z0-9_]*$": {
"type": "object",
"properties": {
"Content": {
"type": "string"
},
"Description": {
"type": "string"
},
"category": {
"type": "string",
"enum": [
"Essential Tweaks",
"Performance Plans",
"Customize Preferences",
"z__Advanced Tweaks - CAUTION",
"Shortcuts"
]
},
"panel": {
"type": "string",
"pattern": "^\\d+$"
},
"Order": {
"type": "string",
"pattern": "^[0-9a-f]+_$"
},
"registry": {
"type": "array",
"items": {
"type": "object",
"properties": {
"Path": {
"type": "string"
},
"Name": {
"type": "string"
},
"Type": {
"type": "string"
},
"Value": {
"type": "string"
},
"OriginalValue": {
"type": "string"
}
},
"required": ["Path", "Name", "Type", "Value", "OriginalValue"]
}
},
"service": {
"type": "array",
"items": {
"type": "object",
"properties": {
"Name": {
"type": "string"
},
"StartupType": {
"type": "string"
},
"OriginalType": {
"type": "string"
}
},
"required": ["Name", "StartupType", "OriginalType"]
}
},
"appx": {
"type": "array",
"items": {
"type": "string"
}
},
"ScheduledTask": {
"type":"array",
"items": {
"type": "object",
"properties": {
"Name": {
"type": "string"
},
"State": {
"$ref": "#/definitions/toggle-state"
},
"OriginalState": {
"$ref": "#/definitions/toggle-state"
}
},
"required": ["Name", "State", "OriginalState"]
}
},
"InvokeScript": {
"type": "array",
"items": {
"type": "string"
}
},
"UndoScript": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": ["Content", "Description", "category", "panel", "Order"],
"additionalProperties": false
}
}
}

View File

@ -85,16 +85,22 @@ try {
$sync["Form"] = [Windows.Markup.XamlReader]::Load( $reader )
$readerOperationSuccessful = $true
} catch [System.Management.Automation.MethodInvocationException] {
Write-Host "We ran into a problem with the XAML code. Check the syntax for this control..." -ForegroundColor Red
Write-Warning "We ran into a problem with the XAML code. Check the syntax for this control..."
Write-Host $error[0].Exception.Message -ForegroundColor Red
If ($error[0].Exception.Message -like "*button*") {
write-Host "Ensure your &lt;button in the `$inputXML does NOT have a Click=ButtonClick property. PS can't handle this`n`n`n`n" -ForegroundColor Red
write-warning "Ensure your &lt;button in the `$inputXML does NOT have a Click=ButtonClick property. PS can't handle this`n`n`n`n"
}
} catch {
Write-Host "Unable to load Windows.Markup.XamlReader. Double-check syntax and ensure .net is installed." -ForegroundColor Red
Write-Host "Unable to load Windows.Markup.XamlReader. Double-check syntax and ensure .net is installed."
}
# Load the configuration files
#Invoke-WPFUIElements -configVariable $sync.configs.nav -targetGridName "WPFMainGrid"
Invoke-WPFUIElements -configVariable $sync.configs.applications -targetGridName "appspanel" -columncount 5
Invoke-WPFUIElements -configVariable $sync.configs.tweaks -targetGridName "tweakspanel" -columncount 2
Invoke-WPFUIElements -configVariable $sync.configs.feature -targetGridName "featurespanel" -columncount 2
if (-NOT ($readerOperationSuccessful)) {
Write-Host "Failed to parse xaml content using Windows.Markup.XamlReader's Load Method." -ForegroundColor Red
Write-Host "Quitting winutil..." -ForegroundColor Red
@ -104,12 +110,6 @@ if (-NOT ($readerOperationSuccessful)) {
exit 1
}
# Load the configuration files
#Invoke-WPFUIElements -configVariable $sync.configs.nav -targetGridName "WPFMainGrid"
Invoke-WPFUIElements -configVariable $sync.configs.applications -targetGridName "appspanel" -columncount 5
Invoke-WPFUIElements -configVariable $sync.configs.tweaks -targetGridName "tweakspanel" -columncount 2
Invoke-WPFUIElements -configVariable $sync.configs.feature -targetGridName "featurespanel" -columncount 2
#===========================================================================
# Store Form Objects In PowerShell
#===========================================================================

View File

@ -27,11 +27,11 @@ if ($Run) {
$PARAM_RUN = $true
}
$dateTime = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
if (!(Test-Path -Path $ENV:TEMP)) {
New-Item -ItemType Directory -Force -Path $ENV:TEMP
}
$logdir = "$env:localappdata\winutil\logs"
[System.IO.Directory]::CreateDirectory("$logdir")
Start-Transcript -Path "$logdir\winutil_$dateTime.log" -Append
Start-Transcript $ENV:TEMP\Winutil.log -Append
# Load DLLs
Add-Type -AssemblyName PresentationFramework

View File

@ -315,7 +315,7 @@
Margin="2"
SnapsToDevicePixels="True"/>
<Path x:Name="CheckMark"
Stroke="{ToggleButtonOnColor}"
Stroke="{TemplateBinding Foreground}"
StrokeThickness="2"
Data="M 0 5 L 5 10 L 12 0"
Visibility="Collapsed"/>
@ -427,11 +427,7 @@
Width="34" Height="17">
<Ellipse x:Name="Ellipse" Fill="{MainForegroundColor}" Stretch="Uniform"
Margin="2,2,2,1"
HorizontalAlignment="Left" Width="10.8"
RenderTransformOrigin="0.5, 0.5">
<Ellipse.RenderTransform>
<ScaleTransform ScaleX="1" ScaleY="1" />
</Ellipse.RenderTransform>
HorizontalAlignment="Left" Width="12">
</Ellipse>
</Border>
</Grid>
@ -442,35 +438,12 @@
<Setter TargetName="Border" Property="Background" Value="{LinkHoverForegroundColor}"/>
<Setter Property="Cursor" Value="Hand" />
<Setter Property="Panel.ZIndex" Value="1000"/>
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Ellipse"
Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
To="1.1" Duration="0:0:0.1" />
<DoubleAnimation Storyboard.TargetName="Ellipse"
Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
To="1.1" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="Ellipse"
Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
To="1.0" Duration="0:0:0.1" />
<DoubleAnimation Storyboard.TargetName="Ellipse"
Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
To="1.0" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="False">
<Setter TargetName="Border" Property="Background" Value="{MainBackgroundColor}" />
<Setter TargetName="Border" Property="BorderBrush" Value="#707070" />
<Setter TargetName="Ellipse" Property="Fill" Value="#707070" />
<Setter TargetName="Border" Property="BorderBrush" Value="{MainForegroundColor}" />
<Setter TargetName="Ellipse" Property="Fill" Value="{MainForegroundColor}" />
</Trigger>
<Trigger Property="ToggleButton.IsChecked" Value="True">
@ -814,11 +787,11 @@
<RowDefinition Height="0.95*"/>
</Grid.RowDefinitions>
<StackPanel Background="{MainBackgroundColor}" Orientation="Horizontal" Grid.Row="0" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Column="0" Grid.ColumnSpan="3" Margin="{TabContentMargin}">
<Button Name="WPFInstall" Content=" Install/Upgrade Selected" Margin="2" />
<Button Name="WPFinstall" Content=" Install/Upgrade Selected" Margin="2" />
<Button Name="WPFInstallUpgrade" Content=" Upgrade All" Margin="2"/>
<Button Name="WPFUninstall" Content=" Uninstall Selected" Margin="2"/>
<Button Name="WPFuninstall" Content=" Uninstall Selected" Margin="2"/>
<Button Name="WPFGetInstalled" Content=" Get Installed" Margin="2"/>
<Button Name="WPFClearInstallSelection" Content=" Clear Selection" Margin="2"/>
<Button Name="WPFclearWinget" Content=" Clear Selection" Margin="2"/>
</StackPanel>
<ScrollViewer x:Name="scrollViewer" Grid.Row="1" Grid.Column="0" Margin="{TabContentMargin}" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"
@ -869,20 +842,6 @@
</Border>
</Grid>
</ScrollViewer>
<Border Grid.Row="1" Background="{MainBackgroundColor}" BorderBrush="{BorderColor}" BorderThickness="1" CornerRadius="5" HorizontalAlignment="Stretch" Padding="10">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="1*" />
</Grid.ColumnDefinitions>
<!-- Buttons on the left half -->
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center" Grid.Column="0">
<Button Name="WPFTweaksbutton" Content="Run Tweaks" Margin="5"/>
<Button Name="WPFUndoall" Content="Undo Selected Tweaks" Margin="5"/>
</StackPanel>
</Grid>
</Border>
</Grid>
</TabItem>
<TabItem Header="Config" Visibility="Collapsed" Name="WPFTab3">