The response has been limited to 50k tokens of the smallest files in the repo. You can remove this limitation by removing the max tokens filter.
├── .gitattributes
├── .github
    ├── CODEOWNERS
    ├── CODE_OF_CONDUCT.md
    ├── CONTRIBUTING.md
    ├── FUNDING.yml
    ├── ISSUE_TEMPLATE
    │   ├── bug_report.yaml
    │   ├── config.yml
    │   └── feature_request.yaml
    ├── PULL_REQUEST_TEMPLATE.md
    ├── SECURITY.md
    ├── dependabot.yml
    ├── release-drafter.yml
    └── workflows
    │   ├── close-discussion-on-pr.yaml
    │   ├── close-old-issues.yaml
    │   ├── compile-check.yaml
    │   ├── issue-slash-commands.yaml
    │   ├── pre-release.yaml
    │   ├── remove-winutil.yaml
    │   ├── sponsors.yaml
    │   └── unittests.yaml
├── .gitignore
├── Compile.ps1
├── LICENSE
├── README.md
├── Test-WingetInstall.ps1
├── config
    ├── applications.json
    ├── appnavigation.json
    ├── autounattend.xml
    ├── dns.json
    ├── feature.json
    ├── preset.json
    ├── themes.json
    └── tweaks.json
├── functions
    ├── microwin
    │   ├── Invoke-Microwin.ps1
    │   ├── Invoke-MicrowinBusyInfo.ps1
    │   ├── Invoke-MicrowinGetIso.ps1
    │   ├── Microwin-Classes.ps1
    │   ├── Microwin-CopyToUSB.ps1
    │   ├── Microwin-CopyVirtIO.ps1
    │   ├── Microwin-GetLangFromCulture.ps1
    │   ├── Microwin-GetLocalizedUsers.ps1
    │   ├── Microwin-GetOscdimg.ps1
    │   ├── Microwin-NewCheckInstall.ps1
    │   ├── Microwin-NewFirstRun.ps1
    │   ├── Microwin-NewUnattend.ps1
    │   ├── Microwin-RemoveFeatures.ps1
    │   ├── Microwin-RemoveFileOrDirectory.ps1
    │   ├── Microwin-RemovePackages.ps1
    │   ├── Microwin-RemoveProvisionedPackages.ps1
    │   ├── Microwin-TestCompatibleImage.ps1
    │   └── Toggle-MicrowinPanel.ps1
    ├── private
    │   ├── Add-SelectedAppsMenuItem.ps1
    │   ├── Copy-Files.ps1
    │   ├── Find-AppsByNameOrDescription.ps1
    │   ├── Find-TweaksByNameOrDescription.ps1
    │   ├── Get-LocalizedYesNo.ps1
    │   ├── Get-WPFObjectName.ps1
    │   ├── Get-WinUtilCheckBoxes.ps1
    │   ├── Get-WinUtilInstallerProcess.ps1
    │   ├── Get-WinUtilSelectedPackages.ps1
    │   ├── Get-WinUtilToggleStatus.ps1
    │   ├── Get-WinUtilVariables.ps1
    │   ├── Hide-WPFInstallAppBusy.ps1
    │   ├── Initalize-InstallAppEntry.ps1
    │   ├── Initialize-InstallAppArea.ps1
    │   ├── Initialize-InstallCategoryAppList.ps1
    │   ├── Install-WinUtilChoco.ps1
    │   ├── Install-WinUtilProgramChoco.ps1
    │   ├── Install-WinUtilProgramWinget.ps1
    │   ├── Install-WinUtilWinget.ps1
    │   ├── Invoke-WinUtilAssets.ps1
    │   ├── Invoke-WinUtilCurrentSystem.ps1
    │   ├── Invoke-WinUtilExplorerUpdate.ps1
    │   ├── Invoke-WinUtilFeatureInstall.ps1
    │   ├── Invoke-WinUtilGPU.ps1
    │   ├── Invoke-WinUtilInstallPSProfile.ps1
    │   ├── Invoke-WinUtilSSHServer.ps1
    │   ├── Invoke-WinUtilScript.ps1
    │   ├── Invoke-WinUtilSponsors.ps1
    │   ├── Invoke-WinUtilTweaks.ps1
    │   ├── Invoke-WinUtilUninstallPSProfile.ps1
    │   ├── Invoke-WinutilThemeChange.ps1
    │   ├── Remove-WinUtilAPPX.ps1
    │   ├── Set-PackageManagerPreference.ps1
    │   ├── Set-WinUtilDNS.ps1
    │   ├── Set-WinUtilProgressbar.ps1
    │   ├── Set-WinUtilRegistry.ps1
    │   ├── Set-WinUtilScheduledTask.ps1
    │   ├── Set-WinUtilService.ps1
    │   ├── Set-WinUtilTaskbarItem.ps1
    │   ├── Show-CustomDialog.ps1
    │   ├── Show-WPFInstallAppBusy.ps1
    │   ├── Test-WinUtilPackageManager.ps1
    │   └── Update-WinUtilProgramWinget.ps1
    └── public
    │   ├── Initialize-WPFUI.ps1
    │   ├── Invoke-ScratchDialog.ps1
    │   ├── Invoke-WPFButton.ps1
    │   ├── Invoke-WPFCloseButton.ps1
    │   ├── Invoke-WPFControlPanel.ps1
    │   ├── Invoke-WPFFeatureInstall.ps1
    │   ├── Invoke-WPFFixesNetwork.ps1
    │   ├── Invoke-WPFFixesUpdate.ps1
    │   ├── Invoke-WPFFixesWinget.ps1
    │   ├── Invoke-WPFGetInstalled.ps1
    │   ├── Invoke-WPFImpex.ps1
    │   ├── Invoke-WPFInstall.ps1
    │   ├── Invoke-WPFInstallUpgrade.ps1
    │   ├── Invoke-WPFOOSU.ps1
    │   ├── Invoke-WPFPanelAutologin.ps1
    │   ├── Invoke-WPFPopup.ps1
    │   ├── Invoke-WPFPresets.ps1
    │   ├── Invoke-WPFRunAdobeCCCleanerTool.ps1
    │   ├── Invoke-WPFRunspace.ps1
    │   ├── Invoke-WPFSSHServer.ps1
    │   ├── Invoke-WPFSelectedAppsUpdate.ps1
    │   ├── Invoke-WPFSystemRepair.ps1
    │   ├── Invoke-WPFTab.ps1
    │   ├── Invoke-WPFTweakPS7.ps1
    │   ├── Invoke-WPFUIElements.ps1
    │   ├── Invoke-WPFUltimatePerformance.ps1
    │   ├── Invoke-WPFUnInstall.ps1
    │   ├── Invoke-WPFUpdatesdefault.ps1
    │   ├── Invoke-WPFUpdatesdisable.ps1
    │   ├── Invoke-WPFUpdatessecurity.ps1
    │   ├── Invoke-WPFtweaksbutton.ps1
    │   ├── Invoke-WPFundoall.ps1
    │   └── Show-CTTLogo.ps1
├── lint
    └── PSScriptAnalyser.ps1
├── overrides
    └── main.html
├── pester
    ├── configs.Tests.ps1
    └── functions.Tests.ps1
├── releases
    └── oscdimg.exe
├── scripts
    ├── main.ps1
    └── start.ps1
├── sign.bat
├── tools
    ├── Invoke-Preprocessing.ps1
    └── devdocs-generator.ps1
├── windev.ps1
└── xaml
    └── inputXML.xaml


/.gitattributes:
--------------------------------------------------------------------------------
 1 | * text=auto
 2 | 
 3 | *.ps1 text eol=crlf
 4 | *.json text eol=crlf
 5 | *.cfg text eol=crlf
 6 | 
 7 | *.png binary
 8 | *.jpg binary
 9 | 
10 | config/* diff
11 | config/applications.json diff
12 | *.json diff
13 | 


--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
 1 | # This is a comment.
 2 | # Each line is a file pattern followed by one or more owners.
 3 | 
 4 | # These owners will be the default owners for everything in
 5 | # the repo. Unless a later match takes precedence,
 6 | # @global-owner1 and @global-owner2 will be requested for
 7 | # review when someone opens a pull request.
 8 | *       @ChrisTitusTech
 9 | 
10 | # Order is important; the last matching pattern takes the most
11 | # precedence. When someone opens a pull request that only
12 | # modifies JS files, only @js-owner and not the global
13 | # owner(s) will be requested for a review.
14 | # *.js    @js-owner #This is an inline comment.
15 | 
16 | # You can also use email addresses if you prefer. They'll be
17 | # used to look up users just like we do for commit author
18 | # emails.
19 | # *.go docs@example.com
20 | 
21 | # Teams can be specified as code owners as well. Teams should
22 | # be identified in the format @org/team-name. Teams must have
23 | # explicit write access to the repository. In this example,
24 | # the octocats team in the octo-org organization owns all .txt files.
25 | # *.txt @octo-org/octocats
26 | 
27 | # In this example, @doctocat owns any files in the build/logs
28 | # directory at the root of the repository and any of its
29 | # subdirectories.
30 | # /build/logs/ @doctocat
31 | 
32 | # The `docs/*` pattern will match files like
33 | # `docs/getting-started.md` but not further nested files like
34 | # `docs/build-app/troubleshooting.md`.
35 | # docs/*  docs@example.com
36 | 
37 | # In this example, @octocat owns any file in an apps directory
38 | # anywhere in your repository.
39 | # apps/ @octocat
40 | 
41 | # In this example, @doctocat owns any file in the `/docs`
42 | # directory in the root of your repository and any of its
43 | # subdirectories.
44 | # /docs/ @doctocat
45 | 
46 | # In this example, any change inside the `/scripts` directory
47 | # will require approval from @doctocat or @octocat.
48 | # /scripts/ @doctocat @octocat
49 | 
50 | # In this example, @octocat owns any file in a `/logs` directory such as
51 | # `/build/logs`, `/scripts/logs`, and `/deeply/nested/logs`. Any changes
52 | # in a `/logs` directory will require approval from @octocat.
53 | # **/logs @octocat
54 | 
55 | # In this example, @octocat owns any file in the `/apps`
56 | # directory in the root of your repository except for the `/apps/github`
57 | # subdirectory, as its owners are left empty.
58 | # /apps/ @octocat
59 | # /apps/github


--------------------------------------------------------------------------------
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | custom: https://www.cttstore.com/windows-toolbox
2 | github: christitustech
3 | 


--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.yaml:
--------------------------------------------------------------------------------
 1 | name: "Bug report"
 2 | description: "Report a bug to help us identify and fix issues in the project."
 3 | labels: ["bug"]
 4 | 
 5 | body:
 6 |   - type: markdown
 7 |     attributes:
 8 |       value: |
 9 |         # 🐞 **Issue Report**
10 |         Thank you for taking the time to report an issue! Please provide as much detail as possible to help us address the problem efficiently.
11 | 
12 |         ## ⚠️ **IMPORTANT**
13 |         - 🛠️ **Supported environments only:** We only support Windows 11. Custom ISOs that are not made using Microwin are not supported.
14 |         - 💡 For general questions, use the [Discussions section](https://github.com/Christitustech/winutil/discussions) or join our Community-driven [Discord Server](https://discord.gg/RUbZUZyByQ).
15 | 
16 |   - type: checkboxes
17 |     attributes:
18 |       label: ⚙️ Issue Checklist
19 |       options:
20 |         - label: I have read the guidelines.
21 |         - label: I checked for duplicate issues.
22 |         - label: I searched for existing discussions.
23 |         - label: I checked for an existing pull request that addresses this issue.
24 |     validations:
25 |       required: true
26 | 
27 |   - type: input
28 |     id: affected_part
29 |     attributes:
30 |       label: 📜 What part of Winutil are you having issues with?
31 |       placeholder: "e.g., Microwin, Tweaks, etc."
32 |     validations:
33 |       required: true
34 | 
35 |   - type: textarea
36 |     id: issue_description
37 |     attributes:
38 |       label: 📝 Provide a clear and concise description of the issue.
39 |     validations:
40 |       required: true
41 | 
42 |   - type: textarea
43 |     id: steps_to_reproduce
44 |     attributes:
45 |       label: 🔄 Steps to reproduce the issue.
46 |       placeholder: "e.g., Step 1: ..., Step 2: ..."
47 |     validations:
48 |       required: true
49 | 
50 |   - type: textarea
51 |     id: error_output
52 |     attributes:
53 |       label: ❌ Paste the full error output (if available).
54 |       placeholder: "Include any relevant logs or error messages."
55 | 
56 |   - type: textarea
57 |     id: additional_context
58 |     attributes:
59 |       label: 🖼️ Additional context.
60 |       placeholder: "Include screenshots, code blocks (use triple backticks ```), or any other relevant information."
61 |     validations:
62 |       required: false
63 | 


--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 |     - name: 💻 Community Discord
4 |       url: https://discord.gg/RUbZUZyByQ
5 |       about: Join our Community Discord server to chat with other users in the Winutil community.
6 | 


--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.yaml:
--------------------------------------------------------------------------------
 1 | name: "Feature request"
 2 | description: "Suggest a new feature or improvement for the project."
 3 | labels: ["enhancement"]
 4 | 
 5 | body:
 6 |   - type: markdown
 7 |     attributes:
 8 |       value: |
 9 |         # ✨ **Feature request**
10 |         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.
11 | 
12 |         ## ⚠️ **IMPORTANT**
13 |         - 🛠️ **Supported environments only:** We only support Windows 11.
14 |         - 💡 For general questions, use the [Discussions section](https://github.com/Christitustech/winutil/discussions) or join our Community-driven [Discord Server](https://discord.gg/RUbZUZyByQ).
15 | 
16 |   - type: checkboxes
17 |     attributes:
18 |       label: ⚙️ Issue Checklist
19 |       options:
20 |         - label: I have read the guidelines.
21 |         - label: I checked for duplicate issues.
22 |         - label: I searched for existing discussions.
23 |         - label: I checked for an existing pull request that addresses this request.
24 |     validations:
25 |       required: true
26 | 
27 |   - type: textarea
28 |     id: problem_statement
29 |     attributes:
30 |       label: ❓ Is your feature request related to a problem?
31 |       placeholder: "Provide a clear and concise description of the issue you're facing. Example: 'I'm always frustrated when [...]'"
32 |     validations:
33 |       required: false
34 | 
35 |   - type: textarea
36 |     id: proposed_solution
37 |     attributes:
38 |       label: 💡 Describe the solution you'd like
39 |       placeholder: "Provide a clear and concise description of what you want to happen."
40 |     validations:
41 |       required: true
42 | 
43 |   - type: textarea
44 |     id: alternatives
45 |     attributes:
46 |       label: 🔄 Describe alternatives you've considered
47 |       placeholder: "Provide details on any alternative solutions or features you've thought about."
48 |     validations:
49 |       required: false
50 | 
51 |   - type: textarea
52 |     id: additional_context
53 |     attributes:
54 |       label: 🖼️ Additional context
55 |       placeholder: "Include screenshots, code blocks (use triple backticks ```), or any other relevant information."
56 |     validations:
57 |       required: false
58 | 


--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
 1 | <!--Before you make this PR have you followed the docs here? - https://christitustech.github.io/winutil/contribute/ -->
 2 | 
 3 | ## Type of Change
 4 | - [ ] New feature
 5 | - [ ] Bug fix
 6 | - [ ] Documentation update
 7 | - [ ] Refactoring
 8 | - [ ] Hotfix
 9 | - [ ] Security patch
10 | - [ ] UI/UX improvement
11 | 
12 | ## Description
13 | <!--[Provide a detailed explanation of the changes you have made. Include the reasons behind these changes and any relevant context. Link any related issues.]-->
14 | 
15 | ## Testing
16 | <!--[Detail the testing you have performed to ensure that these changes function as intended. Include information about any added tests.]-->
17 | 
18 | ## Impact
19 | <!--[Discuss the impact of your changes on the project. This might include effects on performance, new dependencies, or changes in behaviour.]-->
20 | 
21 | ## Issue related to PR
22 | <!--[What issue/discussion is related to this PR (if any)]-->
23 | - Resolves #
24 | 
25 | ## Additional Information
26 | <!--[Any additional information that reviewers should be aware of.]-->
27 | 
28 | ## Checklist
29 | - [ ] My code adheres to the coding and style guidelines of the project.
30 | - [ ] I have performed a self-review of my own code.
31 | - [ ] I have commented my code, particularly in hard-to-understand areas.
32 | - [ ] I have made corresponding changes to the documentation.
33 | - [ ] My changes generate no errors/warnings/merge conflicts.
34 | 


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


--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
 1 | version: 2
 2 | updates:
 3 |   - package-ecosystem: "github-actions"
 4 |     directory: "/"
 5 |     schedule:
 6 |       interval: "weekly"
 7 |     ignore:
 8 |       - dependency-name: "actions/stale"
 9 |         versions: '>= 9'
10 | 


--------------------------------------------------------------------------------
/.github/release-drafter.yml:
--------------------------------------------------------------------------------
 1 | tag-prefix: ''
 2 | categories:
 3 |   - title: '🚀 Features'
 4 |     labels:
 5 |       - 'feature'
 6 |       - 'enhancement'
 7 |   - title: '🐛 Bug Fixes'
 8 |     labels:
 9 |       - 'fix'
10 |       - 'bugfix'
11 |       - 'bug'
12 |   - title: '📚 Documentation'
13 |     label: 'documentation'
14 |   - title: '🔒 Security'
15 |     label: 'security'
16 | change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
17 | template: |
18 |   ## Changes
19 | 
20 |   $CHANGES
21 | 
22 | change-title-escapes: '\<*_&"'''
23 | autolabeler:
24 |   - label: 'documentation'
25 |     files:
26 |       - '*.md'
27 |     branch:
28 |       - '/docs{0,1}\/.+/'
29 |   - label: 'bug'
30 |     branch:
31 |       - '/fix\/.+/'
32 |     title:
33 |       - '/fix/i'
34 |   - label: 'enhancement'
35 |     branch:
36 |       - '/feature\/.+/'
37 |     body:
38 |       - '/[A-Z]+-[0-9]+/'
39 |   - label: 'documentation'
40 |     files:
41 |       - '**/*.md'
42 |       - 'docs/**/*'
43 |   - label: 'security'
44 |     branch:
45 |       - '/security\/.+/'
46 | replacers:
47 |   - search: /"/g
48 |     replace: ''
49 |   - search: /'/g
50 |     replace: ''
51 | exclude-labels:
52 |   - 'skip-changelog'
53 | 
54 | filter-by-commitish: true
55 | 


--------------------------------------------------------------------------------
/.github/workflows/close-discussion-on-pr.yaml:
--------------------------------------------------------------------------------
 1 | name: Close Discussion on PR Merge
 2 | 
 3 | on:
 4 |   pull_request:
 5 |     types: [closed]
 6 | 
 7 | jobs:
 8 |   closeDiscussion:
 9 |     runs-on: ubuntu-latest
10 |     steps:
11 |       - name: Checkout repository
12 |         uses: actions/checkout@v4
13 | 
14 |       - name: Check if PR was merged
15 |         if: github.event.pull_request.merged == true
16 |         run: echo "PR was merged"
17 | 
18 |       - name: Extract Discussion Number & Close If any Were Found
19 |         env:
20 |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
21 |         if: github.event.pull_request.merged == true
22 |         id: extract-discussion
23 |         run: |
24 |           pr_body="${{ github.event.pull_request.body }}"
25 |           discussion_ids=$(echo "$pr_body" | grep -oP '(?i)(resolve|fix|close)[s|d]? #\K[0-9]+')
26 | 
27 |           if [ -z "$discussion_ids" ]; then
28 |             echo "No discussion IDs found."
29 |             exit 0
30 |           fi
31 | 
32 |           for discussion_id in $discussion_ids; do
33 |             echo "Attempting to close discussion #$discussion_id"
34 |             response=$(curl -s -X PATCH -H "Authorization: token $GITHUB_TOKEN" \
35 |                  -H "Accept: application/vnd.github.v3+json" \
36 |                  -d '{"state": "closed"}' \
37 |                  "https://api.github.com/repos/${{ github.repository }}/discussions/$discussion_id")
38 | 
39 |             if echo "$response" | jq -e '.id' > /dev/null; then
40 |               echo "Successfully closed discussion #$discussion_id"
41 |             else
42 |               error_message=$(echo "$response" | jq -r '.message // "Unknown error"')
43 |               echo "Warning: Failed to close discussion #$discussion_id. Error: $error_message"
44 |               echo "Full response: $response"
45 |             fi
46 |           done
47 |         shell: bash
48 |         continue-on-error: true
49 | 


--------------------------------------------------------------------------------
/.github/workflows/close-old-issues.yaml:
--------------------------------------------------------------------------------
 1 | name: Close Inactive Issues
 2 | 
 3 | on:
 4 |   schedule:
 5 |     - cron: '0 0 * * *'  # Run daily
 6 |   workflow_dispatch:  # This line enables manual triggering
 7 | 
 8 | jobs:
 9 |   close-issues:
10 |     runs-on: ubuntu-latest
11 |     permissions:
12 |       issues: write  # Ensure necessary permissions for issues
13 |       pull-requests: none
14 |       contents: none
15 |     steps:
16 |     - name: Close inactive issues
17 |       uses: actions/stale@v8
18 |       with:
19 |         # A list of labels to reference when looking through issues,
20 |         # and only when one (or even more) of these labels are found..
21 |         # then skip this issue, and never try to stale and/or close it.
22 |         exempt-issue-labels: "Keep Issue Open"
23 |         # Split it into two weeks, after one week the issue will be marked as stale,
24 |         # after another week have pasted without any update.. the issue will then be closed.
25 |         days-before-issue-stale: 90
26 |         days-before-issue-close: 365
27 |         # NEVER mark PRs as Stale or Close + this workflow should never have write permissions on PRs, EVER!
28 |         days-before-pr-stale: -1
29 |         days-before-pr-close: -1
30 |         # Sends a message for both the Stale and Close events of an issue.
31 |         stale-issue-message: "This issue was marked as stale due to inactivity."
32 |         close-issue-message: "This issue was closed after remaining stale without updates."
33 |         # Increase this value if the project receives a lot of
34 |         # PRs (yes.. apparently they're processed no matter what) & Issues.
35 |         # Default value for it (according to the docs) is 30
36 |         operations-per-run: 200
37 |         # Make this field equal true if you want to test your configuration if it works correctly or not
38 |         debug-only: false
39 |         repo-token: ${{ secrets.GITHUB_TOKEN }}
40 | 


--------------------------------------------------------------------------------
/.github/workflows/compile-check.yaml:
--------------------------------------------------------------------------------
 1 | name: Compile & Check
 2 | 
 3 | on:
 4 |   push:
 5 |     branches: ["main"]
 6 |   pull_request:
 7 |     branches: ["main"]
 8 |   workflow_dispatch: # Manual trigger added
 9 |   workflow_call: # Allow other Actions to call this workflow
10 | 
11 | jobs:
12 |   Compile-and-Check:
13 |     runs-on: windows-latest
14 |     steps:
15 |     - name: Checkout Sources
16 |       uses: actions/checkout@v4
17 | 
18 |     - name: Compile and Syntaxcheck winutil.ps1
19 |       shell: pwsh
20 |       run: |
21 |         Set-ExecutionPolicy Bypass -Scope Process -Force; ./Compile.ps1
22 |       continue-on-error: false # Directly fail the job on error, removing the need for a separate check
23 | 


--------------------------------------------------------------------------------
/.github/workflows/issue-slash-commands.yaml:
--------------------------------------------------------------------------------
  1 | name: Issue slash commands
  2 | 
  3 | on:
  4 |   issue_comment:
  5 |     types: [created, edited]
  6 | 
  7 | jobs:
  8 |   issueCommands:
  9 |     # Skip this job if the comment was created/edited on a PR
 10 |     if: ${{ !github.event.issue.pull_request }}
 11 |     runs-on: ubuntu-latest
 12 |     permissions:
 13 |       issues: write
 14 |       pull-requests: none
 15 |       contents: read
 16 | 
 17 |     steps:
 18 |       - run: echo "command=false" >> $GITHUB_ENV
 19 | 
 20 |       - name: Check for /label command
 21 |         id: check_label_command
 22 |         run: |
 23 |           if [[ "${{ contains(github.event.comment.body, '/label') }}" == "true" ]]; then
 24 |             echo "command=true" >> $GITHUB_ENV
 25 |             LABEL_NAME=$(echo "${{ github.event.comment.body }}" | awk -F"/label" '/\/label/ { match($2, /'\''([^'\'']*)'\''/, arr); if (arr[1] != "") print arr[1] }')
 26 |             echo "label_command=true" >> $GITHUB_ENV
 27 |             echo "label_name=${LABEL_NAME}" >> $GITHUB_ENV
 28 |           else
 29 |             echo "label_command=false" >> $GITHUB_ENV
 30 |           fi
 31 | 
 32 |       - name: Check for /unlabel command
 33 |         id: check_unlabel_command
 34 |         run: |
 35 |           if [[ "${{ contains(github.event.comment.body, '/unlabel') }}" == "true" ]]; then
 36 |             echo "command=true" >> $GITHUB_ENV
 37 |             UNLABEL_NAME=$(echo "${{ github.event.comment.body }}" | awk -F"/unlabel" '/\/unlabel/ { match($2, /'\''([^'\'']*)'\''/, arr); if (arr[1] != "") print arr[1] }')
 38 |             echo "unlabel_command=true" >> $GITHUB_ENV
 39 |             echo "unlabel_name=${UNLABEL_NAME}" >> $GITHUB_ENV
 40 |           else
 41 |             echo "unlabel_command=false" >> $GITHUB_ENV
 42 |           fi
 43 | 
 44 |       - name: Check for /close command
 45 |         id: check_close_command
 46 |         run: |
 47 |           if [[ "${{ contains(github.event.comment.body, '/close') }}" == "true" ]]; then
 48 |             echo "command=true" >> $GITHUB_ENV
 49 |             echo "close_command=true" >> $GITHUB_ENV
 50 |             echo "reopen_command=false" >> $GITHUB_ENV
 51 |           else
 52 |             echo "close_command=false" >> $GITHUB_ENV
 53 |           fi
 54 | 
 55 |       - name: Check for /open or /reopen command
 56 |         id: check_reopen_command
 57 |         run: |
 58 |           if [[ "${{ contains(github.event.comment.body, '/open') }}" == "true" ]] || [[ "${{ contains(github.event.comment.body, '/reopen') }}" == "true" ]]; then
 59 |             echo "command=true" >> $GITHUB_ENV
 60 |             echo "reopen_command=true" >> $GITHUB_ENV
 61 |             echo "close_command=false" >> $GITHUB_ENV
 62 |           else
 63 |             echo "reopen_command=false" >> $GITHUB_ENV
 64 |           fi
 65 | 
 66 |       - name: Check if the user is allowed
 67 |         id: check_user
 68 |         if: env.command == 'true'
 69 |         run: |
 70 |           ALLOWED_USERS=("ChrisTitusTech" "og-mrk" "Marterich" "MyDrift-user" "Real-MullaC" "CodingWonders")
 71 |           if [[ " ${ALLOWED_USERS[@]} " =~ " ${{ github.event.comment.user.login }} " ]]; then
 72 |             echo "user=true" >> $GITHUB_ENV
 73 |           else
 74 |             exit 0
 75 |           fi
 76 | 
 77 |       - name: Close issue
 78 |         if: env.close_command == 'true'
 79 |         env:
 80 |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 81 |           ISSUE_NUMBER: ${{ github.event.issue.number }}
 82 |         run: |
 83 |           echo Closing the issue...
 84 |           if [[ "${{ contains(github.event.comment.body, 'not planned') }}" == "true" ]]; then
 85 |             gh issue close $ISSUE_NUMBER --repo ${{ github.repository }} --reason 'not planned'
 86 |           else
 87 |             gh issue close $ISSUE_NUMBER --repo ${{ github.repository }}
 88 |           fi
 89 | 
 90 |       - name: Reopen issue
 91 |         if: env.reopen_command == 'true'
 92 |         env:
 93 |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
 94 |           ISSUE_NUMBER: ${{ github.event.issue.number }}
 95 |         run: |
 96 |           echo Reopening the issue...
 97 |           gh issue reopen $ISSUE_NUMBER --repo ${{ github.repository }}
 98 | 
 99 |       - name: Label issue
100 |         if: env.label_command == 'true'
101 |         env:
102 |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
103 |           ISSUE_NUMBER: ${{ github.event.issue.number }}
104 |         run: |
105 |           echo Labeling the issue...
106 |           gh issue edit $ISSUE_NUMBER --repo ${{ github.repository }} --add-label "${{ env.label_name }}"
107 | 
108 |       - name: Remove labels
109 |         if: env.unlabel_command == 'true'
110 |         env:
111 |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
112 |           ISSUE_NUMBER: ${{ github.event.issue.number }}
113 |         run: |
114 |           echo Unlabeling the issue...
115 |           gh issue edit $ISSUE_NUMBER --repo ${{ github.repository }} --remove-label "${{ env.unlabel_name }}"
116 | 


--------------------------------------------------------------------------------
/.github/workflows/pre-release.yaml:
--------------------------------------------------------------------------------
 1 | name: Pre-Release WinUtil
 2 | 
 3 | permissions:
 4 |   contents: write
 5 |   actions: read
 6 | 
 7 | on:
 8 |   workflow_dispatch: # Manual trigger added
 9 | 
