Compare commits

..

27 Commits

Author SHA1 Message Date
52de4690ab Update start.ps1 (#3223)
- use join method to parse $argList
- use $PSCommandPath instead of $MyInvocation.MyCommand.Path
- use ScriptBlock method to create request for latest winutil.ps1 with join $argList 
- condition for $processCmd because in case when wt.exe is not available, there was double/redundant declaration of shell which lead to code mishmash (incorrect interpretation of quotes from Start-Process ArgumentList parameters 
- changes in quotes and escape characters because command where not interpreted correctly in all possible cases of $powershellCmd and $processCmd
2025-03-05 12:15:13 -06:00
ef97a8da24 [WinGet] Fix install loop (#3235)
Only this parameter was missing
2025-03-05 12:13:39 -06:00
18a7f17a0b [APP addition] Zen Browser (#3231)
* add Zen to Browsers for Applications

* remove choco option since it currently needs the --pre flag
2025-03-04 14:31:28 -06:00
5a8cf5deb6 Removing Github and Nuget method. Revamp of Version check to use DesktopAppInstaller (#3233) 2025-03-04 14:30:54 -06:00
e4b2a38372 fix a few tweak errors 2025-03-03 14:31:18 -06:00
94c5d89430 fix winget for good (#3096) 2025-03-03 14:16:53 -06:00
8a0e0c7715 [UI/UX] Refractor Install Tab (#2859)
* initial visual implementation

- remove idiotic border logic from Invoke-WPFUIElements
- add "application" type & style
- add "radiobutton" type & style
- remove prefer choco checkbox (did not modify logic outside of xaml, so i currently get errors due to that)

* add image support via choco db

- add image support via choco db
- backup image should be taken from unigetui db
- backup backup image is some random package one rn

* add compatibility for every app

* performance improvements

- move get logo to runspace (not working rn)
- readd choco checkbox to mute errors

* add border name

* fix scrollviewer & reimplement logo logic into ui elements

* noimage fix

* add notes

* cleanup & remove nav from search effects

* add button action

* rename buttons

* add sort by options

* move scrollviewer & app buttons into uielements logic

* format logic for app action buttons

* fix app action button logic & move get & clear to sidepanel

* change category of new buttons

* add virtualisation & layouting fixes

- commented out prefer choco logic
- add virtualisation
- layouting improvements

* fix radiobuttons

* LETS GOOO  (#12)

* Add Selected Apps Label, Reshuffel the nesting of the checkbox and the label to be able to reference the name from the actual checkbox

* Add visual selection and allow click on the whole app section

* Fix Theme definition to work with theme change

* Fix Highlight on if label or icon is clicked

* change applications.json to powershell object list and refactor UI Creation logic

* Optimization and Add Collapsable Categories

* Add Button functionality for install, uninstall, info, install selected, uninstall selected, clear and implement search

* Rest application.json to Main

* Reset Compile to main

* Pretty much revamp_apps but without changes to applications.json

* Small fixes

* Add Get-Installed Loading Indicator + small fixes

* Re-Add Choco Preference

* Remove Logic from Invoke-WPFUIElements that is Moved to Invoke-WPFUIApps

* Remove Alphabetical List, Sort Apps inside Category Alphabetically

* Small fixes to the Get-Installed function and formatting stuff

* Style for Hidden Checkbox but visible Content

* Hotfix for Category Expansion during search

* Replace Category Label with ToggleButton, Fix Search Bugs

* First Try at implementing a Compact Mode for the App page

* Fix Whitespace when using Search

* Keep the search status when switching between compact and full view

* Fix weird buggy behaviour in regards to switching the Display Mode and using Show-SelectedOnly

* Improve Togglebutton

- add initial implementation of togglebutton style
- add togglebuttons to appnavigation.json
- refractor UI element creation for Togglebutton
- commit preprocessing changes

* Togglebutton fixes

- move dot to the right in style
- cleanup code
- fix arrangement of content

* Add logic to the new ToggleButtons in the sidebar of the install tab and remove old buttons

* reorder buttons & fix Togglebutton toggling if action not possible

- reorder getinstalled and clearselection
- set togglebutton back if no app is selected

* Slight modificatoin to togglebutton style & fix sidebar width

* Add hover effect for the app tiles

* ToggleButtonStyle animation

- add hover animation to white dot
- remove IsPressed trigger
- improve some comments

* disable show selected filter on clear selection

* Add a Popup Dropdown for Selected Apps with the ability to deselect them

* Split up the functions to seperate files like the rest of the repo

* Fix Bug where Scrollviewer dosnt work

* disable autofallback checkbox

* run preprocessing

* remove installation scope

- remove all 3 radiobuttons from appnavigation.json

* remove scrollviewer from WPFUIElements

* toggle showselected on GetInstalled

* remove unused autofallback

---------

Co-authored-by: Martin Wiethan <47688561+Marterich@users.noreply.github.com>
Co-authored-by: Chris Titus <contact@christitus.com>
2025-03-01 13:50:12 -06:00
1ae16f6f38 Update dev docs table of contents links (#3181) 2025-02-28 10:59:42 -06:00
6038556e64 Feature/disable wpbt execution (#3188)
* add IDE

* add tweak
2025-02-28 10:56:45 -06:00
329a3de9a6 Fix winget command and update FxSound description (#3207) 2025-02-28 10:55:19 -06:00
f6e5d0e053 Deploying to main from @ ChrisTitusTech/winutil@364076c25e 🚀 2025-02-27 15:33:22 +00:00
364076c25e [GHTemplates] Use new preview of Issue templates (#3202)
* use new issue preview

- convert existing issue templates to new template style
- move issue validation to start
- add important section at start
- improve checkbox UX
- improve wording a bit
- add config to link discord & remove blank issues

* remove description
2025-02-25 11:29:18 -06:00
a051e64a91 Deploying to main from @ ChrisTitusTech/winutil@dccda61ab4 🚀 2025-02-20 15:33:18 +00:00
dccda61ab4 Deploying to main from @ ChrisTitusTech/winutil@048f580a56 🚀 2025-02-06 15:32:52 +00:00
048f580a56 Deploying to main from @ ChrisTitusTech/winutil@bfb83ced79 🚀 2025-02-05 15:33:03 +00:00
bfb83ced79 Deploying to main from @ ChrisTitusTech/winutil@e2b37445f6 🚀 2025-02-01 15:31:03 +00:00
e2b37445f6 Deploying to main from @ ChrisTitusTech/winutil@c2fb98b0dc 🚀 2025-01-31 15:30:57 +00:00
c2fb98b0dc Deploying to main from @ ChrisTitusTech/winutil@cf8787a700 🚀 2025-01-30 15:32:01 +00:00
cf8787a700 Fixed impartial nerd font uninstallation (#3171)
* fix: nerdfonts uninstall now deletes corresponding registry keys

* change ErrorAction to SilentlyContinue

* fix some code styling

* removed unused files/docs as per Cryostrixx advice

* restored portions of the feature.json
2025-01-28 13:59:00 -06:00
53b723fa11 update application.json (#3166) 2025-01-28 13:50:31 -06:00
32cb94f392 [MicroWin] Fixed divide by zero error for fallback (#3174)
<Insert the never mind - misspelled a variable meme here>
2025-01-28 11:03:35 -06:00
5550e40270 Deploying to main from @ ChrisTitusTech/winutil@bcecf67c7d 🚀 2025-01-28 15:32:37 +00:00
bcecf67c7d Deploying to main from @ ChrisTitusTech/winutil@3b50ff813c 🚀 2025-01-27 15:30:51 +00:00
3b50ff813c Deploying to main from @ ChrisTitusTech/winutil@eba5b35978 🚀 2025-01-26 15:30:58 +00:00
eba5b35978 Deploying to main from @ ChrisTitusTech/winutil@254738a420 🚀 2025-01-20 15:32:07 +00:00
254738a420 Use HTTPS instead of HTTP for URLs where supported. (#3161) 2025-01-17 08:42:42 -06:00
bcc801683d [Tweaks] Disable output for DISM for the Recall tweak (#3154)
* Fixed lock caused by expected input for DISM

This is the main event

* Miscellaneous file

Don't know why this file was modified by the compile preprocessor
2025-01-17 08:40:04 -06:00
49 changed files with 1472 additions and 693 deletions

View File

@ -1,30 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: 'bug'
assignees: ''
---
## Describe the bug
<!-- A clear and concise description of what the bug is. -->
## Steps to reproduce
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See the error.
## Expected behavior
<!-- A clear and concise description of what you expected to happen. -->
## Screenshots
<!-- If applicable, add screenshots to help explain your problem. -->
## Additional context
<!-- Add any other context about the problem here. -->
## Issue validation
- [ ] I checked for duplicate issues.
- [ ] I checked for already existing discussions.
- [ ] I checked for an already existing pull request addressing the issue.

62
.github/ISSUE_TEMPLATE/bug_report.yaml vendored Normal file
View File

@ -0,0 +1,62 @@
name: "Bug report"
description: "Report a bug to help us identify and fix issues in the project."
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
# 🐞 **Issue Report**
Thank you for taking the time to report an issue! Please provide as much detail as possible to help us address the problem efficiently.
## ⚠️ **IMPORTANT**
- 🛠️ **Supported environments only:** We only support Windows 11. Custom ISOs that are not made using Microwin are not supported.
- 💡 For general questions, use the [Discussions section](https://github.com/Christitustech/winutil/discussions) or join our Community-driven [Discord Server](https://discord.gg/RUbZUZyByQ).
- type: checkboxes
attributes:
label: ⚙️ Issue Checklist
options:
- label: I have read the guidelines.
- label: I checked for duplicate issues.
- label: I searched for existing discussions.
- label: I checked for an existing pull request that addresses this issue.
validations:
required: true
- type: input
id: affected_part
attributes:
label: 📜 What part of Winutil are you having issues with?
placeholder: "e.g., Microwin, Tweaks, etc."
validations:
required: true
- type: textarea
id: issue_description
attributes:
label: 📝 Provide a clear and concise description of the issue.
validations:
required: true
- type: textarea
id: steps_to_reproduce
attributes:
label: 🔄 Steps to reproduce the issue.
placeholder: "e.g., Step 1: ..., Step 2: ..."
validations:
required: true
- type: textarea
id: error_output
attributes:
label: ❌ Paste the full error output (if available).
placeholder: "Include any relevant logs or error messages."
- type: textarea
id: additional_context
attributes:
label: 🖼️ Additional context.
placeholder: "Include screenshots, code blocks (use triple backticks ```), or any other relevant information."
validations:
required: false

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: 💻 Community Discord
url: https://discord.gg/RUbZUZyByQ
about: Join our Community Discord server to chat with other users in the Winutil community.

View File

@ -1,24 +0,0 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: 'enhancement'
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 [...] -->
## Describe the solution you'd like
<!-- 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. -->
## Additional context
<!-- Add any other context or screenshots about the feature request here. -->
## Issue validation
- [ ] I checked for duplicate issues.
- [ ] I checked for already existing discussions.
- [ ] I checked for an already existing pull request addressing the issue.

View File

@ -0,0 +1,57 @@
name: "Feature request"
description: "Suggest a new feature or improvement for the project."
labels: ["enhancement"]
body:
- type: markdown
attributes:
value: |
# ✨ **Feature request**
Thank you for taking the time to suggest a feature! Please provide as much detail as possible to help us understand and evaluate your request.
## ⚠️ **IMPORTANT**
- 🛠️ **Supported environments only:** We only support Windows 11.
- 💡 For general questions, use the [Discussions section](https://github.com/Christitustech/winutil/discussions) or join our Community-driven [Discord Server](https://discord.gg/RUbZUZyByQ).
- type: checkboxes
attributes:
label: ⚙️ Issue Checklist
options:
- label: I have read the guidelines.
- label: I checked for duplicate issues.
- label: I searched for existing discussions.
- label: I checked for an existing pull request that addresses this request.
validations:
required: true
- type: textarea
id: problem_statement
attributes:
label: ❓ Is your feature request related to a problem?
placeholder: "Provide a clear and concise description of the issue you're facing. Example: 'I'm always frustrated when [...]'"
validations:
required: false
- type: textarea
id: proposed_solution
attributes:
label: 💡 Describe the solution you'd like
placeholder: "Provide a clear and concise description of what you want to happen."
validations:
required: true
- type: textarea
id: alternatives
attributes:
label: 🔄 Describe alternatives you've considered
placeholder: "Provide details on any alternative solutions or features you've thought about."
validations:
required: false
- type: textarea
id: additional_context
attributes:
label: 🖼️ Additional context
placeholder: "Include screenshots, code blocks (use triple backticks ```), or any other relevant information."
validations:
required: false

1
.gitignore vendored
View File

@ -2,6 +2,7 @@
# Configuration folder
.vscode/
.idea/
### Visual Studio ###

View File

@ -52,7 +52,7 @@ If you have Issues, refer to [Known Issues](https://christitustech.github.io/win
These are the sponsors that help keep this project alive with monthly contributions.
<!-- sponsors --><a href="https://github.com/TriHydera"><img src="https:&#x2F;&#x2F;github.com&#x2F;TriHydera.png" width="60px" alt="User avatar: TriHydera" /></a><a href="https://github.com/jozozovko"><img src="https:&#x2F;&#x2F;github.com&#x2F;jozozovko.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/DelDongo"><img src="https:&#x2F;&#x2F;github.com&#x2F;DelDongo.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/markamos"><img src="https:&#x2F;&#x2F;github.com&#x2F;markamos.png" width="60px" alt="User avatar: Mark Amos" /></a><a href="https://github.com/dwelfusius"><img src="https:&#x2F;&#x2F;github.com&#x2F;dwelfusius.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/mews-se"><img src="https:&#x2F;&#x2F;github.com&#x2F;mews-se.png" width="60px" alt="User avatar: Martin Stockzell" /></a><a href="https://github.com/jdiegmueller"><img src="https:&#x2F;&#x2F;github.com&#x2F;jdiegmueller.png" width="60px" alt="User avatar: Jason A. Diegmueller" /></a><a href="https://github.com/AlanTristar"><img src="https:&#x2F;&#x2F;github.com&#x2F;AlanTristar.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/zepled112"><img src="https:&#x2F;&#x2F;github.com&#x2F;zepled112.png" width="60px" alt="User avatar: wyatt" /></a><a href="https://github.com/altugtekiner"><img src="https:&#x2F;&#x2F;github.com&#x2F;altugtekiner.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/robertsandrock"><img src="https:&#x2F;&#x2F;github.com&#x2F;robertsandrock.png" width="60px" alt="User avatar: RMS" /></a><a href="https://github.com/KenichiQaz"><img src="https:&#x2F;&#x2F;github.com&#x2F;KenichiQaz.png" width="60px" alt="User avatar: Stefan" /></a><a href="https://github.com/paulsheets"><img src="https:&#x2F;&#x2F;github.com&#x2F;paulsheets.png" width="60px" alt="User avatar: Paul" /></a><a href="https://github.com/djones369"><img src="https:&#x2F;&#x2F;github.com&#x2F;djones369.png" width="60px" alt="User avatar: Dave Jones" /></a><a href="https://github.com/anthonymendez"><img src="https:&#x2F;&#x2F;github.com&#x2F;anthonymendez.png" width="60px" alt="User avatar: Anthony Mendez" /></a><a href="https://github.com/claudemods"><img src="https:&#x2F;&#x2F;github.com&#x2F;claudemods.png" width="60px" alt="User avatar: Claudemods" /></a><a href="https://github.com/FatBastard0"><img src="https:&#x2F;&#x2F;github.com&#x2F;FatBastard0.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/Ascent7910"><img src="https:&#x2F;&#x2F;github.com&#x2F;Ascent7910.png" width="60px" alt="User avatar: Max" /></a><a href="https://github.com/DursleyGuy"><img src="https:&#x2F;&#x2F;github.com&#x2F;DursleyGuy.png" width="60px" alt="User avatar: DursleyGuy" /></a><a href="https://github.com/YamiSandman616"><img src="https:&#x2F;&#x2F;github.com&#x2F;YamiSandman616.png" width="60px" alt="User avatar: Sandman616" /></a><a href="https://github.com/realmuddy"><img src="https:&#x2F;&#x2F;github.com&#x2F;realmuddy.png" width="60px" alt="User avatar: Phillip Waters" /></a><a href="https://github.com/quaszi"><img src="https:&#x2F;&#x2F;github.com&#x2F;quaszi.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/EgoRaInevitable"><img src="https:&#x2F;&#x2F;github.com&#x2F;EgoRaInevitable.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/Unambiguous"><img src="https:&#x2F;&#x2F;github.com&#x2F;Unambiguous.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/Freestyler589"><img src="https:&#x2F;&#x2F;github.com&#x2F;Freestyler589.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/EA-1356"><img src="https:&#x2F;&#x2F;github.com&#x2F;EA-1356.png" width="60px" alt="User avatar: meris" /></a><!-- sponsors -->
<!-- sponsors --><a href="https://github.com/TriHydera"><img src="https:&#x2F;&#x2F;github.com&#x2F;TriHydera.png" width="60px" alt="User avatar: TriHydera" /></a><a href="https://github.com/jozozovko"><img src="https:&#x2F;&#x2F;github.com&#x2F;jozozovko.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/DelDongo"><img src="https:&#x2F;&#x2F;github.com&#x2F;DelDongo.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/markamos"><img src="https:&#x2F;&#x2F;github.com&#x2F;markamos.png" width="60px" alt="User avatar: Mark Amos" /></a><a href="https://github.com/dwelfusius"><img src="https:&#x2F;&#x2F;github.com&#x2F;dwelfusius.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/mews-se"><img src="https:&#x2F;&#x2F;github.com&#x2F;mews-se.png" width="60px" alt="User avatar: Martin Stockzell" /></a><a href="https://github.com/jdiegmueller"><img src="https:&#x2F;&#x2F;github.com&#x2F;jdiegmueller.png" width="60px" alt="User avatar: Jason A. Diegmueller" /></a><a href="https://github.com/altugtekiner"><img src="https:&#x2F;&#x2F;github.com&#x2F;altugtekiner.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/robertsandrock"><img src="https:&#x2F;&#x2F;github.com&#x2F;robertsandrock.png" width="60px" alt="User avatar: RMS" /></a><a href="https://github.com/KenichiQaz"><img src="https:&#x2F;&#x2F;github.com&#x2F;KenichiQaz.png" width="60px" alt="User avatar: Stefan" /></a><a href="https://github.com/paulsheets"><img src="https:&#x2F;&#x2F;github.com&#x2F;paulsheets.png" width="60px" alt="User avatar: Paul" /></a><a href="https://github.com/djones369"><img src="https:&#x2F;&#x2F;github.com&#x2F;djones369.png" width="60px" alt="User avatar: Dave Jones" /></a><a href="https://github.com/anthonymendez"><img src="https:&#x2F;&#x2F;github.com&#x2F;anthonymendez.png" width="60px" alt="User avatar: Anthony Mendez" /></a><a href="https://github.com/claudemods"><img src="https:&#x2F;&#x2F;github.com&#x2F;claudemods.png" width="60px" alt="User avatar: Claudemods" /></a><a href="https://github.com/FatBastard0"><img src="https:&#x2F;&#x2F;github.com&#x2F;FatBastard0.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/Ascent7910"><img src="https:&#x2F;&#x2F;github.com&#x2F;Ascent7910.png" width="60px" alt="User avatar: Max" /></a><a href="https://github.com/DursleyGuy"><img src="https:&#x2F;&#x2F;github.com&#x2F;DursleyGuy.png" width="60px" alt="User avatar: DursleyGuy" /></a><a href="https://github.com/realmuddy"><img src="https:&#x2F;&#x2F;github.com&#x2F;realmuddy.png" width="60px" alt="User avatar: Phillip Waters" /></a><a href="https://github.com/quaszi"><img src="https:&#x2F;&#x2F;github.com&#x2F;quaszi.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/DwayneTheRockLobster1"><img src="https:&#x2F;&#x2F;github.com&#x2F;DwayneTheRockLobster1.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/KieraKujisawa"><img src="https:&#x2F;&#x2F;github.com&#x2F;KieraKujisawa.png" width="60px" alt="User avatar: Kiera Meredith" /></a><!-- sponsors -->
## 🏅 Thanks to all Contributors
Thanks a lot for spending your time helping Winutil grow. Thanks a lot! Keep rocking 🍻.

View File

@ -1,5 +1,6 @@
# Import the function (adjust the path according to your setup)
. "./functions/private/Get-WinUtilWingetLatest.ps1"
. "./functions/private/Install-WinUtilWinget.ps1"
. "./functions/private/Test-WinUtilPackageManager.ps1"
# Set up Information stream to be visible
$InformationPreference = "Continue"
@ -7,20 +8,7 @@ $InformationPreference = "Continue"
Write-Host "Starting Winget installation test..." -ForegroundColor Cyan
try {
# Test the function with verbose output
Write-Host "Attempting to run Get-WinUtilWingetLatest..." -ForegroundColor Cyan
Get-WinUtilWingetLatest -Verbose
# Verify Winget is working
if (Get-Command winget -ErrorAction SilentlyContinue) {
Write-Host "Success! Winget is installed and accessible." -ForegroundColor Green
# Display Winget version
Write-Host "`nWinget version:" -ForegroundColor Cyan
winget --version
} else {
Write-Host "Warning: Winget is installed but not accessible in the current session. You may need to restart your terminal." -ForegroundColor Yellow
}
Install-WinUtilWinget
} catch {
Write-Host "Error occurred during testing: $($_.Exception.Message)" -ForegroundColor Red
Write-Host "Stack Trace:" -ForegroundColor Red

View File

@ -683,9 +683,9 @@
"category": "Multimedia Tools",
"choco": "fxsound",
"content": "FxSound",
"description": "FxSound is a cutting-edge audio enhancement software that elevates your listening experience across all media.",
"description": "FxSound is free open-source software to boost sound quality, volume, and bass. Including an equalizer, effects, and presets for customized audio.",
"link": "https://www.fxsound.com/",
"winget": "FxSoundLLC.FxSound"
"winget": "FxSound.FxSound"
},
"fzf": {
"category": "Utilities",
@ -916,7 +916,7 @@
"choco": "imgburn",
"content": "ImgBurn",
"description": "ImgBurn is a lightweight CD, DVD, HD-DVD, and Blu-ray burning application with advanced features for creating and burning disc images.",
"link": "http://www.imgburn.com/",
"link": "https://www.imgburn.com/",
"winget": "LIGHTNINGUK.ImgBurn"
},
"inkscape": {
@ -988,7 +988,7 @@
"choco": "jdownloader",
"content": "JDownloader",
"description": "JDownloader is a feature-rich download manager with support for various file hosting services.",
"link": "http://jdownloader.org/",
"link": "https://jdownloader.org/",
"winget": "AppWork.JDownloader"
},
"jellyfinmediaplayer": {
@ -1380,7 +1380,7 @@
"choco": "na",
"content": "nGlide (3dfx compatibility)",
"description": "nGlide is a 3Dfx Voodoo Glide wrapper. It allows you to play games that use Glide API on modern graphics cards without the need for a 3Dfx Voodoo graphics card.",
"link": "http://www.zeus-software.com/downloads/nglide",
"link": "https://www.zeus-software.com/downloads/nglide",
"winget": "ZeusSoftware.nGlide"
},
"nmap": {
@ -2204,7 +2204,7 @@
"choco": "na",
"content": "Thorium Browser AVX2",
"description": "Browser built for speed over vanilla chromium. It is built with AVX2 optimizations and is the fastest browser on the market.",
"link": "http://thorium.rocks/",
"link": "https://thorium.rocks/",
"winget": "Alex313031.Thorium.AVX2"
},
"thunderbird": {
@ -2461,7 +2461,7 @@
"content": "UniGetUI",
"description": "UniGetUI is a GUI for Winget, Chocolatey, and other Windows CLI package managers.",
"link": "https://www.marticliment.com/wingetui/",
"winget": "SomePythonThings.WingetUIStore"
"winget": "MartiCliment.UniGetUI"
},
"winmerge": {
"category": "Document",
@ -2934,5 +2934,13 @@
"description": "Fork - a fast and friendly git client.",
"link": "https://git-fork.com/",
"winget": "Fork.Fork"
},
"ZenBrowser": {
"category": "Browsers",
"choco": "na",
"content": "Zen Browser",
"description": "The modern, privacy-focused, performance-driven browser built on Firefox",
"link": "https://zen-browser.app/",
"winget": "Zen-Team.Zen-Browser"
}
}

48
config/appnavigation.json Normal file
View File

@ -0,0 +1,48 @@
{
"WPFToggleView": {
"Content": ["Expanded View", "Compact View"],
"Category": "____Actions",
"Type": "ToggleButton",
"Order": "1",
"Description": "Toggle between a list and a compact grid like view"
},
"WPFSelectedFilter": {
"Content": [ "Show All", "Show Selected"],
"Category": "____Actions",
"Type": "ToggleButton",
"Order": "2",
"Description": "Toggle between showing all or only the selected applications"
},
"WPFClearInstallSelection": {
"Content": "Clear Selection",
"Category": "____Actions",
"Type": "Button",
"Order": "3",
"Description": "Clear the selection of applications"
},
"WPFGetInstalled": {
"Content": "Get Installed",
"Category": "____Actions",
"Type": "Button",
"Order": "4",
"Description": "Show installed applications"
},
"WingetRadioButton": {
"Content": "Winget",
"Category": "__Package Manager",
"Type": "RadioButton",
"GroupName": "PackageManagerGroup",
"Checked": true,
"Order": "1",
"Description": "Use Winget for package management"
},
"ChocoRadioButton": {
"Content": "Chocolatey",
"Category": "__Package Manager",
"Type": "RadioButton",
"GroupName": "PackageManagerGroup",
"Checked": false,
"Order": "2",
"Description": "Use Chocolatey for package management"
}
}

View File

@ -312,8 +312,7 @@
"panel": "2",
"Order": "a083_",
"Type": "Button",
"ButtonWidth": "300",
"link": "https://christitustech.github.io/winutil/dev/features/Powershell-Profile/PSProfileInstall"
"ButtonWidth": "300"
},
"WPFWinUtilUninstallPSProfile": {
"Content": "Uninstall CTT PowerShell Profile",
@ -321,8 +320,7 @@
"panel": "2",
"Order": "a084_",
"Type": "Button",
"ButtonWidth": "300",
"link": "https://christitustech.github.io/winutil/dev/features/Powershell-Profile/PSProfileUninstall"
"ButtonWidth": "300"
},
"WPFWinUtilSSHServer": {
"Content": "Enable OpenSSH Server",

View File

@ -38,6 +38,9 @@
"ButtonCornerRadius": "2"
},
"Light": {
"AppInstallUnselectedColor": "#F0F0F0",
"AppInstallHighlightedColor": "#CFCFCF",
"AppInstallSelectedColor": "#C2C2C2",
"ComboBoxForegroundColor": "#232629",
"ComboBoxBackgroundColor": "#F7F7F7",
"LabelboxForegroundColor": "#232629",
@ -73,6 +76,9 @@
},
"Dark": {
"AppInstallUnselectedColor": "#232629",
"AppInstallHighlightedColor": "#3C3C3C",
"AppInstallSelectedColor": "#4C4C4C",
"ComboBoxForegroundColor": "#F7F7F7",
"ComboBoxBackgroundColor": "#1E3747",
"LabelboxForegroundColor": "#0567ff",

View File

@ -423,26 +423,6 @@
"StartupType": "Automatic",
"OriginalType": "Automatic"
},
{
"Name": "DoSvc",
"StartupType": "AutomaticDelayedStart",
"OriginalType": "Automatic"
},
{
"Name": "DsSvc",
"StartupType": "Manual",
"OriginalType": "Manual"
},
{
"Name": "DsmSvc",
"StartupType": "Manual",
"OriginalType": "Manual"
},
{
"Name": "DusmSvc",
"StartupType": "Automatic",
"OriginalType": "Automatic"
},
{
"Name": "EFS",
"StartupType": "Manual",
@ -898,11 +878,6 @@
"StartupType": "Manual",
"OriginalType": "Manual"
},
{
"Name": "SgrmBroker",
"StartupType": "Automatic",
"OriginalType": "Automatic"
},
{
"Name": "SharedAccess",
"StartupType": "Manual",
@ -933,11 +908,6 @@
"StartupType": "Manual",
"OriginalType": "Manual"
},
{
"Name": "StateRepository",
"StartupType": "Manual",
"OriginalType": "Automatic"
},
{
"Name": "StiSvc",
"StartupType": "Manual",
@ -973,11 +943,6 @@
"StartupType": "Automatic",
"OriginalType": "Automatic"
},
{
"Name": "TextInputManagementService",
"StartupType": "Manual",
"OriginalType": "Automatic"
},
{
"Name": "Themes",
"StartupType": "Automatic",
@ -2596,13 +2561,15 @@
"InvokeScript": [
"
Write-Host \"Disable Recall\"
DISM /Online /Disable-Feature /FeatureName:Recall
DISM /Online /Disable-Feature /FeatureName:Recall /Quiet /NoRestart
Write-Host \"Please restart your computer in order for the changes to be fully applied.\"
"
],
"UndoScript": [
"
Write-Host \"Enable Recall\"
DISM /Online /Enable-Feature /FeatureName:Recall
DISM /Online /Enable-Feature /FeatureName:Recall /Quiet /NoRestart
Write-Host \"Please restart your computer in order for the changes to be fully applied.\"
"
],
"link": "https://christitustech.github.io/winutil/dev/tweaks/Essential-Tweaks/DisableRecall"
@ -2665,6 +2632,22 @@
],
"link": "https://christitustech.github.io/winutil/dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableLMS1"
},
"WPFTweaksDisableWpbtExecution": {
"Content": "Disable Windows Platform Binary Table (WPBT)",
"Description": "If enabled then allows your computer vendor to execute a program each time it boots. It enables computer vendors to force install anti-theft software, software drivers, or a software program conveniently. This could also be a security risk.",
"category": "z__Advanced Tweaks - CAUTION",
"panel": "1",
"Order": "a027_",
"registry": [
{
"Path": "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager",
"Name": "DisableWpbtExecution",
"Value": "1",
"OriginalValue": "<RemoveEntry>",
"Type": "DWord"
}
]
},
"WPFTweaksRemoveOnedrive": {
"Content": "Remove OneDrive",
"Description": "Moves OneDrive files to Default Home Folders and Uninstalls it.",

View File

@ -6,7 +6,7 @@
#### **Run the latest pre-release**
```ps1
irm christitus.com/windev | iex
irm https://christitus.com/windev | iex
```
!!! bug "Keep in mind"

View File

@ -6,7 +6,7 @@ Windows Security (formerly Defender) and other anti-virus software are known to
To resolve this, allow/whitelist the script in your anti-virus software settings, or temporarily disable real-time protection. Since the project is open source, you may audit the code if security is a concern.
### Download not working
If `christitus.com/win` is not working, or you want to download the code from GitHub directly, you can use the direct download link:
If `https://christitus.com/win` is not working, or you want to download the code from GitHub directly, you can use the direct download link:
```ps1
irm https://github.com/ChrisTitusTech/winutil/releases/latest/download/winutil.ps1 | iex
@ -34,7 +34,7 @@ If you are still having issues, try using a **VPN**, or changing your **DNS prov
2. In the PowerShell window, type this to allow unsigned code to execute and run the installation script:
```ps1
Set-ExecutionPolicy Unrestricted -Scope Process -Force
irm christitus.com/win | iex
irm https://christitus.com/win | iex
```
## Runtime Issues

View File

@ -1,38 +0,0 @@
# Install CTT PowerShell Profile
Last Updated: 2024-10-01
!!! info
The Development Documentation is auto generated for every compilation of WinUtil, meaning a part of it will always stay up-to-date. **Developers do have the ability to add custom content, which won't be updated automatically.**
<!-- BEGIN CUSTOM CONTENT -->
<!-- END CUSTOM CONTENT -->
<details>
<summary>Preview Code</summary>
```json
{
"Content": "Install CTT PowerShell Profile",
"category": "Powershell Profile",
"panel": "2",
"Order": "a083_",
"Type": "Button",
"ButtonWidth": "300",
"link": "https://christitustech.github.io/winutil/dev/features/Powershell-Profile/PSProfileInstall"
}
```
</details>
<!-- BEGIN SECOND CUSTOM CONTENT -->
<!-- END SECOND CUSTOM CONTENT -->
[View the JSON file](https://github.com/ChrisTitusTech/winutil/tree/main/config/feature.json)

View File

@ -1,38 +0,0 @@
# Uninstall CTT PowerShell Profile
Last Updated: 2024-10-01
!!! info
The Development Documentation is auto generated for every compilation of WinUtil, meaning a part of it will always stay up-to-date. **Developers do have the ability to add custom content, which won't be updated automatically.**
<!-- BEGIN CUSTOM CONTENT -->
<!-- END CUSTOM CONTENT -->
<details>
<summary>Preview Code</summary>
```json
{
"Content": "Uninstall CTT PowerShell Profile",
"category": "Powershell Profile",
"panel": "2",
"Order": "a084_",
"Type": "Button",
"ButtonWidth": "300",
"link": "https://christitustech.github.io/winutil/dev/features/Powershell-Profile/PSProfileUninstall"
}
```
</details>
<!-- BEGIN SECOND CUSTOM CONTENT -->
<!-- END SECOND CUSTOM CONTENT -->
[View the JSON file](https://github.com/ChrisTitusTech/winutil/tree/main/config/feature.json)

View File

@ -5,104 +5,104 @@
### Essential-Tweaks
- [Change Windows Terminal default: PowerShell 5 -> PowerShell 7](../docs/dev/tweaks/Essential-Tweaks/Powershell7.md)
- [Create Restore Point](../docs/dev/tweaks/Essential-Tweaks/RestorePoint.md)
- [Debloat Edge](../docs/dev/tweaks/Essential-Tweaks/EdgeDebloat.md)
- [Delete Temporary Files](../docs/dev/tweaks/Essential-Tweaks/DeleteTempFiles.md)
- [Disable Activity History](../docs/dev/tweaks/Essential-Tweaks/AH.md)
- [Disable ConsumerFeatures](../docs/dev/tweaks/Essential-Tweaks/ConsumerFeatures.md)
- [Disable GameDVR](../docs/dev/tweaks/Essential-Tweaks/DVR.md)
- [Disable Hibernation](../docs/dev/tweaks/Essential-Tweaks/Hiber.md)
- [Disable Homegroup](../docs/dev/tweaks/Essential-Tweaks/Home.md)
- [Disable Location Tracking](../docs/dev/tweaks/Essential-Tweaks/Loc.md)
- [Disable Powershell 7 Telemetry](../docs/dev/tweaks/Essential-Tweaks/Powershell7Tele.md)
- [Disable Storage Sense](../docs/dev/tweaks/Essential-Tweaks/Storage.md)
- [Disable Telemetry](../docs/dev/tweaks/Essential-Tweaks/Tele.md)
- [Disable Wifi-Sense](../docs/dev/tweaks/Essential-Tweaks/Wifi.md)
- [Enable End Task With Right Click](../docs/dev/tweaks/Essential-Tweaks/EndTaskOnTaskbar.md)
- [Prefer IPv4 over IPv6](../docs/dev/tweaks/Essential-Tweaks/IPv46.md)
- [Run Disk Cleanup](../docs/dev/tweaks/Essential-Tweaks/DiskCleanup.md)
- [Set Hibernation as default (good for laptops)](../docs/dev/tweaks/Essential-Tweaks/LaptopHibernation.md)
- [Set Services to Manual](../docs/dev/tweaks/Essential-Tweaks/Services.md)
- [Change Windows Terminal default: PowerShell 5 -> PowerShell 7](../dev/tweaks/Essential-Tweaks/Powershell7/)
- [Create Restore Point](../dev/tweaks/Essential-Tweaks/RestorePoint/)
- [Debloat Edge](../dev/tweaks/Essential-Tweaks/EdgeDebloat/)
- [Delete Temporary Files](../dev/tweaks/Essential-Tweaks/DeleteTempFiles/)
- [Disable Activity History](../dev/tweaks/Essential-Tweaks/AH/)
- [Disable ConsumerFeatures](../dev/tweaks/Essential-Tweaks/ConsumerFeatures/)
- [Disable GameDVR](../dev/tweaks/Essential-Tweaks/DVR/)
- [Disable Hibernation](../dev/tweaks/Essential-Tweaks/Hiber/)
- [Disable Homegroup](../dev/tweaks/Essential-Tweaks/Home/)
- [Disable Location Tracking](../dev/tweaks/Essential-Tweaks/Loc/)
- [Disable Powershell 7 Telemetry](../dev/tweaks/Essential-Tweaks/Powershell7Tele/)
- [Disable Storage Sense](../dev/tweaks/Essential-Tweaks/Storage/)
- [Disable Telemetry](../dev/tweaks/Essential-Tweaks/Tele/)
- [Disable Wifi-Sense](../dev/tweaks/Essential-Tweaks/Wifi/)
- [Enable End Task With Right Click](../dev/tweaks/Essential-Tweaks/EndTaskOnTaskbar/)
- [Prefer IPv4 over IPv6](../dev/tweaks/Essential-Tweaks/IPv46/)
- [Run Disk Cleanup](../dev/tweaks/Essential-Tweaks/DiskCleanup/)
- [Set Hibernation as default (good for laptops)](../dev/tweaks/Essential-Tweaks/LaptopHibernation/)
- [Set Services to Manual](../dev/tweaks/Essential-Tweaks/Services/)
### Shortcuts
- [Create WinUtil Shortcut](../docs/dev/tweaks/Shortcuts/Shortcut.md)
- [Create WinUtil Shortcut](../dev/tweaks/Shortcuts/Shortcut/)
### z--Advanced-Tweaks---CAUTION
- [Adobe Debloat](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/DebloatAdobe.md)
- [Adobe Network Block](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/BlockAdobeNet.md)
- [Disable Background Apps](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableBGapps.md)
- [Disable Fullscreen Optimizations](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableFSO.md)
- [Disable Intel MM (vPro LMS)](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableLMS1.md)
- [Disable IPv6](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/Disableipsix.md)
- [Disable Microsoft Copilot](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/RemoveCopilot.md)
- [Disable Notification Tray/Calendar](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableNotifications.md)
- [Disable Teredo](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/Teredo.md)
- [DNS](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/changedns.md)
- [Remove ALL MS Store Apps - NOT RECOMMENDED](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/DeBloat.md)
- [Remove Home and Gallery from explorer](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/RemoveHomeGallery.md)
- [Remove Microsoft Edge](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/RemoveEdge.md)
- [Remove OneDrive](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/RemoveOnedrive.md)
- [Run OO Shutup 10](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/OOSUbutton.md)
- [Set Classic Right-Click Menu ](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/RightClickMenu.md)
- [Set Display for Performance](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/Display.md)
- [Set Time to UTC (Dual Boot)](../docs/dev/tweaks/z--Advanced-Tweaks---CAUTION/UTC.md)
- [Adobe Debloat](../dev/tweaks/z--Advanced-Tweaks---CAUTION/DebloatAdobe/)
- [Adobe Network Block](../dev/tweaks/z--Advanced-Tweaks---CAUTION/BlockAdobeNet/)
- [Disable Background Apps](../dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableBGapps/)
- [Disable Fullscreen Optimizations](../dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableFSO/)
- [Disable Intel MM (vPro LMS)](../dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableLMS1/)
- [Disable IPv6](../dev/tweaks/z--Advanced-Tweaks---CAUTION/Disableipsix/)
- [Disable Microsoft Copilot](../dev/tweaks/z--Advanced-Tweaks---CAUTION/RemoveCopilot/)
- [Disable Notification Tray/Calendar](../dev/tweaks/z--Advanced-Tweaks---CAUTION/DisableNotifications/)
- [Disable Teredo](../dev/tweaks/z--Advanced-Tweaks---CAUTION/Teredo/)
- [DNS](../dev/tweaks/z--Advanced-Tweaks---CAUTION/changedns/)
- [Remove ALL MS Store Apps - NOT RECOMMENDED](../dev/tweaks/z--Advanced-Tweaks---CAUTION/DeBloat/)
- [Remove Home and Gallery from explorer](../dev/tweaks/z--Advanced-Tweaks---CAUTION/RemoveHomeGallery/)
- [Remove Microsoft Edge](../dev/tweaks/z--Advanced-Tweaks---CAUTION/RemoveEdge/)
- [Remove OneDrive](../dev/tweaks/z--Advanced-Tweaks---CAUTION/RemoveOnedrive/)
- [Run OO Shutup 10](../dev/tweaks/z--Advanced-Tweaks---CAUTION/OOSUbutton/)
- [Set Classic Right-Click Menu ](../dev/tweaks/z--Advanced-Tweaks---CAUTION/RightClickMenu/)
- [Set Display for Performance](../dev/tweaks/z--Advanced-Tweaks---CAUTION/Display/)
- [Set Time to UTC (Dual Boot)](../dev/tweaks/z--Advanced-Tweaks---CAUTION/UTC/)
### Customize-Preferences
- [Bing Search in Start Menu](../docs/dev/tweaks/Customize-Preferences/BingSearch.md)
- [Center Taskbar Items](../docs/dev/tweaks/Customize-Preferences/TaskbarAlignment.md)
- [Dark Theme for Windows](../docs/dev/tweaks/Customize-Preferences/DarkMode.md)
- [Detailed BSoD](../docs/dev/tweaks/Customize-Preferences/DetailedBSoD.md)
- [Mouse Acceleration](../docs/dev/tweaks/Customize-Preferences/MouseAcceleration.md)
- [NumLock on Startup](../docs/dev/tweaks/Customize-Preferences/NumLock.md)
- [Search Button in Taskbar](../docs/dev/tweaks/Customize-Preferences/TaskbarSearch.md)
- [Show File Extensions](../docs/dev/tweaks/Customize-Preferences/ShowExt.md)
- [Show Hidden Files](../docs/dev/tweaks/Customize-Preferences/HiddenFiles.md)
- [Snap Assist Flyout](../docs/dev/tweaks/Customize-Preferences/SnapFlyout.md)
- [Snap Assist Suggestion](../docs/dev/tweaks/Customize-Preferences/SnapSuggestion.md)
- [Snap Window](../docs/dev/tweaks/Customize-Preferences/SnapWindow.md)
- [Sticky Keys](../docs/dev/tweaks/Customize-Preferences/StickyKeys.md)
- [Task View Button in Taskbar](../docs/dev/tweaks/Customize-Preferences/TaskView.md)
- [Verbose Messages During Logon](../docs/dev/tweaks/Customize-Preferences/VerboseLogon.md)
- [Widgets Button in Taskbar](../docs/dev/tweaks/Customize-Preferences/TaskbarWidgets.md)
- [Bing Search in Start Menu](../dev/tweaks/Customize-Preferences/BingSearch/)
- [Center Taskbar Items](../dev/tweaks/Customize-Preferences/TaskbarAlignment/)
- [Dark Theme for Windows](../dev/tweaks/Customize-Preferences/DarkMode/)
- [Detailed BSoD](../dev/tweaks/Customize-Preferences/DetailedBSoD/)
- [Mouse Acceleration](../dev/tweaks/Customize-Preferences/MouseAcceleration/)
- [NumLock on Startup](../dev/tweaks/Customize-Preferences/NumLock/)
- [Search Button in Taskbar](../dev/tweaks/Customize-Preferences/TaskbarSearch/)
- [Show File Extensions](../dev/tweaks/Customize-Preferences/ShowExt/)
- [Show Hidden Files](../dev/tweaks/Customize-Preferences/HiddenFiles/)
- [Snap Assist Flyout](../dev/tweaks/Customize-Preferences/SnapFlyout/)
- [Snap Assist Suggestion](../dev/tweaks/Customize-Preferences/SnapSuggestion/)
- [Snap Window](../dev/tweaks/Customize-Preferences/SnapWindow/)
- [Sticky Keys](../dev/tweaks/Customize-Preferences/StickyKeys/)
- [Task View Button in Taskbar](../dev/tweaks/Customize-Preferences/TaskView/)
- [Verbose Messages During Logon](../dev/tweaks/Customize-Preferences/VerboseLogon/)
- [Widgets Button in Taskbar](../dev/tweaks/Customize-Preferences/TaskbarWidgets/)
### Performance-Plans
- [Add and Activate Ultimate Performance Profile](../docs/dev/tweaks/Performance-Plans/AddUltPerf.md)
- [Remove Ultimate Performance Profile](../docs/dev/tweaks/Performance-Plans/RemoveUltPerf.md)
- [Add and Activate Ultimate Performance Profile](../dev/tweaks/Performance-Plans/AddUltPerf/)
- [Remove Ultimate Performance Profile](../dev/tweaks/Performance-Plans/RemoveUltPerf/)
## Features
### Fixes
- [Remove Adobe Creative Cloud](../docs/dev/features/Fixes/RunAdobeCCCleanerTool.md)
- [Reset Network](../docs/dev/features/Fixes/Network.md)
- [Reset Windows Update](../docs/dev/features/Fixes/Update.md)
- [Set Up Autologin](../docs/dev/features/Fixes/Autologin.md)
- [System Corruption Scan](../docs/dev/features/Fixes/DISM.md)
- [WinGet Reinstall](../docs/dev/features/Fixes/Winget.md)
- [Remove Adobe Creative Cloud](../dev/features/Fixes/RunAdobeCCCleanerTool/)
- [Reset Network](../dev/features/Fixes/Network/)
- [Reset Windows Update](../dev/features/Fixes/Update/)
- [Set Up Autologin](../dev/features/Fixes/Autologin/)
- [System Corruption Scan](../dev/features/Fixes/DISM/)
- [WinGet Reinstall](../dev/features/Fixes/Winget/)
### Legacy-Windows-Panels
- [Control Panel](../docs/dev/features/Legacy-Windows-Panels/control.md)
- [Network Connections](../docs/dev/features/Legacy-Windows-Panels/network.md)
- [Power Panel](../docs/dev/features/Legacy-Windows-Panels/power.md)
- [Printer Settings](../docs/dev/features/Legacy-Windows-Panels/printer.md)
- [Region](../docs/dev/features/Legacy-Windows-Panels/region.md)
- [Sound Settings](../docs/dev/features/Legacy-Windows-Panels/sound.md)
- [System Properties](../docs/dev/features/Legacy-Windows-Panels/system.md)
- [User Accounts](../docs/dev/features/Legacy-Windows-Panels/user.md)
- [Control Panel](../dev/features/Legacy-Windows-Panels/control/)
- [Network Connections](../dev/features/Legacy-Windows-Panels/network/)
- [Power Panel](../dev/features/Legacy-Windows-Panels/power/)
- [Printer Settings](../dev/features/Legacy-Windows-Panels/printer/)
- [Region](../dev/features/Legacy-Windows-Panels/region/)
- [Sound Settings](../dev/features/Legacy-Windows-Panels/sound/)
- [System Properties](../dev/features/Legacy-Windows-Panels/system/)
- [User Accounts](../dev/features/Legacy-Windows-Panels/user/)
### Features
- [All .Net Framework (2,3,4)](../docs/dev/features/Features/dotnet.md)
- [Disable Legacy F8 Boot Recovery](../docs/dev/features/Features/DisableLegacyRecovery.md)
- [Disable Search Box Web Suggestions in Registry(explorer restart)](../docs/dev/features/Features/DisableSearchSuggestions.md)
- [Enable Daily Registry Backup Task 12.30am](../docs/dev/features/Features/RegBackup.md)
- [Enable Legacy F8 Boot Recovery](../docs/dev/features/Features/EnableLegacyRecovery.md)
- [Enable Search Box Web Suggestions in Registry(explorer restart)](../docs/dev/features/Features/EnableSearchSuggestions.md)
- [HyperV Virtualization](../docs/dev/features/Features/hyperv.md)
- [Install Features](../docs/dev/features/Features/Install.md)
- [Legacy Media (WMP, DirectPlay)](../docs/dev/features/Features/legacymedia.md)
- [NFS - Network File System](../docs/dev/features/Features/nfs.md)
- [Windows Sandbox](../docs/dev/features/Features/Sandbox.md)
- [Windows Subsystem for Linux](../docs/dev/features/Features/wsl.md)
- [All .Net Framework (2,3,4)](../dev/features/Features/dotnet/)
- [Disable Legacy F8 Boot Recovery](../dev/features/Features/DisableLegacyRecovery/)
- [Disable Search Box Web Suggestions in Registry(explorer restart)](../dev/features/Features/DisableSearchSuggestions/)
- [Enable Daily Registry Backup Task 12.30am](../dev/features/Features/RegBackup/)
- [Enable Legacy F8 Boot Recovery](../dev/features/Features/EnableLegacyRecovery/)
- [Enable Search Box Web Suggestions in Registry(explorer restart)](../dev/features/Features/EnableSearchSuggestions/)
- [HyperV Virtualization](../dev/features/Features/hyperv/)
- [Install Features](../dev/features/Features/Install/)
- [Legacy Media (WMP, DirectPlay)](../dev/features/Features/legacymedia/)
- [NFS - Network File System](../dev/features/Features/nfs/)
- [Windows Sandbox](../dev/features/Features/Sandbox/)
- [Windows Subsystem for Linux](../dev/features/Features/wsl/)

View File

@ -11,7 +11,7 @@ Welcome to the official documentation for WinUtil, your go-to utility for optimi
* You will first need to start a Powershell terminal **as Admin**.
* Now you can run the following command:
```ps1
irm christitus.com/win | iex
irm https://christitus.com/win | iex
```
!!! info

View File

@ -258,6 +258,6 @@ With MicroWin, you can also configure your user before proceeding if you don't w
* On any supported Windows machine, open PowerShell **as Admin** and run the following command to automatically apply tweaks and install apps from the config file.
```ps1
iex "& { $(irm christitus.com/win) } -Config [path-to-your-config] -Run"
iex "& { $(irm https://christitus.com/win) } -Config [path-to-your-config] -Run"
```
* Have a cup of coffee! Come back when it's done.

View File

@ -88,7 +88,7 @@ function Microwin-RemovePackages {
} else {
foreach ($package in $pkgList) {
$status = "Removing package $package"
Write-Progress -Activity "Removing features" -Status $status -PercentComplete ($counter++/$featlist.Count*100)
Write-Progress -Activity "Removing Packages" -Status $status -PercentComplete ($counter++/$pkglist.Count*100)
Write-Debug "Removing package $package"
dism /english /image="$scratchDir" /remove-package /packagename=$package /remove /quiet /norestart | Out-Null
if ($? -eq $false) {

View File

@ -0,0 +1,50 @@
function Add-SelectedAppsMenuItem {
<#
.SYNOPSIS
This is a helper function that generates and adds the Menu Items to the Selected Apps Popup.
.Parameter name
The actual Name of an App like "Chrome" or "Brave"
This name is contained in the "Content" property inside the applications.json
.PARAMETER key
The key which identifies an app object in applications.json
For Chrome this would be "WPFInstallchrome" because "WPFInstall" is prepended automatically for each key in applications.json
#>
param ([string]$name, [string]$key)
$selectedAppGrid = New-Object Windows.Controls.Grid
$selectedAppGrid.ColumnDefinitions.Add((New-Object System.Windows.Controls.ColumnDefinition -Property @{Width = "*"}))
$selectedAppGrid.ColumnDefinitions.Add((New-Object System.Windows.Controls.ColumnDefinition -Property @{Width = "30"}))
# Sets the name to the Content as well as the Tooltip, because the parent Popup Border has a fixed width and text could "overflow".
# With the tooltip, you can still read the whole entry on hover
$selectedAppLabel = New-Object Windows.Controls.Label
$selectedAppLabel.Content = $name
$selectedAppLabel.ToolTip = $name
$selectedAppLabel.HorizontalAlignment = "Left"
$selectedAppLabel.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor")
[System.Windows.Controls.Grid]::SetColumn($selectedAppLabel, 0)
$selectedAppGrid.Children.Add($selectedAppLabel)
$selectedAppRemoveButton = New-Object Windows.Controls.Button
$selectedAppRemoveButton.FontFamily = "Segoe MDL2 Assets"
$selectedAppRemoveButton.Content = [string]([char]0xE711)
$selectedAppRemoveButton.HorizontalAlignment = "Center"
$selectedAppRemoveButton.Tag = $key
$selectedAppRemoveButton.ToolTip = "Remove the App from Selection"
$selectedAppRemoveButton.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor")
$selectedAppRemoveButton.SetResourceReference([Windows.Controls.Control]::StyleProperty, "HoverButtonStyle")
# Highlight the Remove icon on Hover
$selectedAppRemoveButton.Add_MouseEnter({ $this.Foreground = "Red" })
$selectedAppRemoveButton.Add_MouseLeave({ $this.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") })
$selectedAppRemoveButton.Add_Click({
$sync.($this.Tag).isChecked = $false # On click of the remove button, we only have to uncheck the corresponding checkbox. This will kick of all neccessary changes to update the UI
})
[System.Windows.Controls.Grid]::SetColumn($selectedAppRemoveButton, 1)
$selectedAppGrid.Children.Add($selectedAppRemoveButton)
# Add new Element to Popup
$sync.selectedAppsstackPanel.Children.Add($selectedAppGrid)
}

View File

@ -0,0 +1,35 @@
function Find-AppsByNameOrDescription {
<#
.SYNOPSIS
Searches through the Apps on the Install Tab and hides all entries that do not match the string
.PARAMETER SearchString
The string to be searched for
#>
param(
[Parameter(Mandatory=$false)]
[string]$SearchString = ""
)
# Reset the visibility if the search string is empty or the search is cleared
if ([string]::IsNullOrWhiteSpace($SearchString)) {
Set-CategoryVisibility -Category "*"
return
}
$sync.ItemsControl.Items | ForEach-Object {
# Hide all CategoryWrapPanel and ToggleButton
$_.Visibility = [Windows.Visibility]::Collapsed
if ($_.Tag -like "CategoryWrapPanel_*") {
# Search for Apps that match the search string
$_.Children | Foreach-Object {
if ($sync.configs.applicationsHashtable.$($_.Tag).Content -like "*$SearchString*") {
# Show the App and the parent CategoryWrapPanel if the string is found
$_.Visibility = [Windows.Visibility]::Visible
$_.parent.Visibility = [Windows.Visibility]::Visible
}
else {
$_.Visibility = [Windows.Visibility]::Collapsed
}
}
}
}
}

View File

@ -1,104 +0,0 @@
function Get-WinUtilWingetLatest {
[CmdletBinding()]
param()
<#
.SYNOPSIS
Uses GitHub API to check for the latest release of Winget.
.DESCRIPTION
This function first attempts to update WinGet using winget itself, then falls back to manual installation if needed.
#>
$ProgressPreference = "SilentlyContinue"
$InformationPreference = 'Continue'
try {
$wingetCmd = Get-Command winget -ErrorAction Stop
Write-Information "Attempting to update WinGet using WinGet..."
$result = Start-Process -FilePath "`"$($wingetCmd.Source)`"" -ArgumentList "install -e --accept-source-agreements --accept-package-agreements Microsoft.AppInstaller" -Wait -NoNewWindow -PassThru
if ($result.ExitCode -ne 0) {
throw "WinGet update failed with exit code: $($result.ExitCode)"
}
return $true
}
catch {
Write-Information "WinGet not found or update failed. Attempting to install from Microsoft Store..."
try {
# Try to close any running WinGet processes
Get-Process -Name "DesktopAppInstaller", "winget" -ErrorAction SilentlyContinue | ForEach-Object {
Write-Information "Stopping running WinGet process..."
$_.Kill()
Start-Sleep -Seconds 2
}
# Try to load Windows Runtime assemblies more reliably
$null = [System.Runtime.WindowsRuntime.WindowsRuntimeSystemExtensions]
Add-Type -AssemblyName System.Runtime.WindowsRuntime
# Load required assemblies from Windows SDK
$null = @(
[Windows.Management.Deployment.PackageManager, Windows.Management.Deployment, ContentType = WindowsRuntime]
[Windows.Foundation.Uri, Windows.Foundation, ContentType = WindowsRuntime]
[Windows.Management.Deployment.DeploymentOptions, Windows.Management.Deployment, ContentType = WindowsRuntime]
)
# Initialize PackageManager
$packageManager = New-Object Windows.Management.Deployment.PackageManager
# Rest of the Microsoft Store installation logic
$appxPackage = "https://aka.ms/getwinget"
$uri = New-Object Windows.Foundation.Uri($appxPackage)
$deploymentOperation = $packageManager.AddPackageAsync($uri, $null, "Add")
# Add timeout check for deployment operation
$timeout = 300
$timer = [System.Diagnostics.Stopwatch]::StartNew()
while ($deploymentOperation.Status -eq 0) {
if ($timer.Elapsed.TotalSeconds -gt $timeout) {
throw "Installation timed out after $timeout seconds"
}
Start-Sleep -Milliseconds 100
}
if ($deploymentOperation.Status -eq 1) {
Write-Information "Successfully installed WinGet from Microsoft Store"
return $true
} else {
throw "Installation failed with status: $($deploymentOperation.Status)"
}
}
catch [System.Management.Automation.RuntimeException] {
Write-Information "Windows Runtime components not available. Attempting manual download..."
try {
# Try to close any running WinGet processes
Get-Process -Name "DesktopAppInstaller", "winget" -ErrorAction SilentlyContinue | ForEach-Object {
Write-Information "Stopping running WinGet process..."
$_.Kill()
Start-Sleep -Seconds 2
}
# Fallback to direct download from GitHub
$apiUrl = "https://api.github.com/repos/microsoft/winget-cli/releases/latest"
$release = Invoke-RestMethod -Uri $apiUrl
$msixBundleUrl = ($release.assets | Where-Object { $_.name -like "*.msixbundle" }).browser_download_url
$tempFile = Join-Path $env:TEMP "Microsoft.DesktopAppInstaller.msixbundle"
Invoke-WebRequest -Uri $msixBundleUrl -OutFile $tempFile
Add-AppxPackage -Path $tempFile -ErrorAction Stop
Remove-Item $tempFile -Force
Write-Information "Successfully installed WinGet from GitHub release"
return $true
}
catch {
Write-Error "Failed to install WinGet: $_"
return $false
}
}
catch {
Write-Error "Failed to install WinGet: $_"
return $false
}
}
}

View File

@ -0,0 +1,197 @@
function Initialize-InstallAppEntry {
<#
.SYNOPSIS
Creates the app entry to be placed on the isntall tab for a given app
Used to as part of the Install Tab UI generation
.PARAMETER TargetElement
The Element into which the Apps should be placed
.PARAMETER AppKey
The Key of the app inside the $sync.configs.applicationsHashtable
#>
param(
[Windows.Controls.WrapPanel]$TargetElement,
$AppKey
)
$App = $sync.configs.applicationsHashtable.$AppKey
# Create the outer Border for the application type
$border = New-Object Windows.Controls.Border
$border.BorderBrush = [Windows.Media.Brushes]::Gray
$border.SetResourceReference([Windows.Controls.Control]::BorderThicknessProperty, "AppTileBorderThickness")
$border.CornerRadius = 5
$border.SetResourceReference([Windows.Controls.Control]::PaddingProperty, "AppTileMargins")
$border.SetResourceReference([Windows.Controls.Control]::WidthProperty, "AppTileWidth")
$border.VerticalAlignment = "Top"
$border.SetResourceReference([Windows.Controls.Control]::MarginProperty, "AppTileMargins")
$border.Cursor = [System.Windows.Input.Cursors]::Hand
$border.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor")
$border.Tag = $Appkey
$border.ToolTip = $App.description
$border.Add_MouseUp({
$childCheckbox = ($this.Child.Children | Where-Object {$_.Template.TargetType -eq [System.Windows.Controls.Checkbox]})[0]
$childCheckBox.isChecked = -not $childCheckbox.IsChecked
})
$border.Add_MouseEnter({
if (($sync.$($this.Tag).IsChecked) -eq $false) {
$this.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallHighlightedColor")
}
})
$border.Add_MouseLeave({
if (($sync.$($this.Tag).IsChecked) -eq $false) {
$this.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor")
}
})
# Create a DockPanel inside the Border
$dockPanel = New-Object Windows.Controls.DockPanel
$dockPanel.LastChildFill = $true
$border.Child = $dockPanel
# Create the CheckBox, vertically centered
$checkBox = New-Object Windows.Controls.CheckBox
$checkBox.Name = $AppKey
$checkBox.Background = "Transparent"
$checkBox.HorizontalAlignment = "Left"
$checkBox.VerticalAlignment = "Center"
$checkBox.SetResourceReference([Windows.Controls.Control]::MarginProperty, "AppTileMargins")
$checkBox.SetResourceReference([Windows.Controls.Control]::StyleProperty, "CollapsedCheckBoxStyle")
$checkbox.Add_Checked({
Invoke-WPFSelectedAppsUpdate -type "Add" -checkbox $this
$borderElement = $this.Parent.Parent
$borderElement.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallSelectedColor")
})
$checkbox.Add_Unchecked({
Invoke-WPFSelectedAppsUpdate -type "Remove" -checkbox $this
$borderElement = $this.Parent.Parent
$borderElement.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor")
})
$sync.$($checkBox.Name) = $checkBox
# Create a StackPanel for the image and name
$imageAndNamePanel = New-Object Windows.Controls.StackPanel
$imageAndNamePanel.Orientation = "Horizontal"
$imageAndNamePanel.VerticalAlignment = "Center"
# Create the Image and set a placeholder
$image = New-Object Windows.Controls.Image
# $image.Name = "wpfapplogo" + $App.Name
$image.Width = 40
$image.Height = 40
$image.Margin = New-Object Windows.Thickness(0, 0, 10, 0)
$image.Source = $noimage # Ensure $noimage is defined in your script
# Clip the image corners
$image.Clip = New-Object Windows.Media.RectangleGeometry
$image.Clip.Rect = New-Object Windows.Rect(0, 0, $image.Width, $image.Height)
$image.Clip.RadiusX = 5
$image.Clip.RadiusY = 5
$image.SetResourceReference([Windows.Controls.Control]::VisibilityProperty, "AppTileCompactVisibility")
$imageAndNamePanel.Children.Add($image) | Out-Null
# Create the TextBlock for the application name
$appName = New-Object Windows.Controls.TextBlock
$appName.Text = $App.Content
$appName.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "AppTileFontSize")
$appName.FontWeight = [Windows.FontWeights]::Bold
$appName.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor")
$appName.VerticalAlignment = "Center"
$appName.SetResourceReference([Windows.Controls.Control]::MarginProperty, "AppTileMargins")
$appName.Background = "Transparent"
$imageAndNamePanel.Children.Add($appName) | Out-Null
# Add the image and name panel to the Checkbox
$checkBox.Content = $imageAndNamePanel
# Add the checkbox to the DockPanel
[Windows.Controls.DockPanel]::SetDock($checkBox, [Windows.Controls.Dock]::Left)
$dockPanel.Children.Add($checkBox) | Out-Null
# Create the StackPanel for the buttons and dock it to the right
$buttonPanel = New-Object Windows.Controls.StackPanel
$buttonPanel.Orientation = "Horizontal"
$buttonPanel.HorizontalAlignment = "Right"
$buttonPanel.VerticalAlignment = "Center"
$buttonPanel.SetResourceReference([Windows.Controls.Control]::MarginProperty, "AppTileMargins")
$buttonPanel.SetResourceReference([Windows.Controls.Control]::VisibilityProperty, "AppTileCompactVisibility")
[Windows.Controls.DockPanel]::SetDock($buttonPanel, [Windows.Controls.Dock]::Right)
# Create the "Install" button
$installButton = New-Object Windows.Controls.Button
$installButton.Width = 45
$installButton.Height = 35
$installButton.Margin = New-Object Windows.Thickness(0, 0, 10, 0)
$installIcon = New-Object Windows.Controls.TextBlock
$installIcon.Text = [char]0xE118 # Install Icon
$installIcon.FontFamily = "Segoe MDL2 Assets"
$installIcon.FontSize = 20
$installIcon.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor")
$installIcon.Background = "Transparent"
$installIcon.HorizontalAlignment = "Center"
$installIcon.VerticalAlignment = "Center"
$installButton.Content = $installIcon
$installButton.ToolTip = "Install or Upgrade the application"
$buttonPanel.Children.Add($installButton) | Out-Null
# Add Click event for the "Install" button
$installButton.Add_Click({
$appKey = $this.Parent.Parent.Parent.Tag
$appObject = $sync.configs.applicationsHashtable.$appKey
Invoke-WPFInstall -PackagesToInstall $appObject
})
# Create the "Uninstall" button
$uninstallButton = New-Object Windows.Controls.Button
$uninstallButton.Width = 45
$uninstallButton.Height = 35
$uninstallIcon = New-Object Windows.Controls.TextBlock
$uninstallIcon.Text = [char]0xE74D # Uninstall Icon
$uninstallIcon.FontFamily = "Segoe MDL2 Assets"
$uninstallIcon.FontSize = 20
$uninstallIcon.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor")
$uninstallIcon.Background = "Transparent"
$uninstallIcon.HorizontalAlignment = "Center"
$uninstallIcon.VerticalAlignment = "Center"
$uninstallButton.Content = $uninstallIcon
$buttonPanel.Children.Add($uninstallButton) | Out-Null
$uninstallButton.ToolTip = "Uninstall the application"
$uninstallButton.Add_Click({
$appKey = $this.Parent.Parent.Parent.Tag
$appObject = $sync.configs.applicationsHashtable.$appKey
Invoke-WPFUnInstall -PackagesToUninstall $appObject
})
# Create the "Info" button
$infoButton = New-Object Windows.Controls.Button
$infoButton.Width = 45
$infoButton.Height = 35
$infoButton.Margin = New-Object Windows.Thickness(10, 0, 0, 0)
$infoIcon = New-Object Windows.Controls.TextBlock
$infoIcon.Text = [char]0xE946 # Info Icon
$infoIcon.FontFamily = "Segoe MDL2 Assets"
$infoIcon.FontSize = 20
$infoIcon.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor")
$infoIcon.Background = "Transparent"
$infoIcon.HorizontalAlignment = "Center"
$infoIcon.VerticalAlignment = "Center"
$infoButton.Content = $infoIcon
$infoButton.ToolTip = "Open the application's website in your default browser"
$buttonPanel.Children.Add($infoButton) | Out-Null
$infoButton.Add_Click({
$appKey = $this.Parent.Parent.Parent.Tag
$appObject = $sync.configs.applicationsHashtable.$appKey
Start-Process $appObject.link
})
# Add the button panel to the DockPanel
$dockPanel.Children.Add($buttonPanel) | Out-Null
# Add the border to the corresponding Category
$TargetElement.Children.Add($border) | Out-Null
}

View File

@ -0,0 +1,36 @@
function Initialize-InstallAppArea {
<#
.SYNOPSIS
Creates a [Windows.Controls.ScrollViewer] containing a [Windows.Controls.ItemsControl] which is setup to use Virtualization to only load the visible elements for performance reasons.
This is used as the parent object for all category and app entries on the install tab
Used to as part of the Install Tab UI generation
.PARAMETER TargetElement
The element to which the AppArea shoud be added
#>
param($TargetElement)
$scrollViewer = New-Object Windows.Controls.ScrollViewer
$scrollViewer.VerticalScrollBarVisibility = 'Auto'
$scrollViewer.HorizontalAlignment = 'Stretch'
$scrollViewer.VerticalAlignment = 'Stretch'
$scrollViewer.CanContentScroll = $true
$itemsControl = New-Object Windows.Controls.ItemsControl
$itemsControl.HorizontalAlignment = 'Stretch'
$itemsControl.VerticalAlignment = 'Stretch'
$itemsPanelTemplate = New-Object Windows.Controls.ItemsPanelTemplate
$factory = New-Object Windows.FrameworkElementFactory ([Windows.Controls.VirtualizingStackPanel])
$itemsPanelTemplate.VisualTree = $factory
$itemsControl.ItemsPanel = $itemsPanelTemplate
$itemsControl.SetValue([Windows.Controls.VirtualizingStackPanel]::IsVirtualizingProperty, $true)
$itemsControl.SetValue([Windows.Controls.VirtualizingStackPanel]::VirtualizationModeProperty, [Windows.Controls.VirtualizationMode]::Recycling)
$scrollViewer.Content = $itemsControl
[Windows.Controls.DockPanel]::SetDock($scrollViewer, [Windows.Controls.Dock]::Bottom)
$null = $TargetElement.Children.Add($scrollViewer)
return $itemsControl
}

View File

@ -0,0 +1,28 @@
function Initialize-InstallAppsMainElement {
<#
.SYNOPSIS
Clears the given WPF Grid and creates a [Windows.Controls.Border] containing a [Windows.Controls.StackPanel]
Used to as part of the Install Tab UI generation
.PARAMETER TargetGridName
The WPF Grid name
.OUTPUTS
Returns the created [Windows.Controls.StackPanel] element
#>
param(
[Parameter(Mandatory)]
[string]$TargetGridName
)
$targetGrid = $sync.Form.FindName($TargetGridName)
$null = $targetGrid.Children.Clear()
$Border = New-Object Windows.Controls.Border
$Border.VerticalAlignment = "Stretch"
$Border.SetResourceReference([Windows.Controls.Control]::StyleProperty, "BorderStyle")
$dockPanel = New-Object Windows.Controls.DockPanel
$Border.Child = $dockPanel
$null = $targetGrid.Children.Add($Border)
return $dockPanel
}

View File

@ -0,0 +1,72 @@
function Initialize-InstallCategoryAppList {
<#
.SYNOPSIS
Clears the Target Element and sets up a "Loading" message. This is done, because loading of all apps can take a bit of time in some scenarios
Iterates through all Categories and Apps and adds them to the UI
Used to as part of the Install Tab UI generation
.PARAMETER TargetElement
The Element into which the Categories and Apps should be placed
.PARAMETER Apps
The Hashtable of Apps to be added to the UI
The Categories are also extracted from the Apps Hashtable
#>
param(
$TargetElement,
$Apps
)
function Add-Category {
param(
[string]$Category,
[Windows.Controls.ItemsControl]$TargetElement
)
$toggleButton = New-Object Windows.Controls.Primitives.ToggleButton
$toggleButton.Content = "$Category"
$toggleButton.Tag = "CategoryToggleButton"
$toggleButton.Cursor = [System.Windows.Input.Cursors]::Hand
$toggleButton.SetResourceReference([Windows.Controls.Control]::StyleProperty, "CategoryToggleButtonStyle")
$sync.Buttons.Add($toggleButton)
$toggleButton.Add_Checked({
# Clear the search bar when a category is clicked
$sync.SearchBar.Text = ""
Set-CategoryVisibility -Category $this.Content -overrideState Expand
})
$toggleButton.Add_Unchecked({
Set-CategoryVisibility -Category $this.Content -overrideState Collapse
})
$null = $TargetElement.Items.Add($toggleButton)
}
$loadingLabel = New-Object Windows.Controls.Label
$loadingLabel.Content = "Loading, please wait..."
$loadingLabel.HorizontalAlignment = "Center"
$loadingLabel.VerticalAlignment = "Center"
$loadingLabel.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "FontSizeHeading")
$loadingLabel.FontWeight = [Windows.FontWeights]::Bold
$loadingLabel.Foreground = [Windows.Media.Brushes]::Gray
$sync.LoadingLabel = $loadingLabel
$TargetElement.Items.Clear()
$null = $TargetElement.Items.Add($sync.LoadingLabel)
# Use the Dispatcher to make sure the Loading message is shown before the logic loading the apps starts, and only is removed when the loading is complete and the apps are added to the UI
$TargetElement.Dispatcher.Invoke([System.Windows.Threading.DispatcherPriority]::Background, [action]{
$TargetElement.Items.Clear() # Remove the loading message
$categories = $Apps.Values | Select-Object -ExpandProperty category -Unique | Sort-Object
foreach ($category in $categories) {
Add-Category -Category $category -TargetElement $TargetElement
$wrapPanel = New-Object Windows.Controls.WrapPanel
$wrapPanel.Orientation = "Horizontal"
$wrapPanel.HorizontalAlignment = "Stretch"
$wrapPanel.VerticalAlignment = "Center"
$wrapPanel.Margin = New-Object Windows.Thickness(0, 0, 0, 20)
$wrapPanel.Visibility = [Windows.Visibility]::Collapsed
$wrapPanel.Tag = "CategoryWrapPanel_$category"
$null = $TargetElement.Items.Add($wrapPanel)
$Apps.Keys | Where-Object { $Apps.$_.Category -eq $category } | Sort-Object | ForEach-Object {
Initialize-InstallAppEntry -TargetElement $wrapPanel -AppKey $_
}
}
})
}

View File

@ -0,0 +1,89 @@
function Initialize-InstallHeader {
<#
.SYNOPSIS
Creates the Multi Selection Header Elements on the Install Tab
Used to as part of the Install Tab UI generation
.PARAMETER TargetElement
The Parent Element into which the Header should be placed
#>
param($TargetElement)
function New-WPFButton {
param (
[string]$Name,
[string]$Content
)
$button = New-Object Windows.Controls.Button
$button.Name = $Name
$button.Content = $Content
$button.Margin = New-Object Windows.Thickness(2)
$button.HorizontalAlignment = "Stretch"
return $button
}
$wrapPanelTop = New-Object Windows.Controls.WrapPanel
$wrapPanelTop.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "MainBackgroundColor")
$wrapPanelTop.HorizontalAlignment = "Left"
$wrapPanelTop.VerticalAlignment = "Top"
$wrapPanelTop.Orientation = "Horizontal"
$wrapPanelTop.SetResourceReference([Windows.Controls.Control]::MarginProperty, "TabContentMargin")
$buttonConfigs = @(
@{Name="WPFInstall"; Content="Install/Upgrade Selected"},
@{Name="WPFInstallUpgrade"; Content="Upgrade All"},
@{Name="WPFUninstall"; Content="Uninstall Selected"}
)
foreach ($config in $buttonConfigs) {
$button = New-WPFButton -Name $config.Name -Content $config.Content
$null = $wrapPanelTop.Children.Add($button)
$sync[$config.Name] = $button
}
$selectedAppsButton = New-Object Windows.Controls.Button
$selectedAppsButton.Name = "WPFselectedAppsButton"
$selectedAppsButton.Content = "Selected Apps: 0"
$selectedAppsButton.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "FontSizeHeading")
$selectedAppsButton.SetResourceReference([Windows.Controls.Control]::MarginProperty, "TabContentMargin")
$selectedAppsButton.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor")
$selectedAppsButton.HorizontalAlignment = "Center"
$selectedAppsButton.VerticalAlignment = "Center"
$selectedAppsPopup = New-Object Windows.Controls.Primitives.Popup
$selectedAppsPopup.IsOpen = $false
$selectedAppsPopup.PlacementTarget = $selectedAppsButton
$selectedAppsPopup.Placement = [System.Windows.Controls.Primitives.PlacementMode]::Bottom
$selectedAppsPopup.AllowsTransparency = $true
$selectedAppsBorder = New-Object Windows.Controls.Border
$selectedAppsBorder.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "MainBackgroundColor")
$selectedAppsBorder.SetResourceReference([Windows.Controls.Control]::BorderBrushProperty, "MainForegroundColor")
$selectedAppsBorder.SetResourceReference([Windows.Controls.Control]::BorderThicknessProperty, "ButtonBorderThickness")
$selectedAppsBorder.Width = 200
$selectedAppsBorder.Padding = 5
$selectedAppsPopup.Child = $selectedAppsBorder
$sync.selectedAppsPopup = $selectedAppsPopup
$sync.selectedAppsstackPanel = New-Object Windows.Controls.StackPanel
$selectedAppsBorder.Child = $sync.selectedAppsstackPanel
# Toggle selectedAppsPopup open/close with button
$selectedAppsButton.Add_Click({
$sync.selectedAppsPopup.IsOpen = -not $sync.selectedAppsPopup.IsOpen
})
# Close selectedAppsPopup when mouse leaves both button and selectedAppsPopup
$selectedAppsButton.Add_MouseLeave({
if (-not $sync.selectedAppsPopup.IsMouseOver) {
$sync.selectedAppsPopup.IsOpen = $false
}
})
$selectedAppsPopup.Add_MouseLeave({
if (-not $selectedAppsButton.IsMouseOver) {
$sync.selectedAppsPopup.IsOpen = $false
}
})
$null = $wrapPanelTop.Children.Add($selectedAppsButton)
$sync.$($selectedAppsButton.Name) = $selectedAppsButton
[Windows.Controls.DockPanel]::SetDock($wrapPanelTop, [Windows.Controls.Dock]::Top)
$null = $TargetElement.Children.Add($wrapPanelTop)
}

View File

@ -33,18 +33,44 @@ function Install-WinUtilWinget {
return
}
# Install Winget via GitHub method.
# Used part of my own script with some modification: ruxunderscore/windows-initialization
Write-Host "Downloading Winget and License File`r"
Get-WinUtilWingetLatest
Write-Host "Enabling NuGet and Module..."
Install-PackageProvider -Name NuGet -Force
Install-Module -Name Microsoft.WinGet.Client -Force
# Winget only needs a refresh of the environment variables to be used.
Write-Output "Refreshing Environment Variables...`n"
$ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
} catch {
Write-Error "Failed to install Winget: $($_.Exception.Message)"
}
Write-Host "Attempting to install/update Winget`r"
try {
$wingetCmd = Get-Command winget -ErrorAction Stop
Write-Information "Attempting to update WinGet using WinGet..."
$result = Start-Process -FilePath "`"$($wingetCmd.Source)`"" -ArgumentList "install -e --accept-source-agreements --accept-package-agreements Microsoft.AppInstaller" -Wait -NoNewWindow -PassThru
if ($result.ExitCode -ne 0) {
throw "WinGet update failed with exit code: $($result.ExitCode)"
}
Write-Output "Refreshing Environment Variables...`n"
$ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
return
} catch {
Write-Information "WinGet not found or update failed. Attempting to install from Microsoft Store..."
}
try {
Write-Host "Attempting to repair WinGet using Repair-WinGetPackageManager..." -ForegroundColor Yellow
# Check if Windows version supports Repair-WinGetPackageManager (24H2 and above)
if ([System.Environment]::OSVersion.Version.Build -ge 26100) {
Repair-WinGetPackageManager -Force -Latest -Verbose
# Verify if repair was successful
$wingetCmd = Get-Command winget -ErrorAction Stop
Write-Host "WinGet repair successful!" -ForegroundColor Green
} else {
Write-Host "Repair-WinGetPackageManager is only available on Windows 24H2 and above. Your version doesn't support this method." -ForegroundColor Yellow
throw "Windows version not supported for repair method"
}
Write-Output "Refreshing Environment Variables...`n"
$ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
return
} catch {
Write-Error "All installation methods failed. Unable to install WinGet."
throw
}
} catch {
Write-Error "An error occurred during WinGet installation: $_"
throw
}
}

View File

@ -38,6 +38,32 @@ function Invoke-WinUtilUninstallPSProfile {
if (-not $Fonts) {
Write-Host "===> Successfully Uninstalled: Nerd Fonts. <===" -ForegroundColor Yellow
}
}
# Helper function used to uninstall a specific Nerd Fonts font corresponding registry keys.
function Uninstall-NerdFontRegKeys {
# Define the parameters block for the Uninstall-NerdFontsRegKey function.
param (
[string]$FontsRegPath = "HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts",
[string]$FontFamilyName = "CaskaydiaCove"
)
try {
# Get all properties (font registrations) from the registry path
$registryProperties = Get-ItemProperty -Path $FontsRegPath
# Filter and remove properties that match the font family name
$registryProperties.PSObject.Properties |
Where-Object { $_.Name -match $FontFamilyName } |
ForEach-Object {
If ($_.Name -like "*$FontFamilyName*") {
Remove-ItemProperty -path $FontsRegPath -Name $_.Name -ErrorAction SilentlyContinue
}
}
} catch {
Write-Host "Error removing registry keys: $($_.exception.message)" -ForegroundColor Red
}
}
# Check if Chris Titus Tech's PowerShell profile is currently available in the PowerShell profile folder.
@ -87,11 +113,28 @@ function Invoke-WinUtilUninstallPSProfile {
# Call the function used to uninstall the specified Nerd Fonts package from the system.
Uninstall-NerdFonts -FontsPath $FontsPath -FontFamilyName $FontFamilyName
} catch {
# Let the user know that an error was encountered when uninstalling Nerd Fonts.
Write-Host "Failed to uninstall Nerd Fonts. Error: $_" -ForegroundColor Red
}
# Attempt to uninstall the specified Nerd Fonts registry keys from the system.
try {
# Specify the registry path that the specified font registry keys will be uninstalled from.
[string]$FontsRegPath = "HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts"
# Specify the name of the font registry keys that is to be uninstalled from the system.
[string]$FontFamilyName = "CaskaydiaCove"
# Call the function used to uninstall the specified Nerd Fonts registry keys from the system.
Uninstall-NerdFontRegKeys -FontsPath $FontsRegPath -FontFamilyName $FontFamilyName
} catch {
# Let the user know that an error was encountered when uninstalling Nerd Font registry keys.
Write-Host "Failed to uninstall Nerd Font Registry Keys. Error: $_" -ForegroundColor Red
}
# Attempt to uninstall the Terminal-Icons PowerShell module from the system.
try {
# Get the content of the backup PowerShell profile and store it in-memory.
@ -185,3 +228,4 @@ function Invoke-WinUtilUninstallPSProfile {
}
}
}

View File

@ -1,50 +0,0 @@
function Invoke-WinUtilpsProfile {
<#
.SYNOPSIS
Installs & applies the CTT Powershell Profile
#>
Invoke-WPFRunspace -Argumentlist $PROFILE -DebugPreference $DebugPreference -ScriptBlock {
param ( $psprofile)
function Invoke-PSSetup {
$url = "https://raw.githubusercontent.com/ChrisTitusTech/powershell-profile/main/Microsoft.PowerShell_profile.ps1"
$oldhash = Get-FileHash $psprofile -ErrorAction SilentlyContinue
Invoke-RestMethod $url -OutFile "$env:temp/Microsoft.PowerShell_profile.ps1"
$newhash = Get-FileHash "$env:temp/Microsoft.PowerShell_profile.ps1"
if ($newhash.Hash -ne $oldhash.Hash) {
write-host "===> Installing Profile.. <===" -ForegroundColor Yellow
# Starting new hidden shell process bc setup does not work in a runspace
Start-Process -FilePath "pwsh" -ArgumentList "-ExecutionPolicy Bypass -NoProfile -Command `"Invoke-Expression (Invoke-WebRequest `'https://github.com/ChrisTitusTech/powershell-profile/raw/main/setup.ps1`')`"" -WindowStyle Hidden -Wait
Write-Host "Profile has been installed. Please restart your shell to reflect changes!" -ForegroundColor Magenta
write-host "===> Finished <===" -ForegroundColor Yellow
} else {
Write-Host "Profile is up to date" -ForegroundColor Green
}
}
if (Get-Command "pwsh" -ErrorAction SilentlyContinue) {
if ($PSVersionTable.PSVersion.Major -ge 7) {
Invoke-PSSetup
}
else {
write-host "Profile requires Powershell 7, which is currently installed but not used!" -ForegroundColor Red
# Load the necessary assembly for Windows Forms
Add-Type -AssemblyName System.Windows.Forms
# Display the Yes/No message box
$question = [System.Windows.Forms.MessageBox]::Show("Profile requires Powershell 7, which is currently installed but not used! Do you want to install Profile for Powershell 7?", "Question",
[System.Windows.Forms.MessageBoxButtons]::YesNo,
[System.Windows.Forms.MessageBoxIcon]::Question)
# Check the result
if ($question -eq [System.Windows.Forms.DialogResult]::Yes) {
Invoke-PSSetup
}
else {
Write-Host "Not proceeding with the profile setup!"
}
}
}
else {
write-host "Profile requires Powershell 7, which is not installed!" -ForegroundColor Red
}
}
}

View File

@ -0,0 +1,44 @@
function Set-CategoryVisibility {
<#
.SYNOPSIS
Used to expand or collapse categories and corresponding apps on the install tab
.PARAMETER Category
Can eigther be a specific category name like "Browsers" OR "*" to affect all categories at once
.PARAMETER overrideState
"Expand" => expands the corresponding elements
"Collapse" => collapses the corresponding elements
N/A => if compactView is active expand, otherwise collapse elements
#>
param(
[Parameter(Mandatory=$true)]
[string]$Category,
[ValidateSet("Expand", "Collapse")]
[string]$overrideState
)
switch ($overrideState) {
"Expand" {$state = $true}
"Collapse" {$state = $false}
default {$state = $sync.CompactView}
}
# If all the Categories are affected, update the Checked state of the ToggleButtons.
# Otherwise, the state is not synced when toggling between the display modes
if ($category -eq "*") {
$items = $sync.ItemsControl.Items | Where-Object {($_.Tag -like "CategoryWrapPanel_*")}
$sync.ItemsControl.Items | Where-Object {($_.Tag -eq "CategoryToggleButton")} | Foreach-Object { $_.Visibility = [Windows.Visibility]::Visible; $_.IsChecked = $state }
} else {
$items = $sync.ItemsControl.Items | Where-Object {($_.Tag -eq "CategoryWrapPanel_$Category")}
}
$elementVisibility = if ($state -eq $true) {[Windows.Visibility]::Visible} else {[Windows.Visibility]::Collapsed}
$items | ForEach-Object {
$_.Visibility = $elementVisibility
}
$items.Children | ForEach-Object {
$_.Visibility = $elementVisibility
}
}

View File

@ -47,7 +47,7 @@ function Set-WinUtilRegistry {
Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception"
} catch [System.Management.Automation.ItemNotFoundException] {
Write-Warning $psitem.Exception.ErrorRecord
} catch [System.UnauthorizedAccessException]{
} catch [System.UnauthorizedAccessException] {
Write-Warning $psitem.Exception.Message
} catch {
Write-Warning "Unable to set $Name due to unhandled exception"

View File

@ -0,0 +1,54 @@
function Show-OnlyCheckedApps {
<#
.SYNOPSIS
Toggle between showing only the actively selected apps on the Install Tab and hiding everything else and displaying every app.
If no apps are selected, dont do anything
.PARAMETER appKeys
Expects a List of appKeys that are selected at the moment
If not provided, or empty, the function exits without any visual change to the ui
.EXAMPLE
Show-OnlyCheckedApps -appKeys $sync.SelectedApps
Show-OnlyCheckedApps -appKeys ("WPFInstallChrome", "WPFInstall7zip")
#>
param (
[Parameter(Mandatory=$false)]
[String[]]$appKeys
)
# If no apps are selected, do not allow switching to show only selected
if (($false -eq $sync.ShowOnlySelected) -and ($appKeys.Length -eq 0)) {
Write-Host "No apps selected"
$sync.wpfselectedfilter.IsChecked = $false
return
}
$sync.ShowOnlySelected = -not $sync.ShowOnlySelected
if ($sync.ShowOnlySelected) {
$sync.Buttons | Where-Object {$_.Name -like "ShowSelectedAppsButton"} | ForEach-Object {
$_.Content = "Show All"
}
$sync.ItemsControl.Items | Foreach-Object {
# Search for App Container and set them to visible
if ($_.Tag -like "CategoryWrapPanel_*") {
$_.Visibility = [Windows.Visibility]::Visible
# Iterate through all the apps in the container and set them to visible if they are in the appKeys array
$_.Children | ForEach-Object {
if ($appKeys -contains $_.Tag) {
$_.Visibility = [Windows.Visibility]::Visible
}
else {
$_.Visibility = [Windows.Visibility]::Collapsed
}
}
}
else {
# Set all other items to collapsed
$_.Visibility = [Windows.Visibility]::Collapsed
}
}
} else {
$sync.Buttons | Where-Object {$_.Name -like "ShowSelectedAppsButton"} | ForEach-Object {
$_.Content = "Show Selected"
}
Set-CategoryVisibility -Category "*"
}
}

View File

@ -23,14 +23,22 @@ function Test-WinUtilPackageManager {
# Check if Winget is available while getting it's Version if it's available
$wingetExists = $true
try {
$wingetVersionFull = winget --version
$wingetInfo = winget --info
# Extract the package version from the output
$wingetVersionFull = ($wingetInfo | Select-String -Pattern 'Microsoft\.DesktopAppInstaller v\d+\.\d+\.\d+\.\d+').Matches.Value
if ($wingetVersionFull) {
$wingetVersionFull = $wingetVersionFull.Split(' ')[-1].TrimStart('v')
} else {
# Fallback in case the pattern isn't found
$wingetVersionFull = ($wingetInfo | Select-String -Pattern 'Package Manager v\d+\.\d+\.\d+').Matches.Value.Split(' ')[-1]
}
} catch [System.Management.Automation.CommandNotFoundException], [System.Management.Automation.ApplicationFailedException] {
Write-Warning "Winget was not found due to un-availablity reasons"
$wingetExists = $false
} catch {
Write-Warning "Winget was not found due to un-known reasons, The Stack Trace is:`n$($psitem.Exception.StackTrace)"
$wingetExists = $false
}
}
# If Winget is available, Parse it's Version and give proper information to Terminal Output.
# If it isn't available, the return of this funtion will be "not-installed", indicating that
@ -48,13 +56,14 @@ function Test-WinUtilPackageManager {
# Check if Winget's Version is too old.
$wingetCurrentVersion = [System.Version]::Parse($wingetVersion.Trim('v'))
# Grabs the latest release of Winget from the Github API for version check process.
$response = Invoke-RestMethod -Uri "https://api.github.com/repos/microsoft/Winget-cli/releases/latest" -Method Get -ErrorAction Stop
$wingetLatestVersion = [System.Version]::Parse(($response.tag_name).Trim('v')) #Stores version number of latest release.
$wingetOutdated = $wingetCurrentVersion -lt $wingetLatestVersion
$response = winget search -e Microsoft.AppInstaller --accept-source-agreements
$wingetLatestVersion = ($response | Select-String -Pattern '\d+\.\d+\.\d+\.\d+').Matches.Value
Write-Host "Latest Search Version: $wingetLatestVersion" -ForegroundColor White
Write-Host "Current Installed Version: $wingetCurrentVersion" -ForegroundColor White
$wingetOutdated = $wingetCurrentVersion -lt [System.Version]::Parse($wingetLatestVersion)
Write-Host "===========================================" -ForegroundColor Green
Write-Host "--- Winget is installed ---" -ForegroundColor Green
Write-Host "===========================================" -ForegroundColor Green
Write-Host "Version: $wingetVersionFull" -ForegroundColor White
if (!$wingetPreview) {
Write-Host " - Winget is a release version." -ForegroundColor Green

View File

@ -26,7 +26,8 @@ function Invoke-WPFButton {
"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*"}
"WPFClearInstallSelection" {Invoke-WPFPresets -imported $true -checkboxfilterpattern "WPFInstall*"; Show-OnlyCheckedApps; $sync.wpfselectedfilter.IsChecked = $false}
"WPFSelectedFilter" {Show-OnlyCheckedApps -appKeys $sync.SelectedApps}
"WPFtweaksbutton" {Invoke-WPFtweaksbutton}
"WPFOOSUbutton" {Invoke-WPFOOSU}
"WPFAddUltPerf" {Invoke-WPFUltimatePerformance -State "Enable"}

View File

@ -9,42 +9,49 @@ function Invoke-WPFGetInstalled {
#>
param($checkbox)
if($sync.ProcessRunning) {
if ($sync.ProcessRunning) {
$msg = "[Invoke-WPFGetInstalled] Install process is currently running."
[System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
return
}
if(($sync.WPFpreferChocolatey.IsChecked -eq $false) -and ((Test-WinUtilPackageManager -winget) -eq "not-installed") -and $checkbox -eq "winget") {
if (($sync.ChocoRadioButton.IsChecked -eq $false) -and ((Test-WinUtilPackageManager -winget) -eq "not-installed") -and $checkbox -eq "winget") {
return
}
$preferChoco = $sync.WPFpreferChocolatey.IsChecked
Invoke-WPFRunspace -ArgumentList $checkbox, $preferChoco -DebugPreference $DebugPreference -ScriptBlock {
param($checkbox, $preferChoco, $DebugPreference)
$preferChoco = $sync.ChocoRadioButton.IsChecked
$sync.ItemsControl.Dispatcher.Invoke([action] {
$sync.ItemsControl.Items | ForEach-Object { $_.Visibility = [Windows.Visibility]::Collapsed }
$null = $sync.itemsControl.Items.Add($sync.LoadingLabel)
})
Invoke-WPFRunspace -ParameterList @(("preferChoco", $preferChoco),("checkbox", $checkbox),("ShowOnlyCheckedApps", ${function:Show-OnlyCheckedApps})) -DebugPreference $DebugPreference -ScriptBlock {
param (
[string]$checkbox,
[boolean]$preferChoco,
[scriptblock]$ShowOnlyCheckedApps
)
$sync.ProcessRunning = $true
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" })
$sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state "Indeterminate" })
if($checkbox -eq "winget") {
if ($checkbox -eq "winget") {
Write-Host "Getting Installed Programs..."
if ($preferChoco) { $Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox "choco" }
else { $Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox $checkbox }
}
if($checkbox -eq "tweaks") {
elseif ($checkbox -eq "tweaks") {
Write-Host "Getting Installed Tweaks..."
}
if ($preferChoco -and $checkbox -eq "winget") {
$Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox "choco"
}
else{
$Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox $checkbox
}
$sync.form.Dispatcher.invoke({
foreach($checkbox in $Checkboxes) {
foreach ($checkbox in $Checkboxes) {
$sync.$checkbox.ischecked = $True
}
})
$sync.ItemsControl.Dispatcher.Invoke([action] {
$ShowOnlyCheckedApps.Invoke($sync.SelectedApps)
$sync["WPFSelectedFilter"].IsChecked = $true
$sync.ItemsControl.Items.Remove($sync.LoadingLabel)
})
Write-Host "Done..."
$sync.ProcessRunning = $false
$sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state "None" })

View File

@ -46,7 +46,7 @@ function Invoke-WPFImpex {
if ($Config) {
$jsonFile = Get-WinUtilCheckBoxes -unCheck $false | ConvertTo-Json
$jsonFile | Out-File $Config -Force
"iex ""& { `$(irm christitus.com/win) } -Config '$Config'""" | Set-Clipboard
"iex ""& { `$(irm https://christitus.com/win) } -Config '$Config'""" | Set-Clipboard
}
} catch {
Write-Error "An error occurred while exporting: $_"

View File

@ -1,4 +1,8 @@
function Invoke-WPFInstall {
param (
[Parameter(Mandatory=$false)]
[PSObject[]]$PackagesToInstall = $($sync.selectedApps | Foreach-Object { $sync.configs.applicationsHashtable.$_ })
)
<#
.SYNOPSIS
@ -12,14 +16,12 @@ function Invoke-WPFInstall {
return
}
$PackagesToInstall = (Get-WinUtilCheckBoxes)["Install"]
Write-Host $PackagesToInstall
if ($PackagesToInstall.Count -eq 0) {
$WarningMsg = "Please select the program(s) to install or upgrade"
[System.Windows.MessageBox]::Show($WarningMsg, $AppTitle, [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
return
}
$ChocoPreference = $($sync.WPFpreferChocolatey.IsChecked)
$ChocoPreference = $($sync.ChocoRadioButton.IsChecked)
$installHandle = Invoke-WPFRunspace -ParameterList @(("PackagesToInstall", $PackagesToInstall),("ChocoPreference", $ChocoPreference)) -DebugPreference $DebugPreference -ScriptBlock {
param($PackagesToInstall, $ChocoPreference, $DebugPreference)
if ($PackagesToInstall.count -eq 1) {

View File

@ -5,7 +5,7 @@ function Invoke-WPFInstallUpgrade {
Invokes the function that upgrades all installed programs
#>
if ($sync.WPFpreferChocolatey.IsChecked) {
if ($sync.ChocoRadioButton.IsChecked) {
Install-WinUtilChoco
$chocoUpgradeStatus = (Start-Process "choco" -ArgumentList "upgrade all -y" -Wait -PassThru -NoNewWindow).ExitCode
if ($chocoUpgradeStatus -eq 0) {

View File

@ -0,0 +1,43 @@
function Invoke-WPFSelectedAppsUpdate {
<#
.SYNOPSIS
This is a helper function that is called by the Checked and Unchecked events of the Checkboxes on the install tab.
It Updates the "Selected Apps" selectedAppLabel on the Install Tab to represent the current collection
.PARAMETER type
Eigther: Add | Remove
.PARAMETER checkbox
should contain the current instance of the checkbox that triggered the Event.
Most of the time will be the automatic variable $this
.EXAMPLE
$checkbox.Add_Unchecked({Invoke-WPFSelectedAppsUpdate -type "Remove" -checkbox $this})
OR
Invoke-WPFSelectedAppsUpdate -type "Add" -checkbox $specificCheckbox
#>
param (
$type,
$checkbox
)
$selectedAppsButton = $sync.WPFselectedAppsButton
# Get the actual Name from the selectedAppLabel inside the Checkbox
$appKey = $checkbox.Parent.Parent.Tag
if ($type -eq "Add") {
$sync.selectedApps.Add($appKey)
# The List type needs to be specified again, because otherwise Sort-Object will convert the list to a string if there is only a single entry
[System.Collections.Generic.List[pscustomobject]]$sync.selectedApps = $sync.SelectedApps | Sort-Object
}
elseif ($type -eq "Remove") {
$sync.SelectedApps.Remove($appKey)
}
else{
Write-Error "Type: $type not implemented"
}
$count = $sync.SelectedApps.Count
$selectedAppsButton.Content = "Selected Apps: $count"
# On every change, remove all entries inside the Popup Menu. This is done, so we can keep the alphabetical order even if elements are selected in a random way
$sync.selectedAppsstackPanel.Children.Clear()
$sync.SelectedApps | Foreach-Object { Add-SelectedAppsMenuItem -name $($sync.configs.applicationsHashtable.$_.Content) -key $_ }
}

View File

@ -28,4 +28,5 @@ function Invoke-WPFTab {
$sync.$tabNav.Items[$tabNumber].IsSelected = $true
}
}
$sync.currentTab = $sync.$tabNav.Items[$tabNumber].Header
}

View File

@ -0,0 +1,22 @@
function Invoke-WPFUIApps {
[OutputType([void])]
param(
[Parameter(Mandatory, Position = 0)]
[PSCustomObject[]]$Apps,
[Parameter(Mandatory, Position = 1)]
[string]$TargetGridName
)
switch ($TargetGridName) {
"appspanel" {
$dockPanel = Initialize-InstallAppsMainElement -TargetGridName $TargetGridName
$null = Initialize-InstallHeader -TargetElement $dockPanel
$sync.ItemsControl = Initialize-InstallAppArea -TargetElement $dockPanel
Initialize-InstallCategoryAppList -TargetElement $sync.ItemsControl -Apps $Apps
}
default {
Write-Output "$TargetGridName not yet implemented"
}
}
}

View File

@ -11,26 +11,26 @@ function Invoke-WPFUIElements {
.EXAMPLE
Invoke-WPFUIElements -configVariable $sync.configs.applications -targetGridName "install" -columncount 5
.NOTES
Future me/contributer: If possible please wrap this into a runspace to make it load all panels at the same time.
Future me/contributor: If possible, please wrap this into a runspace to make it load all panels at the same time.
#>
param(
[Parameter(Mandatory, position=0)]
[Parameter(Mandatory, Position = 0)]
[PSCustomObject]$configVariable,
[Parameter(Mandatory, position=1)]
[Parameter(Mandatory, Position = 1)]
[string]$targetGridName,
[Parameter(Mandatory, position=2)]
[Parameter(Mandatory, Position = 2)]
[int]$columncount
)
$window = $sync["Form"]
$window = $sync.form
$theme = $sync.Form.Resources
$borderstyle = $window.FindResource("BorderStyle")
$HoverTextBlockStyle = $window.FindResource("HoverTextBlockStyle")
$ColorfulToggleSwitchStyle = $window.FindResource("ColorfulToggleSwitchStyle")
$ToggleButtonStyle = $window.FindResource("ToggleButtonStyle")
if (!$borderstyle -or !$HoverTextBlockStyle -or !$ColorfulToggleSwitchStyle) {
throw "Failed to retrieve Styles using 'FindResource' from main window element."
@ -59,6 +59,8 @@ function Invoke-WPFUIElements {
$configHashtable[$_] = $configVariable.$_
}
$radioButtonGroups = @{}
$organizedData = @{}
# Iterate through JSON data and organize by panel and category
foreach ($entry in $configHashtable.Keys) {
@ -66,19 +68,18 @@ function Invoke-WPFUIElements {
# Create an object for the application
$entryObject = [PSCustomObject]@{
Name = $entry
Order = $entryInfo.order
Category = $entryInfo.Category
Content = $entryInfo.Content
Choco = $entryInfo.choco
Winget = $entryInfo.winget
Panel = if ($entryInfo.Panel) { $entryInfo.Panel } else { "0" }
Link = $entryInfo.link
Name = $entry
Order = $entryInfo.order
Category = $entryInfo.Category
Content = $entryInfo.Content
Panel = if ($entryInfo.Panel) { $entryInfo.Panel } else { "0" }
Link = $entryInfo.link
Description = $entryInfo.description
Type = $entryInfo.type
ComboItems = $entryInfo.ComboItems
Checked = $entryInfo.Checked
Type = $entryInfo.type
ComboItems = $entryInfo.ComboItems
Checked = $entryInfo.Checked
ButtonWidth = $entryInfo.ButtonWidth
GroupName = $entryInfo.GroupName # Added for RadioButton groupings
}
if (-not $organizedData.ContainsKey($entryObject.Panel)) {
@ -96,11 +97,13 @@ function Invoke-WPFUIElements {
if ($targetGridName -eq "appspanel") {
$panelcount = 0
$entrycount = $configHashtable.Keys.Count + $organizedData["0"].Keys.Count
$maxcount = [Math]::Round($entrycount / $columncount + 0.5)
}
}
# Initialize panel count
$panelcount = 0
# Iterate through 'organizedData' by panel, category, and application
$count = 0
foreach ($panelKey in ($organizedData.Keys | Sort-Object)) {
@ -111,78 +114,46 @@ function Invoke-WPFUIElements {
$border.style = $borderstyle
$targetGrid.Children.Add($border) | Out-Null
# Create a StackPanel inside the Border
$stackPanel = New-Object Windows.Controls.StackPanel
$stackPanel.Background = [Windows.Media.Brushes]::Transparent
$stackPanel.SnapsToDevicePixels = $true
$stackPanel.VerticalAlignment = "Stretch"
$border.Child = $stackPanel
# Use a DockPanel to contain the content
$dockPanelContainer = New-Object Windows.Controls.DockPanel
$border.Child = $dockPanelContainer
# Create an ItemsControl for application content
$itemsControl = New-Object Windows.Controls.ItemsControl
$itemsControl.HorizontalAlignment = 'Stretch'
$itemsControl.VerticalAlignment = 'Stretch'
# Set the ItemsPanel to a VirtualizingStackPanel
$itemsPanelTemplate = New-Object Windows.Controls.ItemsPanelTemplate
$factory = New-Object Windows.FrameworkElementFactory ([Windows.Controls.VirtualizingStackPanel])
$itemsPanelTemplate.VisualTree = $factory
$itemsControl.ItemsPanel = $itemsPanelTemplate
# Set virtualization properties
$itemsControl.SetValue([Windows.Controls.VirtualizingStackPanel]::IsVirtualizingProperty, $true)
$itemsControl.SetValue([Windows.Controls.VirtualizingStackPanel]::VirtualizationModeProperty, [Windows.Controls.VirtualizationMode]::Recycling)
# Add the ItemsControl directly to the DockPanel
[Windows.Controls.DockPanel]::SetDock($itemsControl, [Windows.Controls.Dock]::Bottom)
$dockPanelContainer.Children.Add($itemsControl) | Out-Null
$panelcount++
# Add Windows Version label if this is the updates panel
if ($targetGridName -eq "updatespanel") {
$windowsVersion = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion").ProductName
$versionLabel = New-Object Windows.Controls.Label
$versionLabel.Content = "Windows Version: $windowsVersion"
$versionLabel.FontSize = $theme.FontSize
$versionLabel.HorizontalAlignment = "Left"
$stackPanel.Children.Add($versionLabel) | Out-Null
}
# Now proceed with adding category labels and entries to $itemsControl
foreach ($category in ($organizedData[$panelKey].Keys | Sort-Object)) {
$count++
if ($targetGridName -eq "appspanel" -and $columncount -gt 0) {
$panelcount2 = [Int](($count) / $maxcount - 0.5)
if ($panelcount -eq $panelcount2) {
# Create a new Border for the new column
$border = New-Object Windows.Controls.Border
$border.VerticalAlignment = "Stretch"
[System.Windows.Controls.Grid]::SetColumn($border, $panelcount)
$border.style = $borderstyle
$targetGrid.Children.Add($border) | Out-Null
# Create a new StackPanel inside the Border
$stackPanel = New-Object Windows.Controls.StackPanel
$stackPanel.Background = [Windows.Media.Brushes]::Transparent
$stackPanel.SnapsToDevicePixels = $true
$stackPanel.VerticalAlignment = "Stretch"
$border.Child = $stackPanel
$panelcount++
}
}
$label = New-Object Windows.Controls.Label
$label.Content = $category -replace ".*__", ""
$label.FontSize = $theme.HeadingFontSize
$label.FontFamily = $theme.HeaderFontFamily
$stackPanel.Children.Add($label) | Out-Null
$label.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "FontSizeHeading")
$label.SetResourceReference([Windows.Controls.Control]::FontFamilyProperty, "HeaderFontFamily")
$itemsControl.Items.Add($label) | Out-Null
$sync[$category] = $label
# Sort entries by Order and then by Name, but only display Name
# Sort entries by Order and then by Name
$entries = $organizedData[$panelKey][$category] | Sort-Object Order, Name
foreach ($entryInfo in $entries) {
$count++
if ($targetGridName -eq "appspanel" -and $columncount -gt 0) {
$panelcount2 = [Int](($count) / $maxcount - 0.5)
if ($panelcount -eq $panelcount2) {
# Create a new Border for the new column
$border = New-Object Windows.Controls.Border
$border.VerticalAlignment = "Stretch"
[System.Windows.Controls.Grid]::SetColumn($border, $panelcount)
$border.style = $borderstyle
$targetGrid.Children.Add($border) | Out-Null
# Create a new StackPanel inside the Border
$stackPanel = New-Object Windows.Controls.StackPanel
$stackPanel.Background = [Windows.Media.Brushes]::Transparent
$stackPanel.SnapsToDevicePixels = $true
$stackPanel.VerticalAlignment = "Stretch"
$border.Child = $stackPanel
$panelcount++
}
}
# Create the UI elements based on the entry type
switch ($entryInfo.Type) {
"Toggle" {
$dockPanel = New-Object Windows.Controls.DockPanel
@ -196,10 +167,10 @@ function Invoke-WPFUIElements {
$label.Content = $entryInfo.Content
$label.ToolTip = $entryInfo.Description
$label.HorizontalAlignment = "Left"
$label.FontSize = $theme.FontSize
$label.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "FontSize")
$label.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor")
$dockPanel.Children.Add($label) | Out-Null
$stackPanel.Children.Add($dockPanel) | Out-Null
$itemsControl.Items.Add($dockPanel) | Out-Null
$sync[$entryInfo.Name] = $checkBox
@ -217,35 +188,29 @@ function Invoke-WPFUIElements {
}
"ToggleButton" {
$toggleButton = New-Object Windows.Controls.ToggleButton
$toggleButton = New-Object Windows.Controls.Primitives.ToggleButton
$toggleButton.Name = $entryInfo.Name
$toggleButton.Name = "WPFTab" + ($stackPanel.Children.Count + 1) + "BT"
$toggleButton.Content = $entryInfo.Content[1]
$toggleButton.ToolTip = $entryInfo.Description
$toggleButton.HorizontalAlignment = "Left"
$toggleButton.Height = $theme.TabButtonHeight
$toggleButton.Width = $theme.TabButtonWidth
$toggleButton.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "ButtonInstallBackgroundColor")
$toggleButton.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor")
$toggleButton.FontWeight = [Windows.FontWeights]::Bold
$toggleButton.Style = $ToggleButtonStyle
$textBlock = New-Object Windows.Controls.TextBlock
$textBlock.FontSize = $theme.TabButtonFontSize
$textBlock.Background = [Windows.Media.Brushes]::Transparent
$textBlock.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "ButtonInstallForegroundColor")
$toggleButton.Tag = @{
contentOn = if ($entryInfo.Content.Count -ge 1) { $entryInfo.Content[0] } else { "" }
contentOff = if ($entryInfo.Content.Count -ge 2) { $entryInfo.Content[1] } else { $contentOn }
}
$underline = New-Object Windows.Documents.Underline
$underline.Inlines.Add($entryInfo.name -replace "(.).*", "`$1")
$run = New-Object Windows.Documents.Run
$run.Text = $entryInfo.name -replace "^.", ""
$textBlock.Inlines.Add($underline)
$textBlock.Inlines.Add($run)
$toggleButton.Content = $textBlock
$stackPanel.Children.Add($toggleButton) | Out-Null
$itemsControl.Items.Add($toggleButton) | Out-Null
$sync[$entryInfo.Name] = $toggleButton
$sync[$entryInfo.Name].Add_Checked({
$this.Content = $this.Tag.contentOn
})
$sync[$entryInfo.Name].Add_Unchecked({
$this.Content = $this.Tag.contentOff
})
}
"Combobox" {
@ -257,26 +222,26 @@ function Invoke-WPFUIElements {
$label.Content = $entryInfo.Content
$label.HorizontalAlignment = "Left"
$label.VerticalAlignment = "Center"
$label.FontSize = $theme.ButtonFontSize
$label.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "ButtonFontSize")
$horizontalStackPanel.Children.Add($label) | Out-Null
$comboBox = New-Object Windows.Controls.ComboBox
$comboBox.Name = $entryInfo.Name
$comboBox.Height = $theme.ButtonHeight
$comboBox.Width = $theme.ButtonWidth
$comboBox.SetResourceReference([Windows.Controls.Control]::HeightProperty, "ButtonHeight")
$comboBox.SetResourceReference([Windows.Controls.Control]::WidthProperty, "ButtonWidth")
$comboBox.HorizontalAlignment = "Left"
$comboBox.VerticalAlignment = "Center"
$comboBox.Margin = $theme.ButtonMargin
$comboBox.SetResourceReference([Windows.Controls.Control]::MarginProperty, "ButtonMargin")
foreach ($comboitem in ($entryInfo.ComboItems -split " ")) {
$comboBoxItem = New-Object Windows.Controls.ComboBoxItem
$comboBoxItem.Content = $comboitem
$comboBoxItem.FontSize = $theme.ButtonFontSize
$comboBoxItem.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "ButtonFontSize")
$comboBox.Items.Add($comboBoxItem) | Out-Null
}
$horizontalStackPanel.Children.Add($comboBox) | Out-Null
$stackPanel.Children.Add($horizontalStackPanel) | Out-Null
$itemsControl.Items.Add($horizontalStackPanel) | Out-Null
$comboBox.SelectedIndex = 0
@ -288,16 +253,50 @@ function Invoke-WPFUIElements {
$button.Name = $entryInfo.Name
$button.Content = $entryInfo.Content
$button.HorizontalAlignment = "Left"
$button.Margin = $theme.ButtonMargin
$button.FontSize = $theme.ButtonFontSize
$button.SetResourceReference([Windows.Controls.Control]::MarginProperty, "ButtonMargin")
$button.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "ButtonFontSize")
if ($entryInfo.ButtonWidth) {
$button.Width = $entryInfo.ButtonWidth
}
$stackPanel.Children.Add($button) | Out-Null
$itemsControl.Items.Add($button) | Out-Null
$sync[$entryInfo.Name] = $button
}
"RadioButton" {
# Check if a container for this GroupName already exists
if (-not $radioButtonGroups.ContainsKey($entryInfo.GroupName)) {
# Create a StackPanel for this group
$groupStackPanel = New-Object Windows.Controls.StackPanel
$groupStackPanel.Orientation = "Vertical"
# Add the group container to the ItemsControl
$itemsControl.Items.Add($groupStackPanel) | Out-Null
}
else {
# Retrieve the existing group container
$groupStackPanel = $radioButtonGroups[$entryInfo.GroupName]
}
# Create the RadioButton
$radioButton = New-Object Windows.Controls.RadioButton
$radioButton.Name = $entryInfo.Name
$radioButton.GroupName = $entryInfo.GroupName
$radioButton.Content = $entryInfo.Content
$radioButton.HorizontalAlignment = "Left"
$radioButton.SetResourceReference([Windows.Controls.Control]::MarginProperty, "CheckBoxMargin")
$radioButton.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "ButtonFontSize")
$radioButton.ToolTip = $entryInfo.Description
if ($entryInfo.Checked -eq $true) {
$radioButton.IsChecked = $true
}
# Add the RadioButton to the group container
$groupStackPanel.Children.Add($radioButton) | Out-Null
$sync[$entryInfo.Name] = $radioButton
}
default {
$horizontalStackPanel = New-Object Windows.Controls.StackPanel
$horizontalStackPanel.Orientation = "Horizontal"
@ -305,9 +304,9 @@ function Invoke-WPFUIElements {
$checkBox = New-Object Windows.Controls.CheckBox
$checkBox.Name = $entryInfo.Name
$checkBox.Content = $entryInfo.Content
$checkBox.FontSize = $theme.FontSize
$checkBox.SetResourceReference([Windows.Controls.Control]::FontSizeProperty, "FontSize")
$checkBox.ToolTip = $entryInfo.Description
$checkBox.Margin = $theme.CheckBoxMargin
$checkBox.SetResourceReference([Windows.Controls.Control]::MarginProperty, "CheckBoxMargin")
if ($entryInfo.Checked -eq $true) {
$checkBox.IsChecked = $entryInfo.Checked
}
@ -325,7 +324,7 @@ function Invoke-WPFUIElements {
$sync[$textBlock.Name] = $textBlock
}
$stackPanel.Children.Add($horizontalStackPanel) | Out-Null
$itemsControl.Items.Add($horizontalStackPanel) | Out-Null
$sync[$entryInfo.Name] = $checkBox
}
}

View File

@ -1,9 +1,12 @@
function Invoke-WPFUnInstall {
param(
[Parameter(Mandatory=$false)]
[PSObject[]]$PackagesToUninstall = $($sync.selectedApps | Foreach-Object { $sync.configs.applicationsHashtable.$_ })
)
<#
.SYNOPSIS
Uninstalls the selected programs
#>
if($sync.ProcessRunning) {
@ -12,9 +15,7 @@ function Invoke-WPFUnInstall {
return
}
$PackagesToInstall = (Get-WinUtilCheckBoxes)["Install"]
if ($PackagesToInstall.Count -eq 0) {
if ($PackagesToUninstall.Count -eq 0) {
$WarningMsg = "Please select the program(s) to uninstall"
[System.Windows.MessageBox]::Show($WarningMsg, $AppTitle, [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
return
@ -22,17 +23,17 @@ function Invoke-WPFUnInstall {
$ButtonType = [System.Windows.MessageBoxButton]::YesNo
$MessageboxTitle = "Are you sure?"
$Messageboxbody = ("This will uninstall the following applications: `n $($PackagesToInstall | Format-Table | Out-String)")
$Messageboxbody = ("This will uninstall the following applications: `n $($PackagesToUninstall | Select-Object Name, Description| Out-String)")
$MessageIcon = [System.Windows.MessageBoxImage]::Information
$confirm = [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon)
if($confirm -eq "No") {return}
$ChocoPreference = $($sync.WPFpreferChocolatey.IsChecked)
$ChocoPreference = $($sync.ChocoRadioButton.IsChecked)
Invoke-WPFRunspace -ArgumentList @(("PackagesToInstall", $PackagesToInstall),("ChocoPreference", $ChocoPreference)) -DebugPreference $DebugPreference -ScriptBlock {
param($PackagesToInstall, $ChocoPreference, $DebugPreference)
if ($PackagesToInstall.count -eq 1) {
Invoke-WPFRunspace -ArgumentList @(("PackagesToUninstall", $PackagesToUninstall),("ChocoPreference", $ChocoPreference)) -DebugPreference $DebugPreference -ScriptBlock {
param($PackagesToUninstall, $ChocoPreference, $DebugPreference)
if ($PackagesToUninstall.count -eq 1) {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
} else {
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" })
@ -41,7 +42,7 @@ function Invoke-WPFUnInstall {
$packagesWinget = [System.Collections.ArrayList]::new()
$packagesChoco = [System.Collections.ArrayList]::new()
foreach ($package in $PackagesToInstall) {
foreach ($package in $PackagesToUninstall) {
if ($ChocoPreference) {
if ($package.choco -eq "na") {
$packagesWinget.add($package.winget)
@ -62,7 +63,7 @@ function Invoke-WPFUnInstall {
}
}
return $packagesWinget, $packagesChoco
}.Invoke($PackagesToInstall)
}.Invoke($PackagesToUninstall)
try {
$sync.ProcessRunning = $true

View File

@ -108,8 +108,27 @@ $sync.Form.Add_Loaded({
Invoke-WinutilThemeChange -init $true
# Load the configuration files
#Invoke-WPFUIElements -configVariable $sync.configs.nav -targetGridName "WPFMainGrid"
Invoke-WPFUIElements -configVariable $sync.configs.applications -targetGridName "appspanel" -columncount 5
$noimage = "https://images.emojiterra.com/google/noto-emoji/unicode-15/color/512px/1f4e6.png"
$noimage = [Windows.Media.Imaging.BitmapImage]::new([Uri]::new($noimage))
$sync.configs.applicationsHashtable = @{}
$sync.configs.applications.PSObject.Properties | ForEach-Object {
$sync.configs.applicationsHashtable[$_.Name] = $_.Value
}
# Now call the function with the final merged config
Invoke-WPFUIElements -configVariable $sync.configs.appnavigation -targetGridName "appscategory" -columncount 1
# Add logic to handle click to the ToggleView Button on the Install Tab
$sync.WPFToggleView.Add_Click({
$sync.CompactView = -not $sync.CompactView
Update-AppTileProperties
if ($sync.SearchBar.Text -eq "") {
Set-CategoryVisibility -Category "*"
}
})
Invoke-WPFUIApps -Apps $sync.configs.applicationsHashtable -targetGridName "appspanel"
Invoke-WPFUIElements -configVariable $sync.configs.tweaks -targetGridName "tweakspanel" -columncount 2
Invoke-WPFUIElements -configVariable $sync.configs.feature -targetGridName "featurespanel" -columncount 2
# Future implementation: Add Windows Version to updates panel
@ -123,10 +142,10 @@ $xaml.SelectNodes("//*[@Name]") | ForEach-Object {$sync["$("$($psitem.Name)")"]
#Persist the Chocolatey preference across winutil restarts
$ChocoPreferencePath = "$env:LOCALAPPDATA\winutil\preferChocolatey.ini"
$sync.WPFpreferChocolatey.Add_Checked({New-Item -Path $ChocoPreferencePath -Force })
$sync.WPFpreferChocolatey.Add_Unchecked({Remove-Item $ChocoPreferencePath -Force})
$sync.ChocoRadioButton.Add_Checked({New-Item -Path $ChocoPreferencePath -Force })
$sync.ChocoRadioButton.Add_Unchecked({Remove-Item $ChocoPreferencePath -Force})
if (Test-Path $ChocoPreferencePath) {
$sync.WPFpreferChocolatey.IsChecked = $true
$sync.ChocoRadioButton.IsChecked = $true
}
$sync.keys | ForEach-Object {
@ -183,6 +202,32 @@ Invoke-WPFRunspace -ScriptBlock {
# Print the logo
Invoke-WPFFormVariables
$sync.CompactView = $false
$sync.Form.Resources.AppTileWidth = [double]::NaN
$sync.Form.Resources.AppTileCompactVisibility = [Windows.Visibility]::Visible
$sync.Form.Resources.AppTileFontSize = [double]16
$sync.Form.Resources.AppTileMargins = [Windows.Thickness]5
$sync.Form.Resources.AppTileBorderThickness = [Windows.Thickness]0
function Update-AppTileProperties {
if ($sync.CompactView -eq $true) {
$sync.Form.Resources.AppTileWidth = [double]::NaN
$sync.Form.Resources.AppTileCompactVisibility = [Windows.Visibility]::Collapsed
$sync.Form.Resources.AppTileFontSize = [double]12
$sync.Form.Resources.AppTileMargins = [Windows.Thickness]2
$sync.Form.Resources.AppTileBorderThickness = [Windows.Thickness]0
}
else {
$sync.Form.Resources.AppTileWidth = $sync.ItemsControl.ActualWidth -20
$sync.Form.Resources.AppTileCompactVisibility = [Windows.Visibility]::Visible
$sync.Form.Resources.AppTileFontSize = [double]16
$sync.Form.Resources.AppTileMargins = [Windows.Thickness]5
$sync.Form.Resources.AppTileBorderThickness = [Windows.Thickness]1
}
}
# We need to update the app tile properties when the form is resized because to fill a WrapPanel update the width of the elemenmt manually (afaik)
$sync.Form.Add_SizeChanged({
Update-AppTileProperties
})
# Progress bar in taskbaritem > Set-WinUtilProgressbar
$sync["Form"].TaskbarItemInfo = New-Object System.Windows.Shell.TaskbarItemInfo
@ -414,73 +459,22 @@ if ($sync["ISOLanguage"].Items.Count -eq 1) {
}
$sync["ISOLanguage"].SelectedIndex = 0
# Load Checkboxes and Labels outside of the Filter function only once on startup for performance reasons
$filter = Get-WinUtilVariables -Type CheckBox
$CheckBoxes = ($sync.GetEnumerator()).where{ $psitem.Key -in $filter }
$filter = Get-WinUtilVariables -Type Label
$labels = @{}
($sync.GetEnumerator()).where{$PSItem.Key -in $filter} | ForEach-Object {$labels[$_.Key] = $_.Value}
$allCategories = $checkBoxes.Name | ForEach-Object {$sync.configs.applications.$_} | Select-Object -Unique -ExpandProperty category
$sync["SearchBar"].Add_TextChanged({
if ($sync.SearchBar.Text -ne "") {
$sync.SearchBarClearButton.Visibility = "Visible"
} else {
$sync.SearchBarClearButton.Visibility = "Collapsed"
}
$activeApplications = @()
$textToSearch = $sync.SearchBar.Text.ToLower()
foreach ($CheckBox in $CheckBoxes) {
# Skip if the checkbox is null, it doesn't have content or it is the prefer Choco checkbox
if ($CheckBox -eq $null -or $CheckBox.Value -eq $null -or $CheckBox.Value.Content -eq $null -or $CheckBox.Name -eq "WPFpreferChocolatey") {
continue
switch ($sync.currentTab) {
"Install" {
Find-AppsByNameOrDescription -SearchString $sync.SearchBar.Text
}
$checkBoxName = $CheckBox.Key
$textBlockName = $checkBoxName + "Link"
# Retrieve the corresponding text block based on the generated name
$textBlock = $sync[$textBlockName]
if ($CheckBox.Value.Content.ToString().ToLower().Contains($textToSearch)) {
$CheckBox.Value.Visibility = "Visible"
$activeApplications += $sync.configs.applications.$checkboxName
# Set the corresponding text block visibility
if ($textBlock -ne $null -and $textBlock -is [System.Windows.Controls.TextBlock]) {
$textBlock.Visibility = "Visible"
}
} else {
$CheckBox.Value.Visibility = "Collapsed"
# Set the corresponding text block visibility
if ($textBlock -ne $null -and $textBlock -is [System.Windows.Controls.TextBlock]) {
$textBlock.Visibility = "Collapsed"
}
}
}
$activeCategories = $activeApplications | Select-Object -ExpandProperty category -Unique
foreach ($category in $activeCategories) {
$sync[$category].Visibility = "Visible"
}
if ($activeCategories) {
$inactiveCategories = Compare-Object -ReferenceObject $allCategories -DifferenceObject $activeCategories -PassThru
} else {
$inactiveCategories = $allCategories
}
foreach ($category in $inactiveCategories) {
$sync[$category].Visibility = "Collapsed"
}
})
$sync["Form"].Add_Loaded({
param($e)
$sync.Form.MinWidth = "1000"
$sync["Form"].MaxWidth = [Double]::PositiveInfinity
$sync["Form"].MaxHeight = [Double]::PositiveInfinity
})
@ -585,5 +579,7 @@ $sync["SponsorMenuItem"].Add_Click({
Show-CustomDialog -Title "Sponsors" -Message $authorInfo -EnableScroll $true
})
$sync["Form"].ShowDialog() | out-null
Stop-Transcript

View File

@ -37,7 +37,15 @@ $sync = [Hashtable]::Synchronized(@{})
$sync.PSScriptRoot = $PSScriptRoot
$sync.version = "#{replaceme}"
$sync.configs = @{}
$sync.Buttons = [System.Collections.Generic.List[PSObject]]::new()
$sync.ProcessRunning = $false
$sync.selectedApps = [System.Collections.Generic.List[string]]::new()
$sync.ShowOnlySeleced = $false
$sync.currentTab = "Install"
$sync.ShowOnlySelected = $false
$sync.selectedAppsStackPanel
$sync.selectedAppsPopup
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
Write-Output "Winutil needs to be run as Administrator. Attempting to relaunch."
@ -46,21 +54,27 @@ if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]:
$PSBoundParameters.GetEnumerator() | ForEach-Object {
$argList += if ($_.Value -is [switch] -and $_.Value) {
"-$($_.Key)"
} elseif ($_.Value -is [array]) {
"-$($_.Key) $($_.Value -join ',')"
} elseif ($_.Value) {
"-$($_.Key) `"$($_.Value)`""
"-$($_.Key) '$($_.Value)'"
}
}
$script = if ($MyInvocation.MyCommand.Path) {
"& { & '$($MyInvocation.MyCommand.Path)' $argList }"
$script = if ($PSCommandPath) {
"& { & `'$($PSCommandPath)`' $($argList -join ' ') }"
} else {
"iex '& { $(irm https://github.com/ChrisTitusTech/winutil/releases/latest/download/winutil.ps1) } $argList'"
"&([ScriptBlock]::Create((irm https://github.com/ChrisTitusTech/winutil/releases/latest/download/winutil.ps1))) $($argList -join ' ')"
}
$powershellcmd = if (Get-Command pwsh -ErrorAction SilentlyContinue) { "pwsh" } else { "powershell" }
$processCmd = if (Get-Command wt.exe -ErrorAction SilentlyContinue) { "wt.exe" } else { $powershellcmd }
$powershellCmd = if (Get-Command pwsh -ErrorAction SilentlyContinue) { "pwsh" } else { "powershell" }
$processCmd = if (Get-Command wt.exe -ErrorAction SilentlyContinue) { "wt.exe" } else { "$powershellCmd" }
Start-Process $processCmd -ArgumentList "$powershellcmd -ExecutionPolicy Bypass -NoProfile -Command $script" -Verb RunAs
if ($processCmd -eq "wt.exe") {
Start-Process $processCmd -ArgumentList "$powershellCmd -ExecutionPolicy Bypass -NoProfile -Command `"$script`"" -Verb RunAs
} else {
Start-Process $processCmd -ArgumentList "-ExecutionPolicy Bypass -NoProfile -Command `"$script`"" -Verb RunAs
}
break
}

View File

@ -197,6 +197,45 @@
<Setter Property="Background" Value="{DynamicResource LabelBackgroundColor}"/>
<Setter Property="FontFamily" Value="{DynamicResource FontFamily}"/>
</Style>
<!-- Category Toggle Button Style for the Apps Window-->
<Style x:Key="CategoryToggleButtonStyle" TargetType="ToggleButton">
<Setter Property="Foreground" Value="{DynamicResource LabelboxForegroundColor}"/>
<Setter Property="Background" Value="{DynamicResource MainBackgroundColor}"/>
<Setter Property="FontFamily" Value="{DynamicResource HeaderFontFamily}"/>
<Setter Property="FontSize" Value="{DynamicResource FontSizeHeading}"/>
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="Padding" Value="10,2,10,2"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Border Background="{TemplateBinding Background}"
BorderBrush="{DynamicResource BorderColor}"
BorderThickness="0"
CornerRadius="{DynamicResource ButtonCornerRadius}">
<StackPanel Orientation="Horizontal" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" Margin="{TemplateBinding Padding}">
<TextBlock x:Name="PrefixTextBlock"/>
<ContentPresenter Content="{TemplateBinding Content}" />
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="PrefixTextBlock" Property="Text" Value="[-] "/>
</Trigger>
<Trigger Property="IsChecked" Value="False">
<Setter TargetName="PrefixTextBlock" Property="Text" Value="[+] "/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundMouseoverColor}"/>
</Trigger>
</Style.Triggers>
</Style>
<!-- TextBlock template -->
<Style TargetType="TextBlock">
@ -298,6 +337,103 @@
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ToggleButtonStyle" TargetType="ToggleButton">
<Setter Property="Margin" Value="{DynamicResource ButtonMargin}"/>
<Setter Property="Foreground" Value="{DynamicResource ButtonForegroundColor}"/>
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundColor}"/>
<Setter Property="Height" Value="{DynamicResource ButtonHeight}"/>
<Setter Property="Width" Value="{DynamicResource ButtonWidth}"/>
<Setter Property="FontSize" Value="{DynamicResource ButtonFontSize}"/>
<Setter Property="FontFamily" Value="{DynamicResource FontFamily}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleButton">
<Grid>
<Border x:Name="BackgroundBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{DynamicResource ButtonBorderThickness}"
CornerRadius="{DynamicResource ButtonCornerRadius}">
<Grid>
<!-- Toggle Dot Background -->
<Ellipse Width="8" Height="16"
Fill="{DynamicResource ToggleButtonOnColor}"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Margin="0,3,5,0" />
<!-- Toggle Dot with hover grow effect -->
<Ellipse x:Name="ToggleDot"
Width="8" Height="8"
Fill="{DynamicResource ButtonForegroundColor}"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Margin="0,3,5,0"
RenderTransformOrigin="0.5,0.5">
<Ellipse.RenderTransform>
<ScaleTransform ScaleX="1" ScaleY="1"/>
</Ellipse.RenderTransform>
</Ellipse>
<!-- Content Presenter -->
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="10,2,10,2"/>
</Grid>
</Border>
</Grid>
<!-- Triggers for ToggleButton states -->
<ControlTemplate.Triggers>
<!-- Hover effect -->
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="BackgroundBorder" Property="Background" Value="{DynamicResource ButtonBackgroundMouseoverColor}"/>
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<!-- Animation to grow the dot when hovered -->
<DoubleAnimation Storyboard.TargetName="ToggleDot"
Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
To="1.2" Duration="0:0:0.1"/>
<DoubleAnimation Storyboard.TargetName="ToggleDot"
Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
To="1.2" Duration="0:0:0.1"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<!-- Animation to shrink the dot back to original size when not hovered -->
<DoubleAnimation Storyboard.TargetName="ToggleDot"
Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleX)"
To="1.0" Duration="0:0:0.1"/>
<DoubleAnimation Storyboard.TargetName="ToggleDot"
Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)"
To="1.0" Duration="0:0:0.1"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
<!-- IsChecked state -->
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="ToggleDot" Property="VerticalAlignment" Value="Bottom"/>
<Setter TargetName="ToggleDot" Property="Margin" Value="0,0,5,3"/>
</Trigger>
<!-- IsEnabled state -->
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="BackgroundBorder" Property="Background" Value="{DynamicResource ButtonBackgroundSelectedColor}"/>
<Setter Property="Foreground" Value="DimGray"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="SearchBarClearButtonStyle" TargetType="Button">
<Setter Property="FontFamily" Value="{DynamicResource FontFamily}"/>
<Setter Property="FontSize" Value="{DynamicResource SearchBarClearButtonFontSize}"/>
@ -366,6 +502,19 @@
</Setter.Value>
</Setter>
</Style>
<!-- Collapsed Checkbox Style -->
<Style x:Key="CollapsedCheckBoxStyle" TargetType="CheckBox">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<ContentPresenter Content="{TemplateBinding Content}"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Margin="{TemplateBinding Padding}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="RadioButton">
<Setter Property="Foreground" Value="{DynamicResource MainForegroundColor}"/>
<Setter Property="Background" Value="{DynamicResource MainBackgroundColor}"/>
@ -864,7 +1013,6 @@
</Border>
</Popup>
<Button Name="SettingsButton"
Style="{StaticResource HoverButtonStyle}"
Grid.Column="3" BorderBrush="Transparent"
@ -917,29 +1065,18 @@
<TabItem Header="Install" Visibility="Collapsed" Name="WPFTab1">
<Grid Background="Transparent" >
<Grid.RowDefinitions>
<RowDefinition Height="45px"/>
<RowDefinition Height="0.95*"/>
</Grid.RowDefinitions>
<StackPanel Background="{DynamicResource MainBackgroundColor}" Orientation="Horizontal" Grid.Row="0" HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Column="0" Grid.ColumnSpan="3" Margin="{DynamicResource TabContentMargin}">
<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="WPFGetInstalled" Content=" Get Installed" Margin="2"/>
<Button Name="WPFClearInstallSelection" Content=" Clear Selection" Margin="2"/>
<CheckBox Name="WPFpreferChocolatey" VerticalAlignment="Center" VerticalContentAlignment="Center">
<TextBlock Text="Prefer Chocolatey" ToolTip="Prefers Chocolatey as Download Engine instead of Winget" VerticalAlignment="Center" />
</CheckBox>
</StackPanel>
<Grid Grid.Row="0" Grid.Column="0" Margin="{DynamicResource TabContentMargin}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="225" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ScrollViewer x:Name="scrollViewer" Grid.Row="1" Grid.Column="0" Margin="{DynamicResource TabContentMargin}" VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"
BorderBrush="Transparent" BorderThickness="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid Name="appspanel" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid Name="appscategory" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
</Grid>
</ScrollViewer>
<Rectangle Grid.Row="1" Grid.Column="0" Width="22" Height="22" Fill="{DynamicResource MainBackgroundColor}" HorizontalAlignment="Right" VerticalAlignment="Bottom" Style="{StaticResource ScrollVisibilityRectangle}"/>
<Grid Name="appspanel" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
</Grid>
</Grid>
</Grid>
</TabItem>
<TabItem Header="Tweaks" Visibility="Collapsed" Name="WPFTab2">