10 | jobs:
11 |   build-runspace:
12 |     runs-on: windows-latest
13 |     env:
14 |       CERTIFICATE_BASE64: ${{ secrets.CERTIFICATE_BASE64 }}
15 |     steps:
16 |       - name: Checkout Repository
17 |         uses: actions/checkout@v4
18 | 
19 |       - name: Compile project
20 |         shell: pwsh
21 |         run: |
22 |           Set-ExecutionPolicy Bypass -Scope Process -Force; ./Compile.ps1
23 |         continue-on-error: false # Directly fail the job on error, removing the need for a separate check
24 | 
25 |       - name: Set Version to Todays Date
26 |         id: extract_version
27 |         run: |
28 |           $version = (Get-Date -Format "yy.MM.dd")
29 |           echo "VERSION=$version" >> $env:GITHUB_ENV
30 |         shell: pwsh
31 | 
32 |       - name: Create Tag
33 |         id: create_tag
34 |         run: |
35 |           $tagExists = git tag -l $env:VERSION
36 |           if ($tagExists -eq "") {
37 |             git tag $env:VERSION
38 |             if ($LASTEXITCODE -ne 0) {
39 |               Write-Error "Failed to create tag $env:VERSION"
40 |               exit 1
41 |             }
42 |             git push origin $env:VERSION
43 |             if ($LASTEXITCODE -ne 0) {
44 |               Write-Error "Failed to push tag $env:VERSION"
45 |               exit 1
46 |             }
47 |           } else {
48 |             Write-Host "Tag $env:VERSION already exists, skipping tag creation"
49 |           }
50 |         shell: pwsh
51 | 
52 |       - name: Generate Release Notes
53 |         id: generate_notes
54 |         uses: release-drafter/release-drafter@v6
55 |         env:
56 |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
57 |         with:
58 |           config-name: release-drafter.yml
59 |           version: ${{ env.VERSION }} # Pass the version variable
60 | 
61 |       - name: Create and Upload Release
62 |         id: create_release
63 |         uses: softprops/action-gh-release@v2
64 |         with:
65 |           tag_name: ${{ env.VERSION }}
66 |           name: Pre-Release ${{ env.VERSION }}
67 |           body: |
68 |             ${{ steps.generate_notes.outputs.body }}
69 | 
70 |             ![GitHub Downloads (specific asset, specific tag)](https://img.shields.io/github/downloads/ChrisTitusTech/winutil/${{ env.VERSION }}/winutil.ps1)
71 |           append_body: false
72 |           files: ./winutil.ps1
73 |           prerelease: true
74 |         env:
75 |           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
76 | 


--------------------------------------------------------------------------------
/.github/workflows/remove-winutil.yaml:
--------------------------------------------------------------------------------
 1 | name: Remove winutil.ps1 if included in a Push
 2 | 
 3 | on:
 4 |   push:
 5 |     branches:
 6 |       - '**'
 7 | 
 8 | jobs:
 9 |   check-and-delete-file:
10 |     runs-on: ubuntu-latest
11 | 
12 |     steps:
13 |     - name: Checkout code
14 |       uses: actions/checkout@v4
15 | 
16 |     - name: Check if winutil.ps1 exists
17 |       id: check_existence
18 |       run: |
19 |         if [ -f "winutil.ps1" ]; then
20 |           echo "winutil_exists=true" >> $GITHUB_OUTPUT
21 |         else
22 |           echo "winutil_exists=false" >> $GITHUB_OUTPUT
23 |         fi
24 | 
25 |     - name: Delete winutil.ps1 if it exists
26 |       if: steps.check_existence.outputs.winutil_exists == 'true'
27 |       run: |
28 |         git config --global user.email "winutil-action@noreply.github.com"
29 |         git config --global user.name "winutil-action"
30 |         git rm winutil.ps1
31 |         git commit -m "Delete winutil.ps1 as it is not allowed"
32 |         git push origin HEAD:${{ github.ref }}
33 |       env:
34 |         GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
35 | 


--------------------------------------------------------------------------------
/.github/workflows/sponsors.yaml:
--------------------------------------------------------------------------------
 1 | name: Generate Sponsors README
 2 | on:
 3 |   workflow_dispatch:
 4 |   schedule:
 5 |     - cron: 30 15 * * 0-6
 6 | permissions:
 7 |   contents: write
 8 | jobs:
 9 |   deploy:
10 |     runs-on: ubuntu-latest
11 |     if: (github.event_name == 'schedule' && github.repository == 'ChrisTitusTech/winutil') || (github.event_name != 'schedule')
12 |     steps:
13 |       - name: Checkout 🛎️
14 |         uses: actions/checkout@v4
15 | 
16 |       - name: Generate Sponsors 💖
17 |         uses: JamesIves/github-sponsors-readme-action@v1
18 |         with:
19 |           token: ${{ secrets.PAT }}
20 |           file: 'README.md'
21 | 
22 |       - name: Deploy to GitHub Pages 🚀
23 |         uses: JamesIves/github-pages-deploy-action@v4
24 |         with:
25 |           branch: main
26 |           folder: '.'
27 | 


--------------------------------------------------------------------------------
/.github/workflows/unittests.yaml:
--------------------------------------------------------------------------------
 1 | name: Unit Tests
 2 | 
 3 | on:
 4 |   push:
 5 | 
 6 | jobs:
 7 |   lint:
 8 |     name: PS Script Analyzer
 9 |     runs-on: ubuntu-latest
10 |     steps:
11 |     - uses: actions/checkout@v4
12 |     - name: lint
13 |       uses: devblackops/github-action-psscriptanalyzer@master
14 |       with:
15 |         sendComment: false
16 |         settingsPath: lint/PSScriptAnalyser.ps1
17 |         failOnErrors: false
18 |         failOnWarnings: false
19 |         failOnInfos: false
20 |   test:
21 |     runs-on: windows-latest
22 | 
23 |     steps:
24 |     - name: Checkout code
25 |       uses: actions/checkout@v4
26 | 
27 |     - name: Install Pester
28 |       run: |
29 |         Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
30 |         Install-Module -Name Pester -Force -SkipPublisherCheck -AllowClobber
31 |       shell: pwsh
32 | 
33 |     - name: Run Pester tests
34 |       run: |
35 |         Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
36 |         Invoke-Pester -Path 'pester/*.Tests.ps1' -Output Detailed
37 | 
38 |       shell: pwsh
39 |       env:
40 |         TEMP: ${{ runner.temp }}
41 | 


--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
 1 | ### VSCode ###
 2 | 
 3 | # Configuration folder
 4 | .vscode/
 5 | .idea/
 6 | 
 7 | ### Visual Studio ###
 8 | 
 9 | # Visual Studio user-specific files
10 | .vs/
11 | 
12 | winutil.pdb
13 | 
14 | ### Preprocessor Hashes ###
15 | .preprocessor_hashes.json
16 | 
17 | ### Windows ###
18 | 
19 | # Folder config file
20 | [Dd]esktop.ini
21 | 
22 | # Ignore Generated XAML Files
23 | xaml/inputApp.xaml
24 | xaml/inputFeatures.xaml
25 | xaml/inputTweaks.xaml
26 | 
27 | # Executables and Configs
28 | winget.msixbundle
29 | pester.ps1
30 | *.psd*
31 | ooshutup10.cfg
32 | winutil.exe.config
33 | Microsoft.UI.Xaml*
34 | license1.xml
35 | winutil.ps1
36 | 
37 | # Libraries
38 | System.Management.Automation.dll
39 | Microsoft.PowerShell.ConsoleHost.dll
40 | 
41 | # Compressed files
42 | *.zip
43 | 
44 | ### MacOS ###
45 | 
46 | # General
47 | .DS_Store
48 | microwin.log
49 | True
50 | test.ps1
51 | winutil.ps1
52 | 
53 | # temporary excludes for docs
54 | .github/site/
55 | 
56 | binary/
57 | 


--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
 1 | MIT License
 2 | 
 3 | Copyright (c) 2022 CT Tech Group LLC
 4 | 
 5 | Permission is hereby granted, free of charge, to any person obtaining a copy
 6 | of this software and associated documentation files (the "Software"), to deal
 7 | in the Software without restriction, including without limitation the rights
 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 | 
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 | 
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 | 


--------------------------------------------------------------------------------
/Test-WingetInstall.ps1:
--------------------------------------------------------------------------------
 1 | # Import the function (adjust the path according to your setup)
 2 | . "./functions/private/Install-WinUtilWinget.ps1"
 3 | . "./functions/private/Test-WinUtilPackageManager.ps1"
 4 | 
 5 | # Set up Information stream to be visible
 6 | $InformationPreference = "Continue"
 7 | 
 8 | Write-Host "Starting Winget installation test..." -ForegroundColor Cyan
 9 | 
10 | try {
11 |     Install-WinUtilWinget
12 | } catch {
13 |     Write-Host "Error occurred during testing: $($_.Exception.Message)" -ForegroundColor Red
14 |     Write-Host "Stack Trace:" -ForegroundColor Red
15 |     $_.ScriptStackTrace
16 | }
17 | 


--------------------------------------------------------------------------------
/config/appnavigation.json:
--------------------------------------------------------------------------------
 1 | {
 2 |     "WPFInstall": {
 3 |         "Content": "Install/Upgrade Applications",
 4 |         "Category": "____Actions",
 5 |         "Type": "Button",
 6 |         "Order": "1",
 7 |         "Description": "Install or upgrade the selected applications"
 8 |     },
 9 |     "WPFUninstall": {
10 |         "Content": "Uninstall Applications",
11 |         "Category": "____Actions",
12 |         "Type": "Button",
13 |         "Order": "2",
14 |         "Description": "Uninstall the selected applications"
15 |     },
16 |     "WPFInstallUpgrade": {
17 |         "Content": "Upgrade all Applications",
18 |         "Category": "____Actions",
19 |         "Type": "Button",
20 |         "Order": "3",
21 |         "Description": "Upgrade all applications to the latest version"
22 |     },
23 |     "WingetRadioButton": {
24 |         "Content": "Winget",
25 |         "Category": "__Package Manager",
26 |         "Type": "RadioButton",
27 |         "GroupName": "PackageManagerGroup",
28 |         "Checked": true,
29 |         "Order": "1",
30 |         "Description": "Use Winget for package management"
31 |     },
32 |     "ChocoRadioButton": {
33 |         "Content": "Chocolatey",
34 |         "Category": "__Package Manager",
35 |         "Type": "RadioButton",
36 |         "GroupName": "PackageManagerGroup",
37 |         "Checked": false,
38 |         "Order": "2",
39 |         "Description": "Use Chocolatey for package management"
40 |     },
41 |     "WPFClearInstallSelection": {
42 |         "Content": "Clear Selection",
43 |         "Category": "__Selection",
44 |         "Type": "Button",
45 |         "Order": "1",
46 |         "Description": "Clear the selection of applications"
47 |     },
48 |     "WPFGetInstalled": {
49 |         "Content": "Get Installed",
50 |         "Category": "__Selection",
51 |         "Type": "Button",
52 |         "Order": "2",
53 |         "Description": "Show installed applications"
54 |     },
55 |     "WPFselectedAppsButton": {
56 |         "Content": "Selected Apps: 0",
57 |         "Category": "__Selection",
58 |         "Type": "Button",
59 |         "Order": "3",
60 |         "Description": "Show the selected applications"
61 |     }
62 | }
63 | 


--------------------------------------------------------------------------------
/config/dns.json:
--------------------------------------------------------------------------------
 1 | {
 2 |     "Google":{
 3 |         "Primary": "8.8.8.8",
 4 |         "Secondary": "8.8.4.4",
 5 |         "Primary6": "2001:4860:4860::8888",
 6 |         "Secondary6": "2001:4860:4860::8844"
 7 |     },
 8 |     "Cloudflare":{
 9 |         "Primary": "1.1.1.1",
10 |         "Secondary": "1.0.0.1",
11 |         "Primary6": "2606:4700:4700::1111",
12 |         "Secondary6": "2606:4700:4700::1001"
13 |     },
14 |     "Cloudflare_Malware":{
15 |         "Primary": "1.1.1.2",
16 |         "Secondary": "1.0.0.2",
17 |         "Primary6": "2606:4700:4700::1112",
18 |         "Secondary6": "2606:4700:4700::1002"
19 |     },
20 |     "Cloudflare_Malware_Adult":{
21 |         "Primary": "1.1.1.3",
22 |         "Secondary": "1.0.0.3",
23 |         "Primary6": "2606:4700:4700::1113",
24 |         "Secondary6": "2606:4700:4700::1003"
25 |     },
26 |     "Open_DNS":{
27 |         "Primary": "208.67.222.222",
28 |         "Secondary": "208.67.220.220",
29 |         "Primary6": "2620:119:35::35",
30 |         "Secondary6": "2620:119:53::53"
31 |     },
32 |     "Quad9":{
33 |         "Primary": "9.9.9.9",
34 |         "Secondary": "149.112.112.112",
35 |         "Primary6": "2620:fe::fe",
36 |         "Secondary6": "2620:fe::9"
37 |     },
38 |     "AdGuard_Ads_Trackers":{
39 |         "Primary": "94.140.14.14",
40 |         "Secondary": "94.140.15.15",
41 |         "Primary6": "2a10:50c0::ad1:ff",
42 |         "Secondary6": "2a10:50c0::ad2:ff"
43 |     },
44 |     "AdGuard_Ads_Trackers_Malware_Adult":{
45 |         "Primary": "94.140.14.15",
46 |         "Secondary": "94.140.15.16",
47 |         "Primary6": "2a10:50c0::bad1:ff",
48 |         "Secondary6": "2a10:50c0::bad2:ff"
49 |     },
50 |     "dns0.eu_Open":{
51 |         "Primary": "193.110.81.254",
52 |         "Secondary": "185.253.5.254",
53 |         "Primary6": "2a0f:fc80::ffff",
54 |         "Secondary6": "2a0f:fc81::ffff"
55 |     },
56 |     "dns0.eu_ZERO":{
57 |         "Primary": "193.110.81.9",
58 |         "Secondary": "185.253.5.9",
59 |         "Primary6": "2a0f:fc80::9",
60 |         "Secondary6": "2a0f:fc81::9"
61 |     },
62 |     "dns0.eu_KIDS":{
63 |         "Primary": "193.110.81.1",
64 |         "Secondary": "185.253.5.1",
65 |         "Primary6": "2a0f:fc80::1",
66 |         "Secondary6": "2a0f:fc81::1"
67 |     }
68 | }
69 | 


--------------------------------------------------------------------------------
/config/preset.json:
--------------------------------------------------------------------------------
 1 | {
 2 |   "Standard": [
 3 |     "WPFTweaksAH",
 4 |     "WPFTweaksConsumerFeatures",
 5 |     "WPFTweaksDisableExplorerAutoDiscovery",
 6 |     "WPFTweaksDVR",
 7 |     "WPFTweaksHome",
 8 |     "WPFTweaksLoc",
 9 |     "WPFTweaksServices",
10 |     "WPFTweaksStorage",
11 |     "WPFTweaksTele",
12 |     "WPFTweaksWifi",
13 |     "WPFTweaksDiskCleanup",
14 |     "WPFTweaksDeleteTempFiles",
15 |     "WPFTweaksEndTaskOnTaskbar",
16 |     "WPFTweaksRestorePoint",
17 |     "WPFTweaksPowershell7Tele"
18 |   ],
19 |   "Minimal": [
20 |     "WPFTweaksConsumerFeatures",
21 |     "WPFTweaksDisableExplorerAutoDiscovery",
22 |     "WPFTweaksHome",
23 |     "WPFTweaksServices",
24 |     "WPFTweaksTele"
25 |   ]
26 | }
27 | 


--------------------------------------------------------------------------------
/functions/microwin/Invoke-MicrowinBusyInfo.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-MicrowinBusyInfo {
 2 |     <#
 3 |     .DESCRIPTION
 4 |     Function to display the busy info for the Microwin process
 5 |     #>
 6 |     [CmdletBinding(DefaultParameterSetName='done')]
 7 |     param(
 8 |         [Parameter(ParameterSetName='wip', Mandatory, Position = 0)]
 9 |         [Parameter(ParameterSetName='warning', Mandatory, Position = 0)]
10 |         [Parameter(ParameterSetName='done', Mandatory, Position = 0)]
11 |         [Parameter(ParameterSetName='hide', Mandatory, Position = 0)]
12 |         [ValidateSet('wip', 'warning', 'done', 'hide')]
13 |         [string]$action,
14 | 
15 |         [Parameter(ParameterSetName='wip', Mandatory, Position = 1)]
16 |         [Parameter(ParameterSetName='warning', Mandatory, Position = 1)]
17 |         [Parameter(ParameterSetName='done', Mandatory, Position = 1)]
18 |         [string]$message,
19 | 
20 |         [Parameter(ParameterSetName='wip', Position = 2)] [bool]$interactive = $false
21 |     )
22 | 
23 |     switch ($action) {
24 |         "wip" {
25 |             $sync.form.Dispatcher.BeginInvoke([action]{
26 |                 $sync.MicrowinBusyIndicator.Visibility="Visible"
27 |                 $finalMessage = ""
28 |                 if ($interactive -eq $false) {
29 |                     $finalMessage += "Please wait. "
30 |                 }
31 |                 $finalMessage += $message
32 |                 $sync.BusyText.Text = $finalMessage
33 |                 $sync.BusyIcon.Foreground="#FFA500"
34 |                 $sync.BusyText.Foreground="#FFA500"
35 |             })
36 |         }
37 |         "warning" {
38 |             $sync.form.Dispatcher.BeginInvoke([action]{
39 |                 $sync.MicrowinBusyIndicator.Visibility="Visible"
40 |                 $sync.BusyText.Text=$message
41 |                 $sync.BusyText.Foreground="#FF0000"
42 |                 $sync.BusyIcon.Foreground="#FF0000"
43 |             })
44 |         }
45 |         "done" {
46 |             $sync.form.Dispatcher.BeginInvoke([action]{
47 |                 $sync.MicrowinBusyIndicator.Visibility="Visible"
48 |                 $sync.BusyText.Text=$message
49 |                 $sync.BusyText.Foreground="#00FF00"
50 |                 $sync.BusyIcon.Foreground="#00FF00"
51 |             })
52 |         }
53 |         "hide" {
54 |             $sync.form.Dispatcher.BeginInvoke([action]{
55 |                 $sync.MicrowinBusyIndicator.Visibility="Hidden"
56 |                 $sync.BusyText.Foreground=$sync.Form.Resources.MicrowinBusyColor
57 |                 $sync.BusyIcon.Foreground=$sync.Form.Resources.MicrowinBusyColor
58 |             })
59 |         }
60 |     }
61 | 
62 |     # Force the UI to process pending messages
63 |     [System.Windows.Forms.Application]::DoEvents()
64 |     Start-Sleep -Milliseconds 50
65 | }
66 | 


--------------------------------------------------------------------------------
/functions/microwin/Microwin-Classes.ps1:
--------------------------------------------------------------------------------
 1 | class ErroredPackage {
 2 |     [string]$PackageName
 3 |     [string]$ErrorMessage
 4 |     ErroredPackage() { $this.Init(@{} )}
 5 |     # Constructor for packages that have errored out
 6 |     ErroredPackage([string]$pkgName, [string]$reason) {
 7 |         $this.PackageName = $pkgName
 8 |         $this.ErrorMessage = $reason
 9 |     }
10 | }
11 | 


--------------------------------------------------------------------------------
/functions/microwin/Microwin-CopyToUSB.ps1:
--------------------------------------------------------------------------------
 1 | function Microwin-CopyToUSB([string]$fileToCopy) {
 2 |     foreach ($volume in Get-Volume) {
 3 |         if ($volume -and $volume.FileSystemLabel -ieq "ventoy") {
 4 |             $destinationPath = "$($volume.DriveLetter):\"
 5 |             #Copy-Item -Path $fileToCopy -Destination $destinationPath -Force
 6 |             # Get the total size of the file
 7 |             $totalSize = (Get-Item "$fileToCopy").length
 8 | 
 9 |             Copy-Item -Path "$fileToCopy" -Destination "$destinationPath" -Verbose -Force -Recurse -Container -PassThru |
10 |                 ForEach-Object {
11 |                     # Calculate the percentage completed
12 |                     $completed = ($_.BytesTransferred / $totalSize) * 100
13 | 
14 |                     # Display the progress bar
15 |                     Write-Progress -Activity "Copying File" -Status "Progress" -PercentComplete $completed -CurrentOperation ("{0:N2} MB / {1:N2} MB" -f ($_.BytesTransferred / 1MB), ($totalSize / 1MB))
16 |                 }
17 | 
18 |             Write-Host "File copied to Ventoy drive $($volume.DriveLetter)"
19 | 
20 |             # Detect if config files are present, move them if they are, and configure the Ventoy drive to not bypass the requirements
21 |             $customVentoyConfig = @'
22 | {
23 |     "control":[
24 |         { "VTOY_WIN11_BYPASS_CHECK": "0" },
25 |         { "VTOY_WIN11_BYPASS_NRO": "0" }
26 |     ],
27 |     "control_legacy":[
28 |         { "VTOY_WIN11_BYPASS_CHECK": "0" },
29 |         { "VTOY_WIN11_BYPASS_NRO": "0" }
30 |     ],
31 |     "control_uefi":[
32 |         { "VTOY_WIN11_BYPASS_CHECK": "0" },
33 |         { "VTOY_WIN11_BYPASS_NRO": "0" }
34 |     ],
35 |     "control_ia32":[
36 |         { "VTOY_WIN11_BYPASS_CHECK": "0" },
37 |         { "VTOY_WIN11_BYPASS_NRO": "0" }
38 |     ],
39 |     "control_aa64":[
40 |         { "VTOY_WIN11_BYPASS_CHECK": "0" },
41 |         { "VTOY_WIN11_BYPASS_NRO": "0" }
42 |     ],
43 |     "control_mips":[
44 |         { "VTOY_WIN11_BYPASS_CHECK": "0" },
45 |         { "VTOY_WIN11_BYPASS_NRO": "0" }
46 |     ]
47 | }
48 | '@
49 | 
50 |             try {
51 |                 Write-Host "Writing custom Ventoy configuration. Please wait..."
52 |                 if (Test-Path -Path "$($volume.DriveLetter):\ventoy\ventoy.json" -PathType Leaf) {
53 |                     Write-Host "A Ventoy configuration file exists. Moving it..."
54 |                     Move-Item -Path "$($volume.DriveLetter):\ventoy\ventoy.json" -Destination "$($volume.DriveLetter):\ventoy\ventoy.json.old" -Force
55 |                     Write-Host "Existing Ventoy configuration has been moved to `"ventoy.json.old`". Feel free to put your config back into the `"ventoy.json`" file."
56 |                 }
57 |                 if (-not (Test-Path -Path "$($volume.DriveLetter):\ventoy")) {
58 |                     New-Item -Path "$($volume.DriveLetter):\ventoy" -ItemType Directory -Force | Out-Null
59 |                 }
60 |                 $customVentoyConfig | Out-File -FilePath "$($volume.DriveLetter):\ventoy\ventoy.json" -Encoding utf8 -Force
61 |                 Write-Host "The Ventoy drive has been successfully configured."
62 |             } catch {
63 |                 Write-Host "Could not configure Ventoy drive. Error: $($_.Exception.Message)`n"
64 |                 Write-Host "Be sure to add the following configuration to the Ventoy drive by either creating a `"ventoy.json`" file in the `"ventoy`" directory (create it if it doesn't exist) or by editing an existing one: `n`n$customVentoyConfig`n"
65 |                 Write-Host "Failure to do this will cause conflicts with your target ISO file."
66 |             }
67 |             return
68 |         }
69 |     }
70 |     Write-Host "Ventoy USB Key is not inserted"
71 | }
72 | 


--------------------------------------------------------------------------------
/functions/microwin/Microwin-CopyVirtIO.ps1:
--------------------------------------------------------------------------------
 1 | function Microwin-CopyVirtIO {
 2 |     <#
 3 |         .SYNOPSIS
 4 |             Downloads and copies the VirtIO Guest Tools drivers to the target MicroWin ISO
 5 |         .NOTES
 6 |             A network connection must be available and the servers of Fedora People must be up. Automatic driver installation will not be added yet - I want this implementation to be reliable.
 7 |     #>
 8 | 
 9 |     try {
10 |         Write-Host "Checking existing files..."
11 |         if (Test-Path -Path "$($env:TEMP)\virtio.iso" -PathType Leaf) {
12 |             Write-Host "VirtIO ISO has been detected. Deleting..."
13 |             Remove-Item -Path "$($env:TEMP)\virtio.iso" -Force
14 |         }
15 |         Write-Host "Getting latest VirtIO drivers. Please wait. This can take some time, depending on your network connection speed and the speed of the servers..."
16 |         Start-BitsTransfer -Source "https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso" -Destination "$($env:TEMP)\virtio.iso" -DisplayName "Downloading VirtIO drivers..."
17 |         # Do everything else if the VirtIO ISO exists
18 |         if (Test-Path -Path "$($env:TEMP)\virtio.iso" -PathType Leaf) {
19 |             Write-Host "Mounting ISO. Please wait."
20 |             $virtIO_ISO = Mount-DiskImage -PassThru "$($env:TEMP)\virtio.iso"
21 |             $driveLetter = (Get-Volume -DiskImage $virtIO_ISO).DriveLetter
22 |             # Create new directory for VirtIO on ISO
23 |             New-Item -Path "$mountDir\VirtIO" -ItemType Directory | Out-Null
24 |             $totalTime = Measure-Command { Copy-Files "$($driveLetter):" "$mountDir\VirtIO" -Recurse -Force }
25 |             Write-Host "VirtIO contents have been successfully copied. Time taken: $($totalTime.Minutes) minutes, $($totalTime.Seconds) seconds`n"
26 |             Get-Volume $driveLetter | Get-DiskImage | Dismount-DiskImage
27 |             Remove-Item -Path "$($env:TEMP)\virtio.iso" -Force -ErrorAction SilentlyContinue
28 |             Write-Host "To proceed with installation of the MicroWin image in QEMU/Proxmox VE:"
29 |             Write-Host "1. Proceed with Setup until you reach the disk selection screen, in which you won't see any drives"
30 |             Write-Host "2. Click `"Load Driver`" and click Browse"
31 |             Write-Host "3. In the folder selection dialog, point to this path:`n`n    `"D:\VirtIO\vioscsi\w11\amd64`" (replace amd64 with ARM64 if you are using Windows on ARM, and `"D:`" with the drive letter of the ISO)`n"
32 |             Write-Host "4. Select all drivers that will appear in the list box and click OK"
33 |         } else {
34 |             throw "Could not download VirtIO drivers"
35 |         }
36 |     } catch {
37 |         Write-Host "We could not download and/or prepare the VirtIO drivers. Error information: $_`n"
38 |         Write-Host "You will need to download these drivers manually. Location: https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/stable-virtio/virtio-win.iso"
39 |     }
40 | }
41 | 


--------------------------------------------------------------------------------
/functions/microwin/Microwin-GetLangFromCulture.ps1:
--------------------------------------------------------------------------------
 1 | function Microwin-GetLangFromCulture {
 2 | 
 3 |     param (
 4 |         [Parameter(Mandatory, Position = 0)] [string]$langName
 5 |     )
 6 | 
 7 |     switch -Wildcard ($langName)
 8 |     {
 9 |         "ar*" { return "Arabic" }
10 |         "pt-BR" { return "Brazilian Portuguese" }
11 |         "bg*" { return "Bulgarian" }
12 |         {($_ -eq "zh-CH") -or ($_ -like "zh-Hans*") -or ($_ -eq "zh-SG") -or ($_ -eq "zh-CHS")} { return "Chinese (Simplified)" }
13 |         {($_ -eq "zh") -or ($_ -eq "zh-Hant") -or ($_ -eq "zh-HK") -or ($_ -eq "zh-MO") -or ($_ -eq "zh-TW") -or ($_ -eq "zh-CHT")} { return "Chinese (Traditional)" }
14 |         "hr*" { return "Croatian" }
15 |         "cs*" { return "Czech" }
16 |         "da*" { return "Danish" }
17 |         "nl*" { return "Dutch" }
18 |         "en-US" { return "English" }
19 |         {($_ -like "en*") -and ($_ -ne "en-US")} { return "English International" }
20 |         "et*" { return "Estonian" }
21 |         "fi*" { return "Finnish" }
22 |         {($_ -like "fr*") -and ($_ -ne "fr-CA")} { return "French" }
23 |         "fr-CA" { return "French Canadian" }
24 |         "de*" { return "German" }
25 |         "el*" { return "Greek" }
26 |         "he*" { return "Hebrew" }
27 |         "hu*" { return "Hungarian" }
28 |         "it*" { return "Italian" }
29 |         "ja*" { return "Japanese" }
30 |         "ko*" { return "Korean" }
31 |         "lv*" { return "Latvian" }
32 |         "lt*" { return "Lituanian" }
33 |         "nb*" { return "Norwegian" }
34 |         "pl*" { return "Polish" }
35 |         {($_ -like "pt*") -and ($_ -ne "pt-BR")} { return "Portuguese" }
36 |         "ro*" { return "Romanian" }
37 |         "ru*" { return "Russian" }
38 |         "sr-Latn*" { return "Serbian Latin" }
39 |         "sk*" { return "Slovak" }
40 |         "sl*" { return "Slovenian" }
41 |         {($_ -like "es*") -and ($_ -ne "es-MX")} { return "Spanish" }
42 |         "es-MX" { return "Spanish (Mexico)" }
43 |         "sv*" { return "Swedish" }
44 |         "th*" { return "Thai" }
45 |         "tr*" { return "Turkish" }
46 |         "uk*" { return "Ukrainian" }
47 |         default { return "English" }
48 |     }
49 | }
50 | 


--------------------------------------------------------------------------------
/functions/microwin/Microwin-GetLocalizedUsers.ps1:
--------------------------------------------------------------------------------
 1 | function Microwin-GetLocalizedUsers
 2 | {
 3 |     <#
 4 |         .SYNOPSIS
 5 |             Gets a localized user group representation for ICACLS commands (Port from DISMTools PE Helper)
 6 |         .PARAMETER admins
 7 |             Determines whether to get a localized user group representation for the Administrators user group
 8 |         .OUTPUTS
 9 |             A string containing the localized user group
10 |         .EXAMPLE
11 |             Microwin-GetLocalizedUsers -admins $true
12 |     #>
13 |     param (
14 |         [Parameter(Mandatory = $true, Position = 0)] [bool]$admins
15 |     )
16 |     if ($admins) {
17 |         return (Get-LocalGroup | Where-Object { $_.SID.Value -like "S-1-5-32-544" }).Name
18 |     } else {
19 |         return (Get-LocalGroup | Where-Object { $_.SID.Value -like "S-1-5-32-545" }).Name
20 |     }
21 | }
22 | 


--------------------------------------------------------------------------------
/functions/microwin/Microwin-GetOscdimg.ps1:
--------------------------------------------------------------------------------
 1 | function Microwin-GetOscdimg {
 2 |     <#
 3 |         .DESCRIPTION
 4 |         This function will download oscdimg file from github Release folders and put it into env:temp folder
 5 | 
 6 |         .EXAMPLE
 7 |         Microwin-GetOscdimg
 8 |     #>
 9 | 
10 |     param(
11 |         [Parameter(Mandatory, position=0)]
12 |         [string]$oscdimgPath
13 |     )
14 | 
15 |     $oscdimgPath = "$env:TEMP\oscdimg.exe"
16 |     $downloadUrl = "https://github.com/ChrisTitusTech/winutil/raw/main/releases/oscdimg.exe"
17 |     Invoke-RestMethod -Uri $downloadUrl -OutFile $oscdimgPath
18 |     $hashResult = Get-FileHash -Path $oscdimgPath -Algorithm SHA256
19 |     $sha256Hash = $hashResult.Hash
20 | 
21 |     Write-Host "[INFO] oscdimg.exe SHA-256 Hash: $sha256Hash"
22 | 
23 |     $expectedHash = "AB9E161049D293B544961BFDF2D61244ADE79376D6423DF4F60BF9B147D3C78D"  # Replace with the actual expected hash
24 |     if ($sha256Hash -eq $expectedHash) {
25 |         Write-Host "Hashes match. File is verified."
26 |     } else {
27 |         Write-Host "Hashes do not match. File may be corrupted or tampered with."
28 |     }
29 | }
30 | 


--------------------------------------------------------------------------------
/functions/microwin/Microwin-NewCheckInstall.ps1:
--------------------------------------------------------------------------------
 1 | function Microwin-NewCheckInstall {
 2 | 
 3 |     # using here string to embedd firstrun
 4 |     $checkInstall = @'
 5 |     @echo off
 6 |     if exist "%HOMEDRIVE%\windows\cpu.txt" (
 7 |         echo %HOMEDRIVE%\windows\cpu.txt exists
 8 |     ) else (
 9 |         echo %HOMEDRIVE%\windows\cpu.txt does not exist
10 |     )
11 |     if exist "%HOMEDRIVE%\windows\SerialNumber.txt" (
12 |         echo %HOMEDRIVE%\windows\SerialNumber.txt exists
13 |     ) else (
14 |         echo %HOMEDRIVE%\windows\SerialNumber.txt does not exist
15 |     )
16 |     if exist "%HOMEDRIVE%\unattend.xml" (
17 |         echo %HOMEDRIVE%\unattend.xml exists
18 |     ) else (
19 |         echo %HOMEDRIVE%\unattend.xml does not exist
20 |     )
21 |     if exist "%HOMEDRIVE%\Windows\Setup\Scripts\SetupComplete.cmd" (
22 |         echo %HOMEDRIVE%\Windows\Setup\Scripts\SetupComplete.cmd exists
23 |     ) else (
24 |         echo %HOMEDRIVE%\Windows\Setup\Scripts\SetupComplete.cmd does not exist
25 |     )
26 |     if exist "%HOMEDRIVE%\Windows\Panther\unattend.xml" (
27 |         echo %HOMEDRIVE%\Windows\Panther\unattend.xml exists
28 |     ) else (
29 |         echo %HOMEDRIVE%\Windows\Panther\unattend.xml does not exist
30 |     )
31 |     if exist "%HOMEDRIVE%\Windows\System32\Sysprep\unattend.xml" (
32 |         echo %HOMEDRIVE%\Windows\System32\Sysprep\unattend.xml exists
33 |     ) else (
34 |         echo %HOMEDRIVE%\Windows\System32\Sysprep\unattend.xml does not exist
35 |     )
36 |     if exist "%HOMEDRIVE%\Windows\FirstStartup.ps1" (
37 |         echo %HOMEDRIVE%\Windows\FirstStartup.ps1 exists
38 |     ) else (
39 |         echo %HOMEDRIVE%\Windows\FirstStartup.ps1 does not exist
40 |     )
41 |     if exist "%HOMEDRIVE%\Windows\winutil.ps1" (
42 |         echo %HOMEDRIVE%\Windows\winutil.ps1 exists
43 |     ) else (
44 |         echo %HOMEDRIVE%\Windows\winutil.ps1 does not exist
45 |     )
46 |     if exist "%HOMEDRIVE%\Windows\LogSpecialize.txt" (
47 |         echo %HOMEDRIVE%\Windows\LogSpecialize.txt exists
48 |     ) else (
49 |         echo %HOMEDRIVE%\Windows\LogSpecialize.txt does not exist
50 |     )
51 |     if exist "%HOMEDRIVE%\Windows\LogAuditUser.txt" (
52 |         echo %HOMEDRIVE%\Windows\LogAuditUser.txt exists
53 |     ) else (
54 |         echo %HOMEDRIVE%\Windows\LogAuditUser.txt does not exist
55 |     )
56 |     if exist "%HOMEDRIVE%\Windows\LogOobeSystem.txt" (
57 |         echo %HOMEDRIVE%\Windows\LogOobeSystem.txt exists
58 |     ) else (
59 |         echo %HOMEDRIVE%\Windows\LogOobeSystem.txt does not exist
60 |     )
61 |     if exist "%HOMEDRIVE%\windows\csup.txt" (
62 |         echo %HOMEDRIVE%\windows\csup.txt exists
63 |     ) else (
64 |         echo %HOMEDRIVE%\windows\csup.txt does not exist
65 |     )
66 |     if exist "%HOMEDRIVE%\windows\LogFirstRun.txt" (
67 |         echo %HOMEDRIVE%\windows\LogFirstRun.txt exists
68 |     ) else (
69 |         echo %HOMEDRIVE%\windows\LogFirstRun.txt does not exist
70 |     )
71 | '@
72 |     $checkInstall | Out-File -FilePath "$env:temp\checkinstall.cmd" -Force -Encoding Ascii
73 | }
74 | 


--------------------------------------------------------------------------------
/functions/microwin/Microwin-NewFirstRun.ps1:
--------------------------------------------------------------------------------
 1 | function Microwin-NewFirstRun {
 2 | 
 3 |     # using here string to embedd firstrun
 4 |     $firstRun = @'
 5 |     # Set the global error action preference to continue
 6 |     $ErrorActionPreference = "Continue"
 7 |     function Remove-RegistryValue {
 8 |         param (
 9 |             [Parameter(Mandatory = $true)]
10 |             [string]$RegistryPath,
11 | 
12 |             [Parameter(Mandatory = $true)]
13 |             [string]$ValueName
14 |         )
15 | 
16 |         # Check if the registry path exists
17 |         if (Test-Path -Path $RegistryPath) {
18 |             $registryValue = Get-ItemProperty -Path $RegistryPath -Name $ValueName -ErrorAction SilentlyContinue
19 | 
20 |             # Check if the registry value exists
21 |             if ($registryValue) {
22 |                 # Remove the registry value
23 |                 Remove-ItemProperty -Path $RegistryPath -Name $ValueName -Force
24 |                 Write-Host "Registry value '$ValueName' removed from '$RegistryPath'."
25 |             } else {
26 |                 Write-Host "Registry value '$ValueName' not found in '$RegistryPath'."
27 |             }
28 |         } else {
29 |             Write-Host "Registry path '$RegistryPath' not found."
30 |         }
31 |     }
32 | 
33 |     "FirstStartup has worked" | Out-File -FilePath "$env:HOMEDRIVE\windows\LogFirstRun.txt" -Append -NoClobber
34 | 
35 |     $taskbarPath = "$env:AppData\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar"
36 |     # Delete all files on the Taskbar
37 |     Get-ChildItem -Path $taskbarPath -File | Remove-Item -Force
38 |     Remove-RegistryValue -RegistryPath "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband" -ValueName "FavoritesRemovedChanges"
39 |     Remove-RegistryValue -RegistryPath "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband" -ValueName "FavoritesChanges"
40 |     Remove-RegistryValue -RegistryPath "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband" -ValueName "Favorites"
41 | 
42 |     # Delete Edge Icon from the desktop
43 |     $edgeShortcutFiles = Get-ChildItem -Path $desktopPath -Filter "*Edge*.lnk"
44 |     # Check if Edge shortcuts exist on the desktop
45 |     if ($edgeShortcutFiles) {
46 |         foreach ($shortcutFile in $edgeShortcutFiles) {
47 |             # Remove each Edge shortcut
48 |             Remove-Item -Path $shortcutFile.FullName -Force
49 |             Write-Host "Edge shortcut '$($shortcutFile.Name)' removed from the desktop."
50 |         }
51 |     }
52 |     Remove-Item -Path "$env:USERPROFILE\Desktop\*.lnk"
53 |     Remove-Item -Path "$env:HOMEDRIVE\Users\Default\Desktop\*.lnk"
54 | 
55 |     try
56 |     {
57 |         if ((Get-WindowsOptionalFeature -Online | Where-Object { $_.State -eq 'Enabled' -and $_.FeatureName -like "Recall" }).Count -gt 0)
58 |         {
59 |             Disable-WindowsOptionalFeature -Online -FeatureName "Recall" -Remove
60 |         }
61 |     }
62 |     catch
63 |     {
64 | 
65 |     }
66 | 
67 |     # Get BCD entries and set bootmgr timeout accordingly
68 |     try
69 |     {
70 |         # Check if the number of occurrences of "path" is 2 - this fixes the Boot Manager screen issue (#2562)
71 |         if ((bcdedit | Select-String "path").Count -eq 2)
72 |         {
73 |             # Set bootmgr timeout to 0
74 |             bcdedit /set `{bootmgr`} timeout 0
75 |         }
76 |     }
77 |     catch
78 |     {
79 | 
80 |     }
81 | 
82 |     reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.Suggested" /f
83 |     reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.Suggested" /v Enabled /t REG_DWORD /d 0 /f
84 |     reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.StartupApp" /f
85 |     reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.StartupApp" /v Enabled /t REG_DWORD /d 0 /f
86 |     reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Microsoft.SkyDrive.Desktop" /f
87 |     reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Microsoft.SkyDrive.Desktop" /v Enabled /t REG_DWORD /d 0 /f
88 | 
89 | '@
90 |     $firstRun | Out-File -FilePath "$env:temp\FirstStartup.ps1" -Force
91 | }
92 | 


--------------------------------------------------------------------------------
/functions/microwin/Microwin-RemoveFeatures.ps1:
--------------------------------------------------------------------------------
 1 | function Microwin-RemoveFeatures() {
 2 |     <#
 3 |         .SYNOPSIS
 4 |             Removes certain features from ISO image
 5 | 
 6 |         .PARAMETER UseCmdlets
 7 |             Determines whether or not to use the DISM cmdlets for processing.
 8 |             - If true, DISM cmdlets will be used
 9 |             - If false, calls to the DISM executable will be made whilst selecting bits and pieces from the output as a string (that was how MicroWin worked before
10 |               the DISM conversion to cmdlets)
11 | 
12 |         .EXAMPLE
13 |             Microwin-RemoveFeatures -UseCmdlets $true
14 |     #>
15 |     param (
16 |         [Parameter(Mandatory = $true, Position = 0)] [bool]$UseCmdlets
17 |     )
18 |     try {
19 |         if ($UseCmdlets) {
20 |             $featlist = (Get-WindowsOptionalFeature -Path "$scratchDir")
21 | 
22 |             $featlist = $featlist | Where-Object {
23 |                 $_.FeatureName -NotLike "*Defender*" -AND
24 |                 $_.FeatureName -NotLike "*Printing*" -AND
25 |                 $_.FeatureName -NotLike "*TelnetClient*" -AND
26 |                 $_.FeatureName -NotLike "*PowerShell*" -AND
27 |                 $_.FeatureName -NotLike "*NetFx*" -AND
28 |                 $_.FeatureName -NotLike "*Media*" -AND
29 |                 $_.FeatureName -NotLike "*NFS*" -AND
30 |                 $_.FeatureName -NotLike "*SearchEngine*" -AND
31 |                 $_.FeatureName -NotLike "*RemoteDesktop*" -AND
32 |                 $_.State -ne "Disabled"
33 |             }
34 |         } else {
35 |             $featList = dism /english /image="$scratchDir" /get-features | Select-String -Pattern "Feature Name : " -CaseSensitive -SimpleMatch
36 |             if ($?) {
37 |                 $featList = $featList -split "Feature Name : " | Where-Object {$_}
38 |                 # Exclude the same items. Note: for now, this doesn't exclude those features that are disabled.
39 |                 # This will appear in the future
40 |                 $featList = $featList | Where-Object {
41 |                     $_ -NotLike "*Defender*" -AND
42 |                     $_ -NotLike "*Printing*" -AND
43 |                     $_ -NotLike "*TelnetClient*" -AND
44 |                     $_ -NotLike "*PowerShell*" -AND
45 |                     $_ -NotLike "*NetFx*" -AND
46 |                     $_ -NotLike "*Media*" -AND
47 |                     $_ -NotLike "*NFS*" -AND
48 |                     $_ -NotLike "*SearchEngine*" -AND
49 |                     $_ -NotLike "*RemoteDesktop*"
50 |                 }
51 |             } else {
52 |                 Write-Host "Features could not be obtained with DISM. MicroWin processing will continue, but features will be skipped."
53 |                 return
54 |             }
55 |         }
56 | 
57 |         if ($UseCmdlets) {
58 |             foreach ($feature in $featList) {
59 |                 $status = "Removing feature $($feature.FeatureName)"
60 |                 Write-Progress -Activity "Removing features" -Status $status -PercentComplete ($counter++/$featlist.Count*100)
61 |                 Write-Debug "Removing feature $($feature.FeatureName)"
62 |                 Disable-WindowsOptionalFeature -Path "$scratchDir" -FeatureName $($feature.FeatureName) -Remove  -ErrorAction SilentlyContinue -NoRestart
63 |             }
64 |         } else {
65 |             foreach ($feature in $featList) {
66 |                 $status = "Removing feature $feature"
67 |                 Write-Progress -Activity "Removing features" -Status $status -PercentComplete ($counter++/$featlist.Count*100)
68 |                 Write-Debug "Removing feature $feature"
69 |                 dism /english /image="$scratchDir" /disable-feature /featurename=$feature /remove /quiet /norestart | Out-Null
70 |                 if ($? -eq $false) {
71 |                     Write-Host "Feature $feature could not be disabled."
72 |                 }
73 |             }
74 |         }
75 |         Write-Progress -Activity "Removing features" -Status "Ready" -Completed
76 |         Write-Host "You can re-enable the disabled features at any time, using either Windows Update or the SxS folder in <installation media>\Sources."
77 |     } catch {
78 |         Write-Host "Unable to get information about the features. A fallback will be used..."
79 |         Write-Host "Error information: $($_.Exception.Message)" -ForegroundColor Yellow
80 |         Microwin-RemoveFeatures -UseCmdlets $false
81 |     }
82 | }
83 | 


--------------------------------------------------------------------------------
/functions/microwin/Microwin-RemoveFileOrDirectory.ps1:
--------------------------------------------------------------------------------
 1 | function Microwin-RemoveFileOrDirectory([string]$pathToDelete, [string]$mask = "", [switch]$Directory = $false) {
 2 |     if(([string]::IsNullOrEmpty($pathToDelete))) { return }
 3 |     if (-not (Test-Path -Path "$($pathToDelete)")) { return }
 4 | 
 5 |     $yesNo = Get-LocalizedYesNo
 6 |     Write-Host "[INFO] In Your local takeown expects '$($yesNo[0])' as a Yes answer."
 7 | 
 8 |     $itemsToDelete = [System.Collections.ArrayList]::new()
 9 | 
10 |     if ($mask -eq "") {
11 |         Write-Debug "Adding $($pathToDelete) to array."
12 |         [void]$itemsToDelete.Add($pathToDelete)
13 |     } else {
14 |         Write-Debug "Adding $($pathToDelete) to array and mask is $($mask)"
15 |         if ($Directory) {
16 |             $itemsToDelete = Get-ChildItem $pathToDelete -Include $mask -Recurse -Directory
17 |         } else {
18 |             $itemsToDelete = Get-ChildItem $pathToDelete -Include $mask -Recurse
19 |         }
20 |     }
21 | 
22 |     foreach($itemToDelete in $itemsToDelete) {
23 |         $status = "Deleting $($itemToDelete)"
24 |         Write-Progress -Activity "Removing Items" -Status $status -PercentComplete ($counter++/$itemsToDelete.Count*100)
25 | 
26 |         if (Test-Path -Path "$($itemToDelete)" -PathType Container) {
27 |             $status = "Deleting directory: $($itemToDelete)"
28 | 
29 |             takeown /r /d $yesNo[0] /a /f "$($itemToDelete)"
30 |             icacls "$($itemToDelete)" /q /c /t /reset
31 |             icacls $itemToDelete /setowner "*S-1-5-32-544"
32 |             icacls $itemToDelete /grant "*S-1-5-32-544:(OI)(CI)F" /t /c /q
33 |             Remove-Item -Force -Recurse "$($itemToDelete)"
34 |         }
35 |         elseif (Test-Path -Path "$($itemToDelete)" -PathType Leaf) {
36 |             $status = "Deleting file: $($itemToDelete)"
37 | 
38 |             takeown /a /f "$($itemToDelete)"
39 |             icacls "$($itemToDelete)" /q /c /t /reset
40 |             icacls "$($itemToDelete)" /setowner "*S-1-5-32-544"
41 |             icacls "$($itemToDelete)" /grant "*S-1-5-32-544:(OI)(CI)F" /t /c /q
42 |             Remove-Item -Force "$($itemToDelete)"
43 |         }
44 |     }
45 |     Write-Progress -Activity "Removing Items" -Status "Ready" -Completed
46 | }
47 | 


--------------------------------------------------------------------------------
/functions/microwin/Microwin-RemoveProvisionedPackages.ps1:
--------------------------------------------------------------------------------
 1 | function Microwin-RemoveProvisionedPackages() {
 2 |     <#
 3 |         .SYNOPSIS
 4 |         Removes AppX packages from a Windows image during MicroWin processing
 5 | 
 6 |         .PARAMETER UseCmdlets
 7 |             Determines whether or not to use the DISM cmdlets for processing.
 8 |             - If true, DISM cmdlets will be used
 9 |             - If false, calls to the DISM executable will be made whilst selecting bits and pieces from the output as a string (that was how MicroWin worked before
10 |               the DISM conversion to cmdlets)
11 | 
12 |         .EXAMPLE
13 |         Microwin-RemoveProvisionedPackages
14 |     #>
15 |     param (
16 |         [Parameter(Mandatory = $true, Position = 0)] [bool]$UseCmdlets
17 |     )
18 |     try
19 |     {
20 |         if ($UseCmdlets) {
21 |             $appxProvisionedPackages = Get-AppxProvisionedPackage -Path "$($scratchDir)" | Where-Object {
22 |                     $_.PackageName -NotLike "*AppInstaller*" -AND
23 |                     $_.PackageName -NotLike "*Store*" -and
24 |                     $_.PackageName -NotLike "*Notepad*" -and
25 |                     $_.PackageName -NotLike "*Printing*" -and
26 |                     $_.PackageName -NotLike "*YourPhone*" -and
27 |                     $_.PackageName -NotLike "*Xbox*" -and
28 |                     $_.PackageName -NotLike "*WindowsTerminal*" -and
29 |                     $_.PackageName -NotLike "*Calculator*" -and
30 |                     $_.PackageName -NotLike "*Photos*" -and
31 |                     $_.PackageName -NotLike "*VCLibs*" -and
32 |                     $_.PackageName -NotLike "*Paint*" -and
33 |                     $_.PackageName -NotLike "*Gaming*" -and
34 |                     $_.PackageName -NotLike "*Extension*" -and
35 |                     $_.PackageName -NotLike "*SecHealthUI*" -and
36 |                     $_.PackageName -NotLike "*ScreenSketch*"
37 |             }
38 |         } else {
39 |             $appxProvisionedPackages = dism /english /image="$scratchDir" /get-provisionedappxpackages | Select-String -Pattern "PackageName : " -CaseSensitive -SimpleMatch
40 |             if ($?) {
41 |                 $appxProvisionedPackages = $appxProvisionedPackages -split "PackageName : " | Where-Object {$_}
42 |                 # Exclude the same items.
43 |                 $appxProvisionedPackages = $appxProvisionedPackages | Where-Object {
44 |                     $_ -NotLike "*AppInstaller*" -AND
45 |                     $_ -NotLike "*Store*" -and
46 |                     $_ -NotLike "*Notepad*" -and
47 |                     $_ -NotLike "*Printing*" -and
48 |                     $_ -NotLike "*YourPhone*" -and
49 |                     $_ -NotLike "*Xbox*" -and
50 |                     $_ -NotLike "*WindowsTerminal*" -and
51 |                     $_ -NotLike "*Calculator*" -and
52 |                     $_ -NotLike "*Photos*" -and
53 |                     $_ -NotLike "*VCLibs*" -and
54 |                     $_ -NotLike "*Paint*" -and
55 |                     $_ -NotLike "*Gaming*" -and
56 |                     $_ -NotLike "*Extension*" -and
57 |                     $_ -NotLike "*SecHealthUI*" -and
58 |                     $_ -NotLike "*ScreenSketch*"
59 |                 }
60 |             } else {
61 |                 Write-Host "AppX packages could not be obtained with DISM. MicroWin processing will continue, but AppX packages will be skipped."
62 |                 return
63 |             }
64 |         }
65 | 
66 |         $counter = 0
67 |         if ($UseCmdlets) {
68 |             foreach ($appx in $appxProvisionedPackages) {
69 |                 $status = "Removing Provisioned $($appx.PackageName)"
70 |                 Write-Progress -Activity "Removing Provisioned Apps" -Status $status -PercentComplete ($counter++/$appxProvisionedPackages.Count*100)
71 |                 try {
72 |                     Remove-AppxProvisionedPackage -Path "$scratchDir" -PackageName $appx.PackageName -ErrorAction SilentlyContinue
73 |                 } catch {
74 |                     Write-Host "Application $($appx.PackageName) could not be removed"
75 |                     continue
76 |                 }
77 |             }
78 |         } else {
79 |             foreach ($appx in $appxProvisionedPackages) {
80 |                 $status = "Removing Provisioned $appx"
81 |                 Write-Progress -Activity "Removing Provisioned Apps" -Status $status -PercentComplete ($counter++/$appxProvisionedPackages.Count*100)
82 |                 dism /english /image="$scratchDir" /remove-provisionedappxpackage /packagename=$appx /quiet /norestart | Out-Null
83 |                 if ($? -eq $false) {
84 |                     Write-Host "AppX package $appx could not be removed."
85 |                 }
86 |             }
87 |         }
88 |         Write-Progress -Activity "Removing Provisioned Apps" -Status "Ready" -Completed
89 |     }
90 |     catch
91 |     {
92 |         Write-Host "Unable to get information about the AppX packages. A fallback will be used..."
93 |         Write-Host "Error information: $($_.Exception.Message)" -ForegroundColor Yellow
94 |         Microwin-RemoveProvisionedPackages -UseCmdlets $false
95 |     }
96 | }
97 | 


--------------------------------------------------------------------------------
/functions/microwin/Microwin-TestCompatibleImage.ps1:
--------------------------------------------------------------------------------
 1 | function Microwin-TestCompatibleImage() {
 2 |     <#
 3 |         .SYNOPSIS
 4 |             Checks the version of a Windows image and determines whether or not it is compatible with a specific feature depending on a desired version
 5 | 
 6 |         .PARAMETER Name
 7 |             imgVersion - The version of the Windows image
 8 |             desiredVersion - The version to compare the image version with
 9 |     #>
10 | 
11 |     param
12 |     (
13 |     [Parameter(Mandatory, position=0)]
14 |     [string]$imgVersion,
15 | 
16 |     [Parameter(Mandatory, position=1)]
17 |     [Version]$desiredVersion
18 |     )
19 | 
20 |     try {
21 |         $version = [Version]$imgVersion
22 |         return $version -ge $desiredVersion
23 |     } catch {
24 |         return $False
25 |     }
26 | }
27 | 


--------------------------------------------------------------------------------
/functions/microwin/Toggle-MicrowinPanel.ps1:
--------------------------------------------------------------------------------
 1 | function Toggle-MicrowinPanel {
 2 |     <#
 3 |     .SYNOPSIS
 4 |     Toggles the visibility of the Microwin options and ISO panels in the GUI.
 5 |     .DESCRIPTION
 6 |     This function toggles the visibility of the Microwin options and ISO panels in the GUI.
 7 |     .PARAMETER MicrowinOptionsPanel
 8 |     The panel containing Microwin options.
 9 |     .PARAMETER MicrowinISOPanel
10 |     The panel containing the Microwin ISO options.
11 |     .EXAMPLE
12 |     Toggle-MicrowinPanel 1
13 |     #>
14 |     param (
15 |         [Parameter(Mandatory = $true, Position = 0)]
16 |         [ValidateSet(1, 2)]
17 |         [int]$PanelNumber
18 |     )
19 | 
20 |     if ($PanelNumber -eq 1) {
21 |         $sync.MicrowinISOPanel.Visibility = 'Visible'
22 |         $sync.MicrowinOptionsPanel.Visibility = 'Collapsed'
23 | 
24 |     } elseif ($PanelNumber -eq 2) {
25 |         $sync.MicrowinOptionsPanel.Visibility = 'Visible'
26 |         $sync.MicrowinISOPanel.Visibility = 'Collapsed'
27 |     }
28 | }
29 | 


--------------------------------------------------------------------------------
/functions/private/Add-SelectedAppsMenuItem.ps1:
--------------------------------------------------------------------------------
 1 |     function Add-SelectedAppsMenuItem {
 2 |         <#
 3 |         .SYNOPSIS
 4 |             This is a helper function that generates and adds the Menu Items to the Selected Apps Popup.
 5 | 
 6 |         .Parameter name
 7 |             The actual Name of an App like "Chrome" or "Brave"
 8 |             This name is contained in the "Content" property inside the applications.json
 9 |         .PARAMETER key
10 |             The key which identifies an app object in applications.json
11 |             For Chrome this would be "WPFInstallchrome" because "WPFInstall" is prepended automatically for each key in applications.json
12 |         #>
13 | 
14 |         param ([string]$name, [string]$key)
15 | 
16 |         $selectedAppGrid = New-Object Windows.Controls.Grid
17 | 
18 |         $selectedAppGrid.ColumnDefinitions.Add((New-Object System.Windows.Controls.ColumnDefinition -Property @{Width = "*"}))
19 |         $selectedAppGrid.ColumnDefinitions.Add((New-Object System.Windows.Controls.ColumnDefinition -Property @{Width = "30"}))
20 | 
21 |         # Sets the name to the Content as well as the Tooltip, because the parent Popup Border has a fixed width and text could "overflow".
22 |         # With the tooltip, you can still read the whole entry on hover
23 |         $selectedAppLabel = New-Object Windows.Controls.Label
24 |         $selectedAppLabel.Content = $name
25 |         $selectedAppLabel.ToolTip = $name
26 |         $selectedAppLabel.HorizontalAlignment = "Left"
27 |         $selectedAppLabel.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor")
28 |         [System.Windows.Controls.Grid]::SetColumn($selectedAppLabel, 0)
29 |         $selectedAppGrid.Children.Add($selectedAppLabel)
30 | 
31 |         $selectedAppRemoveButton = New-Object Windows.Controls.Button
32 |         $selectedAppRemoveButton.FontFamily = "Segoe MDL2 Assets"
33 |         $selectedAppRemoveButton.Content = [string]([char]0xE711)
34 |         $selectedAppRemoveButton.HorizontalAlignment = "Center"
35 |         $selectedAppRemoveButton.Tag = $key
36 |         $selectedAppRemoveButton.ToolTip = "Remove the App from Selection"
37 |         $selectedAppRemoveButton.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor")
38 |         $selectedAppRemoveButton.SetResourceReference([Windows.Controls.Control]::StyleProperty, "HoverButtonStyle")
39 | 
40 |         # Highlight the Remove icon on Hover
41 |         $selectedAppRemoveButton.Add_MouseEnter({ $this.Foreground = "Red" })
42 |         $selectedAppRemoveButton.Add_MouseLeave({ $this.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") })
43 |         $selectedAppRemoveButton.Add_Click({
44 |             $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
45 |         })
46 |         [System.Windows.Controls.Grid]::SetColumn($selectedAppRemoveButton, 1)
47 |         $selectedAppGrid.Children.Add($selectedAppRemoveButton)
48 |         # Add new Element to Popup
49 |         $sync.selectedAppsstackPanel.Children.Add($selectedAppGrid)
50 |     }
51 | 


--------------------------------------------------------------------------------
/functions/private/Copy-Files.ps1:
--------------------------------------------------------------------------------
 1 | function Copy-Files {
 2 |     <#
 3 | 
 4 |         .DESCRIPTION
 5 |             Copies the contents of a given ISO file to a given destination
 6 |         .PARAMETER Path
 7 |             The source of the files to copy
 8 |         .PARAMETER Destination
 9 |             The destination to copy the files to
10 |         .PARAMETER Recurse
11 |             Determines whether or not to copy all files of the ISO file, including those in subdirectories
12 |         .PARAMETER Force
13 |             Determines whether or not to overwrite existing files
14 |         .EXAMPLE
15 |             Copy-Files "D:" "C:\ISOFile" -Recurse -Force
16 | 
17 |     #>
18 |     param (
19 |         [string]$Path,
20 |         [string]$Destination,
21 |         [switch]$Recurse = $false,
22 |         [switch]$Force = $false
23 |     )
24 | 
25 |     try {
26 | 
27 |         $files = Get-ChildItem -Path $path -Recurse:$recurse
28 |         Write-Host "Copy $($files.Count) file(s) from $path to $destination"
29 | 
30 |         foreach ($file in $files) {
31 |             $status = "Copying file {0} of {1}: {2}" -f $counter, $files.Count, $file.Name
32 |             Write-Progress -Activity "Copy disc image files" -Status $status -PercentComplete ($counter++/$files.count*100)
33 |             $restpath = $file.FullName -Replace $path, ''
34 | 
35 |             if ($file.PSIsContainer -eq $true) {
36 |                 Write-Debug "Creating $($destination + $restpath)"
37 |                 New-Item ($destination+$restpath) -Force:$force -Type Directory -ErrorAction SilentlyContinue
38 |             } else {
39 |                 Write-Debug "Copy from $($file.FullName) to $($destination+$restpath)"
40 |                 Copy-Item $file.FullName ($destination+$restpath) -ErrorAction SilentlyContinue -Force:$force
41 |                 Set-ItemProperty -Path ($destination+$restpath) -Name IsReadOnly -Value $false
42 |             }
43 |         }
44 |         Write-Progress -Activity "Copy disc image files" -Status "Ready" -Completed
45 |     } catch {
46 |         Write-Host "Unable to Copy all the files due to an unhandled exception" -ForegroundColor Yellow
47 |         Write-Host "Error information: $($_.Exception.Message)`n" -ForegroundColor Yellow
48 |         Write-Host "Additional information:" -ForegroundColor Yellow
49 |         Write-Host $PSItem.Exception.StackTrace
50 |         # Write possible suggestions
51 |         Write-Host "`nIf you are using an antivirus, try configuring exclusions"
52 |     }
53 | }
54 | 


--------------------------------------------------------------------------------
/functions/private/Find-AppsByNameOrDescription.ps1:
--------------------------------------------------------------------------------
 1 | function Find-AppsByNameOrDescription {
 2 |     <#
 3 |         .SYNOPSIS
 4 |             Searches through the Apps on the Install Tab and hides all entries that do not match the string
 5 | 
 6 |         .PARAMETER SearchString
 7 |             The string to be searched for
 8 |     #>
 9 |     param(
10 |         [Parameter(Mandatory=$false)]
11 |         [string]$SearchString = ""
12 |     )
13 |     # Reset the visibility if the search string is empty or the search is cleared
14 |     if ([string]::IsNullOrWhiteSpace($SearchString)) {
15 |         $sync.ItemsControl.Items | ForEach-Object {
16 |             $_.Visibility = [Windows.Visibility]::Visible
17 |             $_.Children | ForEach-Object {
18 |                 if ($null -ne $_) {
19 |                     $_.Visibility = [Windows.Visibility]::Visible
20 |                 }
21 | 
22 |             }
23 |         }
24 |         return
25 |     }
26 |     $sync.ItemsControl.Items | ForEach-Object {
27 |         # Ensure ToggleButtons remain visible
28 |         if ($_.Tag -like "CategoryToggleButton") {
29 |             $_.Visibility = [Windows.Visibility]::Visible
30 |             return
31 |         }
32 |         # Hide all CategoryWrapPanel and ToggleButton
33 |         $_.Visibility = [Windows.Visibility]::Collapsed
34 |         if ($_.Tag -like "CategoryWrapPanel_*") {
35 |             # Search for Apps that match the search string
36 |             $_.Children | Foreach-Object {
37 |                 $appEntry = $sync.configs.applicationsHashtable.$($_.Tag)
38 |                 if ($appEntry.Content -like "*$SearchString*" -or $appEntry.Description -like "*$SearchString*") {
39 |                     # Show the App and the parent CategoryWrapPanel if the string is found
40 |                     $_.Visibility = [Windows.Visibility]::Visible
41 |                     $_.parent.Visibility = [Windows.Visibility]::Visible
42 |                 }
43 |                 else {
44 |                     $_.Visibility = [Windows.Visibility]::Collapsed
45 |                 }
46 |             }
47 |         }
48 |     }
49 | }
50 | 


--------------------------------------------------------------------------------
/functions/private/Find-TweaksByNameOrDescription.ps1:
--------------------------------------------------------------------------------
  1 | function Find-TweaksByNameOrDescription {
  2 |     <#
  3 |         .SYNOPSIS
  4 |             Searches through the Tweaks on the Tweaks Tab and hides all entries that do not match the search string
  5 | 
  6 |         .PARAMETER SearchString
  7 |             The string to be searched for
  8 |     #>
  9 |     param(
 10 |         [Parameter(Mandatory=$false)]
 11 |         [string]$SearchString = ""
 12 |     )
 13 | 
 14 |     # Reset the visibility if the search string is empty or the search is cleared
 15 |     if ([string]::IsNullOrWhiteSpace($SearchString)) {
 16 |         # Show all categories
 17 |         $tweakspanel = $sync.Form.FindName("tweakspanel")
 18 |         $tweakspanel.Children | ForEach-Object {
 19 |             $_.Visibility = [Windows.Visibility]::Visible
 20 | 
 21 |             # Foreach category section, show all items
 22 |             if ($_ -is [Windows.Controls.Border]) {
 23 |                 $_.Visibility = [Windows.Visibility]::Visible
 24 | 
 25 |                 # Find ItemsControl
 26 |                 $dockPanel = $_.Child
 27 |                 if ($dockPanel -is [Windows.Controls.DockPanel]) {
 28 |                     $itemsControl = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] }
 29 |                     if ($itemsControl) {
 30 |                         # Show items in the category
 31 |                         foreach ($item in $itemsControl.Items) {
 32 |                             if ($item -is [Windows.Controls.Label]) {
 33 |                                 $item.Visibility = [Windows.Visibility]::Visible
 34 |                             } elseif ($item -is [Windows.Controls.DockPanel] -or
 35 |                                       $item -is [Windows.Controls.StackPanel]) {
 36 |                                 $item.Visibility = [Windows.Visibility]::Visible
 37 |                             }
 38 |                         }
 39 |                     }
 40 |                 }
 41 |             }
 42 |         }
 43 |         return
 44 |     }
 45 | 
 46 |     # Search for matching tweaks when search string is not null
 47 |     $tweakspanel = $sync.Form.FindName("tweakspanel")
 48 | 
 49 |     $tweakspanel.Children | ForEach-Object {
 50 |         $categoryBorder = $_
 51 |         $categoryVisible = $false
 52 | 
 53 |         if ($_ -is [Windows.Controls.Border]) {
 54 |             # Find the ItemsControl
 55 |             $dockPanel = $_.Child
 56 |             if ($dockPanel -is [Windows.Controls.DockPanel]) {
 57 |                 $itemsControl = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] }
 58 |                 if ($itemsControl) {
 59 |                     $categoryLabel = $null
 60 | 
 61 |                     # Process all items in the ItemsControl
 62 |                     for ($i = 0; $i -lt $itemsControl.Items.Count; $i++) {
 63 |                         $item = $itemsControl.Items[$i]
 64 | 
 65 |                         if ($item -is [Windows.Controls.Label]) {
 66 |                             $categoryLabel = $item
 67 |                             $item.Visibility = [Windows.Visibility]::Collapsed
 68 |                         } elseif ($item -is [Windows.Controls.DockPanel]) {
 69 |                             $checkbox = $item.Children | Where-Object { $_ -is [Windows.Controls.CheckBox] } | Select-Object -First 1
 70 |                             $label = $item.Children | Where-Object { $_ -is [Windows.Controls.Label] } | Select-Object -First 1
 71 | 
 72 |                             if ($label -and ($label.Content -like "*$SearchString*" -or $label.ToolTip -like "*$SearchString*")) {
 73 |                                 $item.Visibility = [Windows.Visibility]::Visible
 74 |                                 if ($categoryLabel) { $categoryLabel.Visibility = [Windows.Visibility]::Visible }
 75 |                                 $categoryVisible = $true
 76 |                             } else {
 77 |                                 $item.Visibility = [Windows.Visibility]::Collapsed
 78 |                             }
 79 |                         } elseif ($item -is [Windows.Controls.StackPanel]) {
 80 |                             # StackPanel which contain checkboxes or other elements
 81 |                             $checkbox = $item.Children | Where-Object { $_ -is [Windows.Controls.CheckBox] } | Select-Object -First 1
 82 | 
 83 |                             if ($checkbox -and ($checkbox.Content -like "*$SearchString*" -or $checkbox.ToolTip -like "*$SearchString*")) {
 84 |                                 $item.Visibility = [Windows.Visibility]::Visible
 85 |                                 if ($categoryLabel) { $categoryLabel.Visibility = [Windows.Visibility]::Visible }
 86 |                                 $categoryVisible = $true
 87 |                             } else {
 88 |                                 $item.Visibility = [Windows.Visibility]::Collapsed
 89 |                             }
 90 |                         }
 91 |                     }
 92 |                 }
 93 |             }
 94 | 
 95 |             # Set the visibility based on if any item matched
 96 |             $categoryBorder.Visibility = if ($categoryVisible) { [Windows.Visibility]::Visible } else { [Windows.Visibility]::Collapsed }
 97 | 
 98 |         }
 99 |     }
100 | }
101 | 


--------------------------------------------------------------------------------
/functions/private/Get-LocalizedYesNo.ps1:
--------------------------------------------------------------------------------
 1 | function Get-LocalizedYesNo {
 2 |     <#
 3 |     .SYNOPSIS
 4 |     This function runs choice.exe and captures its output to extract yes no in a localized Windows
 5 | 
 6 |     .DESCRIPTION
 7 |     The function retrieves the output of the command 'cmd /c "choice <nul 2>nul"' and converts the default output for Yes and No
 8 |     in the localized format, such as "Yes=<first character>, No=<second character>".
 9 | 
10 |     .EXAMPLE
11 |     $yesNoArray = Get-LocalizedYesNo
12 |     Write-Host "Yes=$($yesNoArray[0]), No=$($yesNoArray[1])"
13 |     #>
14 | 
15 |     # Run choice and capture its options as output
16 |     # The output shows the options for Yes and No as "[Y,N]?" in the (partitially) localized format.
17 |     # eg. English: [Y,N]?
18 |     # Dutch: [Y,N]?
19 |     # German: [J,N]?
20 |     # French: [O,N]?
21 |     # Spanish: [S,N]?
22 |     # Italian: [S,N]?
23 |     # Russian: [Y,N]?
24 | 
25 |     $line = cmd /c "choice <nul 2>nul"
26 |     $charactersArray = @()
27 |     $regexPattern = '([a-zA-Z])'
28 |     $charactersArray = [regex]::Matches($line, $regexPattern) | ForEach-Object { $_.Groups[1].Value }
29 | 
30 |     Write-Debug "According to takeown.exe local Yes is $charactersArray[0]"
31 |     # Return the array of characters
32 |     return $charactersArray
33 | 
34 |   }
35 | 


--------------------------------------------------------------------------------
/functions/private/Get-WPFObjectName.ps1:
--------------------------------------------------------------------------------
 1 | function Get-WPFObjectName {
 2 |     <#
 3 |         .SYNOPSIS
 4 |             This is a helper function that generates an objectname with the prefix WPF that can be used as a Powershell Variable after compilation.
 5 |             To achieve this, all characters that are not a-z, A-Z or 0-9 are simply removed from the name.
 6 | 
 7 |         .PARAMETER type
 8 |             The type of object for which the name should be generated. (e.g. Label, Button, CheckBox...)
 9 | 
10 |         .PARAMETER name
11 |             The name or description to be used for the object. (invalid characters are removed)
12 | 
13 |         .OUTPUTS
14 |             A string that can be used as a object/variable name in powershell.
15 |             For example: WPFLabelMicrosoftTools
16 | 
17 |         .EXAMPLE
18 |             Get-WPFObjectName -type Label -name "Microsoft Tools"
19 |     #>
20 | 
21 |     param(
22 |         [Parameter(Mandatory, position=0)]
23 |         [string]$type,
24 | 
25 |         [Parameter(position=1)]
26 |         [string]$name
27 |     )
28 | 
29 |     $Output = $("WPF"+$type+$name) -replace '[^a-zA-Z0-9]', ''
30 |     return $Output
31 | }
32 | 


--------------------------------------------------------------------------------
/functions/private/Get-WinUtilCheckBoxes.ps1:
--------------------------------------------------------------------------------
 1 | Function Get-WinUtilCheckBoxes {
 2 | 
 3 |     <#
 4 | 
 5 |     .SYNOPSIS
 6 |         Finds all checkboxes that are checked on the specific tab and inputs them into a script.
 7 | 
 8 |     .PARAMETER unCheck
 9 |         Whether to uncheck the checkboxes that are checked. Defaults to true
10 | 
11 |     .OUTPUTS
12 |         A List containing the name of each checked checkbox
13 | 
14 |     .EXAMPLE
15 |         Get-WinUtilCheckBoxes "WPFInstall"
16 | 
17 |     #>
18 | 
19 |     Param(
20 |         [boolean]$unCheck = $false
21 |     )
22 | 
23 |     $Output = @{
24 |         Install      = @()
25 |         WPFTweaks     = @()
26 |         WPFFeature    = @()
27 |         WPFInstall    = @()
28 |     }
29 | 
30 |     $CheckBoxes = $sync.GetEnumerator() | Where-Object { $_.Value -is [System.Windows.Controls.CheckBox] }
31 | 
32 |     # First check and add WPFTweaksRestorePoint if checked
33 |     $RestorePoint = $CheckBoxes | Where-Object { $_.Key -eq 'WPFTweaksRestorePoint' -and $_.Value.IsChecked -eq $true }
34 |     if ($RestorePoint) {
35 |         $Output["WPFTweaks"] = @('WPFTweaksRestorePoint')
36 |         Write-Debug "Adding WPFTweaksRestorePoint as first in WPFTweaks"
37 | 
38 |         if ($unCheck) {
39 |             $RestorePoint.Value.IsChecked = $false
40 |         }
41 |     }
42 | 
43 |     foreach ($CheckBox in $CheckBoxes) {
44 |         if ($CheckBox.Key -eq 'WPFTweaksRestorePoint') { continue }  # Skip since it's already handled
45 | 
46 |         $group = if ($CheckBox.Key.StartsWith("WPFInstall")) { "Install" }
47 |                 elseif ($CheckBox.Key.StartsWith("WPFTweaks")) { "WPFTweaks" }
48 |                 elseif ($CheckBox.Key.StartsWith("WPFFeature")) { "WPFFeature" }
49 |         if ($group) {
50 |             if ($CheckBox.Value.IsChecked -eq $true) {
51 |                 $feature = switch ($group) {
52 |                     "Install" {
53 |                         # Get the winget value
54 |                         [PsCustomObject]@{
55 |                             winget="$($sync.configs.applications.$($CheckBox.Name).winget)";
56 |                             choco="$($sync.configs.applications.$($CheckBox.Name).choco)";
57 |                         }
58 | 
59 |                     }
60 |                     default {
61 |                         $CheckBox.Name
62 |                     }
63 |                 }
64 | 
65 |                 if (-not $Output.ContainsKey($group)) {
66 |                     $Output[$group] = @()
67 |                 }
68 |                 if ($group -eq "Install") {
69 |                     $Output["WPFInstall"] += $CheckBox.Name
70 |                     Write-Debug "Adding: $($CheckBox.Name) under: WPFInstall"
71 |                 }
72 | 
73 |                 Write-Debug "Adding: $($feature) under: $($group)"
74 |                 $Output[$group] += $feature
75 | 
76 |                 if ($unCheck) {
77 |                     $CheckBox.Value.IsChecked = $false
78 |                 }
79 |             }
80 |         }
81 |     }
82 |     return  $Output
83 | }
84 | 


--------------------------------------------------------------------------------
/functions/private/Get-WinUtilInstallerProcess.ps1:
--------------------------------------------------------------------------------
 1 | function Get-WinUtilInstallerProcess {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Checks if the given process is running
 6 | 
 7 |     .PARAMETER Process
 8 |         The process to check
 9 | 
10 |     .OUTPUTS
11 |         Boolean - True if the process is running
12 | 
13 |     #>
14 | 
15 |     param($Process)
16 | 
17 |     if ($Null -eq $Process) {
18 |         return $false
19 |     }
20 |     if (Get-Process -Id $Process.Id -ErrorAction SilentlyContinue) {
21 |         return $true
22 |     }
23 |     return $false
24 | }
25 | 


--------------------------------------------------------------------------------
/functions/private/Get-WinUtilSelectedPackages.ps1:
--------------------------------------------------------------------------------
 1 | function Get-WinUtilSelectedPackages
 2 | {
 3 |      <#
 4 |     .SYNOPSIS
 5 |         Sorts given packages based on installer preference and availability.
 6 | 
 7 |     .OUTPUTS
 8 |         Hashtable. Key = Package Manager, Value = ArrayList of packages to install
 9 |     #>
10 |     param (
11 |         [Parameter(Mandatory=$true)]
12 |         $PackageList,
13 |         [Parameter(Mandatory=$true)]
14 |         [PackageManagers]$Preference
15 |     )
16 | 
17 |     if ($PackageList.count -eq 1) {
18 |         $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
19 |     } else {
20 |         $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" })
21 |     }
22 | 
23 |     $packages = [System.Collections.Hashtable]::new()
24 |     $packagesWinget = [System.Collections.ArrayList]::new()
25 |     $packagesChoco = [System.Collections.ArrayList]::new()
26 |     $packages[[PackageManagers]::Winget] = $packagesWinget
27 |     $packages[[PackageManagers]::Choco] = $packagesChoco
28 | 
29 |     Write-Debug "Checking packages using Preference '$($Preference)'"
30 | 
31 |     foreach ($package in $PackageList) {
32 |         switch ($Preference) {
33 |             "Choco" {
34 |                 if ($package.choco -eq "na") {
35 |                     Write-Debug "$($package.content) has no Choco value."
36 |                     $null = $packagesWinget.add($($package.winget))
37 |                     Write-Host "Queueing $($package.winget) for Winget"
38 |                 } else {
39 |                     $null = $packagesChoco.add($package.choco)
40 |                     Write-Host "Queueing $($package.choco) for Chocolatey"
41 |                 }
42 |                 break
43 |             }
44 |             "Winget" {
45 |                 if ($package.winget -eq "na") {
46 |                     Write-Debug "$($package.content) has no Winget value."
47 |                     $null = $packagesChoco.add($package.choco)
48 |                     Write-Host "Queueing $($package.choco) for Chocolatey"
49 |                 } else {
50 |                     $null = $packagesWinget.add($($package.winget))
51 |                     Write-Host "Queueing $($package.winget) for Winget"
52 |                 }
53 |                 break
54 |             }
55 |         }
56 |     }
57 | 
58 |     return $packages
59 | }
60 | 


--------------------------------------------------------------------------------
/functions/private/Get-WinUtilToggleStatus.ps1:
--------------------------------------------------------------------------------
 1 | Function Get-WinUtilToggleStatus {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Pulls the registry keys for the given toggle switch and checks whether the toggle should be checked or unchecked
 6 | 
 7 |     .PARAMETER ToggleSwitch
 8 |         The name of the toggle to check
 9 | 
10 |     .OUTPUTS
11 |         Boolean to set the toggle's status to
12 | 
13 |     #>
14 | 
15 |     Param($ToggleSwitch)
16 | 
17 |     $ToggleSwitchReg = $sync.configs.tweaks.$ToggleSwitch.registry
18 | 
19 |     try {
20 |         if (($ToggleSwitchReg.path -imatch "hku") -and !(Get-PSDrive -Name HKU -ErrorAction SilentlyContinue)) {
21 |             $null = (New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS)
22 |             if (Get-PSDrive -Name HKU -ErrorAction SilentlyContinue) {
23 |                 Write-Debug "HKU drive created successfully"
24 |             } else {
25 |                 Write-Debug "Failed to create HKU drive"
26 |             }
27 |         }
28 |     } catch {
29 |         Write-Error "An error occurred regarding the HKU Drive: $_"
30 |         return $false
31 |     }
32 | 
33 |     if ($ToggleSwitchReg) {
34 |         $count = 0
35 | 
36 |         foreach ($regentry in $ToggleSwitchReg) {
37 |             try {
38 |                 if (!(Test-Path $regentry.Path)) {
39 |                     New-Item -Path $regentry.Path -Force | Out-Null
40 |                 }
41 |                 $regstate = (Get-ItemProperty -path $regentry.Path).$($regentry.Name)
42 |                 if ($regstate -eq $regentry.Value) {
43 |                     $count += 1
44 |                     Write-Debug "$($regentry.Name) is true (state: $regstate, value: $($regentry.Value), original: $($regentry.OriginalValue))"
45 |                 } else {
46 |                     Write-Debug "$($regentry.Name) is false (state: $regstate, value: $($regentry.Value), original: $($regentry.OriginalValue))"
47 |                 }
48 |                 if (!$regstate) {
49 |                     switch ($regentry.DefaultState) {
50 |                         "true" {
51 |                             $regstate = $regentry.Value
52 |                             $count += 1
53 |                         }
54 |                         "false" {
55 |                             $regstate = $regentry.OriginalValue
56 |                         }
57 |                         default {
58 |                             Write-Error "Entry for $($regentry.Name) does not exist and no DefaultState is defined."
59 |                             $regstate = $regentry.OriginalValue
60 |                         }
61 |                     }
62 |                 }
63 |             } catch {
64 |                 Write-Error "An unexpected error occurred: $_"
65 |             }
66 |         }
67 | 
68 |         if ($count -eq $ToggleSwitchReg.Count) {
69 |             Write-Debug "$($ToggleSwitchReg.Name) is true (count: $count)"
70 |             return $true
71 |         } else {
72 |             Write-Debug "$($ToggleSwitchReg.Name) is false (count: $count)"
73 |             return $false
74 |         }
75 |     } else {
76 |         return $false
77 |     }
78 | }
79 | 


--------------------------------------------------------------------------------
/functions/private/Get-WinUtilVariables.ps1:
--------------------------------------------------------------------------------
 1 | function Get-WinUtilVariables {
 2 | 
 3 |     <#
 4 |     .SYNOPSIS
 5 |         Gets every form object of the provided type
 6 | 
 7 |     .OUTPUTS
 8 |         List containing every object that matches the provided type
 9 |     #>
10 |     param (
11 |         [Parameter()]
12 |         [string[]]$Type
13 |     )
14 |     $keys = ($sync.keys).where{ $_ -like "WPF*" }
15 |     if ($Type) {
16 |         $output = $keys | ForEach-Object {
17 |             try {
18 |                 $objType = $sync["$psitem"].GetType().Name
19 |                 if ($Type -contains $objType) {
20 |                     Write-Output $psitem
21 |                 }
22 |             } catch {
23 |                 <#I am here so errors don't get outputted for a couple variables that don't have the .GetType() attribute#>
24 |             }
25 |         }
26 |         return $output
27 |     }
28 |     return $keys
29 | }
30 | 


--------------------------------------------------------------------------------
/functions/private/Hide-WPFInstallAppBusy.ps1:
--------------------------------------------------------------------------------
 1 | function Hide-WPFInstallAppBusy {
 2 |     <#
 3 |     .SYNOPSIS
 4 |         Hides the busy overlay in the install app area of the WPF form.
 5 |         This is used to indicate that an install or uninstall has finished.
 6 |     #>
 7 |     $sync.form.Dispatcher.Invoke([action]{
 8 |         $sync.InstallAppAreaOverlay.Visibility = [Windows.Visibility]::Collapsed
 9 |         $sync.InstallAppAreaBorder.IsEnabled = $true
10 |         $sync.InstallAppAreaScrollViewer.Effect.Radius = 0
11 |     })
12 | }
13 | 


--------------------------------------------------------------------------------
/functions/private/Initalize-InstallAppEntry.ps1:
--------------------------------------------------------------------------------
 1 | function Initialize-InstallAppEntry {
 2 |     <#
 3 |         .SYNOPSIS
 4 |             Creates the app entry to be placed on the isntall tab for a given app
 5 |             Used to as part of the Install Tab UI generation
 6 |         .PARAMETER TargetElement
 7 |             The Element into which the Apps should be placed
 8 |         .PARAMETER appKey
 9 |             The Key of the app inside the $sync.configs.applicationsHashtable
10 |     #>
11 |         param(
12 |             [Windows.Controls.WrapPanel]$TargetElement,
13 |             $appKey
14 |         )
15 | 
16 |         # Create the outer Border for the application type
17 |         $border = New-Object Windows.Controls.Border
18 |         $border.Style = $sync.Form.Resources.AppEntryBorderStyle
19 |         $border.Tag = $appKey
20 |         $border.ToolTip = $Apps.$appKey.description
21 |         $border.Add_MouseLeftButtonUp({
22 |             $childCheckbox = ($this.Child | Where-Object {$_.Template.TargetType -eq [System.Windows.Controls.Checkbox]})[0]
23 |             $childCheckBox.isChecked = -not $childCheckbox.IsChecked
24 |         })
25 |         $border.Add_MouseEnter({
26 |             if (($sync.$($this.Tag).IsChecked) -eq $false) {
27 |                 $this.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallHighlightedColor")
28 |             }
29 |         })
30 |         $border.Add_MouseLeave({
31 |             if (($sync.$($this.Tag).IsChecked) -eq $false) {
32 |                 $this.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor")
33 |             }
34 |         })
35 |         $border.Add_MouseRightButtonUp({
36 |             # Store the selected app in a global variable so it can be used in the popup
37 |             $sync.appPopupSelectedApp = $this.Tag
38 |             # Set the popup position to the current mouse position
39 |             $sync.appPopup.PlacementTarget = $this
40 |             $sync.appPopup.IsOpen = $true
41 |         })
42 | 
43 |         $checkBox = New-Object Windows.Controls.CheckBox
44 |         $checkBox.Name = $appKey
45 |         $checkbox.Style = $sync.Form.Resources.AppEntryCheckboxStyle
46 |         $checkbox.Add_Checked({
47 |             Invoke-WPFSelectedAppsUpdate -type "Add" -checkbox $this
48 |             $borderElement = $this.Parent
49 |             $borderElement.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallSelectedColor")
50 |         })
51 | 
52 |         $checkbox.Add_Unchecked({
53 |             Invoke-WPFSelectedAppsUpdate -type "Remove" -checkbox $this
54 |             $borderElement = $this.Parent
55 |             $borderElement.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor")
56 |         })
57 | 
58 |         # Create the TextBlock for the application name
59 |         $appName = New-Object Windows.Controls.TextBlock
60 |         $appName.Style = $sync.Form.Resources.AppEntryNameStyle
61 |         $appName.Text = $Apps.$appKey.content
62 | 
63 |         # Add the name to the Checkbox
64 |         $checkBox.Content = $appName
65 | 
66 |         # Add accessibility properties to make the elements screen reader friendly
67 |         $checkBox.SetValue([Windows.Automation.AutomationProperties]::NameProperty, $Apps.$appKey.content)
68 |         $border.SetValue([Windows.Automation.AutomationProperties]::NameProperty, $Apps.$appKey.content)
69 | 
70 |         $border.Child = $checkBox
71 |         # Add the border to the corresponding Category
72 |         $TargetElement.Children.Add($border) | Out-Null
73 |         return $checkbox
74 |     }
75 | 


--------------------------------------------------------------------------------
/functions/private/Initialize-InstallCategoryAppList.ps1:
--------------------------------------------------------------------------------
 1 | function Initialize-InstallCategoryAppList {
 2 |     <#
 3 |         .SYNOPSIS
 4 |             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
 5 |             Iterates through all Categories and Apps and adds them to the UI
 6 |             Used to as part of the Install Tab UI generation
 7 |         .PARAMETER TargetElement
 8 |             The Element into which the Categories and Apps should be placed
 9 |         .PARAMETER Apps
10 |             The Hashtable of Apps to be added to the UI
11 |             The Categories are also extracted from the Apps Hashtable
12 | 
13 |     #>
14 |         param(
15 |             $TargetElement,
16 |             $Apps
17 |         )
18 |         function Add-Category {
19 |             param(
20 |                 [string]$Category,
21 |                 [Windows.Controls.ItemsControl]$TargetElement
22 |             )
23 | 
24 |             $toggleButton = New-Object Windows.Controls.Label
25 |             $toggleButton.Content = "$Category"
26 |             $toggleButton.Tag = "CategoryToggleButton"
27 |             $sync.$Category = $Category
28 | 
29 |             $null = $TargetElement.Items.Add($toggleButton)
30 |         }
31 | 
32 | 
33 |         # Pre-group apps by category
34 |         $appsByCategory = @{}
35 |         foreach ($appKey in $Apps.Keys) {
36 |             $category = $Apps.$appKey.Category
37 |             if (-not $appsByCategory.ContainsKey($category)) {
38 |                 $appsByCategory[$category] = @()
39 |             }
40 |             $appsByCategory[$category] += $appKey
41 |         }
42 |         foreach ($category in $($appsByCategory.Keys | Sort-Object)) {
43 |             Add-Category -Category $category -TargetElement $TargetElement
44 |             $wrapPanel = New-Object Windows.Controls.WrapPanel
45 |             $wrapPanel.Orientation = "Horizontal"
46 |             $wrapPanel.HorizontalAlignment = "Stretch"
47 |             $wrapPanel.VerticalAlignment = "Center"
48 |             $wrapPanel.Margin = New-Object Windows.Thickness(0, 0, 0, 20)
49 |             $wrapPanel.Visibility = [Windows.Visibility]::Visible
50 |             $wrapPanel.Tag = "CategoryWrapPanel_$category"
51 |             $null = $TargetElement.Items.Add($wrapPanel)
52 |             $appsByCategory[$category] |Sort-Object | ForEach-Object {
53 |                 $sync.$_ =  $(Initialize-InstallAppEntry -TargetElement $wrapPanel -AppKey $_)
54 |             }
55 |         }
56 |     }
57 | 


--------------------------------------------------------------------------------
/functions/private/Install-WinUtilChoco.ps1:
--------------------------------------------------------------------------------
 1 | function Install-WinUtilChoco {
 2 | 
 3 |     <#
 4 | 
 5 |     .SYNOPSIS
 6 |         Installs Chocolatey if it is not already installed
 7 | 
 8 |     #>
 9 | 
10 |     try {
11 |         Write-Host "Checking if Chocolatey is Installed..."
12 | 
13 |         if((Test-WinUtilPackageManager -choco) -eq "installed") {
14 |             return
15 |         }
16 |         # Install logic taken from https://chocolatey.org/install#individual
17 |         Write-Host "Seems Chocolatey is not installed, installing now."
18 |         Set-ExecutionPolicy Bypass -Scope Process -Force;
19 |         [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;
20 |         Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
21 | 
22 |     } catch {
23 |         Write-Host "===========================================" -Foregroundcolor Red
24 |         Write-Host "--     Chocolatey failed to install     ---" -Foregroundcolor Red
25 |         Write-Host "===========================================" -Foregroundcolor Red
26 |     }
27 | 
28 | }
29 | 


--------------------------------------------------------------------------------
/functions/private/Install-WinUtilWinget.ps1:
--------------------------------------------------------------------------------
 1 | function Install-WinUtilWinget {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Installs Winget if it is not already installed.
 6 | 
 7 |     .DESCRIPTION
 8 |         This function will download the latest version of Winget and install it. If Winget is already installed, it will do nothing.
 9 |     #>
10 |     $isWingetInstalled = Test-WinUtilPackageManager -winget
11 | 
12 |     try {
13 |         if ($isWingetInstalled -eq "installed") {
14 |             Write-Host "`nWinget is already installed.`r" -ForegroundColor Green
15 |             return
16 |         } elseif ($isWingetInstalled -eq "outdated") {
17 |             Write-Host "`nWinget is Outdated. Continuing with install.`r" -ForegroundColor Yellow
18 |         } else {
19 |             Write-Host "`nWinget is not Installed. Continuing with install.`r" -ForegroundColor Red
20 |         }
21 | 
22 | 
23 |         # Gets the computer's information
24 |         if ($null -eq $sync.ComputerInfo) {
25 |             $ComputerInfo = Get-ComputerInfo -ErrorAction Stop
26 |         } else {
27 |             $ComputerInfo = $sync.ComputerInfo
28 |         }
29 | 
30 |         if (($ComputerInfo.WindowsVersion) -lt "1809") {
31 |             # Checks if Windows Version is too old for Winget
32 |             Write-Host "Winget is not supported on this version of Windows (Pre-1809)" -ForegroundColor Red
33 |             return
34 |         }
35 | 
36 |         Write-Host "Attempting to install/update Winget`r"
37 |         try {
38 |             $wingetCmd = Get-Command winget -ErrorAction Stop
39 |             Write-Information "Attempting to update WinGet using WinGet..."
40 |             $result = Start-Process -FilePath "`"$($wingetCmd.Source)`"" -ArgumentList "install -e --accept-source-agreements --accept-package-agreements Microsoft.AppInstaller" -Wait -NoNewWindow -PassThru
41 |             if ($result.ExitCode -ne 0) {
42 |                 throw "WinGet update failed with exit code: $($result.ExitCode)"
43 |             }
44 |             Write-Output "Refreshing Environment Variables...`n"
45 |             $ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
46 |             return
47 |         } catch {
48 |             Write-Information "WinGet not found or update failed. Attempting to install from Microsoft Store..."
49 |         }
50 |         try {
51 |             Write-Host "Attempting to repair WinGet using Repair-WinGetPackageManager..." -ForegroundColor Yellow
52 | 
53 |             # Check if Windows version supports Repair-WinGetPackageManager (24H2 and above)
54 |             if ([System.Environment]::OSVersion.Version.Build -ge 26100) {
55 |                 Repair-WinGetPackageManager -Force -Latest -Verbose
56 |                 # Verify if repair was successful
57 |                 $wingetCmd = Get-Command winget -ErrorAction Stop
58 |                 Write-Host "WinGet repair successful!" -ForegroundColor Green
59 |             } else {
60 |                 Write-Host "Repair-WinGetPackageManager is only available on Windows 24H2 and above. Your version doesn't support this method." -ForegroundColor Yellow
61 |                 throw "Windows version not supported for repair method"
62 |             }
63 | 
64 |             Write-Output "Refreshing Environment Variables...`n"
65 |             $ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
66 |             return
67 | 
68 |         } catch {
69 |             Write-Error "All installation methods failed. Unable to install WinGet."
70 |             throw
71 |         }
72 |     } catch {
73 |         Write-Error "An error occurred during WinGet installation: $_"
74 |         throw
75 |     }
76 | }
77 | 


--------------------------------------------------------------------------------
/functions/private/Invoke-WinUtilCurrentSystem.ps1:
--------------------------------------------------------------------------------
  1 | Function Invoke-WinUtilCurrentSystem {
  2 | 
  3 |     <#
  4 | 
  5 |     .SYNOPSIS
  6 |         Checks to see what tweaks have already been applied and what programs are installed, and checks the according boxes
  7 | 
  8 |     .EXAMPLE
  9 |         Get-WinUtilCheckBoxes "WPFInstall"
 10 | 
 11 |     #>
 12 | 
 13 |     param(
 14 |         $CheckBox
 15 |     )
 16 |     if ($CheckBox -eq "choco") {
 17 |         $apps = (choco list | Select-String -Pattern "^\S+").Matches.Value
 18 |         $filter = Get-WinUtilVariables -Type Checkbox | Where-Object {$psitem -like "WPFInstall*"}
 19 |         $sync.GetEnumerator() | Where-Object {$psitem.Key -in $filter} | ForEach-Object {
 20 |             $dependencies = @($sync.configs.applications.$($psitem.Key).choco -split ";")
 21 |             if ($dependencies -in $apps) {
 22 |                 Write-Output $psitem.name
 23 |             }
 24 |         }
 25 |     }
 26 | 
 27 |     if ($checkbox -eq "winget") {
 28 | 
 29 |         $originalEncoding = [Console]::OutputEncoding
 30 |         [Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
 31 |         $Sync.InstalledPrograms = winget list -s winget | Select-Object -skip 3 | ConvertFrom-String -PropertyNames "Name", "Id", "Version", "Available" -Delimiter '\s{2,}'
 32 |         [Console]::OutputEncoding = $originalEncoding
 33 | 
 34 |         $filter = Get-WinUtilVariables -Type Checkbox | Where-Object {$psitem -like "WPFInstall*"}
 35 |         $sync.GetEnumerator() | Where-Object {$psitem.Key -in $filter} | ForEach-Object {
 36 |             $dependencies = @($sync.configs.applications.$($psitem.Key).winget -split ";")
 37 | 
 38 |             if ($dependencies[-1] -in $sync.InstalledPrograms.Id) {
 39 |                 Write-Output $psitem.name
 40 |             }
 41 |         }
 42 |     }
 43 | 
 44 |     if($CheckBox -eq "tweaks") {
 45 | 
 46 |         if(!(Test-Path 'HKU:\')) {$null = (New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS)}
 47 |         $ScheduledTasks = Get-ScheduledTask
 48 | 
 49 |         $sync.configs.tweaks | Get-Member -MemberType NoteProperty | ForEach-Object {
 50 | 
 51 |             $Config = $psitem.Name
 52 |             #WPFEssTweaksTele
 53 |             $registryKeys = $sync.configs.tweaks.$Config.registry
 54 |             $scheduledtaskKeys = $sync.configs.tweaks.$Config.scheduledtask
 55 |             $serviceKeys = $sync.configs.tweaks.$Config.service
 56 | 
 57 |             if($registryKeys -or $scheduledtaskKeys -or $serviceKeys) {
 58 |                 $Values = @()
 59 | 
 60 | 
 61 |                 Foreach ($tweaks in $registryKeys) {
 62 |                     Foreach($tweak in $tweaks) {
 63 | 
 64 |                         if(test-path $tweak.Path) {
 65 |                             $actualValue = Get-ItemProperty -Name $tweak.Name -Path $tweak.Path -ErrorAction SilentlyContinue | Select-Object -ExpandProperty $($tweak.Name)
 66 |                             $expectedValue = $tweak.Value
 67 |                             if ($expectedValue -notlike $actualValue) {
 68 |                                 $values += $False
 69 |                             }
 70 |                         } else {
 71 |                             $values += $False
 72 |                         }
 73 |                     }
 74 |                 }
 75 | 
 76 |                 Foreach ($tweaks in $scheduledtaskKeys) {
 77 |                     Foreach($tweak in $tweaks) {
 78 |                         $task = $ScheduledTasks | Where-Object {$($psitem.TaskPath + $psitem.TaskName) -like "\$($tweak.name)"}
 79 | 
 80 |                         if($task) {
 81 |                             $actualValue = $task.State
 82 |                             $expectedValue = $tweak.State
 83 |                             if ($expectedValue -ne $actualValue) {
 84 |                                 $values += $False
 85 |                             }
 86 |                         }
 87 |                     }
 88 |                 }
 89 | 
 90 |                 Foreach ($tweaks in $serviceKeys) {
 91 |                     Foreach($tweak in $tweaks) {
 92 |                         $Service = Get-Service -Name $tweak.Name
 93 | 
 94 |                         if($Service) {
 95 |                             $actualValue = $Service.StartType
 96 |                             $expectedValue = $tweak.StartupType
 97 |                             if ($expectedValue -ne $actualValue) {
 98 |                                 $values += $False
 99 |                             }
100 |                         }
101 |                     }
102 |                 }
103 | 
104 |                 if($values -notcontains $false) {
105 |                     Write-Output $Config
106 |                 }
107 |             }
108 |         }
109 |     }
110 | }
111 | 


--------------------------------------------------------------------------------
/functions/private/Invoke-WinUtilExplorerUpdate.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WinUtilExplorerUpdate {
 2 |     <#
 3 |     .SYNOPSIS
 4 |         Refreshes the Windows Explorer
 5 |     #>
 6 | 
 7 |     param (
 8 |         [string]$action = "refresh"
 9 |     )
10 | 
11 |     if ($action -eq "refresh") {
12 |         Invoke-WPFRunspace -DebugPreference $DebugPreference -ScriptBlock {
13 |             # Send the WM_SETTINGCHANGE message to all windows
14 |             Add-Type -TypeDefinition @"
15 | using System;
16 | using System.Runtime.InteropServices;
17 | public class Win32 {
18 |     [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
19 |     public static extern IntPtr SendMessageTimeout(
20 |         IntPtr hWnd,
21 |         uint Msg,
22 |         IntPtr wParam,
23 |         string lParam,
24 |         uint fuFlags,
25 |         uint uTimeout,
26 |         out IntPtr lpdwResult);
27 | }
28 | "@
29 | 
30 |             $HWND_BROADCAST = [IntPtr]0xffff
31 |             $WM_SETTINGCHANGE = 0x1A
32 |             $SMTO_ABORTIFHUNG = 0x2
33 |             $timeout = 100
34 | 
35 |             # Send the broadcast message to all windows
36 |             [Win32]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [IntPtr]::Zero, "ImmersiveColorSet", $SMTO_ABORTIFHUNG, $timeout, [ref]([IntPtr]::Zero))
37 |         }
38 |     } elseif ($action -eq "restart") {
39 |         # Restart the Windows Explorer
40 |         taskkill.exe /F /IM "explorer.exe"
41 |         Start-Process "explorer.exe"
42 |     }
43 | }
44 | 


--------------------------------------------------------------------------------
/functions/private/Invoke-WinUtilFeatureInstall.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WinUtilFeatureInstall {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Converts all the values from the tweaks.json and routes them to the appropriate function
 6 | 
 7 |     #>
 8 | 
 9 |     param(
10 |         $CheckBox
11 |     )
12 | 
13 |     $x = 0
14 | 
15 |     $CheckBox | ForEach-Object {
16 |         if($sync.configs.feature.$psitem.feature) {
17 |             Foreach( $feature in $sync.configs.feature.$psitem.feature ) {
18 |                 try {
19 |                     Write-Host "Installing $feature"
20 |                     Enable-WindowsOptionalFeature -Online -FeatureName $feature -All -NoRestart
21 |                 } catch {
22 |                     if ($psitem.Exception.Message -like "*requires elevation*") {
23 |                         Write-Warning "Unable to Install $feature due to permissions. Are you running as admin?"
24 |                         $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" })
25 |                     } else {
26 | 
27 |                         Write-Warning "Unable to Install $feature due to unhandled exception"
28 |                         Write-Warning $psitem.Exception.StackTrace
29 |                     }
30 |                 }
31 |             }
32 |         }
33 |         if($sync.configs.feature.$psitem.InvokeScript) {
34 |             Foreach( $script in $sync.configs.feature.$psitem.InvokeScript ) {
35 |                 try {
36 |                     $Scriptblock = [scriptblock]::Create($script)
37 | 
38 |                     Write-Host "Running Script for $psitem"
39 |                     Invoke-Command $scriptblock -ErrorAction stop
40 |                 } catch {
41 |                     if ($psitem.Exception.Message -like "*requires elevation*") {
42 |                         Write-Warning "Unable to Install $feature due to permissions. Are you running as admin?"
43 |                         $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" })
44 |                     } else {
45 |                         $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" })
46 |                         Write-Warning "Unable to Install $feature due to unhandled exception"
47 |                         Write-Warning $psitem.Exception.StackTrace
48 |                     }
49 |                 }
50 |             }
51 |         }
52 |         $X++
53 |         $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($x/$CheckBox.Count) })
54 |     }
55 | }
56 | 


--------------------------------------------------------------------------------
/functions/private/Invoke-WinUtilGPU.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WinUtilGPU {
 2 |     $gpuInfo = Get-CimInstance Win32_VideoController
 3 | 
 4 |     # GPUs to blacklist from using Demanding Theming
 5 |     $lowPowerGPUs = (
 6 |         "*NVIDIA GeForce*M*",
 7 |         "*NVIDIA GeForce*Laptop*",
 8 |         "*NVIDIA GeForce*GT*",
 9 |         "*AMD Radeon(TM)*",
10 |         "*Intel(R) HD Graphics*",
11 |         "*UHD*"
12 | 
13 |     )
14 | 
15 |     foreach ($gpu in $gpuInfo) {
16 |         foreach ($gpuPattern in $lowPowerGPUs) {
17 |             if ($gpu.Name -like $gpuPattern) {
18 |                 return $false
19 |             }
20 |         }
21 |     }
22 |     return $true
23 | }
24 | 


--------------------------------------------------------------------------------
/functions/private/Invoke-WinUtilSSHServer.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WinUtilSSHServer {
 2 |     <#
 3 |     .SYNOPSIS
 4 |         Enables OpenSSH server to remote into your windows device
 5 |     #>
 6 | 
 7 |     # Get the latest version of OpenSSH Server
 8 |     $FeatureName = Get-WindowsCapability -Online | Where-Object { $_.Name -like "OpenSSH.Server*" }
 9 | 
10 |     # Install the OpenSSH Server feature if not already installed
11 |     if ($FeatureName.State -ne "Installed") {
12 |         Write-Host "Enabling OpenSSH Server"
13 |         Add-WindowsCapability -Online -Name $FeatureName.Name
14 |     }
15 | 
16 |     # Sets up the OpenSSH Server service
17 |     Write-Host "Starting the services"
18 |     Start-Service -Name sshd
19 |     Set-Service -Name sshd -StartupType Automatic
20 | 
21 |     # Sets up the ssh-agent service
22 |     Start-Service 'ssh-agent'
23 |     Set-Service -Name 'ssh-agent' -StartupType 'Automatic'
24 | 
25 |     # Confirm the required services are running
26 |     $SSHDaemonService = Get-Service -Name sshd
27 |     $SSHAgentService = Get-Service -Name 'ssh-agent'
28 | 
29 |     if ($SSHDaemonService.Status -eq 'Running') {
30 |         Write-Host "OpenSSH Server is running."
31 |     } else {
32 |         try {
33 |             Write-Host "OpenSSH Server is not running. Attempting to restart..."
34 |             Restart-Service -Name sshd -Force
35 |             Write-Host "OpenSSH Server has been restarted successfully."
36 |         } catch {
37 |             Write-Host "Failed to restart OpenSSH Server: $_"
38 |         }
39 |     }
40 |     if ($SSHAgentService.Status -eq 'Running') {
41 |         Write-Host "ssh-agent is running."
42 |     } else {
43 |         try {
44 |             Write-Host "ssh-agent is not running. Attempting to restart..."
45 |             Restart-Service -Name sshd -Force
46 |             Write-Host "ssh-agent has been restarted successfully."
47 |         } catch {
48 |             Write-Host "Failed to restart ssh-agent : $_"
49 |         }
50 |     }
51 | 
52 |     #Adding Firewall rule for port 22
53 |     Write-Host "Setting up firewall rules"
54 |     $firewallRule = (Get-NetFirewallRule -Name 'sshd').Enabled
55 |     if ($firewallRule) {
56 |         Write-Host "Firewall rule for OpenSSH Server (sshd) already exists."
57 |     } else {
58 |         New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
59 |         Write-Host "Firewall rule for OpenSSH Server created and enabled."
60 |     }
61 | 
62 |     # Check for the authorized_keys file
63 |     $sshFolderPath = "$env:HOMEDRIVE\$env:HOMEPATH\.ssh"
64 |     $authorizedKeysPath = "$sshFolderPath\authorized_keys"
65 | 
66 |     if (-not (Test-Path -Path $sshFolderPath)) {
67 |         Write-Host "Creating ssh directory..."
68 |         New-Item -Path $sshFolderPath -ItemType Directory -Force
69 |     }
70 | 
71 |     if (-not (Test-Path -Path $authorizedKeysPath)) {
72 |         Write-Host "Creating authorized_keys file..."
73 |         New-Item -Path $authorizedKeysPath -ItemType File -Force
74 |         Write-Host "authorized_keys file created at $authorizedKeysPath."
75 |     } else {
76 |         Write-Host "authorized_keys file already exists at $authorizedKeysPath."
77 |     }
78 |     Write-Host "OpenSSH server was successfully enabled."
79 |     Write-Host "The config file can be located at C:\ProgramData\ssh\sshd_config "
80 |     Write-Host "Add your public keys to this file -> $authorizedKeysPath"
81 | }
82 | 


--------------------------------------------------------------------------------
/functions/private/Invoke-WinUtilScript.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WinUtilScript {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Invokes the provided scriptblock. Intended for things that can't be handled with the other functions.
 6 | 
 7 |     .PARAMETER Name
 8 |         The name of the scriptblock being invoked
 9 | 
10 |     .PARAMETER scriptblock
11 |         The scriptblock to be invoked
12 | 
13 |     .EXAMPLE
14 |         $Scriptblock = [scriptblock]::Create({"Write-output 'Hello World'"})
15 |         Invoke-WinUtilScript -ScriptBlock $scriptblock -Name "Hello World"
16 | 
17 |     #>
18 |     param (
19 |         $Name,
20 |         [scriptblock]$scriptblock
21 |     )
22 | 
23 |     try {
24 |         Write-Host "Running Script for $name"
25 |         Invoke-Command $scriptblock -ErrorAction Stop
26 |     } catch [System.Management.Automation.CommandNotFoundException] {
27 |         Write-Warning "The specified command was not found."
28 |         Write-Warning $PSItem.Exception.message
29 |     } catch [System.Management.Automation.RuntimeException] {
30 |         Write-Warning "A runtime exception occurred."
31 |         Write-Warning $PSItem.Exception.message
32 |     } catch [System.Security.SecurityException] {
33 |         Write-Warning "A security exception occurred."
34 |         Write-Warning $PSItem.Exception.message
35 |     } catch [System.UnauthorizedAccessException] {
36 |         Write-Warning "Access denied. You do not have permission to perform this operation."
37 |         Write-Warning $PSItem.Exception.message
38 |     } catch {
39 |         # Generic catch block to handle any other type of exception
40 |         Write-Warning "Unable to run script for $name due to unhandled exception"
41 |         Write-Warning $psitem.Exception.StackTrace
42 |     }
43 | 
44 | }
45 | 


--------------------------------------------------------------------------------
/functions/private/Invoke-WinUtilSponsors.ps1:
--------------------------------------------------------------------------------
 1 | Function Invoke-WinUtilSponsors {
 2 |     <#
 3 |     .SYNOPSIS
 4 |         Lists Sponsors from ChrisTitusTech
 5 |     .DESCRIPTION
 6 |         Lists Sponsors from ChrisTitusTech
 7 |     .EXAMPLE
 8 |         Invoke-WinUtilSponsors
 9 |     .NOTES
10 |         This function is used to list sponsors from ChrisTitusTech
11 |     #>
12 |     try {
13 |         # Define the URL and headers
14 |         $url = "https://github.com/sponsors/ChrisTitusTech"
15 |         $headers = @{
16 |             "User-Agent" = "Chrome/58.0.3029.110"
17 |         }
18 | 
19 |         # Fetch the webpage content
20 |         try {
21 |             $html = Invoke-RestMethod -Uri $url -Headers $headers
22 |         } catch {
23 |             Write-Output $_.Exception.Message
24 |             exit
25 |         }
26 | 
27 |         # Use regex to extract the content between "Current sponsors" and "Past sponsors"
28 |         $currentSponsorsPattern = '(?s)(?<=Current sponsors).*?(?=Past sponsors)'
29 |         $currentSponsorsHtml = [regex]::Match($html, $currentSponsorsPattern).Value
30 | 
31 |         # Use regex to extract the sponsor usernames from the alt attributes in the "Current Sponsors" section
32 |         $sponsorPattern = '(?<=alt="@)[^"]+'
33 |         $sponsors = [regex]::Matches($currentSponsorsHtml, $sponsorPattern) | ForEach-Object { $_.Value }
34 | 
35 |         # Exclude "ChrisTitusTech" from the sponsors
36 |         $sponsors = $sponsors | Where-Object { $_ -ne "ChrisTitusTech" }
37 | 
38 |         # Return the sponsors
39 |         return $sponsors
40 |     } catch {
41 |         Write-Error "An error occurred while fetching or processing the sponsors: $_"
42 |         return $null
43 |     }
44 | }
45 | 


--------------------------------------------------------------------------------
/functions/private/Invoke-WinUtilTweaks.ps1:
--------------------------------------------------------------------------------
  1 | function Invoke-WinUtilTweaks {
  2 |     <#
  3 | 
  4 |     .SYNOPSIS
  5 |         Invokes the function associated with each provided checkbox
  6 | 
  7 |     .PARAMETER CheckBox
  8 |         The checkbox to invoke
  9 | 
 10 |     .PARAMETER undo
 11 |         Indicates whether to undo the operation contained in the checkbox
 12 | 
 13 |     .PARAMETER KeepServiceStartup
 14 |         Indicates whether to override the startup of a service with the one given from WinUtil,
 15 |         or to keep the startup of said service, if it was changed by the user, or another program, from its default value.
 16 |     #>
 17 | 
 18 |     param(
 19 |         $CheckBox,
 20 |         $undo = $false,
 21 |         $KeepServiceStartup = $true
 22 |     )
 23 | 
 24 |     if ($Checkbox -contains "Toggle") {
 25 |         $CheckBox = $sync.configs.tweaks.$CheckBox
 26 |     }
 27 | 
 28 |     Write-Debug "Tweaks: $($CheckBox)"
 29 |     if($undo) {
 30 |         $Values = @{
 31 |             Registry = "OriginalValue"
 32 |             ScheduledTask = "OriginalState"
 33 |             Service = "OriginalType"
 34 |             ScriptType = "UndoScript"
 35 |         }
 36 | 
 37 |     } else {
 38 |         $Values = @{
 39 |             Registry = "Value"
 40 |             ScheduledTask = "State"
 41 |             Service = "StartupType"
 42 |             OriginalService = "OriginalType"
 43 |             ScriptType = "InvokeScript"
 44 |         }
 45 |     }
 46 |     if($sync.configs.tweaks.$CheckBox.ScheduledTask) {
 47 |         $sync.configs.tweaks.$CheckBox.ScheduledTask | ForEach-Object {
 48 |             Write-Debug "$($psitem.Name) and state is $($psitem.$($values.ScheduledTask))"
 49 |             Set-WinUtilScheduledTask -Name $psitem.Name -State $psitem.$($values.ScheduledTask)
 50 |         }
 51 |     }
 52 |     if($sync.configs.tweaks.$CheckBox.service) {
 53 |         Write-Debug "KeepServiceStartup is $KeepServiceStartup"
 54 |         $sync.configs.tweaks.$CheckBox.service | ForEach-Object {
 55 |             $changeservice = $true
 56 | 
 57 |         # The check for !($undo) is required, without it the script will throw an error for accessing unavailable memeber, which's the 'OriginalService' Property
 58 |             if($KeepServiceStartup -AND !($undo)) {
 59 |                 try {
 60 |                     # Check if the service exists
 61 |                     $service = Get-Service -Name $psitem.Name -ErrorAction Stop
 62 |                     if(!($service.StartType.ToString() -eq $psitem.$($values.OriginalService))) {
 63 |                         Write-Debug "Service $($service.Name) was changed in the past to $($service.StartType.ToString()) from it's original type of $($psitem.$($values.OriginalService)), will not change it to $($psitem.$($values.service))"
 64 |                         $changeservice = $false
 65 |                     }
 66 |                 } catch [System.ServiceProcess.ServiceNotFoundException] {
 67 |                     Write-Warning "Service $($psitem.Name) was not found"
 68 |                 }
 69 |             }
 70 | 
 71 |             if($changeservice) {
 72 |                 Write-Debug "$($psitem.Name) and state is $($psitem.$($values.service))"
 73 |                 Set-WinUtilService -Name $psitem.Name -StartupType $psitem.$($values.Service)
 74 |             }
 75 |         }
 76 |     }
 77 |     if($sync.configs.tweaks.$CheckBox.registry) {
 78 |         $sync.configs.tweaks.$CheckBox.registry | ForEach-Object {
 79 |             Write-Debug "$($psitem.Name) and state is $($psitem.$($values.registry))"
 80 |             if (($psitem.Path -imatch "hku") -and !(Get-PSDrive -Name HKU -ErrorAction SilentlyContinue)) {
 81 |                 $null = (New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS)
 82 |                 if (Get-PSDrive -Name HKU -ErrorAction SilentlyContinue) {
 83 |                     Write-Debug "HKU drive created successfully"
 84 |                 } else {
 85 |                     Write-Debug "Failed to create HKU drive"
 86 |                 }
 87 |             }
 88 |             Set-WinUtilRegistry -Name $psitem.Name -Path $psitem.Path -Type $psitem.Type -Value $psitem.$($values.registry)
 89 |         }
 90 |     }
 91 |     if($sync.configs.tweaks.$CheckBox.$($values.ScriptType)) {
 92 |         $sync.configs.tweaks.$CheckBox.$($values.ScriptType) | ForEach-Object {
 93 |             Write-Debug "$($psitem) and state is $($psitem.$($values.ScriptType))"
 94 |             $Scriptblock = [scriptblock]::Create($psitem)
 95 |             Invoke-WinUtilScript -ScriptBlock $scriptblock -Name $CheckBox
 96 |         }
 97 |     }
 98 | 
 99 |     if(!$undo) {
100 |         if($sync.configs.tweaks.$CheckBox.appx) {
101 |             $sync.configs.tweaks.$CheckBox.appx | ForEach-Object {
102 |                 Write-Debug "UNDO $($psitem.Name)"
103 |                 Remove-WinUtilAPPX -Name $psitem
104 |             }
105 |         }
106 | 
107 |     }
108 | }
109 | 


--------------------------------------------------------------------------------
/functions/private/Remove-WinUtilAPPX.ps1:
--------------------------------------------------------------------------------
 1 | function Remove-WinUtilAPPX {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Removes all APPX packages that match the given name
 6 | 
 7 |     .PARAMETER Name
 8 |         The name of the APPX package to remove
 9 | 
10 |     .EXAMPLE
11 |         Remove-WinUtilAPPX -Name "Microsoft.Microsoft3DViewer"
12 | 
13 |     #>
14 |     param (
15 |         $Name
16 |     )
17 | 
18 |     try {
19 |         Write-Host "Removing $Name"
20 |         Get-AppxPackage "*$Name*" | Remove-AppxPackage -ErrorAction SilentlyContinue
21 |         Get-AppxProvisionedPackage -Online | Where-Object DisplayName -like "*$Name*" | Remove-AppxProvisionedPackage -Online -ErrorAction SilentlyContinue
22 |     } catch [System.Exception] {
23 |         if ($psitem.Exception.Message -like "*The requested operation requires elevation*") {
24 |             Write-Warning "Unable to uninstall $name due to a Security Exception"
25 |         } else {
26 |             Write-Warning "Unable to uninstall $name due to unhandled exception"
27 |             Write-Warning $psitem.Exception.StackTrace
28 |         }
29 |     } catch {
30 |         Write-Warning "Unable to uninstall $name due to unhandled exception"
31 |         Write-Warning $psitem.Exception.StackTrace
32 |     }
33 | }
34 | 


--------------------------------------------------------------------------------
/functions/private/Set-PackageManagerPreference.ps1:
--------------------------------------------------------------------------------
 1 | function Set-PackageManagerPreference {
 2 |     <#
 3 |     .SYNOPSIS
 4 |         Sets the currently selected package manager to global "ManagerPreference" in sync.
 5 |         Also persists preference across Winutil restarts via preference.ini.
 6 | 
 7 |         Reads from preference.ini if no argument sent.
 8 | 
 9 |     .PARAMETER preferedPackageManager
10 |         The PackageManager that was selected.
11 |     #>
12 |     param(
13 |         [Parameter(Position=0, Mandatory=$false)]
14 |         [PackageManagers]$preferedPackageManager
15 |     )
16 | 
17 |     $preferencePath = "$env:LOCALAPPDATA\winutil\preferences.ini"
18 |     $oldChocoPath = "$env:LOCALAPPDATA\winutil\preferChocolatey.ini"
19 | 
20 |     #Try loading from file if no argument given.
21 |     if ($null -eq $preferedPackageManager) {
22 |         # Backwards compat for preferChocolatey.ini
23 |         if (Test-Path -Path $oldChocoPath) {
24 |             $preferedPackageManager = [PackageManagers]::Choco
25 |             Remove-Item -Path $oldChocoPath
26 |         }
27 |         elseif (Test-Path -Path $preferencePath) {
28 |             $potential = Get-Content -Path $preferencePath -TotalCount 1
29 |             $preferedPackageManager = [PackageManagers]$potential
30 |         }
31 |         else {
32 |             Write-Debug "Creating new preference file, defaulting to winget."
33 |             $preferedPackageManager = [PackageManagers]::Winget
34 |         }
35 |     }
36 | 
37 |     $sync["ManagerPreference"] = [PackageManagers]::$preferedPackageManager
38 |     Write-Debug "Manager Preference changed to '$($sync["ManagerPreference"])'"
39 | 
40 | 
41 |     # Write preference to file to persist across restarts.
42 |     Out-File -FilePath $preferencePath -InputObject $sync["ManagerPreference"]
43 | }
44 | 


--------------------------------------------------------------------------------
/functions/private/Set-WinUtilDNS.ps1:
--------------------------------------------------------------------------------
 1 | function Set-WinUtilDNS {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Sets the DNS of all interfaces that are in the "Up" state. It will lookup the values from the DNS.Json file
 6 | 
 7 |     .PARAMETER DNSProvider
 8 |         The DNS provider to set the DNS server to
 9 | 
10 |     .EXAMPLE
11 |         Set-WinUtilDNS -DNSProvider "google"
12 | 
13 |     #>
14 |     param($DNSProvider)
15 |     if($DNSProvider -eq "Default") {return}
16 |     try {
17 |         $Adapters = Get-NetAdapter | Where-Object {$_.Status -eq "Up"}
18 |         Write-Host "Ensuring DNS is set to $DNSProvider on the following interfaces"
19 |         Write-Host $($Adapters | Out-String)
20 | 
21 |         Foreach ($Adapter in $Adapters) {
22 |             if($DNSProvider -eq "DHCP") {
23 |                 Set-DnsClientServerAddress -InterfaceIndex $Adapter.ifIndex -ResetServerAddresses
24 |             } else {
25 |                 Set-DnsClientServerAddress -InterfaceIndex $Adapter.ifIndex -ServerAddresses ("$($sync.configs.dns.$DNSProvider.Primary)", "$($sync.configs.dns.$DNSProvider.Secondary)")
26 |                 Set-DnsClientServerAddress -InterfaceIndex $Adapter.ifIndex -ServerAddresses ("$($sync.configs.dns.$DNSProvider.Primary6)", "$($sync.configs.dns.$DNSProvider.Secondary6)")
27 |             }
28 |         }
29 |     } catch {
30 |         Write-Warning "Unable to set DNS Provider due to an unhandled exception"
31 |         Write-Warning $psitem.Exception.StackTrace
32 |     }
33 | }
34 | 


--------------------------------------------------------------------------------
/functions/private/Set-WinUtilProgressbar.ps1:
--------------------------------------------------------------------------------
 1 | function Set-WinUtilProgressbar{
 2 |     <#
 3 |     .SYNOPSIS
 4 |         This function is used to Update the Progress Bar displayed in the winutil GUI.
 5 |         It will be automatically hidden if the user clicks something and no process is running
 6 |     .PARAMETER Label
 7 |         The Text to be overlayed onto the Progress Bar
 8 |     .PARAMETER PERCENT
 9 |         The percentage of the Progress Bar that should be filled (0-100)
10 |     #>
11 |     param(
12 |         [string]$Label,
13 |         [ValidateRange(0,100)]
14 |         [int]$Percent
15 |     )
16 | 
17 |     $sync.form.Dispatcher.Invoke([action]{$sync.progressBarTextBlock.Text = $label})
18 |     $sync.form.Dispatcher.Invoke([action]{$sync.progressBarTextBlock.ToolTip = $label})
19 |     if ($percent -lt 5 ) {
20 |         $percent = 5 # Ensure the progress bar is not empty, as it looks weird
21 |     }
22 |     $sync.form.Dispatcher.Invoke([action]{ $sync.ProgressBar.Value = $percent})
23 | 
24 | }
25 | 


--------------------------------------------------------------------------------
/functions/private/Set-WinUtilRegistry.ps1:
--------------------------------------------------------------------------------
 1 | function Set-WinUtilRegistry {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Modifies the registry based on the given inputs
 6 | 
 7 |     .PARAMETER Name
 8 |         The name of the key to modify
 9 | 
10 |     .PARAMETER Path
11 |         The path to the key
12 | 
13 |     .PARAMETER Type
14 |         The type of value to set the key to
15 | 
16 |     .PARAMETER Value
17 |         The value to set the key to
18 | 
19 |     .EXAMPLE
20 |         Set-WinUtilRegistry -Name "PublishUserActivities" -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Type "DWord" -Value "0"
21 | 
22 |     #>
23 |     param (
24 |         $Name,
25 |         $Path,
26 |         $Type,
27 |         $Value
28 |     )
29 | 
30 |     try {
31 |         if(!(Test-Path 'HKU:\')) {New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS}
32 | 
33 |         If (!(Test-Path $Path)) {
34 |             Write-Host "$Path was not found, Creating..."
35 |             New-Item -Path $Path -Force -ErrorAction Stop | Out-Null
36 |         }
37 | 
38 |         if ($Value -ne "<RemoveEntry>") {
39 |             Write-Host "Set $Path\$Name to $Value"
40 |             Set-ItemProperty -Path $Path -Name $Name -Type $Type -Value $Value -Force -ErrorAction Stop | Out-Null
41 |         }
42 |         else{
43 |             Write-Host "Remove $Path\$Name"
44 |             Remove-ItemProperty -Path $Path -Name $Name -Force -ErrorAction Stop | Out-Null
45 |         }
46 |     } catch [System.Security.SecurityException] {
47 |         Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception"
48 |     } catch [System.Management.Automation.ItemNotFoundException] {
49 |         Write-Warning $psitem.Exception.ErrorRecord
50 |     } catch [System.UnauthorizedAccessException] {
51 |        Write-Warning $psitem.Exception.Message
52 |     } catch {
53 |         Write-Warning "Unable to set $Name due to unhandled exception"
54 |         Write-Warning $psitem.Exception.StackTrace
55 |     }
56 | }
57 | 


--------------------------------------------------------------------------------
/functions/private/Set-WinUtilScheduledTask.ps1:
--------------------------------------------------------------------------------
 1 | function Set-WinUtilScheduledTask {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Enables/Disables the provided Scheduled Task
 6 | 
 7 |     .PARAMETER Name
 8 |         The path to the Scheduled Task
 9 | 
10 |     .PARAMETER State
11 |         The State to set the Task to
12 | 
13 |     .EXAMPLE
14 |         Set-WinUtilScheduledTask -Name "Microsoft\Windows\Application Experience\Microsoft Compatibility Appraiser" -State "Disabled"
15 | 
16 |     #>
17 |     param (
18 |         $Name,
19 |         $State
20 |     )
21 | 
22 |     try {
23 |         if($State -eq "Disabled") {
24 |             Write-Host "Disabling Scheduled Task $Name"
25 |             Disable-ScheduledTask -TaskName $Name -ErrorAction Stop
26 |         }
27 |         if($State -eq "Enabled") {
28 |             Write-Host "Enabling Scheduled Task $Name"
29 |             Enable-ScheduledTask -TaskName $Name -ErrorAction Stop
30 |         }
31 |     } catch [System.Exception] {
32 |         if($psitem.Exception.Message -like "*The system cannot find the file specified*") {
33 |             Write-Warning "Scheduled Task $name was not Found"
34 |         } else {
35 |             Write-Warning "Unable to set $Name due to unhandled exception"
36 |             Write-Warning $psitem.Exception.Message
37 |         }
38 |     } catch {
39 |         Write-Warning "Unable to run script for $name due to unhandled exception"
40 |         Write-Warning $psitem.Exception.StackTrace
41 |     }
42 | }
43 | 


--------------------------------------------------------------------------------
/functions/private/Set-WinUtilService.ps1:
--------------------------------------------------------------------------------
 1 | Function Set-WinUtilService {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Changes the startup type of the given service
 6 | 
 7 |     .PARAMETER Name
 8 |         The name of the service to modify
 9 | 
10 |     .PARAMETER StartupType
11 |         The startup type to set the service to
12 | 
13 |     .EXAMPLE
14 |         Set-WinUtilService -Name "HomeGroupListener" -StartupType "Manual"
15 | 
16 |     #>
17 |     param (
18 |         $Name,
19 |         $StartupType
20 |     )
21 |     try {
22 |         Write-Host "Setting Service $Name to $StartupType"
23 | 
24 |         # Check if the service exists
25 |         $service = Get-Service -Name $Name -ErrorAction Stop
26 | 
27 |         # Service exists, proceed with changing properties
28 |         $service | Set-Service -StartupType $StartupType -ErrorAction Stop
29 |     } catch [System.ServiceProcess.ServiceNotFoundException] {
30 |         Write-Warning "Service $Name was not found"
31 |     } catch {
32 |         Write-Warning "Unable to set $Name due to unhandled exception"
33 |         Write-Warning $_.Exception.Message
34 |     }
35 | 
36 | }
37 | 


--------------------------------------------------------------------------------
/functions/private/Set-WinUtilTaskbarItem.ps1:
--------------------------------------------------------------------------------
 1 | function Set-WinUtilTaskbaritem {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Modifies the Taskbaritem of the WPF Form
 6 | 
 7 |     .PARAMETER value
 8 |         Value can be between 0 and 1, 0 being no progress done yet and 1 being fully completed
 9 |         Value does not affect item without setting the state to 'Normal', 'Error' or 'Paused'
10 |         Set-WinUtilTaskbaritem -value 0.5
11 | 
12 |     .PARAMETER state
13 |         State can be 'None' > No progress, 'Indeterminate' > inf. loading gray, 'Normal' > Gray, 'Error' > Red, 'Paused' > Yellow
14 |         no value needed:
15 |         - Set-WinUtilTaskbaritem -state "None"
16 |         - Set-WinUtilTaskbaritem -state "Indeterminate"
17 |         value needed:
18 |         - Set-WinUtilTaskbaritem -state "Error"
19 |         - Set-WinUtilTaskbaritem -state "Normal"
20 |         - Set-WinUtilTaskbaritem -state "Paused"
21 | 
22 |     .PARAMETER overlay
23 |         Overlay icon to display on the taskbar item, there are the presets 'None', 'logo' and 'checkmark' or you can specify a path/link to an image file.
24 |         CTT logo preset:
25 |         - Set-WinUtilTaskbaritem -overlay "logo"
26 |         Checkmark preset:
27 |         - Set-WinUtilTaskbaritem -overlay "checkmark"
28 |         Warning preset:
29 |         - Set-WinUtilTaskbaritem -overlay "warning"
30 |         No overlay:
31 |         - Set-WinUtilTaskbaritem -overlay "None"
32 |         Custom icon (needs to be supported by WPF):
33 |         - Set-WinUtilTaskbaritem -overlay "C:\path\to\icon.png"
34 | 
35 |     .PARAMETER description
36 |         Description to display on the taskbar item preview
37 |         Set-WinUtilTaskbaritem -description "This is a description"
38 |     #>
39 |     param (
40 |         [string]$state,
41 |         [double]$value,
42 |         [string]$overlay,
43 |         [string]$description
44 |     )
45 | 
46 |     if ($value) {
47 |         $sync["Form"].taskbarItemInfo.ProgressValue = $value
48 |     }
49 | 
50 |     if ($state) {
51 |         switch ($state) {
52 |             'None' { $sync["Form"].taskbarItemInfo.ProgressState = "None" }
53 |             'Indeterminate' { $sync["Form"].taskbarItemInfo.ProgressState = "Indeterminate" }
54 |             'Normal' { $sync["Form"].taskbarItemInfo.ProgressState = "Normal" }
55 |             'Error' { $sync["Form"].taskbarItemInfo.ProgressState = "Error" }
56 |             'Paused' { $sync["Form"].taskbarItemInfo.ProgressState = "Paused" }
57 |             default { throw "[Set-WinUtilTaskbarItem] Invalid state" }
58 |         }
59 |     }
60 | 
61 |     if ($overlay) {
62 |         switch ($overlay) {
63 |             'logo' {
64 |                 $sync["Form"].taskbarItemInfo.Overlay = $sync["logorender"]
65 |             }
66 |             'checkmark' {
67 |                 $sync["Form"].taskbarItemInfo.Overlay = $sync["checkmarkrender"]
68 |             }
69 |             'warning' {
70 |                 $sync["Form"].taskbarItemInfo.Overlay = $sync["warningrender"]
71 |             }
72 |             'None' {
73 |                 $sync["Form"].taskbarItemInfo.Overlay = $null
74 |             }
75 |             default {
76 |                 if (Test-Path $overlay) {
77 |                     $sync["Form"].taskbarItemInfo.Overlay = $overlay
78 |                 }
79 |             }
80 |         }
81 |     }
82 | 
83 |     if ($description) {
84 |         $sync["Form"].taskbarItemInfo.Description = $description
85 |     }
86 | }
87 | 


--------------------------------------------------------------------------------
/functions/private/Show-WPFInstallAppBusy.ps1:
--------------------------------------------------------------------------------
 1 | function Show-WPFInstallAppBusy {
 2 |     <#
 3 |     .SYNOPSIS
 4 |         Displays a busy overlay in the install app area of the WPF form.
 5 |         This is used to indicate that an install or uninstall is in progress.
 6 |         Dynamically updates the size of the overlay based on the app area on each invocation.
 7 |     .PARAMETER text
 8 |         The text to display in the busy overlay. Defaults to "Installing apps...".
 9 |     #>
10 |     param (
11 |         $text = "Installing apps..."
12 |     )
13 |     $sync.form.Dispatcher.Invoke([action]{
14 |         $sync.InstallAppAreaOverlay.Visibility = [Windows.Visibility]::Visible
15 |         $sync.InstallAppAreaOverlay.Width = $($sync.InstallAppAreaScrollViewer.ActualWidth * 0.4)
16 |         $sync.InstallAppAreaOverlay.Height = $($sync.InstallAppAreaScrollViewer.ActualWidth * 0.4)
17 |         $sync.InstallAppAreaOverlayText.Text = $text
18 |         $sync.InstallAppAreaBorder.IsEnabled = $false
19 |         $sync.InstallAppAreaScrollViewer.Effect.Radius = 5
20 |         })
21 |     }
22 | 


--------------------------------------------------------------------------------
/functions/private/Update-WinUtilProgramWinget.ps1:
--------------------------------------------------------------------------------
 1 | Function Update-WinUtilProgramWinget {
 2 | 
 3 |     <#
 4 | 
 5 |     .SYNOPSIS
 6 |         This will update all programs using Winget
 7 | 
 8 |     #>
 9 | 
10 |     [ScriptBlock]$wingetinstall = {
11 | 
12 |         $host.ui.RawUI.WindowTitle = """Winget Install"""
13 | 
14 |         Start-Transcript "$logdir\winget-update_$dateTime.log" -Append
15 |         winget upgrade --all --accept-source-agreements --accept-package-agreements --scope=machine --silent
16 | 
17 |     }
18 | 
19 |     $global:WinGetInstall = Start-Process -Verb runas powershell -ArgumentList "-command invoke-command -scriptblock {$wingetinstall} -argumentlist '$($ProgramsToInstall -join ",")'" -PassThru
20 | 
21 | }
22 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-ScratchDialog.ps1:
--------------------------------------------------------------------------------
 1 | 
 2 | function Invoke-ScratchDialog {
 3 | 
 4 |     <#
 5 | 
 6 |     .SYNOPSIS
 7 |         Enable Editable Text box Alternate Scartch path
 8 | 
 9 |     .PARAMETER Button
10 |     #>
11 |     $sync.WPFMicrowinISOScratchDir.IsChecked
12 | 
13 | 
14 |     [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
15 |     $Dialog = New-Object System.Windows.Forms.FolderBrowserDialog
16 |     $Dialog.SelectedPath =          $sync.MicrowinScratchDirBox.Text
17 |     $Dialog.ShowDialog()
18 |     $filePath = $Dialog.SelectedPath
19 |         Write-Host "No ISO is chosen+  $filePath"
20 | 
21 |     if ([string]::IsNullOrEmpty($filePath)) {
22 |         Write-Host "No Folder had chosen"
23 |         return
24 |     }
25 | 
26 |        $sync.MicrowinScratchDirBox.Text =  Join-Path $filePath "\"
27 | 
28 | }
29 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFButton.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFButton {
 2 | 
 3 |     <#
 4 | 
 5 |     .SYNOPSIS
 6 |         Invokes the function associated with the clicked button
 7 | 
 8 |     .PARAMETER Button
 9 |         The name of the button that was clicked
10 | 
11 |     #>
12 | 
13 |     Param ([string]$Button)
14 | 
15 |     # Use this to get the name of the button
16 |     #[System.Windows.MessageBox]::Show("$Button","Chris Titus Tech's Windows Utility","OK","Info")
17 |     if (-not $sync.ProcessRunning) {
18 |         Set-WinUtilProgressBar  -label "" -percent 0
19 |     }
20 | 
21 |     Switch -Wildcard ($Button) {
22 |         "WPFTab?BT" {Invoke-WPFTab $Button}
23 |         "WPFInstall" {Invoke-WPFInstall}
24 |         "WPFUninstall" {Invoke-WPFUnInstall}
25 |         "WPFInstallUpgrade" {Invoke-WPFInstallUpgrade}
26 |         "WPFStandard" {Invoke-WPFPresets "Standard" -checkboxfilterpattern "WPFTweak*"}
27 |         "WPFMinimal" {Invoke-WPFPresets "Minimal" -checkboxfilterpattern "WPFTweak*"}
28 |         "WPFClearTweaksSelection" {Invoke-WPFPresets -imported $true -checkboxfilterpattern "WPFTweak*"}
29 |         "WPFClearInstallSelection" {Invoke-WPFPresets -imported $true -checkboxfilterpattern "WPFInstall*"}
30 |         "WPFtweaksbutton" {Invoke-WPFtweaksbutton}
31 |         "WPFOOSUbutton" {Invoke-WPFOOSU}
32 |         "WPFAddUltPerf" {Invoke-WPFUltimatePerformance -State "Enable"}
33 |         "WPFRemoveUltPerf" {Invoke-WPFUltimatePerformance -State "Disable"}
34 |         "WPFundoall" {Invoke-WPFundoall}
35 |         "WPFFeatureInstall" {Invoke-WPFFeatureInstall}
36 |         "WPFPanelDISM" {Invoke-WPFSystemRepair}
37 |         "WPFPanelAutologin" {Invoke-WPFPanelAutologin}
38 |         "WPFPanelcomputer" {Invoke-WPFControlPanel -Panel $button}
39 |         "WPFPanelcontrol" {Invoke-WPFControlPanel -Panel $button}
40 |         "WPFPanelnetwork" {Invoke-WPFControlPanel -Panel $button}
41 |         "WPFPanelpower" {Invoke-WPFControlPanel -Panel $button}
42 |         "WPFPanelregion" {Invoke-WPFControlPanel -Panel $button}
43 |         "WPFPanelsound" {Invoke-WPFControlPanel -Panel $button}
44 |         "WPFPanelprinter" {Invoke-WPFControlPanel -Panel $button}
45 |         "WPFPanelsystem" {Invoke-WPFControlPanel -Panel $button}
46 |         "WPFPaneluser" {Invoke-WPFControlPanel -Panel $button}
47 |         "WPFPanelGodMode" {Invoke-WPFControlPanel -Panel $button}
48 |         "WPFUpdatesdefault" {Invoke-WPFFixesUpdate}
49 |         "WPFFixesUpdate" {Invoke-WPFFixesUpdate}
50 |         "WPFFixesWinget" {Invoke-WPFFixesWinget}
51 |         "WPFRunAdobeCCCleanerTool" {Invoke-WPFRunAdobeCCCleanerTool}
52 |         "WPFFixesNetwork" {Invoke-WPFFixesNetwork}
53 |         "WPFUpdatesdisable" {Invoke-WPFUpdatesdisable}
54 |         "WPFUpdatessecurity" {Invoke-WPFUpdatessecurity}
55 |         "WPFWinUtilShortcut" {Invoke-WPFShortcut -ShortcutToAdd "WinUtil" -RunAsAdmin $true}
56 |         "WPFGetInstalled" {Invoke-WPFGetInstalled -CheckBox "winget"}
57 |         "WPFGetInstalledTweaks" {Invoke-WPFGetInstalled -CheckBox "tweaks"}
58 |         "WPFGetIso" {Invoke-MicrowinGetIso}
59 |         "WPFMicrowin" {Invoke-Microwin}
60 |         "WPFCloseButton" {Invoke-WPFCloseButton}
61 |         "MicrowinScratchDirBT" {Invoke-ScratchDialog}
62 |         "WPFWinUtilInstallPSProfile" {Invoke-WinUtilInstallPSProfile}
63 |         "WPFWinUtilUninstallPSProfile" {Invoke-WinUtilUninstallPSProfile}
64 |         "WPFWinUtilSSHServer" {Invoke-WPFSSHServer}
65 |         "WPFselectedAppsButton" {$sync.selectedAppsPopup.IsOpen = -not $sync.selectedAppsPopup.IsOpen}
66 |         "WPFMicrowinPanelBack" {Toggle-MicrowinPanel 1}
67 |     }
68 | }
69 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFCloseButton.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFCloseButton {
 2 | 
 3 |     <#
 4 | 
 5 |     .SYNOPSIS
 6 |         Close application
 7 | 
 8 |     .PARAMETER Button
 9 |     #>
10 |     $sync["Form"].Close()
11 |     Write-Host "Bye bye!"
12 | }
13 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFControlPanel.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFControlPanel {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Opens the requested legacy panel
 6 | 
 7 |     .PARAMETER Panel
 8 |         The panel to open
 9 | 
10 |     #>
11 |     param($Panel)
12 | 
13 |     switch ($Panel) {
14 |         "WPFPanelcontrol" {control}
15 |         "WPFPanelcomputer" {compmgmt.msc}
16 |         "WPFPanelnetwork" {ncpa.cpl}
17 |         "WPFPanelpower"   {powercfg.cpl}
18 |         "WPFPanelregion"  {intl.cpl}
19 |         "WPFPanelsound"   {mmsys.cpl}
20 |         "WPFPanelprinter" {Start-Process "shell:::{A8A91A66-3A7D-4424-8D24-04E180695C7A}"}
21 |         "WPFPanelsystem"  {sysdm.cpl}
22 |         "WPFPaneluser"    {control userpasswords2}
23 |         "WPFPanelGodMode" {Start-Process "shell:::{ED7BA470-8E54-465E-825C-99712043E01C}"}
24 |     }
25 | }
26 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFFeatureInstall.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFFeatureInstall {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Installs selected Windows Features
 6 | 
 7 |     #>
 8 | 
 9 |     if($sync.ProcessRunning) {
10 |         $msg = "[Invoke-WPFFeatureInstall] Install process is currently running."
11 |         [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
12 |         return
13 |     }
14 | 
15 |     $Features = (Get-WinUtilCheckBoxes)["WPFFeature"]
16 | 
17 |     Invoke-WPFRunspace -ArgumentList $Features -DebugPreference $DebugPreference -ScriptBlock {
18 |         param($Features, $DebugPreference)
19 |         $sync.ProcessRunning = $true
20 |         if ($Features.count -eq 1) {
21 |             $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
22 |         } else {
23 |             $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" })
24 |         }
25 | 
26 |         Invoke-WinUtilFeatureInstall $Features
27 | 
28 |         $sync.ProcessRunning = $false
29 |         $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
30 | 
31 |         Write-Host "==================================="
32 |         Write-Host "---   Features are Installed    ---"
33 |         Write-Host "---  A Reboot may be required   ---"
34 |         Write-Host "==================================="
35 |     }
36 | }
37 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFFixesNetwork.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFFixesNetwork {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Resets various network configurations
 6 | 
 7 |     #>
 8 | 
 9 |     Write-Host "Resetting Network with netsh"
10 | 
11 |     Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo"
12 |     # Reset WinSock catalog to a clean state
13 |     Start-Process -NoNewWindow -FilePath "netsh" -ArgumentList "winsock", "reset"
14 | 
15 |     Set-WinUtilTaskbaritem -state "Normal" -value 0.35 -overlay "logo"
16 |     # Resets WinHTTP proxy setting to DIRECT
17 |     Start-Process -NoNewWindow -FilePath "netsh" -ArgumentList "winhttp", "reset", "proxy"
18 | 
19 |     Set-WinUtilTaskbaritem -state "Normal" -value 0.7 -overlay "logo"
20 |     # Removes all user configured IP settings
21 |     Start-Process -NoNewWindow -FilePath "netsh" -ArgumentList "int", "ip", "reset"
22 | 
23 |     Set-WinUtilTaskbaritem -state "None" -overlay "checkmark"
24 | 
25 |     Write-Host "Process complete. Please reboot your computer."
26 | 
27 |     $ButtonType = [System.Windows.MessageBoxButton]::OK
28 |     $MessageboxTitle = "Network Reset "
29 |     $Messageboxbody = ("Stock settings loaded.`n Please reboot your computer")
30 |     $MessageIcon = [System.Windows.MessageBoxImage]::Information
31 | 
32 |     [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon)
33 |     Write-Host "=========================================="
34 |     Write-Host "-- Network Configuration has been Reset --"
35 |     Write-Host "=========================================="
36 | }
37 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFFixesWinget.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFFixesWinget {
 2 | 
 3 |     <#
 4 | 
 5 |     .SYNOPSIS
 6 |         Fixes Winget by running choco install winget
 7 |     .DESCRIPTION
 8 |         BravoNorris for the fantastic idea of a button to reinstall winget
 9 |     #>
10 |     # Install Choco if not already present
11 |     try {
12 |         Set-WinUtilTaskbaritem -state "Indeterminate" -overlay "logo"
13 |         Install-WinUtilChoco
14 |         Start-Process -FilePath "choco" -ArgumentList "install winget -y --force" -NoNewWindow -Wait
15 |     } catch {
16 |         Write-Error "Failed to install winget: $_"
17 |         Set-WinUtilTaskbaritem -state "Error" -overlay "warning"
18 |     } finally {
19 |         Write-Host "==> Finished Winget Repair"
20 |         Set-WinUtilTaskbaritem -state "None" -overlay "checkmark"
21 |     }
22 | 
23 | }
24 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFGetInstalled.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFGetInstalled {
 2 |     <#
 3 |     TODO: Add the Option to use Chocolatey as Engine
 4 |     .SYNOPSIS
 5 |         Invokes the function that gets the checkboxes to check in a new runspace
 6 | 
 7 |     .PARAMETER checkbox
 8 |         Indicates whether to check for installed 'winget' programs or applied 'tweaks'
 9 | 
10 |     #>
11 |     param($checkbox)
12 |     if ($sync.ProcessRunning) {
13 |         $msg = "[Invoke-WPFGetInstalled] Install process is currently running."
14 |         [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
15 |         return
16 |     }
17 | 
18 |     if (($sync.ChocoRadioButton.IsChecked -eq $false) -and ((Test-WinUtilPackageManager -winget) -eq "not-installed") -and $checkbox -eq "winget") {
19 |         return
20 |     }
21 |     $managerPreference = $sync["ManagerPreference"]
22 | 
23 |     Invoke-WPFRunspace -ParameterList @(("managerPreference", $managerPreference),("checkbox", $checkbox)) -DebugPreference $DebugPreference -ScriptBlock {
24 |         param (
25 |             [string]$checkbox,
26 |             [PackageManagers]$managerPreference
27 |         )
28 |         $sync.ProcessRunning = $true
29 |         $sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state "Indeterminate" })
30 | 
31 |         if ($checkbox -eq "winget") {
32 |             Write-Host "Getting Installed Programs..."
33 |             switch ($managerPreference) {
34 |                 "Choco"{$Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox "choco"; break}
35 |                 "Winget"{$Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox $checkbox; break}
36 |             }
37 |         }
38 |         elseif ($checkbox -eq "tweaks") {
39 |             Write-Host "Getting Installed Tweaks..."
40 |             $Checkboxes = Invoke-WinUtilCurrentSystem -CheckBox $checkbox
41 |         }
42 | 
43 |         $sync.form.Dispatcher.invoke({
44 |             foreach ($checkbox in $Checkboxes) {
45 |                 $sync.$checkbox.ischecked = $True
46 |             }
47 |         })
48 | 
49 |         Write-Host "Done..."
50 |         $sync.ProcessRunning = $false
51 |         $sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state "None" })
52 |     }
53 | }
54 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFImpex.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFImpex {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Handles importing and exporting of the checkboxes checked for the tweaks section
 6 | 
 7 |     .PARAMETER type
 8 |         Indicates whether to 'import' or 'export'
 9 | 
10 |     .PARAMETER checkbox
11 |         The checkbox to export to a file or apply the imported file to
12 | 
13 |     .EXAMPLE
14 |         Invoke-WPFImpex -type "export"
15 | 
16 |     #>
17 |     param(
18 |         $type,
19 |         $Config = $null
20 |     )
21 | 
22 |     function ConfigDialog {
23 |         if (!$Config) {
24 |             switch ($type) {
25 |                 "export" { $FileBrowser = New-Object System.Windows.Forms.SaveFileDialog }
26 |                 "import" { $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog }
27 |             }
28 |             $FileBrowser.InitialDirectory = [Environment]::GetFolderPath('Desktop')
29 |             $FileBrowser.Filter = "JSON Files (*.json)|*.json"
30 |             $FileBrowser.ShowDialog() | Out-Null
31 | 
32 |             if ($FileBrowser.FileName -eq "") {
33 |                 return $null
34 |             } else {
35 |                 return $FileBrowser.FileName
36 |             }
37 |         } else {
38 |             return $Config
39 |         }
40 |     }
41 | 
42 |     switch ($type) {
43 |         "export" {
44 |             try {
45 |                 $Config = ConfigDialog
46 |                 if ($Config) {
47 |                     $jsonFile = Get-WinUtilCheckBoxes -unCheck $false | ConvertTo-Json
48 |                     $jsonFile | Out-File $Config -Force
49 |                     "iex ""& { `$(irm https://christitus.com/win) } -Config '$Config'""" | Set-Clipboard
50 |                 }
51 |             } catch {
52 |                 Write-Error "An error occurred while exporting: $_"
53 |             }
54 |         }
55 |         "import" {
56 |             try {
57 |                 $Config = ConfigDialog
58 |                 if ($Config) {
59 |                     try {
60 |                         if ($Config -match '^https?://') {
61 |                             $jsonFile = (Invoke-WebRequest "$Config").Content | ConvertFrom-Json
62 |                         } else {
63 |                             $jsonFile = Get-Content $Config | ConvertFrom-Json
64 |                         }
65 |                     } catch {
66 |                         Write-Error "Failed to load the JSON file from the specified path or URL: $_"
67 |                         return
68 |                     }
69 |                     $flattenedJson = $jsonFile.PSObject.Properties.Where({ $_.Name -ne "Install" }).ForEach({ $_.Value })
70 |                     Invoke-WPFPresets -preset $flattenedJson -imported $true
71 |                 }
72 |             } catch {
73 |                 Write-Error "An error occurred while importing: $_"
74 |             }
75 |         }
76 |     }
77 | }
78 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFInstall.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFInstall {
 2 |     param (
 3 |         [Parameter(Mandatory=$false)]
 4 |         [PSObject[]]$PackagesToInstall = $($sync.selectedApps | Foreach-Object { $sync.configs.applicationsHashtable.$_ })
 5 |     )
 6 |     <#
 7 | 
 8 |     .SYNOPSIS
 9 |         Installs the selected programs using winget, if one or more of the selected programs are already installed on the system, winget will try and perform an upgrade if there's a newer version to install.
10 | 
11 |     #>
12 | 
13 |     if($sync.ProcessRunning) {
14 |         $msg = "[Invoke-WPFInstall] An Install process is currently running."
15 |         [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
16 |         return
17 |     }
18 | 
19 |     if ($PackagesToInstall.Count -eq 0) {
20 |         $WarningMsg = "Please select the program(s) to install or upgrade"
21 |         [System.Windows.MessageBox]::Show($WarningMsg, $AppTitle, [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
22 |         return
23 |     }
24 | 
25 |     $ManagerPreference = $sync["ManagerPreference"]
26 | 
27 |     Invoke-WPFRunspace -ParameterList @(("PackagesToInstall", $PackagesToInstall),("ManagerPreference", $ManagerPreference)) -DebugPreference $DebugPreference -ScriptBlock {
28 |         param($PackagesToInstall, $ManagerPreference, $DebugPreference)
29 | 
30 |         $packagesSorted = Get-WinUtilSelectedPackages -PackageList $PackagesToInstall -Preference $ManagerPreference
31 | 
32 |         $packagesWinget = $packagesSorted[[PackageManagers]::Winget]
33 |         $packagesChoco = $packagesSorted[[PackageManagers]::Choco]
34 | 
35 |         try {
36 |             $sync.ProcessRunning = $true
37 |             Show-WPFInstallAppBusy -text "Installing apps..."
38 | 
39 |             if($packagesWinget.Count -gt 0) {
40 |                 Install-WinUtilWinget
41 |                 Install-WinUtilProgramWinget -Action Install -Programs $packagesWinget
42 | 
43 |             }
44 |             if($packagesChoco.Count -gt 0) {
45 |                 Install-WinUtilChoco
46 |                 Install-WinUtilProgramChoco -Action Install -Programs $packagesChoco
47 |             }
48 |             Hide-WPFInstallAppBusy
49 |             Write-Host "==========================================="
50 |             Write-Host "--      Installs have finished          ---"
51 |             Write-Host "==========================================="
52 |             $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
53 |         } catch {
54 |             Write-Host "==========================================="
55 |             Write-Host "Error: $_"
56 |             Write-Host "==========================================="
57 |             $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -overlay "warning" })
58 |         }
59 |         $sync.ProcessRunning = $False
60 |     }
61 | }
62 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFInstallUpgrade.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFInstallUpgrade {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Invokes the function that upgrades all installed programs
 6 | 
 7 |     #>
 8 |     if ($sync.ChocoRadioButton.IsChecked) {
 9 |         Install-WinUtilChoco
10 |         $chocoUpgradeStatus = (Start-Process "choco" -ArgumentList "upgrade all -y" -Wait -PassThru -NoNewWindow).ExitCode
11 |         if ($chocoUpgradeStatus -eq 0) {
12 |             Write-Host "Upgrade Successful"
13 |         }
14 |         else{
15 |             Write-Host "Error Occured. Return Code: $chocoUpgradeStatus"
16 |         }
17 |     }
18 |     else{
19 |         if((Test-WinUtilPackageManager -winget) -eq "not-installed") {
20 |             return
21 |         }
22 | 
23 |         if(Get-WinUtilInstallerProcess -Process $global:WinGetInstall) {
24 |             $msg = "[Invoke-WPFInstallUpgrade] Install process is currently running. Please check for a powershell window labeled 'Winget Install'"
25 |             [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
26 |             return
27 |         }
28 | 
29 |         Update-WinUtilProgramWinget
30 | 
31 |         Write-Host "==========================================="
32 |         Write-Host "--           Updates started            ---"
33 |         Write-Host "-- You can close this window if desired ---"
34 |         Write-Host "==========================================="
35 |     }
36 | }
37 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFOOSU.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFOOSU {
 2 |     <#
 3 |     .SYNOPSIS
 4 |         Downloads and runs OO Shutup 10
 5 |     #>
 6 |     try {
 7 |         $OOSU_filepath = "$ENV:temp\OOSU10.exe"
 8 |         $Initial_ProgressPreference = $ProgressPreference
 9 |         $ProgressPreference = "SilentlyContinue" # Disables the Progress Bar to drasticly speed up Invoke-WebRequest
10 |         Invoke-WebRequest -Uri "https://dl5.oo-software.com/files/ooshutup10/OOSU10.exe" -OutFile $OOSU_filepath
11 |         Write-Host "Starting OO Shutup 10 ..."
12 |         Start-Process $OOSU_filepath
13 |     } catch {
14 |         Write-Host "Error Downloading and Running OO Shutup 10" -ForegroundColor Red
15 |     }
16 |     finally {
17 |         $ProgressPreference = $Initial_ProgressPreference
18 |     }
19 | }
20 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFPanelAutologin.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFPanelAutologin {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Enables autologin using Sysinternals Autologon.exe
 6 | 
 7 |     #>
 8 | 
 9 |     # Official Microsoft recommendation: https://learn.microsoft.com/en-us/sysinternals/downloads/autologon
10 |     Invoke-WebRequest -Uri "https://live.sysinternals.com/Autologon.exe" -OutFile "$env:temp\autologin.exe"
11 |     cmd /c "$env:temp\autologin.exe" /accepteula
12 | }
13 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFPopup.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFPopup {
 2 |     param (
 3 |         [ValidateSet("Show", "Hide", "Toggle")]
 4 |         [string]$Action = "",
 5 | 
 6 |         [string[]]$Popups = @(),
 7 | 
 8 |         [ValidateScript({
 9 |             $invalid = $_.GetEnumerator() | Where-Object { $_.Value -notin @("Show", "Hide", "Toggle") }
10 |             if ($invalid) {
11 |                 throw "Found invalid Popup-Action pair(s): " + ($invalid | ForEach-Object { "$($_.Key) = $($_.Value)" } -join "; ")
12 |             }
13 |             $true
14 |         })]
15 |         [hashtable]$PopupActionTable = @{}
16 |     )
17 | 
18 |     if (-not $PopupActionTable.Count -and (-not $Action -or -not $Popups.Count)) {
19 |         throw "Provide either 'PopupActionTable' or both 'Action' and 'Popups'."
20 |     }
21 | 
22 |     if ($PopupActionTable.Count -and ($Action -or $Popups.Count)) {
23 |         throw "Use 'PopupActionTable' on its own, or 'Action' with 'Popups'."
24 |     }
25 | 
26 |     # Collect popups and actions
27 |     $PopupsToProcess = if ($PopupActionTable.Count) {
28 |         $PopupActionTable.GetEnumerator() | ForEach-Object { [PSCustomObject]@{ Name = "$($_.Key)Popup"; Action = $_.Value } }
29 |     } else {
30 |         $Popups | ForEach-Object { [PSCustomObject]@{ Name = "$_`Popup"; Action = $Action } }
31 |     }
32 | 
33 |     $PopupsNotFound = @()
34 | 
35 |     # Apply actions
36 |     foreach ($popupEntry in $PopupsToProcess) {
37 |         $popupName = $popupEntry.Name
38 | 
39 |         if (-not $sync.$popupName) {
40 |             $PopupsNotFound += $popupName
41 |             continue
42 |         }
43 | 
44 |         $sync.$popupName.IsOpen = switch ($popupEntry.Action) {
45 |             "Show" { $true }
46 |             "Hide" { $false }
47 |             "Toggle" { -not $sync.$popupName.IsOpen }
48 |         }
49 |     }
50 | 
51 |     if ($PopupsNotFound.Count -gt 0) {
52 |         throw "Could not find the following popups: $($PopupsNotFound -join ', ')"
53 |     }
54 | }
55 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFPresets.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFPresets {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Sets the options in the tweaks panel to the given preset
 6 | 
 7 |     .PARAMETER preset
 8 |         The preset to set the options to
 9 | 
10 |     .PARAMETER imported
11 |         If the preset is imported from a file, defaults to false
12 | 
13 |     .PARAMETER checkboxfilterpattern
14 |         The Pattern to use when filtering through CheckBoxes, defaults to "**"
15 | 
16 |     #>
17 | 
18 |     param (
19 |         [Parameter(position=0)]
20 |         [Array]$preset = "",
21 | 
22 |         [Parameter(position=1)]
23 |         [bool]$imported = $false,
24 | 
25 |         [Parameter(position=2)]
26 |         [string]$checkboxfilterpattern = "**"
27 |     )
28 | 
29 |     if ($imported -eq $true) {
30 |         $CheckBoxesToCheck = $preset
31 |     } else {
32 |         $CheckBoxesToCheck = $sync.configs.preset.$preset
33 |     }
34 | 
35 |     $CheckBoxes = ($sync.GetEnumerator()).where{ $_.Value -is [System.Windows.Controls.CheckBox] -and $_.Name -notlike "WPFToggle*" -and $_.Name -like "$checkboxfilterpattern"}
36 |     Write-Debug "Getting checkboxes to set, number of checkboxes: $($CheckBoxes.Count)"
37 | 
38 |     if ($CheckBoxesToCheck -ne "") {
39 |         $debugMsg = "CheckBoxes to Check are: "
40 |         $CheckBoxesToCheck | ForEach-Object { $debugMsg += "$_, " }
41 |         $debugMsg = $debugMsg -replace (',\s*
#39;, '')
42 |         Write-Debug "$debugMsg"
43 |     }
44 | 
45 |     foreach ($CheckBox in $CheckBoxes) {
46 |         $checkboxName = $CheckBox.Key
47 | 
48 |         if (-not $CheckBoxesToCheck) {
49 |             $sync.$checkboxName.IsChecked = $false
50 |             continue
51 |         }
52 | 
53 |         # Check if the checkbox name exists in the flattened JSON hashtable
54 |         if ($CheckBoxesToCheck -contains $checkboxName) {
55 |             # If it exists, set IsChecked to true
56 |             $sync.$checkboxName.IsChecked = $true
57 |             Write-Debug "$checkboxName is checked"
58 |         } else {
59 |             # If it doesn't exist, set IsChecked to false
60 |             $sync.$checkboxName.IsChecked = $false
61 |             Write-Debug "$checkboxName is not checked"
62 |         }
63 |     }
64 | }
65 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFRunAdobeCCCleanerTool.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFRunAdobeCCCleanerTool {
 2 |     <#
 3 |     .SYNOPSIS
 4 |         It removes or fixes problem files and resolves permission issues in registry keys.
 5 |     .DESCRIPTION
 6 |         The Creative Cloud Cleaner tool is a utility for experienced users to clean up corrupted installations.
 7 |     #>
 8 | 
 9 |     [string]$url="https://swupmf.adobe.com/webfeed/CleanerTool/win/AdobeCreativeCloudCleanerTool.exe"
10 | 
11 |     Write-Host "The Adobe Creative Cloud Cleaner tool is hosted at"
12 |     Write-Host "$url"
13 | 
14 |     try {
15 |         # Don't show the progress because it will slow down the download speed
16 |         $ProgressPreference='SilentlyContinue'
17 | 
18 |         Invoke-WebRequest -Uri $url -OutFile "$env:TEMP\AdobeCreativeCloudCleanerTool.exe" -UseBasicParsing -ErrorAction SilentlyContinue -Verbose
19 | 
20 |         # Revert back the ProgressPreference variable to the default value since we got the file desired
21 |         $ProgressPreference='Continue'
22 | 
23 |         Start-Process -FilePath "$env:TEMP\AdobeCreativeCloudCleanerTool.exe" -Wait -ErrorAction SilentlyContinue -Verbose
24 |     } catch {
25 |         Write-Error $_.Exception.Message
26 |     } finally {
27 |         if (Test-Path -Path "$env:TEMP\AdobeCreativeCloudCleanerTool.exe") {
28 |             Write-Host "Cleaning up..."
29 |             Remove-Item -Path "$env:TEMP\AdobeCreativeCloudCleanerTool.exe" -Verbose
30 |         }
31 |     }
32 | }
33 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFRunspace.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFRunspace {
 2 | 
 3 |     <#
 4 | 
 5 |     .SYNOPSIS
 6 |         Creates and invokes a runspace using the given scriptblock and argumentlist
 7 | 
 8 |     .PARAMETER ScriptBlock
 9 |         The scriptblock to invoke in the runspace
10 | 
11 |     .PARAMETER ArgumentList
12 |         A list of arguments to pass to the runspace
13 | 
14 |     .PARAMETER ParameterList
15 |         A list of named parameters that should be provided.
16 |     .EXAMPLE
17 |         Invoke-WPFRunspace `
18 |             -ScriptBlock $sync.ScriptsInstallPrograms `
19 |             -ArgumentList "Installadvancedip,Installbitwarden" `
20 | 
21 |         Invoke-WPFRunspace`
22 |             -ScriptBlock $sync.ScriptsInstallPrograms `
23 |             -ParameterList @(("PackagesToInstall", @("Installadvancedip,Installbitwarden")),("ChocoPreference", $true))
24 |     #>
25 | 
26 |     [CmdletBinding()]
27 |     Param (
28 |         $ScriptBlock,
29 |         $ArgumentList,
30 |         $ParameterList,
31 |         $DebugPreference
32 |     )
33 | 
34 |     # Create a PowerShell instance
35 |     $script:powershell = [powershell]::Create()
36 | 
37 |     # Add Scriptblock and Arguments to runspace
38 |     $script:powershell.AddScript($ScriptBlock)
39 |     $script:powershell.AddArgument($ArgumentList)
40 | 
41 |     foreach ($parameter in $ParameterList) {
42 |         $script:powershell.AddParameter($parameter[0], $parameter[1])
43 |     }
44 |     $script:powershell.AddArgument($DebugPreference)  # Pass DebugPreference to the script block
45 |     $script:powershell.RunspacePool = $sync.runspace
46 | 
47 |     # Execute the RunspacePool
48 |     $script:handle = $script:powershell.BeginInvoke()
49 | 
50 |     # Clean up the RunspacePool threads when they are complete, and invoke the garbage collector to clean up the memory
51 |     if ($script:handle.IsCompleted) {
52 |         $script:powershell.EndInvoke($script:handle)
53 |         $script:powershell.Dispose()
54 |         $sync.runspace.Dispose()
55 |         $sync.runspace.Close()
56 |         [System.GC]::Collect()
57 |     }
58 |     # Return the handle
59 |     return $handle
60 | }
61 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFSSHServer.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFSSHServer {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Invokes the OpenSSH Server install in a runspace
 6 | 
 7 |   #>
 8 | 
 9 |     Invoke-WPFRunspace -DebugPreference $DebugPreference -ScriptBlock {
10 | 
11 |         Invoke-WinUtilSSHServer
12 | 
13 |         Write-Host "======================================="
14 |         Write-Host "--     OpenSSH Server installed!    ---"
15 |         Write-Host "======================================="
16 |     }
17 | }
18 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFSelectedAppsUpdate.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFSelectedAppsUpdate {
 2 |     <#
 3 |         .SYNOPSIS
 4 |             This is a helper function that is called by the Checked and Unchecked events of the Checkboxes on the install tab.
 5 |             It Updates the "Selected Apps" selectedAppLabel on the Install Tab to represent the current collection
 6 |         .PARAMETER type
 7 |             Eigther: Add | Remove
 8 |         .PARAMETER checkbox
 9 |             should contain the current instance of the checkbox that triggered the Event.
10 |             Most of the time will be the automatic variable $this
11 |         .EXAMPLE
12 |             $checkbox.Add_Unchecked({Invoke-WPFSelectedAppsUpdate -type "Remove" -checkbox $this})
13 |             OR
14 |             Invoke-WPFSelectedAppsUpdate -type "Add" -checkbox $specificCheckbox
15 |     #>
16 |     param (
17 |         $type,
18 |         $checkbox
19 |     )
20 | 
21 |     $selectedAppsButton = $sync.WPFselectedAppsButton
22 |     # Get the actual Name from the selectedAppLabel inside the Checkbox
23 |     $appKey = $checkbox.Parent.Tag
24 |     if ($type -eq "Add") {
25 |         $sync.selectedApps.Add($appKey)
26 |         # 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
27 |         [System.Collections.Generic.List[pscustomobject]]$sync.selectedApps = $sync.SelectedApps | Sort-Object
28 | 
29 |     }
30 |     elseif ($type -eq "Remove") {
31 |         $sync.SelectedApps.Remove($appKey)
32 |     }
33 |     else{
34 |         Write-Error "Type: $type not implemented"
35 |     }
36 | 
37 |     $count = $sync.SelectedApps.Count
38 |     $selectedAppsButton.Content = "Selected Apps: $count"
39 |     # 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
40 |     $sync.selectedAppsstackPanel.Children.Clear()
41 |     $sync.SelectedApps | Foreach-Object { Add-SelectedAppsMenuItem -name $($sync.configs.applicationsHashtable.$_.Content) -key $_ }
42 | 
43 | }
44 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFTab.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFTab {
 2 | 
 3 |     <#
 4 | 
 5 |     .SYNOPSIS
 6 |         Sets the selected tab to the tab that was clicked
 7 | 
 8 |     .PARAMETER ClickedTab
 9 |         The name of the tab that was clicked
10 | 
11 |     #>
12 | 
13 |     Param (
14 |         [Parameter(Mandatory,position=0)]
15 |         [string]$ClickedTab
16 |     )
17 | 
18 |     $tabNav = Get-WinUtilVariables | Where-Object {$psitem -like "WPFTabNav"}
19 |     $tabNumber = [int]($ClickedTab -replace "WPFTab","" -replace "BT","") - 1
20 | 
21 |     $filter = Get-WinUtilVariables -Type ToggleButton | Where-Object {$psitem -like "WPFTab?BT"}
22 |     ($sync.GetEnumerator()).where{$psitem.Key -in $filter} | ForEach-Object {
23 |         if ($ClickedTab -ne $PSItem.name) {
24 |             $sync[$PSItem.Name].IsChecked = $false
25 |         } else {
26 |             $sync["$ClickedTab"].IsChecked = $true
27 |             $tabNumber = [int]($ClickedTab-replace "WPFTab","" -replace "BT","") - 1
28 |             $sync.$tabNav.Items[$tabNumber].IsSelected = $true
29 |         }
30 |     }
31 |     $sync.currentTab = $sync.$tabNav.Items[$tabNumber].Header
32 | 
33 |     # Always reset the filter for the current tab
34 |     if ($sync.currentTab -eq "Install") {
35 |         # Reset Install tab filter
36 |         Find-AppsByNameOrDescription -SearchString ""
37 |     } elseif ($sync.currentTab -eq "Tweaks") {
38 |         # Reset Tweaks tab filter
39 |         Find-TweaksByNameOrDescription -SearchString ""
40 |     }
41 | 
42 |     # Show search bar in Install and Tweaks tabs
43 |     if ($tabNumber -eq 0 -or $tabNumber -eq 1) {
44 |         $sync.SearchBar.Visibility = "Visible"
45 |         $searchIcon = ($sync.Form.FindName("SearchBar").Parent.Children | Where-Object { $_ -is [System.Windows.Controls.TextBlock] -and $_.Text -eq [char]0xE721 })[0]
46 |         if ($searchIcon) {
47 |             $searchIcon.Visibility = "Visible"
48 |         }
49 |     } else {
50 |         $sync.SearchBar.Visibility = "Collapsed"
51 |         $searchIcon = ($sync.Form.FindName("SearchBar").Parent.Children | Where-Object { $_ -is [System.Windows.Controls.TextBlock] -and $_.Text -eq [char]0xE721 })[0]
52 |         if ($searchIcon) {
53 |             $searchIcon.Visibility = "Collapsed"
54 |         }
55 |         # Hide the clear button if it's visible
56 |         $sync.SearchBarClearButton.Visibility = "Collapsed"
57 |     }
58 | }
59 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFTweakPS7.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFTweakPS7{
 2 |         <#
 3 |     .SYNOPSIS
 4 |         This will edit the config file of the Windows Terminal Replacing the Powershell 5 to Powershell 7 and install Powershell 7 if necessary
 5 |     .PARAMETER action
 6 |         PS7:           Configures Powershell 7 to be the default Terminal
 7 |         PS5:           Configures Powershell 5 to be the default Terminal
 8 |     #>
 9 |     param (
10 |         [ValidateSet("PS7", "PS5")]
11 |         [string]$action
12 |     )
13 | 
14 |     switch ($action) {
15 |         "PS7"{
16 |             if (Test-Path -Path "$env:ProgramFiles\PowerShell\7") {
17 |                 Write-Host "Powershell 7 is already installed."
18 |             } else {
19 |                 Write-Host "Installing Powershell 7..."
20 |                 Install-WinUtilProgramWinget -Action Install -Programs @("Microsoft.PowerShell")
21 |             }
22 |             $targetTerminalName = "PowerShell"
23 |         }
24 |         "PS5"{
25 |             $targetTerminalName = "Windows PowerShell"
26 |         }
27 |     }
28 |     # Check if the Windows Terminal is installed and return if not (Prerequisite for the following code)
29 |     if (-not (Get-Command "wt" -ErrorAction SilentlyContinue)) {
30 |         Write-Host "Windows Terminal not installed. Skipping Terminal preference"
31 |         return
32 |     }
33 |     # Check if the Windows Terminal settings.json file exists and return if not (Prereqisite for the following code)
34 |     $settingsPath = "$env:LOCALAPPDATA\Packages\Microsoft.WindowsTerminal_8wekyb3d8bbwe\LocalState\settings.json"
35 |     if (-not (Test-Path -Path $settingsPath)) {
36 |         Write-Host "Windows Terminal Settings file not found at $settingsPath"
37 |         return
38 |     }
39 | 
40 |     Write-Host "Settings file found."
41 |     $settingsContent = Get-Content -Path $settingsPath | ConvertFrom-Json
42 |     $ps7Profile = $settingsContent.profiles.list | Where-Object { $_.name -eq $targetTerminalName }
43 |     if ($ps7Profile) {
44 |         $settingsContent.defaultProfile = $ps7Profile.guid
45 |         $updatedSettings = $settingsContent | ConvertTo-Json -Depth 100
46 |         Set-Content -Path $settingsPath -Value $updatedSettings
47 |         Write-Host "Default profile updated to " -NoNewline
48 |         Write-Host "$targetTerminalName " -ForegroundColor White -NoNewline
49 |         Write-Host "using the name attribute."
50 |     } else {
51 |         Write-Host "No PowerShell 7 profile found in Windows Terminal settings using the name attribute."
52 |     }
53 | }
54 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFUltimatePerformance.ps1:
--------------------------------------------------------------------------------
 1 | Function Invoke-WPFUltimatePerformance {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Enables or disables the Ultimate Performance power scheme based on its GUID.
 6 | 
 7 |     .PARAMETER State
 8 |         Specifies whether to "Enable" or "Disable" the Ultimate Performance power scheme.
 9 | 
10 |     #>
11 |     param(
12 |         [Parameter(Mandatory = $true)]
13 |         [ValidateSet("Enable", "Disable")]
14 |         [string]$State
15 |     )
16 | 
17 |     try {
18 |         # GUID of the Ultimate Performance power plan
19 |         $ultimateGUID = "e9a42b02-d5df-448d-aa00-03f14749eb61"
20 | 
21 |         switch ($State) {
22 |             "Enable" {
23 |                 # Duplicate the Ultimate Performance power plan using its GUID
24 |                 $duplicateOutput = powercfg /duplicatescheme $ultimateGUID
25 | 
26 |                 $guid = $null
27 |                 $nameFromFile = "ChrisTitus - Ultimate Power Plan"
28 |                 $description = "Ultimate Power Plan, added via WinUtils"
29 | 
30 |                 # Extract the new GUID from the duplicateOutput
31 |                 foreach ($line in $duplicateOutput) {
32 |                     if ($line -match "\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b") {
33 |                         $guid = $matches[0]  # $matches[0] will contain the first match, which is the GUID
34 |                         Write-Output "GUID: $guid has been extracted and stored in the variable."
35 |                         break
36 |                     }
37 |                 }
38 | 
39 |                 if (-not $guid) {
40 |                     Write-Output "No GUID found in the duplicateOutput. Check the output format."
41 |                     exit 1
42 |                 }
43 | 
44 |                 # Change the name of the power plan and set its description
45 |                 $changeNameOutput = powercfg /changename $guid "$nameFromFile" "$description"
46 |                 Write-Output "The power plan name and description have been changed. Output:"
47 |                 Write-Output $changeNameOutput
48 | 
49 |                 # Set the duplicated Ultimate Performance plan as active
50 |                 $setActiveOutput = powercfg /setactive $guid
51 |                 Write-Output "The power plan has been set as active. Output:"
52 |                 Write-Output $setActiveOutput
53 | 
54 |                 Write-Host "> Ultimate Performance plan installed and set as active."
55 |             }
56 |             "Disable" {
57 |                 # Check if the Ultimate Performance plan is installed by GUID
58 |                 $installedPlan = powercfg -list | Select-String -Pattern "ChrisTitus - Ultimate Power Plan"
59 | 
60 |                 if ($installedPlan) {
61 |                     # Extract the GUID of the installed Ultimate Performance plan
62 |                     $ultimatePlanGUID = $installedPlan.Line.Split()[3]
63 | 
64 |                     # Set a different power plan as active before deleting the Ultimate Performance plan
65 |                     $balancedPlanGUID = "381b4222-f694-41f0-9685-ff5bb260df2e"
66 |                     powercfg -setactive $balancedPlanGUID
67 | 
68 |                     # Delete the Ultimate Performance plan by GUID
69 |                     powercfg -delete $ultimatePlanGUID
70 | 
71 |                     Write-Host "Ultimate Performance plan has been uninstalled."
72 |                     Write-Host "> Balanced plan is now active."
73 |                 } else {
74 |                     Write-Host "Ultimate Performance plan is not installed."
75 |                 }
76 |             }
77 |             default {
78 |                 Write-Host "Invalid state. Please use 'Enable' or 'Disable'."
79 |             }
80 |         }
81 |     } catch {
82 |         Write-Error "Error occurred: $_"
83 |     }
84 | }
85 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFUnInstall.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFUnInstall {
 2 |     param(
 3 |         [Parameter(Mandatory=$false)]
 4 |         [PSObject[]]$PackagesToUninstall = $($sync.selectedApps | Foreach-Object { $sync.configs.applicationsHashtable.$_ })
 5 |     )
 6 |     <#
 7 | 
 8 |     .SYNOPSIS
 9 |         Uninstalls the selected programs
10 |     #>
11 | 
12 |     if($sync.ProcessRunning) {
13 |         $msg = "[Invoke-WPFUnInstall] Install process is currently running"
14 |         [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
15 |         return
16 |     }
17 | 
18 |     if ($PackagesToUninstall.Count -eq 0) {
19 |         $WarningMsg = "Please select the program(s) to uninstall"
20 |         [System.Windows.MessageBox]::Show($WarningMsg, $AppTitle, [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
21 |         return
22 |     }
23 | 
24 |     $ButtonType = [System.Windows.MessageBoxButton]::YesNo
25 |     $MessageboxTitle = "Are you sure?"
26 |     $Messageboxbody = ("This will uninstall the following applications: `n $($PackagesToUninstall | Select-Object Name, Description| Out-String)")
27 |     $MessageIcon = [System.Windows.MessageBoxImage]::Information
28 | 
29 |     $confirm = [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon)
30 | 
31 |     if($confirm -eq "No") {return}
32 | 
33 |     $ManagerPreference = $sync["ManagerPreference"]
34 | 
35 |     Invoke-WPFRunspace -ArgumentList @(("PackagesToUninstall", $PackagesToUninstall),("ManagerPreference", $ManagerPreference)) -DebugPreference $DebugPreference -ScriptBlock {
36 |         param($PackagesToUninstall, $ManagerPreference, $DebugPreference)
37 | 
38 |         $packagesSorted = Get-WinUtilSelectedPackages -PackageList $PackagesToUninstall -Preference $ManagerPreference
39 |         $packagesWinget = $packagesSorted[[PackageManagers]::Winget]
40 |         $packagesChoco = $packagesSorted[[PackageManagers]::Choco]
41 | 
42 |         try {
43 |             $sync.ProcessRunning = $true
44 |             Show-WPFInstallAppBusy -text "Uninstalling apps..."
45 | 
46 |             # Uninstall all selected programs in new window
47 |             if($packagesWinget.Count -gt 0) {
48 |                 Install-WinUtilProgramWinget -Action Uninstall -Programs $packagesWinget
49 |             }
50 |             if($packagesChoco.Count -gt 0) {
51 |                 Install-WinUtilProgramChoco -Action Uninstall -Programs $packagesChoco
52 |             }
53 |             Hide-WPFInstallAppBusy
54 |             Write-Host "==========================================="
55 |             Write-Host "--       Uninstalls have finished       ---"
56 |             Write-Host "==========================================="
57 |             $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
58 |         } catch {
59 |             Write-Host "==========================================="
60 |             Write-Host "Error: $_"
61 |             Write-Host "==========================================="
62 |             $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" -overlay "warning" })
63 |         }
64 |         $sync.ProcessRunning = $False
65 | 
66 |     }
67 | }
68 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFUpdatesdefault.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFUpdatesdefault {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Resets Windows Update settings to default
 6 | 
 7 |     #>
 8 |     If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU")) {
 9 |         New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Force | Out-Null
10 |     }
11 |     Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "NoAutoUpdate" -Type DWord -Value 0
12 |     Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "AUOptions" -Type DWord -Value 3
13 |     If (!(Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config")) {
14 |         New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config" -Force | Out-Null
15 |     }
16 |     Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config" -Name "DODownloadMode" -Type DWord -Value 1
17 | 
18 |     $services = @(
19 |         "BITS"
20 |         "wuauserv"
21 |     )
22 | 
23 |     foreach ($service in $services) {
24 |         # -ErrorAction SilentlyContinue is so it doesn't write an error to stdout if a service doesn't exist
25 | 
26 |         Write-Host "Setting $service StartupType to Automatic"
27 |         Get-Service -Name $service -ErrorAction SilentlyContinue | Set-Service -StartupType Automatic
28 |     }
29 |     Write-Host "Enabling driver offering through Windows Update..."
30 |     Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Device Metadata" -Name "PreventDeviceMetadataFromNetwork" -ErrorAction SilentlyContinue
31 |     Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Name "DontPromptForWindowsUpdate" -ErrorAction SilentlyContinue
32 |     Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Name "DontSearchWindowsUpdate" -ErrorAction SilentlyContinue
33 |     Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Name "DriverUpdateWizardWuSearchEnabled" -ErrorAction SilentlyContinue
34 |     Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "ExcludeWUDriversInQualityUpdate" -ErrorAction SilentlyContinue
35 |     Write-Host "Enabling Windows Update automatic restart..."
36 |     Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "NoAutoRebootWithLoggedOnUsers" -ErrorAction SilentlyContinue
37 |     Remove-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "AUPowerManagement" -ErrorAction SilentlyContinue
38 |     Write-Host "Enabled driver offering through Windows Update"
39 |     Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "BranchReadinessLevel" -ErrorAction SilentlyContinue
40 |     Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "DeferFeatureUpdatesPeriodInDays" -ErrorAction SilentlyContinue
41 |     Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "DeferQualityUpdatesPeriodInDays" -ErrorAction SilentlyContinue
42 |     Write-Host "==================================================="
43 |     Write-Host "---  Windows Update Settings Reset to Default   ---"
44 |     Write-Host "==================================================="
45 | 
46 |     Start-Process -FilePath "secedit" -ArgumentList "/configure /cfg $env:windir\inf\defltbase.inf /db defltbase.sdb /verbose" -Wait
47 |     Start-Process -FilePath "cmd.exe" -ArgumentList "/c RD /S /Q $env:WinDir\System32\GroupPolicyUsers" -Wait
48 |     Start-Process -FilePath "cmd.exe" -ArgumentList "/c RD /S /Q $env:WinDir\System32\GroupPolicy" -Wait
49 |     Start-Process -FilePath "gpupdate" -ArgumentList "/force" -Wait
50 |     Remove-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Policies" -Recurse -Force -ErrorAction SilentlyContinue
51 |     Remove-Item -Path "HKCU:\Software\Microsoft\WindowsSelfHost" -Recurse -Force -ErrorAction SilentlyContinue
52 |     Remove-Item -Path "HKCU:\Software\Policies" -Recurse -Force -ErrorAction SilentlyContinue
53 |     Remove-Item -Path "HKLM:\Software\Microsoft\Policies" -Recurse -Force -ErrorAction SilentlyContinue
54 |     Remove-Item -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\Policies" -Recurse -Force -ErrorAction SilentlyContinue
55 |     Remove-Item -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion\WindowsStore\WindowsUpdate" -Recurse -Force -ErrorAction SilentlyContinue
56 |     Remove-Item -Path "HKLM:\Software\Microsoft\WindowsSelfHost" -Recurse -Force -ErrorAction SilentlyContinue
57 |     Remove-Item -Path "HKLM:\Software\Policies" -Recurse -Force -ErrorAction SilentlyContinue
58 |     Remove-Item -Path "HKLM:\Software\WOW6432Node\Microsoft\Policies" -Recurse -Force -ErrorAction SilentlyContinue
59 |     Remove-Item -Path "HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Policies" -Recurse -Force -ErrorAction SilentlyContinue
60 |     Remove-Item -Path "HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\WindowsStore\WindowsUpdate" -Recurse -Force -ErrorAction SilentlyContinue
61 | 
62 |     Write-Host "==================================================="
63 |     Write-Host "---  Windows Local Policies Reset to Default   ---"
64 |     Write-Host "==================================================="
65 | }
66 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFUpdatesdisable.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFUpdatesdisable {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Disables Windows Update
 6 | 
 7 |     .NOTES
 8 |         Disabling Windows Update is not recommended. This is only for advanced users who know what they are doing.
 9 | 
10 |     #>
11 |     If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU")) {
12 |         New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Force | Out-Null
13 |     }
14 |     Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "NoAutoUpdate" -Type DWord -Value 1
15 |     Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "AUOptions" -Type DWord -Value 1
16 |     If (!(Test-Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config")) {
17 |         New-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config" -Force | Out-Null
18 |     }
19 |     Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\DeliveryOptimization\Config" -Name "DODownloadMode" -Type DWord -Value 0
20 | 
21 |     $services = @(
22 |         "BITS"
23 |         "wuauserv"
24 |     )
25 | 
26 |     foreach ($service in $services) {
27 |         # -ErrorAction SilentlyContinue is so it doesn't write an error to stdout if a service doesn't exist
28 | 
29 |         Write-Host "Setting $service StartupType to Disabled"
30 |         Get-Service -Name $service -ErrorAction SilentlyContinue | Set-Service -StartupType Disabled
31 |     }
32 |     Write-Host "================================="
33 |     Write-Host "---   Updates ARE DISABLED    ---"
34 |     Write-Host "================================="
35 | }
36 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFUpdatessecurity.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFUpdatessecurity {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Sets Windows Update to recommended settings
 6 | 
 7 |     .DESCRIPTION
 8 |         1. Disables driver offering through Windows Update
 9 |         2. Disables Windows Update automatic restart
10 |         3. Sets Windows Update to Semi-Annual Channel (Targeted)
11 |         4. Defers feature updates for 365 days
12 |         5. Defers quality updates for 4 days
13 | 
14 |     #>
15 |     Write-Host "Disabling driver offering through Windows Update..."
16 |         If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Device Metadata")) {
17 |             New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Device Metadata" -Force | Out-Null
18 |         }
19 |         Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\Device Metadata" -Name "PreventDeviceMetadataFromNetwork" -Type DWord -Value 1
20 |         If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching")) {
21 |             New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Force | Out-Null
22 |         }
23 |         Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Name "DontPromptForWindowsUpdate" -Type DWord -Value 1
24 |         Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Name "DontSearchWindowsUpdate" -Type DWord -Value 1
25 |         Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DriverSearching" -Name "DriverUpdateWizardWuSearchEnabled" -Type DWord -Value 0
26 |         If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate")) {
27 |             New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" | Out-Null
28 |         }
29 |         Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate" -Name "ExcludeWUDriversInQualityUpdate" -Type DWord -Value 1
30 |         Write-Host "Disabling Windows Update automatic restart..."
31 |         If (!(Test-Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU")) {
32 |             New-Item -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Force | Out-Null
33 |         }
34 |         Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "NoAutoRebootWithLoggedOnUsers" -Type DWord -Value 1
35 |         Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU" -Name "AUPowerManagement" -Type DWord -Value 0
36 |         Write-Host "Disabled driver offering through Windows Update"
37 |         If (!(Test-Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings")) {
38 |             New-Item -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Force | Out-Null
39 |         }
40 |         Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "BranchReadinessLevel" -Type DWord -Value 20
41 |         Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "DeferFeatureUpdatesPeriodInDays" -Type DWord -Value 365
42 |         Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\WindowsUpdate\UX\Settings" -Name "DeferQualityUpdatesPeriodInDays" -Type DWord -Value 4
43 | 
44 |         $ButtonType = [System.Windows.MessageBoxButton]::OK
45 |         $MessageboxTitle = "Set Security Updates"
46 |         $Messageboxbody = ("Recommended Update settings loaded")
47 |         $MessageIcon = [System.Windows.MessageBoxImage]::Information
48 | 
49 |         [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon)
50 |         Write-Host "================================="
51 |         Write-Host "-- Updates Set to Recommended ---"
52 |         Write-Host "================================="
53 | }
54 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFtweaksbutton.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFtweaksbutton {
 2 |   <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Invokes the functions associated with each group of checkboxes
 6 | 
 7 |   #>
 8 | 
 9 |   if($sync.ProcessRunning) {
10 |     $msg = "[Invoke-WPFtweaksbutton] Install process is currently running."
11 |     [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
12 |     return
13 |   }
14 | 
15 |   $Tweaks = (Get-WinUtilCheckBoxes)["WPFTweaks"]
16 | 
17 |   Set-WinUtilDNS -DNSProvider $sync["WPFchangedns"].text
18 | 
19 |   if ($tweaks.count -eq 0 -and  $sync["WPFchangedns"].text -eq "Default") {
20 |     $msg = "Please check the tweaks you wish to perform."
21 |     [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
22 |     return
23 |   }
24 | 
25 |   Write-Debug "Number of tweaks to process: $($Tweaks.Count)"
26 | 
27 |   # The leading "," in the ParameterList is nessecary because we only provide one argument and powershell cannot be convinced that we want a nested loop with only one argument otherwise
28 |   Invoke-WPFRunspace -ParameterList @(,("tweaks",$tweaks)) -DebugPreference $DebugPreference -ScriptBlock {
29 |     param(
30 |       $tweaks,
31 |       $DebugPreference
32 |       )
33 |     Write-Debug "Inside Number of tweaks to process: $($Tweaks.Count)"
34 | 
35 |     $sync.ProcessRunning = $true
36 | 
37 |     if ($Tweaks.count -eq 1) {
38 |         $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
39 |     } else {
40 |         $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" })
41 |     }
42 |     # Execute other selected tweaks
43 | 
44 |     for ($i = 0; $i -lt $Tweaks.Count; $i++) {
45 |       Set-WinUtilProgressBar -Label "Applying $($tweaks[$i])" -Percent ($i / $tweaks.Count * 100)
46 |       Invoke-WinUtilTweaks $tweaks[$i]
47 |       $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i/$Tweaks.Count) })
48 |     }
49 |     Set-WinUtilProgressBar -Label "Tweaks finished" -Percent 100
50 |     $sync.ProcessRunning = $false
51 |     $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
52 |     Write-Host "================================="
53 |     Write-Host "--     Tweaks are Finished    ---"
54 |     Write-Host "================================="
55 | 
56 |     # $ButtonType = [System.Windows.MessageBoxButton]::OK
57 |     # $MessageboxTitle = "Tweaks are Finished "
58 |     # $Messageboxbody = ("Done")
59 |     # $MessageIcon = [System.Windows.MessageBoxImage]::Information
60 |     # [System.Windows.MessageBox]::Show($Messageboxbody, $MessageboxTitle, $ButtonType, $MessageIcon)
61 |   }
62 | }
63 | 


--------------------------------------------------------------------------------
/functions/public/Invoke-WPFundoall.ps1:
--------------------------------------------------------------------------------
 1 | function Invoke-WPFundoall {
 2 |     <#
 3 | 
 4 |     .SYNOPSIS
 5 |         Undoes every selected tweak
 6 | 
 7 |     #>
 8 | 
 9 |     if($sync.ProcessRunning) {
10 |         $msg = "[Invoke-WPFundoall] Install process is currently running."
11 |         [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
12 |         return
13 |     }
14 | 
15 |     $tweaks = (Get-WinUtilCheckBoxes)["WPFtweaks"]
16 | 
17 |     if ($tweaks.count -eq 0) {
18 |         $msg = "Please check the tweaks you wish to undo."
19 |         [System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
20 |         return
21 |     }
22 | 
23 |     Invoke-WPFRunspace -ArgumentList $tweaks -DebugPreference $DebugPreference -ScriptBlock {
24 |         param($tweaks, $DebugPreference)
25 | 
26 |         $sync.ProcessRunning = $true
27 |         if ($tweaks.count -eq 1) {
28 |             $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
29 |         } else {
30 |             $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" })
31 |         }
32 | 
33 | 
34 |         for ($i = 0; $i -lt $tweaks.Count; $i++) {
35 |             Set-WinUtilProgressBar -Label "Undoing $($tweaks[$i])" -Percent ($i / $tweaks.Count * 100)
36 |             Invoke-WinUtiltweaks $tweaks[$i] -undo $true
37 |             $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i/$tweaks.Count) })
38 |         }
39 | 
40 |         Set-WinUtilProgressBar -Label "Undo Tweaks Finished" -Percent 100
41 |         $sync.ProcessRunning = $false
42 |         $sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "None" -overlay "checkmark" })
43 |         Write-Host "=================================="
44 |         Write-Host "---  Undo Tweaks are Finished  ---"
45 |         Write-Host "=================================="
46 | 
47 |     }
48 | }
49 | 


--------------------------------------------------------------------------------
/functions/public/Show-CTTLogo.ps1:
--------------------------------------------------------------------------------
 1 | Function Show-CTTLogo {
 2 |     <#
 3 |         .SYNOPSIS
 4 |             Displays the CTT logo in ASCII art.
 5 |         .DESCRIPTION
 6 |             This function displays the CTT logo in ASCII art format.
 7 |         .PARAMETER None
 8 |             No parameters are required for this function.
 9 |         .EXAMPLE
10 |             Show-CTTLogo
11 |             Prints the CTT logo in ASCII art format to the console.
12 |     #>
13 | 
14 |     $asciiArt = @"
15 |     CCCCCCCCCCCCCTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
16 |  CCC::::::::::::CT:::::::::::::::::::::TT:::::::::::::::::::::T
17 | CC:::::::::::::::CT:::::::::::::::::::::TT:::::::::::::::::::::T
18 | C:::::CCCCCCCC::::CT:::::TT:::::::TT:::::TT:::::TT:::::::TT:::::T
19 | C:::::C       CCCCCCTTTTTT  T:::::T  TTTTTTTTTTTT  T:::::T  TTTTTT
20 | C:::::C                     T:::::T                T:::::T
21 | C:::::C                     T:::::T                T:::::T
22 | C:::::C                     T:::::T                T:::::T
23 | C:::::C                     T:::::T                T:::::T
24 | C:::::C                     T:::::T                T:::::T
25 | C:::::C                     T:::::T                T:::::T
26 | C:::::C       CCCCCC        T:::::T                T:::::T
27 | C:::::CCCCCCCC::::C      TT:::::::TT            TT:::::::TT
28 | CC:::::::::::::::C       T:::::::::T            T:::::::::T
29 | CCC::::::::::::C         T:::::::::T            T:::::::::T
30 |   CCCCCCCCCCCCC          TTTTTTTTTTT            TTTTTTTTTTT
31 | 
32 | ====Chris Titus Tech=====
33 | =====Windows Toolbox=====
34 | "@
35 | 
36 |     Write-Host $asciiArt
37 | }
38 | 
39 | 


--------------------------------------------------------------------------------
/lint/PSScriptAnalyser.ps1:
--------------------------------------------------------------------------------
 1 | @{
 2 |     # Only diagnostic records of the specified severity will be generated.
 3 |     # Uncomment the following line if you only want Errors and Warnings but
 4 |     # not Information diagnostic records.
 5 |     # Severity = @('Error','Warning')
 6 | 
 7 |     # Analyze **only** the following rules. Use IncludeRules when you want
 8 |     # to invoke only a small subset of the default rules.
 9 | <#
10 |     IncludeRules = @('PSAvoidDefaultValueSwitchParameter',
11 |                      'PSMisleadingBacktick',
12 |                      'PSMissingModuleManifestField',
13 |                      'PSReservedCmdletChar',
14 |                      'PSReservedParams',
15 |                      'PSShouldProcess',
16 |                      'PSUseApprovedVerbs',
17 |                      'PSUseDeclaredVarsMoreThanAssignments')
18 | #>
19 |     # Do not analyze the following rules. Use ExcludeRules when you have
20 |     # commented out the IncludeRules settings above and want to include all
21 |     # the default rules except for those you exclude below.
22 |     # Note: if a rule is in both IncludeRules and ExcludeRules, the rule
23 |     # will be excluded.
24 |     ExcludeRules = @('PSAvoidUsingWriteHost')
25 | }
26 | 


--------------------------------------------------------------------------------
/overrides/main.html:
--------------------------------------------------------------------------------
 1 | {% extends "base.html" %}
 2 | 
 3 | {% block header %}
 4 |     {{ super() }}
 5 |     <div style="color: red; text-align: center; padding: 10px; font-size: 20px;">
 6 |         <strong>Announcement:</strong> We are currently reworking the docs to use Hugo rather then mkdocs.
 7 |     </div>
 8 | {% endblock %}
 9 | 
10 | {% block footer %}
11 |     {# Empty block to override the footer #}
12 | {% endblock %}
13 | 


--------------------------------------------------------------------------------
/pester/configs.Tests.ps1:
--------------------------------------------------------------------------------
 1 | # Import Config Files
 2 | $global:importedconfigs = @{}
 3 | Get-ChildItem .\config | Where-Object {$_.Extension -eq ".json"} | ForEach-Object {
 4 |     $global:importedconfigs[$psitem.BaseName] = Get-Content $psitem.FullName | ConvertFrom-Json
 5 | }
 6 | 
 7 | 
 8 | #===========================================================================
 9 | # Tests - Application Installs
10 | #===========================================================================
11 | 
12 | Describe "Config Files" -ForEach @(
13 |     @{
14 |         name = "applications"
15 |         config = $('{
16 |             "winget": "value",
17 |             "choco": "value",
18 |             "category": "value",
19 |             "content": "value",
20 |             "description": "value",
21 |             "link": "value"
22 |           }' | ConvertFrom-Json)
23 |     },
24 |     @{
25 |         name = "tweaks"
26 |         undo = $true
27 |     }
28 | ) {
29 |     Context "$name config file" {
30 |         It "Imports with no errors" {
31 |             $global:importedconfigs.$name | should -Not -BeNullOrEmpty
32 |         }
33 |         if ($config) {
34 |             It "Imports should be the correct structure" {
35 |                 $applications = $global:importedconfigs.$name | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty name
36 |                 $template = $config | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty name
37 |                 $result = New-Object System.Collections.Generic.List[System.Object]
38 |                 Foreach ($application in $applications) {
39 |                     $compare = $global:importedconfigs.$name.$application | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty name
40 |                     if (-not $compare) {
41 |                         throw "Comparison object for application '$application' is null."
42 |                     }
43 |                     if (-not $template) {
44 |                         throw "Template object for application '$application' is null."
45 |                     }
46 |                     if ($(Compare-Object $compare $template) -ne $null) {
47 |                         $result.Add($application)
48 |                     }
49 |                 }
50 | 
51 |                 $result | Select-String "WPF*" | should -BeNullOrEmpty
52 |             }
53 |         }
54 |         if($undo) {
55 |             It "Tweaks should contain original Value" {
56 |                 $tweaks = $global:importedconfigs.$name | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty name
57 |                 $result = New-Object System.Collections.Generic.List[System.Object]
58 | 
59 |                 foreach ($tweak in $tweaks) {
60 |                     $Originals = @(
61 |                         @{
62 |                             name = "registry"
63 |                             value = "OriginalValue"
64 |                         },
65 |                         @{
66 |                             name = "service"
67 |                             value = "OriginalType"
68 |                         },
69 |                         @{
70 |                             name = "ScheduledTask"
71 |                             value = "OriginalState"
72 |                         }
73 |                     )
74 |                     Foreach ($original in $Originals) {
75 |                         $TotalCount = ($global:importedconfigs.$name.$tweak.$($original.name)).count
76 |                         $OriginalCount = ($global:importedconfigs.$name.$tweak.$($original.name).$($original.value) | Where-Object {$_}).count
77 |                         if($TotalCount -ne $OriginalCount) {
78 |                             $result.Add("$Tweak,$($original.name)")
79 |                         }
80 |                     }
81 |                 }
82 |                 $result | Select-String "WPF*" | should -BeNullOrEmpty
83 |             }
84 |         }
85 | 
86 |     }
87 | }
88 | 


--------------------------------------------------------------------------------
/pester/functions.Tests.ps1:
--------------------------------------------------------------------------------
 1 | #===========================================================================
 2 | # Tests - Functions
 3 | #===========================================================================
 4 | Describe "Comprehensive Checks for PS1 Files in Functions Folder" {
 5 |     BeforeAll {
 6 |         # Get all .ps1 files in the functions folder
 7 |         $ps1Files = Get-ChildItem -Path ./functions -Filter *.ps1 -Recurse
 8 |     }
 9 | 
10 |     foreach ($file in $ps1Files) {
11 |         Context "Checking $($file.Name)" {
12 |             It "Should import without errors" {
13 |                 { . $file.FullName } | Should -Not -Throw
14 |             }
15 | 
16 |             It "Should have no syntax errors" {
17 |                 $syntaxErrors = $null
18 |                 $null = [System.Management.Automation.PSParser]::Tokenize((Get-Content -Path $file.FullName -Raw), [ref]$syntaxErrors)
19 |                 $syntaxErrors.Count | Should -Be 0
20 |             }
21 | 
22 |             It "Should not use deprecated cmdlets or aliases" {
23 |                 $content = Get-Content -Path $file.FullName -Raw
24 |                 # Example check for a known deprecated cmdlet or alias
25 |                 $content | Should -Not -Match 'DeprecatedCmdlet'
26 |                 # Add more checks as needed
27 |             }
28 | 
29 |             It "Should follow naming conventions for functions" {
30 |                 $functions = (Get-Command -Path $file.FullName).Name
31 |                 foreach ($function in $functions) {
32 |                     $function | Should -Match '^[a-z]+(-[a-z]+)*
#39; # Enforce lower-kebab-case
33 |                 }
34 |             }
35 | 
36 |             It "Should define mandatory parameters for all functions" {
37 |                 . $file.FullName
38 |                 $functions = (Get-Command -Path $file.FullName).Name
39 |                 foreach ($function in $functions) {
40 |                     $parameters = (Get-Command -Name $function).Parameters.Values
41 |                     $mandatoryParams = $parameters | Where-Object { $_.Attributes.Mandatory -eq $true }
42 |                     $mandatoryParams.Count | Should -BeGreaterThan 0
43 |                 }
44 |             }
45 | 
46 |             It "Should have all functions available after import" {
47 |                 . $file.FullName
48 |                 $functions = (Get-Command -Path $file.FullName).Name
49 |                 foreach ($function in $functions) {
50 |                     { Get-Command -Name $function -CommandType Function } | Should -Not -BeNullOrEmpty
51 |                 }
52 |             }
53 |         }
54 |     }
55 | }
56 | 


--------------------------------------------------------------------------------
/releases/oscdimg.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ChrisTitusTech/winutil/c983ec2253b760cbe5ec5bcbfec0ff76827c7549/releases/oscdimg.exe


--------------------------------------------------------------------------------
/scripts/start.ps1:
--------------------------------------------------------------------------------
 1 | <#
 2 | .NOTES
 3 |     Author         : Chris Titus @christitustech
 4 |     Runspace Author: @DeveloperDurp
 5 |     GitHub         : https://github.com/ChrisTitusTech
 6 |     Version        : #{replaceme}
 7 | #>
 8 | 
 9 | param (
10 |     [switch]$Debug,
11 |     [string]$Config,
12 |     [switch]$Run
13 | )
14 | 
15 | # Set DebugPreference based on the -Debug switch
16 | if ($Debug) {
17 |     $DebugPreference = "Continue"
18 | }
19 | 
20 | if ($Config) {
21 |     $PARAM_CONFIG = $Config
22 | }
23 | 
24 | $PARAM_RUN = $false
25 | # Handle the -Run switch
26 | if ($Run) {
27 |     Write-Host "Running config file tasks..."
28 |     $PARAM_RUN = $true
29 | }
30 | 
31 | # Load DLLs
32 | Add-Type -AssemblyName PresentationFramework
33 | Add-Type -AssemblyName System.Windows.Forms
34 | 
35 | # Variable to sync between runspaces
36 | $sync = [Hashtable]::Synchronized(@{})
37 | $sync.PSScriptRoot = $PSScriptRoot
38 | $sync.version = "#{replaceme}"
39 | $sync.configs = @{}
40 | $sync.Buttons = [System.Collections.Generic.List[PSObject]]::new()
41 | $sync.ProcessRunning = $false
42 | $sync.selectedApps = [System.Collections.Generic.List[string]]::new()
43 | $sync.currentTab = "Install"
44 | $sync.selectedAppsStackPanel
45 | $sync.selectedAppsPopup
46 | 
47 | 
48 | if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
49 |     Write-Output "Winutil needs to be run as Administrator. Attempting to relaunch."
50 |     $argList = @()
51 | 
52 |     $PSBoundParameters.GetEnumerator() | ForEach-Object {
53 |         $argList += if ($_.Value -is [switch] -and $_.Value) {
54 |             "-$($_.Key)"
55 |         } elseif ($_.Value -is [array]) {
56 |             "-$($_.Key) $($_.Value -join ',')"
57 |         } elseif ($_.Value) {
58 |             "-$($_.Key) '$($_.Value)'"
59 |         }
60 |     }
61 | 
62 |     $script = if ($PSCommandPath) {
63 |         "& { & `'$($PSCommandPath)`' $($argList -join ' ') }"
64 |     } else {
65 |         "&([ScriptBlock]::Create((irm https://github.com/ChrisTitusTech/winutil/releases/latest/download/winutil.ps1))) $($argList -join ' ')"
66 |     }
67 | 
68 |     $powershellCmd = if (Get-Command pwsh -ErrorAction SilentlyContinue) { "pwsh" } else { "powershell" }
69 |     $processCmd = if (Get-Command wt.exe -ErrorAction SilentlyContinue) { "wt.exe" } else { "$powershellCmd" }
70 | 
71 |     if ($processCmd -eq "wt.exe") {
72 |         Start-Process $processCmd -ArgumentList "$powershellCmd -ExecutionPolicy Bypass -NoProfile -Command `"$script`"" -Verb RunAs
73 |     } else {
74 |         Start-Process $processCmd -ArgumentList "-ExecutionPolicy Bypass -NoProfile -Command `"$script`"" -Verb RunAs
75 |     }
76 | 
77 |     break
78 | }
79 | 
80 | $dateTime = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
81 | 
82 | $logdir = "$env:localappdata\winutil\logs"
83 | [System.IO.Directory]::CreateDirectory("$logdir") | Out-Null
84 | Start-Transcript -Path "$logdir\winutil_$dateTime.log" -Append -NoClobber | Out-Null
85 | 
86 | # Set PowerShell window title
87 | $Host.UI.RawUI.WindowTitle = "WinUtil (Admin)"
88 | clear-host
89 | 


--------------------------------------------------------------------------------
/sign.bat:
--------------------------------------------------------------------------------
1 | signtool.exe sign /td sha256 /tr http://timestamp.digicert.com /fd sha256 /n "CT Tech Group LLC" .\winutil.ps1
2 | 


--------------------------------------------------------------------------------
/windev.ps1:
--------------------------------------------------------------------------------
 1 | <#
 2 | .SYNOPSIS
 3 |     This Script is used as a target for the https://christitus.com/windev alias.
 4 |     It queries the latest winget release (no matter if Pre-Release, Draft or Full Release) and invokes It
 5 | .DESCRIPTION
 6 |     This Script provides a simple way to always start the bleeding edge release even if it's not yet a full release.
 7 |     This function should be run with administrative privileges.
 8 |     Because this way of recursively invoking scripts via Invoke-Expression it might very well happen that AV Programs flag this because it's a common way of mulitstage exploits to run
 9 | .EXAMPLE
10 |     irm https://christitus.com/windev | iex
11 |     OR
12 |     Run in Admin Powershell >  ./windev.ps1
13 | #>
14 | 
15 | # Function to fetch the latest release tag from the GitHub API
16 | function Get-LatestRelease {
17 |     try {
18 |         $releases = Invoke-RestMethod -Uri 'https://api.github.com/repos/ChrisTitusTech/winutil/releases'
19 |         $latestRelease = $releases | Where-Object {$_.prerelease -eq $true} | Select-Object -First 1
20 |         return $latestRelease.tag_name
21 |     } catch {
22 |         Write-Host "Error fetching release data: $_" -ForegroundColor Red
23 |         return $latestRelease.tag_name
24 |     }
25 | }
26 | 
27 | # Function to redirect to the latest pre-release version
28 | function RedirectToLatestPreRelease {
29 |     $latestRelease = Get-LatestRelease
30 |     if ($latestRelease) {
31 |         $url = "https://github.com/ChrisTitusTech/winutil/releases/download/$latestRelease/winutil.ps1"
32 |     } else {
33 |         Write-Host 'No pre-release version found. This is most likely because the latest release is a full release and no newer pre-release exists.' -ForegroundColor Yellow
34 |         Write-Host "Using latest Full Release"
35 |         $url = "https://github.com/ChrisTitusTech/winutil/releases/latest/download/winutil.ps1"
36 |     }
37 | 
38 |     $script = Invoke-RestMethod $url
39 |     # Elevate Shell if necessary
40 |     if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
41 |         Write-Output "Winutil needs to be run as Administrator. Attempting to relaunch."
42 | 
43 |         $powershellcmd = if (Get-Command pwsh -ErrorAction SilentlyContinue) { "pwsh" } else { "powershell" }
44 |         $processCmd = if (Get-Command wt.exe -ErrorAction SilentlyContinue) { "wt.exe" } else { $powershellcmd }
45 | 
46 |         Start-Process $processCmd -ArgumentList "$powershellcmd -ExecutionPolicy Bypass -NoProfile -Command $(Invoke-Expression $script)" -Verb RunAs
47 |     }
48 |     else{
49 |         Invoke-Expression $script
50 |     }
51 | }
52 | 
53 | # Call the redirect function
54 | 
55 | RedirectToLatestPreRelease
56 | 


--------------------------------------------------------------------------------