mirror of
https://github.com/ChrisTitusTech/winutil.git
synced 2025-07-01 10:32:35 -05:00
Compare commits
630 Commits
9233d934d3
...
main
Author | SHA1 | Date | |
---|---|---|---|
cea4e088cf | |||
32a4311901 | |||
ff95b35f24 | |||
aea9c2cb47 | |||
7fa0594267 | |||
5e65505007 | |||
686e65adcb | |||
1935375f88 | |||
069a1bda2f | |||
661dfa6318 | |||
d6b78d1d06 | |||
51f15a03c2 | |||
ce91307daf | |||
8fe09d0054 | |||
e74258acf4 | |||
28958938fc | |||
91de389c8f | |||
6b22c63d28 | |||
faa4701c43 | |||
cda2babc66 | |||
0e83879c64 | |||
00c295e8d5 | |||
4be99d5f8a | |||
febae28095 | |||
0a77838689 | |||
cccd4298ad | |||
bc7afe8b2a | |||
18de3d59ee | |||
59d968e7c4 | |||
afe85ad7f0 | |||
efb9e5bde6 | |||
56eba47a6c | |||
e57cde423c | |||
de9b643129 | |||
e430e0aad0 | |||
61fd4d2f91 | |||
b72cd83189 | |||
290292ec94 | |||
d22865d79b | |||
5c5b999a09 | |||
0c0e6bd243 | |||
dd06489d63 | |||
41df9d3d88 | |||
63d56bcac9 | |||
962b18e8fa | |||
14e761f438 | |||
3e416f5c14 | |||
95d28ee25d | |||
50071067b7 | |||
3b7d707262 | |||
ea95dac426 | |||
b4d3368680 | |||
0b5c44cbcf | |||
b8b16be24b | |||
14943e3c55 | |||
91365d50b5 | |||
82b6c268b0 | |||
d8c007d2db | |||
48f1c71584 | |||
f770642a6a | |||
963c0a17aa | |||
20769f66a1 | |||
86459b7e24 | |||
89919494e5 | |||
5f6bdb2e48 | |||
f614eea435 | |||
82447a1e7b | |||
51424abfad | |||
3caa3be9a3 | |||
7769a328bb | |||
425f11d787 | |||
6df94df594 | |||
29e2c4d197 | |||
b63a17b7dd | |||
abe059917c | |||
698f1644c3 | |||
fd03f33c50 | |||
8f9e7d1b7c | |||
b3dd1a1a50 | |||
4acad32a38 | |||
0f4fca31b9 | |||
36c984b66c | |||
d215d0fc2c | |||
52de4690ab | |||
ef97a8da24 | |||
18a7f17a0b | |||
5a8cf5deb6 | |||
e4b2a38372 | |||
94c5d89430 | |||
8a0e0c7715 | |||
1ae16f6f38 | |||
6038556e64 | |||
329a3de9a6 | |||
f6e5d0e053 | |||
364076c25e | |||
a051e64a91 | |||
dccda61ab4 | |||
048f580a56 | |||
bfb83ced79 | |||
e2b37445f6 | |||
c2fb98b0dc | |||
cf8787a700 | |||
53b723fa11 | |||
32cb94f392 | |||
5550e40270 | |||
bcecf67c7d | |||
3b50ff813c | |||
eba5b35978 | |||
254738a420 | |||
bcc801683d | |||
72c23823b2 | |||
4e1ce7e417 | |||
1dd0367417 | |||
201f24c76e | |||
9183e92692 | |||
fa9dbcace4 | |||
02f0f85c25 | |||
83ae0579ba | |||
5ebcacf404 | |||
28bea518f0 | |||
61c2e39ddb | |||
0dfa9617fc | |||
2ce4f54b80 | |||
a05556a896 | |||
985d415db1 | |||
f4d4bdad3c | |||
9d47514190 | |||
4fc34e44b3 | |||
c33946bde2 | |||
4466720493 | |||
1d0e3bfd5c | |||
83450aef7b | |||
e2ce998426 | |||
cf7f161a06 | |||
d6c1fbe4a2 | |||
0779dd9096 | |||
d48f212be4 | |||
9c52f01204 | |||
d49b21f881 | |||
39ee4d53c0 | |||
6e708bfe95 | |||
e2b9586b0d | |||
c418fe9030 | |||
d619ee7e85 | |||
bbc18b2d4b | |||
9778c0d572 | |||
8087a607fc | |||
e5b79559bd | |||
66e6aa7e96 | |||
def47fe018 | |||
b382f16ae8 | |||
171441ddcf | |||
7a0c40420e | |||
0f0d9d0ae3 | |||
6149738e6c | |||
aa0b03feda | |||
e0889d51db | |||
ce1ef2a519 | |||
77cb0a14c4 | |||
c254a43f77 | |||
640d2ca107 | |||
c186642998 | |||
47a4f1547e | |||
1caf3111d3 | |||
7dcdc4dbb7 | |||
bfaba14191 | |||
5640f9d04c | |||
c6a832b006 | |||
fe19094395 | |||
fdd32f441f | |||
e4565f1f6f | |||
1404efab26 | |||
1deb863f40 | |||
de73efa868 | |||
59097fc7e1 | |||
207ce43428 | |||
d92284ec83 | |||
d855b08119 | |||
0deac4ebb2 | |||
c6fcf21dce | |||
64ed00c2db | |||
e165388117 | |||
806cbd021a | |||
869071783c | |||
ae74965548 | |||
b43d31088c | |||
4fa1b0ddc7 | |||
f012064574 | |||
db26666f97 | |||
38cf922572 | |||
dd337be45e | |||
3670c78789 | |||
225e774f1e | |||
0703935bfb | |||
fd2ac35228 | |||
f516c09ab3 | |||
182fe09b64 | |||
02751c706d | |||
102231c0e3 | |||
b9d7619f9b | |||
4e39096b51 | |||
662139ca5f | |||
42febae25e | |||
395ac9495d | |||
6cc7d314fe | |||
ba45c3303e | |||
1f683d3f78 | |||
18dff2af5e | |||
377758758e | |||
3f2759f967 | |||
1ee7274bdb | |||
06baebc60b | |||
10917c159c | |||
0251757fc0 | |||
9136ed9802 | |||
b3bbe0dbe5 | |||
16b11e994b | |||
a5a06c2a9b | |||
81aead7a68 | |||
a55a44a54c | |||
9c0b0b8913 | |||
7fe0f9a163 | |||
8e5fcceddb | |||
19a3c7070a | |||
343a72f528 | |||
0b13ca4b11 | |||
215de06a58 | |||
80555d945e | |||
314588283a | |||
00668755c9 | |||
d3ef94f175 | |||
1ac24c236e | |||
ff363d686f | |||
9abe11c975 | |||
14d20cd161 | |||
2b9b1b026c | |||
e9a45a002f | |||
6d996495a3 | |||
473f04ddc5 | |||
95db85f791 | |||
5059b93cd7 | |||
380e1e73a6 | |||
ad37371492 | |||
1bfd8bddcc | |||
6ad31edef1 | |||
c1009c3d7c | |||
885108df7e | |||
b21bc35443 | |||
e2d539048d | |||
588008612d | |||
859a733740 | |||
3bb1881254 | |||
8b37420eec | |||
af7528a60b | |||
0c6b2adb91 | |||
0635145896 | |||
2d751f4e8c | |||
9b9d0c58f5 | |||
531cb4c63c | |||
42bda0dc47 | |||
3414a3eee1 | |||
a4302742b3 | |||
2a0d121cf0 | |||
a397f20ac6 | |||
bddf57bcee | |||
2b3f1a811d | |||
2af864f7ab | |||
2b8592a50a | |||
aad0356c28 | |||
01515db90f | |||
2ba5572b6c | |||
7e1c593510 | |||
b6141808af | |||
a21845327b | |||
2a355c00c8 | |||
2d3dbe4f6a | |||
d315963693 | |||
6c82adbdc9 | |||
c1dd88d84a | |||
b67ec35cbb | |||
c45f36d58f | |||
1fc79bccf2 | |||
2b7d0b6c4b | |||
42061faa81 | |||
889ec8f57d | |||
be6b5b3aa0 | |||
90ddfb02a4 | |||
ece57f8ee2 | |||
6a99be9e05 | |||
488cd8dd98 | |||
7eed393902 | |||
97876348d9 | |||
f8db21bbee | |||
3697be1be4 | |||
51068d9670 | |||
46f827fe2f | |||
f6b238ec30 | |||
cc157f6976 | |||
9ae5092e29 | |||
c741e006eb | |||
322d527a0c | |||
99aff2aefc | |||
cfb9edbce7 | |||
bcfbce66fd | |||
2748767a47 | |||
83fe6c5b12 | |||
2ea708eeb0 | |||
11d3c66fc0 | |||
3dd51a6c3c | |||
307980a7ef | |||
93c96fafd2 | |||
4d2ea15e19 | |||
b0d54e41ad | |||
d0fa506e4f | |||
67be99bb7b | |||
46d9e2c437 | |||
863dd83faa | |||
09eb4eaa00 | |||
17d523d8f8 | |||
fa17abdd49 | |||
8fd08f7ac5 | |||
6c3539edbe | |||
ed1cdf0233 | |||
a046bcd6a2 | |||
bf518522f8 | |||
35dfd847ab | |||
0e85f20680 | |||
bdfc4c076c | |||
8c4dc82d31 | |||
e90156adb9 | |||
5d7d121e1f | |||
0919e78693 | |||
41ac93d09a | |||
5994105fba | |||
0bce9e2647 | |||
723e1a132d | |||
5acbfbd253 | |||
1945fe288d | |||
6ff815eed3 | |||
138c5de5d3 | |||
c619d02724 | |||
a0d15f1584 | |||
c5f29df2b2 | |||
11333a1f17 | |||
ff4398e45c | |||
7841f4bbce | |||
5b993adba9 | |||
73d42dee20 | |||
ee0a2818b6 | |||
9a1fbd77a7 | |||
5e3c6ba452 | |||
478aa4ac7b | |||
123d78116b | |||
a2d9f47ea6 | |||
da824d58a7 | |||
f38f534850 | |||
04c84dce45 | |||
3903eaaa24 | |||
3b2af3fa2b | |||
c979dae926 | |||
a5a8f3ff6f | |||
31aedcf684 | |||
ab6898aebc | |||
68437c2406 | |||
7c214666b8 | |||
9284741cd3 | |||
97e517a9dd | |||
97f67fa4b2 | |||
a77ef020fe | |||
2b01fb739f | |||
f3df13a4ca | |||
33d5d55b15 | |||
0bea5f8ceb | |||
de8a79df22 | |||
1c9cef0079 | |||
49100e1dd6 | |||
547e433b0b | |||
4ee41cf198 | |||
c2addcfedf | |||
09575b0f8d | |||
5a89053534 | |||
1350013b3e | |||
80675b4c3f | |||
2a530d0c12 | |||
fb1a0b919c | |||
83bcf246f6 | |||
e2567bddc9 | |||
2508f28806 | |||
2d185e1919 | |||
5ac13f265e | |||
128593a950 | |||
e7328c2739 | |||
18f9f5e35d | |||
760fb3d30a | |||
a75c80057a | |||
514eddd0b6 | |||
3929459106 | |||
b4bf321e66 | |||
74f58e7957 | |||
875864060e | |||
e38615b4b4 | |||
9f33cb1b82 | |||
313c5f59de | |||
7de93ae208 | |||
140620e76c | |||
8ae328c4b5 | |||
1032d3d5aa | |||
84a84fd34d | |||
b23c685580 | |||
214eb1d332 | |||
5083b84233 | |||
4553f3e758 | |||
8baacc2966 | |||
a8c47e64d7 | |||
fcc48a2b22 | |||
f2a5574a8c | |||
363ed1c41b | |||
706328e674 | |||
2f43975735 | |||
d1a40217c1 | |||
790afac860 | |||
efee03b940 | |||
8beca950a8 | |||
9bc6adf191 | |||
fb34c7cbd8 | |||
ae1b22552a | |||
57f4eba692 | |||
22684da35b | |||
7acb213a77 | |||
b9e8b9f697 | |||
300439c851 | |||
0e7ac225af | |||
0bbbe67446 | |||
376cc1d745 | |||
499848d643 | |||
601e338929 | |||
8045a78c44 | |||
df2fe4a4c6 | |||
8a6116cea1 | |||
e82870da89 | |||
e784604a1a | |||
e8022b8556 | |||
e7ed7829cf | |||
508f909fc9 | |||
60a6c387e2 | |||
1307abc1d6 | |||
45a103f76b | |||
b84c0d9248 | |||
f51c30023a | |||
bce4868896 | |||
8141baa879 | |||
280f8a7dbc | |||
0a472c06c4 | |||
1c72007a29 | |||
07434f706b | |||
4176435ebf | |||
a38cfb14d3 | |||
b319c32ae6 | |||
829e46b3a8 | |||
2304b06f68 | |||
c90363181c | |||
5d3d47eeb5 | |||
bc213d34d9 | |||
df2cd71d1e | |||
a760400aeb | |||
07a78fc3d8 | |||
78a6a60d96 | |||
1fb986a05d | |||
51e5af41ed | |||
7dba867101 | |||
ce787a9074 | |||
425ec42cb5 | |||
b2cd7d7897 | |||
ad9cc6fffd | |||
594ee94f49 | |||
30bea93dde | |||
2e26ae7ef1 | |||
0138a76601 | |||
8340aca48f | |||
265f4eb705 | |||
40cf1f80ef | |||
e182d2433f | |||
4831828b27 | |||
c9934a53b0 | |||
904e0ad468 | |||
792a5c4b38 | |||
ff0b3d29cf | |||
ac9b4fd645 | |||
84ca02a033 | |||
8cfd47e1b7 | |||
8df9a7c590 | |||
1d01b7490f | |||
3245756935 | |||
54ad3198dd | |||
7904380c8b | |||
81e8ca7fdc | |||
86cf331e01 | |||
150a99026f | |||
272a993099 | |||
d4faee5fbc | |||
e5ba389606 | |||
af36d76e65 | |||
5b7f0a0edf | |||
7294064aaa | |||
1e7b73df33 | |||
c68b8d0f75 | |||
2c1031865f | |||
b1e995fcaf | |||
e798ec9126 | |||
c4daafbe79 | |||
1f0ee72834 | |||
950bd59e2f | |||
05267d8a37 | |||
37089aeb5c | |||
bdb60b0b44 | |||
84242db2db | |||
2844b0df54 | |||
b2e3487989 | |||
01837b028a | |||
af1743066f | |||
d261f42ae4 | |||
02f335f4f3 | |||
3cb9a4f0ea | |||
d5c68029fe | |||
5375675347 | |||
8ed7732cbf | |||
fb932d7e10 | |||
78f2aa5979 | |||
5176e3d4ff | |||
b4aff6f7d3 | |||
ae240af11f | |||
cedc752be5 | |||
a1f534e6b5 | |||
cb1aed3bdd | |||
9e155c94d0 | |||
700a785092 | |||
80c7f6045f | |||
3466ea222d | |||
448d27f064 | |||
90f9c16446 | |||
0a821f6e21 | |||
aaaf5f7f85 | |||
d7c2e2cf2a | |||
9f3ad1b998 | |||
88612b4225 | |||
5c14d44afa | |||
d62d41347a | |||
6aaeb09e73 | |||
96d80c486b | |||
47dbbfb4ff | |||
ce7d14b227 | |||
79afb8c1bd | |||
65f76c2a77 | |||
cf9cb52cdb | |||
7dcd0ed67e | |||
49b7224a6f | |||
f04c87f5a3 | |||
d732c40b9a | |||
8984c177a0 | |||
747b1d76fd | |||
1b1ac22251 | |||
bcc8ad8171 | |||
6b73f71876 | |||
b47036630c | |||
e5ca44a0bd | |||
e7d49fe48b | |||
a5fbff142b | |||
e830894819 | |||
d4dc9aec9b | |||
e4d0e16b26 | |||
d6102e8954 | |||
227cb21c24 | |||
1891ea7966 | |||
6c49a8f2c9 | |||
ab384029f1 | |||
0c32d016b4 | |||
45818fd80c | |||
d08954945c | |||
a7ab24e3c9 | |||
a924d91d65 | |||
676e46f59f | |||
37b9c552df | |||
2e12176b2d | |||
7d1e4a8d82 | |||
4f8e7a8ea7 | |||
6c4c24b26d | |||
d205e75030 | |||
12561aba2c | |||
84fd1bc71c | |||
b9cd563915 | |||
58df438b92 | |||
9086b30a75 | |||
b268f98b91 | |||
25a4ebe062 | |||
60f5ef1f8e | |||
491b0b534c | |||
a59a30f905 | |||
227babe0e8 | |||
a0c4b33483 | |||
b831901967 | |||
d0427403f1 | |||
312f42f39a | |||
f68c9bf213 | |||
7b6a624ec6 | |||
43304808a9 | |||
ad0ed09940 | |||
b9813f86b9 | |||
2c5707e18f | |||
b646b139b8 | |||
5b369250b6 | |||
9274c683a2 | |||
f559de3a8c | |||
1e71020757 | |||
83ef15ccaf | |||
c2938f9339 | |||
b2be290be2 | |||
b6723bebf0 | |||
42c1ef434c | |||
a6ad919f16 | |||
52fd667ef9 | |||
04130231ff | |||
a510b52acb | |||
48581d6aad | |||
c3a77e71ad | |||
3d7b232248 | |||
b6d1dc50cb | |||
f6af93afbd | |||
0c841f98e8 | |||
e4c44e4878 | |||
8a78c960ea |
11
.gitattributes
vendored
11
.gitattributes
vendored
@ -1,3 +1,12 @@
|
||||
* text=auto
|
||||
|
||||
*.ps1 text eol=crlf
|
||||
*.json text eol=crlf
|
||||
*.cfg text eol=crlf
|
||||
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
|
||||
config/* diff
|
||||
config/applications.json diff
|
||||
*.json diff
|
||||
*.json diff
|
||||
|
128
.github/CODE_OF_CONDUCT.md
vendored
Normal file
128
.github/CODE_OF_CONDUCT.md
vendored
Normal file
@ -0,0 +1,128 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
and learning from the experience
|
||||
* Focusing on what is best not just for us as individuals, but for the
|
||||
overall community
|
||||
|
||||
Examples of unacceptable behavior include:
|
||||
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported to the community leaders responsible for enforcement at
|
||||
contact@christitus.com.
|
||||
All complaints will be reviewed and investigated promptly and fairly.
|
||||
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## Enforcement Guidelines
|
||||
|
||||
Community leaders will follow these Community Impact Guidelines in determining
|
||||
the consequences for any action they deem in violation of this Code of Conduct:
|
||||
|
||||
### 1. Correction
|
||||
|
||||
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||
unprofessional or unwelcome in the community.
|
||||
|
||||
**Consequence**: A private, written warning from community leaders, providing
|
||||
clarity around the nature of the violation and an explanation of why the
|
||||
behavior was inappropriate. A public apology may be requested.
|
||||
|
||||
### 2. Warning
|
||||
|
||||
**Community Impact**: A violation through a single incident or series
|
||||
of actions.
|
||||
|
||||
**Consequence**: A warning with consequences for continued behavior. No
|
||||
interaction with the people involved, including unsolicited interaction with
|
||||
those enforcing the Code of Conduct, for a specified period of time. This
|
||||
includes avoiding interactions in community spaces as well as external channels
|
||||
like social media. Violating these terms may lead to a temporary or
|
||||
permanent ban.
|
||||
|
||||
### 3. Temporary Ban
|
||||
|
||||
**Community Impact**: A serious violation of community standards, including
|
||||
sustained inappropriate behavior.
|
||||
|
||||
**Consequence**: A temporary ban from any sort of interaction or public
|
||||
communication with the community for a specified period of time. No public or
|
||||
private interaction with the people involved, including unsolicited interaction
|
||||
with those enforcing the Code of Conduct, is allowed during this period.
|
||||
Violating these terms may lead to a permanent ban.
|
||||
|
||||
### 4. Permanent Ban
|
||||
|
||||
**Community Impact**: Demonstrating a pattern of violation of community
|
||||
standards, including sustained inappropriate behavior, harassment of an
|
||||
individual, or aggression toward or disparagement of classes of individuals.
|
||||
|
||||
**Consequence**: A permanent ban from any sort of public interaction within
|
||||
the community.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available at
|
||||
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder](https://github.com/mozilla/diversity).
|
||||
|
||||
[homepage]: https://www.contributor-covenant.org
|
||||
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
https://www.contributor-covenant.org/faq. Translations are available at
|
||||
https://www.contributor-covenant.org/translations.
|
117
.github/CONTRIBUTING.md
vendored
Normal file
117
.github/CONTRIBUTING.md
vendored
Normal file
@ -0,0 +1,117 @@
|
||||
# How to Contribute?
|
||||
|
||||
## Testing
|
||||
|
||||
* Test the latest changes to WinUtil by running the pre-release and reporting issues you are encountering to help us continually improve WinUtil!
|
||||
|
||||
#### **Run the latest pre-release**
|
||||
```ps1
|
||||
irm https://christitus.com/windev | iex
|
||||
```
|
||||
|
||||
!!! bug "Keep in mind"
|
||||
|
||||
This is a pre-release and should be treated as such. It exists for developers to test the utility and report or fix bugs before they get added to the stable release. Don't use it in production!
|
||||
|
||||
## Issues
|
||||
|
||||
* If you encounter any challenges or problems with the script, I kindly request that you submit them via the "Issues" tab on the GitHub repository. By filling out the provided template, you can provide specific details about the issue, allowing me (and others in the community) to promptly address any bugs or consider feature requests.
|
||||
|
||||
## Contribute Code
|
||||
|
||||
* Pull requests are now handled directly on the **MAIN branch**. This was done since we can now select specific releases to launch via releases in GitHub.
|
||||
|
||||
* If you're doing code changes, then you can submit a PR to `main` branch, but I am very selective about these.
|
||||
|
||||
!!! warning "Important"
|
||||
|
||||
Do not use a code formatter, make massive amounts of line changes, or make multiple feature changes. EACH FEATURE CHANGE SHOULD BE IT'S OWN PULL REQUEST!
|
||||
|
||||
* When creating pull requests, it is essential to thoroughly document all changes made. This includes, but is not limited to, documenting any additions made to the `tweaks` section and corresponding `undo tweak`, so users are able to remove the newly added tweaks if necessary, and comprehensive documentation is required for all code changes. Document your changes and briefly explain why you made your changes in your Pull Request Description. Failure to adhere to this format may result in the denial of the pull request. Additionally, any code lacking sufficient documentation may also be denied.
|
||||
|
||||
* By following these guidelines, we can maintain a high standard of quality and ensure that the codebase remains organized and well-documented.
|
||||
|
||||
!!! note
|
||||
|
||||
When creating a function, please include "WPF" or "WinUtil" in the file name so it can be loaded into the runspace.
|
||||
|
||||
## Walk through
|
||||
|
||||
* This is a guide for beginners. If you are still having issues, look at the following official GitHub documentation:
|
||||
* [Commit through WEB](https://docs.github.com/en/pull-requests/committing-changes-to-your-project/creating-and-editing-commits/about-commits)
|
||||
* [Commit through GitHub Desktop](https://docs.github.com/en/desktop/making-changes-in-a-branch/committing-and-reviewing-changes-to-your-project-in-github-desktop#about-commits)
|
||||
* [Create a Pull Request](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request)
|
||||
|
||||
|
||||
### Overview
|
||||
|
||||
``` mermaid
|
||||
%%{init: {"flowchart": {"curve": "cardinal"}} }%%
|
||||
graph TD
|
||||
A[Fork Project] --> B[Clone Repository];
|
||||
B --> C[Create New Branch];
|
||||
C --> D[Make Changes];
|
||||
D --> G[Test Changes];
|
||||
G --> H{Tests Passed?};
|
||||
H -->|Yes| E[Commit Changes];
|
||||
H -->|No| J[Fix Issues];
|
||||
J --> G;
|
||||
E --> F[Push Branch];
|
||||
F --> K[Create Pull Request];
|
||||
K --> L[Fill out PR template];
|
||||
classDef default stroke:#333,stroke-width:4px,font-size:12pt;
|
||||
```
|
||||
!!! info
|
||||
|
||||
This is a diagram to guide you through the process. It may vary depending on the type of change you're making.
|
||||
|
||||
### Fork the Repo
|
||||
* Fork the WinUtil Repository [here](https://github.com/ChrisTitusTech/winutil) to create a copy that will be available in your repository list.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
### Clone the Fork
|
||||
!!! tip
|
||||
|
||||
While you can make your changes directly through the Web, we recommend cloning the repo to your device using the application GitHub Desktop (available in WinUtil) to test your fork easily.
|
||||
|
||||
* Install GitHub Desktop if it is not already installed.
|
||||
* Log in using the same GitHub account you used to fork WinUtil.
|
||||
* Choose the fork under "Your Repositories" and press "clone {repo name}"
|
||||
* Create a new branch and name it something relatable to your changes.
|
||||
|
||||
* Now you can modify WinUtil to your liking using your preferred text editor.
|
||||
|
||||
|
||||
### Testing your changes
|
||||
|
||||
* To test to see if your changes work as intended run following commands in a powershell teminal as admin:
|
||||
|
||||
* Change the directory where you are running the commands to the forked project.
|
||||
* `cd {path to the folder with the compile.ps1}`
|
||||
* Run the following command to compile and run WinUtil:
|
||||
* `.\Compile.ps1 -run`
|
||||
|
||||

|
||||
|
||||
* After seeing that your changes work properly, feel free to commit the changes to the repository and make a PR. For help on that, follow the documentation below.
|
||||
|
||||
### Committing the changes
|
||||
* Before committing your changes, please discard changes made to the `winutil.ps1` file, like the following:
|
||||
|
||||

|
||||
|
||||
* Now, commit your changes once you are happy with the result.
|
||||
|
||||

|
||||
|
||||
* Push the changes to upload them to your fork on github.com.
|
||||
|
||||

|
||||
|
||||
### Making a PR
|
||||
* To make a PR on your repo under a new branch linking to the main branch, a button will show and say Preview and Create pull request. Click that button and fill in all the information that is provided on the template. Once all the information is filled in correctly, check your PR to make sure there is not a WinUtil.ps1 file attached to the PR. Once everything is good, make the PR and wait for Chris (the maintainer) to accept or deny your PR. Once it is accepted by Chris, you will be able to see your changes in the "/windev" build.
|
||||
* If you do not see your feature in the main "/win" build, that is fine. All new changes go into the /windev build to make sure everything is working OK before going fully public.
|
||||
* Congratulations! You just submitted your first PR. Thank you so much for contributing to WinUtil.
|
27
.github/ISSUE_TEMPLATE/bug_report.md
vendored
27
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@ -1,27 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior:
|
||||
1. Go to '...'
|
||||
2. Click on '....'
|
||||
3. Scroll down to '....'
|
||||
4. See error
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
62
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
62
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
name: "Bug report"
|
||||
description: "Report a bug to help us identify and fix issues in the project."
|
||||
labels: ["bug"]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
# 🐞 **Issue Report**
|
||||
Thank you for taking the time to report an issue! Please provide as much detail as possible to help us address the problem efficiently.
|
||||
|
||||
## ⚠️ **IMPORTANT**
|
||||
- 🛠️ **Supported environments only:** We only support Windows 11. Custom ISOs that are not made using Microwin are not supported.
|
||||
- 💡 For general questions, use the [Discussions section](https://github.com/Christitustech/winutil/discussions) or join our Community-driven [Discord Server](https://discord.gg/RUbZUZyByQ).
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: ⚙️ Issue Checklist
|
||||
options:
|
||||
- label: I have read the guidelines.
|
||||
- label: I checked for duplicate issues.
|
||||
- label: I searched for existing discussions.
|
||||
- label: I checked for an existing pull request that addresses this issue.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: affected_part
|
||||
attributes:
|
||||
label: 📜 What part of Winutil are you having issues with?
|
||||
placeholder: "e.g., Microwin, Tweaks, etc."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: issue_description
|
||||
attributes:
|
||||
label: 📝 Provide a clear and concise description of the issue.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: steps_to_reproduce
|
||||
attributes:
|
||||
label: 🔄 Steps to reproduce the issue.
|
||||
placeholder: "e.g., Step 1: ..., Step 2: ..."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: error_output
|
||||
attributes:
|
||||
label: ❌ Paste the full error output (if available).
|
||||
placeholder: "Include any relevant logs or error messages."
|
||||
|
||||
- type: textarea
|
||||
id: additional_context
|
||||
attributes:
|
||||
label: 🖼️ Additional context.
|
||||
placeholder: "Include screenshots, code blocks (use triple backticks ```), or any other relevant information."
|
||||
validations:
|
||||
required: false
|
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 💻 Community Discord
|
||||
url: https://discord.gg/RUbZUZyByQ
|
||||
about: Join our Community Discord server to chat with other users in the Winutil community.
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
@ -1,20 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
57
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
Normal file
57
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
Normal file
@ -0,0 +1,57 @@
|
||||
name: "Feature request"
|
||||
description: "Suggest a new feature or improvement for the project."
|
||||
labels: ["enhancement"]
|
||||
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
# ✨ **Feature request**
|
||||
Thank you for taking the time to suggest a feature! Please provide as much detail as possible to help us understand and evaluate your request.
|
||||
|
||||
## ⚠️ **IMPORTANT**
|
||||
- 🛠️ **Supported environments only:** We only support Windows 11.
|
||||
- 💡 For general questions, use the [Discussions section](https://github.com/Christitustech/winutil/discussions) or join our Community-driven [Discord Server](https://discord.gg/RUbZUZyByQ).
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: ⚙️ Issue Checklist
|
||||
options:
|
||||
- label: I have read the guidelines.
|
||||
- label: I checked for duplicate issues.
|
||||
- label: I searched for existing discussions.
|
||||
- label: I checked for an existing pull request that addresses this request.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: problem_statement
|
||||
attributes:
|
||||
label: ❓ Is your feature request related to a problem?
|
||||
placeholder: "Provide a clear and concise description of the issue you're facing. Example: 'I'm always frustrated when [...]'"
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: proposed_solution
|
||||
attributes:
|
||||
label: 💡 Describe the solution you'd like
|
||||
placeholder: "Provide a clear and concise description of what you want to happen."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: 🔄 Describe alternatives you've considered
|
||||
placeholder: "Provide details on any alternative solutions or features you've thought about."
|
||||
validations:
|
||||
required: false
|
||||
|
||||
- type: textarea
|
||||
id: additional_context
|
||||
attributes:
|
||||
label: 🖼️ Additional context
|
||||
placeholder: "Include screenshots, code blocks (use triple backticks ```), or any other relevant information."
|
||||
validations:
|
||||
required: false
|
33
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
33
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
<!--Before you make this PR have you followed the docs here? - https://christitustech.github.io/winutil/contribute/ -->
|
||||
|
||||
## Type of Change
|
||||
- [ ] New feature
|
||||
- [ ] Bug fix
|
||||
- [ ] Documentation update
|
||||
- [ ] Refactoring
|
||||
- [ ] Hotfix
|
||||
- [ ] Security patch
|
||||
- [ ] UI/UX improvement
|
||||
|
||||
## Description
|
||||
<!--[Provide a detailed explanation of the changes you have made. Include the reasons behind these changes and any relevant context. Link any related issues.]-->
|
||||
|
||||
## Testing
|
||||
<!--[Detail the testing you have performed to ensure that these changes function as intended. Include information about any added tests.]-->
|
||||
|
||||
## Impact
|
||||
<!--[Discuss the impact of your changes on the project. This might include effects on performance, new dependencies, or changes in behaviour.]-->
|
||||
|
||||
## Issue related to PR
|
||||
<!--[What issue/discussion is related to this PR (if any)]-->
|
||||
- Resolves #
|
||||
|
||||
## Additional Information
|
||||
<!--[Any additional information that reviewers should be aware of.]-->
|
||||
|
||||
## Checklist
|
||||
- [ ] My code adheres to the coding and style guidelines of the project.
|
||||
- [ ] I have performed a self-review of my own code.
|
||||
- [ ] I have commented my code, particularly in hard-to-understand areas.
|
||||
- [ ] I have made corresponding changes to the documentation.
|
||||
- [ ] My changes generate no errors/warnings/merge conflicts.
|
5
.github/SECURITY.md
vendored
Normal file
5
.github/SECURITY.md
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
# Security Policy
|
||||
|
||||
If you find a security issue please make post it in the issues tab. If you think it should be private you can email me at contact@christitus.com.
|
||||
|
||||
For immediate response check out our discord server @ [](https://discord.gg/RUbZUZyByQ)
|
9
.github/dependabot.yml
vendored
Normal file
9
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
ignore:
|
||||
- dependency-name: "actions/stale"
|
||||
versions: '>= 9'
|
54
.github/release-drafter.yml
vendored
Normal file
54
.github/release-drafter.yml
vendored
Normal file
@ -0,0 +1,54 @@
|
||||
tag-prefix: ''
|
||||
categories:
|
||||
- title: '🚀 Features'
|
||||
labels:
|
||||
- 'feature'
|
||||
- 'enhancement'
|
||||
- title: '🐛 Bug Fixes'
|
||||
labels:
|
||||
- 'fix'
|
||||
- 'bugfix'
|
||||
- 'bug'
|
||||
- title: '📚 Documentation'
|
||||
label: 'documentation'
|
||||
- title: '🔒 Security'
|
||||
label: 'security'
|
||||
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
|
||||
template: |
|
||||
## Changes
|
||||
|
||||
$CHANGES
|
||||
|
||||
change-title-escapes: '\<*_&"'''
|
||||
autolabeler:
|
||||
- label: 'documentation'
|
||||
files:
|
||||
- '*.md'
|
||||
branch:
|
||||
- '/docs{0,1}\/.+/'
|
||||
- label: 'bug'
|
||||
branch:
|
||||
- '/fix\/.+/'
|
||||
title:
|
||||
- '/fix/i'
|
||||
- label: 'enhancement'
|
||||
branch:
|
||||
- '/feature\/.+/'
|
||||
body:
|
||||
- '/[A-Z]+-[0-9]+/'
|
||||
- label: 'documentation'
|
||||
files:
|
||||
- '**/*.md'
|
||||
- 'docs/**/*'
|
||||
- label: 'security'
|
||||
branch:
|
||||
- '/security\/.+/'
|
||||
replacers:
|
||||
- search: /"/g
|
||||
replace: ''
|
||||
- search: /'/g
|
||||
replace: ''
|
||||
exclude-labels:
|
||||
- 'skip-changelog'
|
||||
|
||||
filter-by-commitish: true
|
48
.github/workflows/close-discussion-on-pr.yaml
vendored
Normal file
48
.github/workflows/close-discussion-on-pr.yaml
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
name: Close Discussion on PR Merge
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
|
||||
jobs:
|
||||
closeDiscussion:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Check if PR was merged
|
||||
if: github.event.pull_request.merged == true
|
||||
run: echo "PR was merged"
|
||||
|
||||
- name: Extract Discussion Number & Close If any Were Found
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
if: github.event.pull_request.merged == true
|
||||
id: extract-discussion
|
||||
run: |
|
||||
pr_body="${{ github.event.pull_request.body }}"
|
||||
discussion_ids=$(echo "$pr_body" | grep -oP '(?i)(resolve|fix|close)[s|d]? #\K[0-9]+')
|
||||
|
||||
if [ -z "$discussion_ids" ]; then
|
||||
echo "No discussion IDs found."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
for discussion_id in $discussion_ids; do
|
||||
echo "Attempting to close discussion #$discussion_id"
|
||||
response=$(curl -s -X PATCH -H "Authorization: token $GITHUB_TOKEN" \
|
||||
-H "Accept: application/vnd.github.v3+json" \
|
||||
-d '{"state": "closed"}' \
|
||||
"https://api.github.com/repos/${{ github.repository }}/discussions/$discussion_id")
|
||||
|
||||
if echo "$response" | jq -e '.id' > /dev/null; then
|
||||
echo "Successfully closed discussion #$discussion_id"
|
||||
else
|
||||
error_message=$(echo "$response" | jq -r '.message // "Unknown error"')
|
||||
echo "Warning: Failed to close discussion #$discussion_id. Error: $error_message"
|
||||
echo "Full response: $response"
|
||||
fi
|
||||
done
|
||||
shell: bash
|
||||
continue-on-error: true
|
24
.github/workflows/close-old-issues.yaml
vendored
24
.github/workflows/close-old-issues.yaml
vendored
@ -14,10 +14,26 @@ jobs:
|
||||
contents: none
|
||||
steps:
|
||||
- name: Close inactive issues
|
||||
uses: actions/stale@v9.0.0
|
||||
uses: actions/stale@v8
|
||||
with:
|
||||
# A list of labels to reference when looking through issues,
|
||||
# and only when one (or even more) of these labels are found..
|
||||
# then skip this issue, and never try to stale and/or close it.
|
||||
exempt-issue-labels: "Keep Issue Open"
|
||||
days-before-issue-close: 14
|
||||
close-issue-message: "This issue was closed because it has been inactive for 14 days"
|
||||
debug-only: false # Make this field equal true if you want to test your configuration if it works or not
|
||||
# Split it into two weeks, after one week the issue will be marked as stale,
|
||||
# after another week have pasted without any update.. the issue will then be closed.
|
||||
days-before-issue-stale: 90
|
||||
days-before-issue-close: 365
|
||||
# NEVER mark PRs as Stale or Close + this workflow should never have write permissions on PRs, EVER!
|
||||
days-before-pr-stale: -1
|
||||
days-before-pr-close: -1
|
||||
# Sends a message for both the Stale and Close events of an issue.
|
||||
stale-issue-message: "This issue was marked as stale due to inactivity."
|
||||
close-issue-message: "This issue was closed after remaining stale without updates."
|
||||
# Increase this value if the project receives a lot of
|
||||
# PRs (yes.. apparently they're processed no matter what) & Issues.
|
||||
# Default value for it (according to the docs) is 30
|
||||
operations-per-run: 200
|
||||
# Make this field equal true if you want to test your configuration if it works correctly or not
|
||||
debug-only: false
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
@ -1,25 +1,22 @@
|
||||
name: Compile
|
||||
name: Compile & Check
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- test*
|
||||
branches: ["main"]
|
||||
pull_request:
|
||||
branches: ["main"]
|
||||
workflow_dispatch: # Manual trigger added
|
||||
workflow_call: # Allow other Actions to call this workflow
|
||||
|
||||
jobs:
|
||||
build-runspace:
|
||||
Compile-and-Check:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
- name: Compile project
|
||||
- name: Checkout Sources
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Compile and Syntaxcheck winutil.ps1
|
||||
shell: pwsh
|
||||
run: |
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force; ./Compile.ps1
|
||||
continue-on-error: false # Directly fail the job on error, removing the need for a separate check
|
||||
- uses: stefanzweifel/git-auto-commit-action@v5
|
||||
with:
|
||||
commit_message: Compile Winutil
|
||||
if: success()
|
115
.github/workflows/issue-slash-commands.yaml
vendored
Normal file
115
.github/workflows/issue-slash-commands.yaml
vendored
Normal file
@ -0,0 +1,115 @@
|
||||
name: Issue slash commands
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created, edited]
|
||||
|
||||
jobs:
|
||||
issueCommands:
|
||||
# Skip this job if the comment was created/edited on a PR
|
||||
if: ${{ !github.event.issue.pull_request }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: none
|
||||
contents: read
|
||||
|
||||
steps:
|
||||
- run: echo "command=false" >> $GITHUB_ENV
|
||||
|
||||
- name: Check for /label command
|
||||
id: check_label_command
|
||||
run: |
|
||||
if [[ "${{ contains(github.event.comment.body, '/label') }}" == "true" ]]; then
|
||||
echo "command=true" >> $GITHUB_ENV
|
||||
LABEL_NAME=$(echo "${{ github.event.comment.body }}" | awk -F"/label" '/\/label/ { match($2, /'\''([^'\'']*)'\''/, arr); if (arr[1] != "") print arr[1] }')
|
||||
echo "label_command=true" >> $GITHUB_ENV
|
||||
echo "label_name=${LABEL_NAME}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "label_command=false" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Check for /unlabel command
|
||||
id: check_unlabel_command
|
||||
run: |
|
||||
if [[ "${{ contains(github.event.comment.body, '/unlabel') }}" == "true" ]]; then
|
||||
echo "command=true" >> $GITHUB_ENV
|
||||
UNLABEL_NAME=$(echo "${{ github.event.comment.body }}" | awk -F"/unlabel" '/\/unlabel/ { match($2, /'\''([^'\'']*)'\''/, arr); if (arr[1] != "") print arr[1] }')
|
||||
echo "unlabel_command=true" >> $GITHUB_ENV
|
||||
echo "unlabel_name=${UNLABEL_NAME}" >> $GITHUB_ENV
|
||||
else
|
||||
echo "unlabel_command=false" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Check for /close command
|
||||
id: check_close_command
|
||||
run: |
|
||||
if [[ "${{ contains(github.event.comment.body, '/close') }}" == "true" ]]; then
|
||||
echo "command=true" >> $GITHUB_ENV
|
||||
echo "close_command=true" >> $GITHUB_ENV
|
||||
echo "reopen_command=false" >> $GITHUB_ENV
|
||||
else
|
||||
echo "close_command=false" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Check for /open or /reopen command
|
||||
id: check_reopen_command
|
||||
run: |
|
||||
if [[ "${{ contains(github.event.comment.body, '/open') }}" == "true" ]] || [[ "${{ contains(github.event.comment.body, '/reopen') }}" == "true" ]]; then
|
||||
echo "command=true" >> $GITHUB_ENV
|
||||
echo "reopen_command=true" >> $GITHUB_ENV
|
||||
echo "close_command=false" >> $GITHUB_ENV
|
||||
else
|
||||
echo "reopen_command=false" >> $GITHUB_ENV
|
||||
fi
|
||||
|
||||
- name: Check if the user is allowed
|
||||
id: check_user
|
||||
if: env.command == 'true'
|
||||
run: |
|
||||
ALLOWED_USERS=("ChrisTitusTech" "og-mrk" "Marterich" "MyDrift-user" "Real-MullaC" "CodingWonders")
|
||||
if [[ " ${ALLOWED_USERS[@]} " =~ " ${{ github.event.comment.user.login }} " ]]; then
|
||||
echo "user=true" >> $GITHUB_ENV
|
||||
else
|
||||
exit 0
|
||||
fi
|
||||
|
||||
- name: Close issue
|
||||
if: env.close_command == 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
run: |
|
||||
echo Closing the issue...
|
||||
if [[ "${{ contains(github.event.comment.body, 'not planned') }}" == "true" ]]; then
|
||||
gh issue close $ISSUE_NUMBER --repo ${{ github.repository }} --reason 'not planned'
|
||||
else
|
||||
gh issue close $ISSUE_NUMBER --repo ${{ github.repository }}
|
||||
fi
|
||||
|
||||
- name: Reopen issue
|
||||
if: env.reopen_command == 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
run: |
|
||||
echo Reopening the issue...
|
||||
gh issue reopen $ISSUE_NUMBER --repo ${{ github.repository }}
|
||||
|
||||
- name: Label issue
|
||||
if: env.label_command == 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
run: |
|
||||
echo Labeling the issue...
|
||||
gh issue edit $ISSUE_NUMBER --repo ${{ github.repository }} --add-label "${{ env.label_name }}"
|
||||
|
||||
- name: Remove labels
|
||||
if: env.unlabel_command == 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ISSUE_NUMBER: ${{ github.event.issue.number }}
|
||||
run: |
|
||||
echo Unlabeling the issue...
|
||||
gh issue edit $ISSUE_NUMBER --repo ${{ github.repository }} --remove-label "${{ env.unlabel_name }}"
|
75
.github/workflows/pre-release.yaml
vendored
Normal file
75
.github/workflows/pre-release.yaml
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
name: Pre-Release WinUtil
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
actions: read
|
||||
|
||||
on:
|
||||
workflow_dispatch: # Manual trigger added
|
||||
|
||||
jobs:
|
||||
build-runspace:
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
CERTIFICATE_BASE64: ${{ secrets.CERTIFICATE_BASE64 }}
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Compile project
|
||||
shell: pwsh
|
||||
run: |
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force; ./Compile.ps1
|
||||
continue-on-error: false # Directly fail the job on error, removing the need for a separate check
|
||||
|
||||
- name: Set Version to Todays Date
|
||||
id: extract_version
|
||||
run: |
|
||||
$version = (Get-Date -Format "yy.MM.dd")
|
||||
echo "VERSION=$version" >> $env:GITHUB_ENV
|
||||
shell: pwsh
|
||||
|
||||
- name: Create Tag
|
||||
id: create_tag
|
||||
run: |
|
||||
$tagExists = git tag -l $env:VERSION
|
||||
if ($tagExists -eq "") {
|
||||
git tag $env:VERSION
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error "Failed to create tag $env:VERSION"
|
||||
exit 1
|
||||
}
|
||||
git push origin $env:VERSION
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Error "Failed to push tag $env:VERSION"
|
||||
exit 1
|
||||
}
|
||||
} else {
|
||||
Write-Host "Tag $env:VERSION already exists, skipping tag creation"
|
||||
}
|
||||
shell: pwsh
|
||||
|
||||
- name: Generate Release Notes
|
||||
id: generate_notes
|
||||
uses: release-drafter/release-drafter@v6
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
config-name: release-drafter.yml
|
||||
version: ${{ env.VERSION }} # Pass the version variable
|
||||
|
||||
- name: Create and Upload Release
|
||||
id: create_release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: ${{ env.VERSION }}
|
||||
name: Pre-Release ${{ env.VERSION }}
|
||||
body: |
|
||||
${{ steps.generate_notes.outputs.body }}
|
||||
|
||||

|
||||
append_body: false
|
||||
files: ./winutil.ps1
|
||||
prerelease: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
45
.github/workflows/release.yaml
vendored
45
.github/workflows/release.yaml
vendored
@ -1,45 +0,0 @@
|
||||
name: Release WinUtil
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["Compile"] #Ensure Compile winget.ps1 is done
|
||||
types:
|
||||
- completed
|
||||
workflow_dispatch: # Manual trigger added
|
||||
|
||||
jobs:
|
||||
build-runspace:
|
||||
runs-on: windows-latest
|
||||
outputs:
|
||||
version: ${{ steps.extract_version.outputs.version }}
|
||||
steps:
|
||||
- name: Checkout Repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Extract Version from winutil.ps1
|
||||
id: extract_version
|
||||
run: |
|
||||
$version = ''
|
||||
Get-Content ./winutil.ps1 -TotalCount 30 | ForEach-Object {
|
||||
if ($_ -match 'Version\s*:\s*(\d{2}\.\d{2}\.\d{2})') {
|
||||
$version = $matches[1]
|
||||
echo "version=$version" >> $GITHUB_ENV
|
||||
echo "::set-output name=version::$version"
|
||||
break
|
||||
}
|
||||
}
|
||||
if (-not $version) {
|
||||
Write-Error "Version not found in winutil.ps1"
|
||||
exit 1
|
||||
}
|
||||
shell: pwsh
|
||||
|
||||
- name: Create and Upload Release
|
||||
id: create_release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
tag_name: ${{ steps.extract_version.outputs.version }}
|
||||
name: Release ${{ steps.extract_version.outputs.version }}
|
||||
files: ./winutil.ps1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
34
.github/workflows/remove-winutil.yaml
vendored
Normal file
34
.github/workflows/remove-winutil.yaml
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
name: Remove winutil.ps1 if included in a Push
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- '**'
|
||||
|
||||
jobs:
|
||||
check-and-delete-file:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Check if winutil.ps1 exists
|
||||
id: check_existence
|
||||
run: |
|
||||
if [ -f "winutil.ps1" ]; then
|
||||
echo "winutil_exists=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "winutil_exists=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Delete winutil.ps1 if it exists
|
||||
if: steps.check_existence.outputs.winutil_exists == 'true'
|
||||
run: |
|
||||
git config --global user.email "winutil-action@noreply.github.com"
|
||||
git config --global user.name "winutil-action"
|
||||
git rm winutil.ps1
|
||||
git commit -m "Delete winutil.ps1 as it is not allowed"
|
||||
git push origin HEAD:${{ github.ref }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
26
.github/workflows/sponsors.yaml
vendored
Normal file
26
.github/workflows/sponsors.yaml
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
name: Generate Sponsors README
|
||||
on:
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
- cron: 30 15 * * 0-6
|
||||
permissions:
|
||||
contents: write
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
if: (github.event_name == 'schedule' && github.repository == 'ChrisTitusTech/winutil') || (github.event_name != 'schedule')
|
||||
steps:
|
||||
- name: Checkout 🛎️
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Generate Sponsors 💖
|
||||
uses: JamesIves/github-sponsors-readme-action@v1
|
||||
with:
|
||||
token: ${{ secrets.PAT }}
|
||||
file: 'README.md'
|
||||
|
||||
- name: Deploy to GitHub Pages 🚀
|
||||
uses: JamesIves/github-pages-deploy-action@v4
|
||||
with:
|
||||
branch: main
|
||||
folder: '.'
|
10
.github/workflows/unittests.yaml
vendored
10
.github/workflows/unittests.yaml
vendored
@ -1,14 +1,14 @@
|
||||
name: Unit Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
push:
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
name: PS Script Analyzer
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
- name: lint
|
||||
uses: devblackops/github-action-psscriptanalyzer@master
|
||||
with:
|
||||
@ -22,7 +22,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install Pester
|
||||
run: |
|
||||
@ -34,7 +34,7 @@ jobs:
|
||||
run: |
|
||||
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
|
||||
Invoke-Pester -Path 'pester/*.Tests.ps1' -Output Detailed
|
||||
|
||||
|
||||
shell: pwsh
|
||||
env:
|
||||
TEMP: ${{ runner.temp }}
|
||||
TEMP: ${{ runner.temp }}
|
||||
|
9
.gitignore
vendored
9
.gitignore
vendored
@ -2,6 +2,7 @@
|
||||
|
||||
# Configuration folder
|
||||
.vscode/
|
||||
.idea/
|
||||
|
||||
### Visual Studio ###
|
||||
|
||||
@ -10,6 +11,9 @@
|
||||
|
||||
winutil.pdb
|
||||
|
||||
### Preprocessor Hashes ###
|
||||
.preprocessor_hashes.json
|
||||
|
||||
### Windows ###
|
||||
|
||||
# Folder config file
|
||||
@ -45,3 +49,8 @@ microwin.log
|
||||
True
|
||||
test.ps1
|
||||
winutil.ps1
|
||||
|
||||
# temporary excludes for docs
|
||||
.github/site/
|
||||
|
||||
binary/
|
||||
|
178
Compile.ps1
178
Compile.ps1
@ -1,15 +1,41 @@
|
||||
param (
|
||||
[switch]$Debug,
|
||||
[switch]$Run
|
||||
[switch]$Run,
|
||||
[string]$Arguments
|
||||
)
|
||||
|
||||
if ((Get-Item ".\winutil.ps1" -ErrorAction SilentlyContinue).IsReadOnly) {
|
||||
Remove-Item ".\winutil.ps1" -Force
|
||||
}
|
||||
|
||||
$OFS = "`r`n"
|
||||
$scriptname = "winutil.ps1"
|
||||
$workingdir = $PSScriptRoot
|
||||
|
||||
Push-Location
|
||||
Set-Location $workingdir
|
||||
|
||||
# Variable to sync between runspaces
|
||||
$sync = [Hashtable]::Synchronized(@{})
|
||||
$sync.PSScriptRoot = $PSScriptRoot
|
||||
$sync.PSScriptRoot = $workingdir
|
||||
$sync.configs = @{}
|
||||
|
||||
function Update-Progress {
|
||||
param (
|
||||
[Parameter(Mandatory, position=0)]
|
||||
[string]$StatusMessage,
|
||||
|
||||
[Parameter(Mandatory, position=1)]
|
||||
[ValidateRange(0,100)]
|
||||
[int]$Percent,
|
||||
|
||||
[Parameter(position=2)]
|
||||
[string]$Activity = "Compiling"
|
||||
)
|
||||
|
||||
Write-Progress -Activity $Activity -Status $StatusMessage -PercentComplete $Percent
|
||||
}
|
||||
|
||||
$header = @"
|
||||
################################################################################################################
|
||||
### ###
|
||||
@ -18,96 +44,102 @@ $header = @"
|
||||
################################################################################################################
|
||||
"@
|
||||
|
||||
|
||||
Update-Progress "Pre-req: Running Preprocessor..." 0
|
||||
|
||||
# Dot source the 'Invoke-Preprocessing' Function from 'tools/Invoke-Preprocessing.ps1' Script
|
||||
$preprocessingFilePath = ".\tools\Invoke-Preprocessing.ps1"
|
||||
. $preprocessingFilePath
|
||||
|
||||
$excludedFiles = @('.\.git\', '.\.gitignore', '.\.gitattributes', '.\.github\CODEOWNERS', '.\LICENSE', "$preprocessingFilePath", '*.png', '*.exe','.\.preprocessor_hashes.json')
|
||||
$msg = "Pre-req: Code Formatting"
|
||||
Invoke-Preprocessing -WorkingDir "$workingdir" -ExcludedFiles $excludedFiles -ProgressStatusMessage $msg
|
||||
|
||||
# Create the script in memory.
|
||||
Update-Progress "Pre-req: Allocating Memory" 0
|
||||
$script_content = [System.Collections.Generic.List[string]]::new()
|
||||
|
||||
Write-Progress -Activity "Compiling" -Status "Adding: Header" -PercentComplete 5
|
||||
Update-Progress "Adding: Header" 5
|
||||
$script_content.Add($header)
|
||||
|
||||
Write-Progress -Activity "Compiling" -Status "Adding: Version" -PercentComplete 10
|
||||
$script_content.Add($(Get-Content .\scripts\start.ps1).replace('#{replaceme}',"$(Get-Date -Format yy.MM.dd)"))
|
||||
Update-Progress "Adding: Version" 10
|
||||
$script_content.Add($(Get-Content "scripts\start.ps1").replace('#{replaceme}',"$(Get-Date -Format yy.MM.dd)"))
|
||||
|
||||
Write-Progress -Activity "Compiling" -Status "Adding: Functions" -PercentComplete 20
|
||||
Get-ChildItem .\functions -Recurse -File | ForEach-Object {
|
||||
Update-Progress "Adding: Functions" 20
|
||||
Get-ChildItem "functions" -Recurse -File | ForEach-Object {
|
||||
$script_content.Add($(Get-Content $psitem.FullName))
|
||||
}
|
||||
Write-Progress -Activity "Compiling" -Status "Adding: Config *.json" -PercentComplete 40
|
||||
Get-ChildItem .\config | Where-Object {$psitem.extension -eq ".json"} | ForEach-Object {
|
||||
Update-Progress "Adding: Config *.json" 40
|
||||
Get-ChildItem "config" | Where-Object {$psitem.extension -eq ".json"} | ForEach-Object {
|
||||
$json = (Get-Content $psitem.FullName -Raw)
|
||||
$jsonAsObject = $json | ConvertFrom-Json
|
||||
|
||||
$json = (Get-Content $psitem.FullName).replace("'","''")
|
||||
|
||||
# Replace every XML Special Character so it'll render correctly in final build
|
||||
# Only do so if json files has content to be displayed (for example the applications, tweaks, features json files)
|
||||
# Some Type Convertion using Casting and Cleaning Up of the convertion result using 'Replace' Method
|
||||
$jsonAsObject = $json | convertfrom-json
|
||||
$firstLevelJsonList = ([System.String]$jsonAsObject).split('=;') | ForEach-Object {
|
||||
$_.Replace('=}','').Replace('@{','').Replace(' ','')
|
||||
# Add 'WPFInstall' as a prefix to every entry-name in 'applications.json' file
|
||||
if ($psitem.Name -eq "applications.json") {
|
||||
foreach ($appEntryName in $jsonAsObject.PSObject.Properties.Name) {
|
||||
$appEntryContent = $jsonAsObject.$appEntryName
|
||||
$jsonAsObject.PSObject.Properties.Remove($appEntryName)
|
||||
$jsonAsObject | Add-Member -MemberType NoteProperty -Name "WPFInstall$appEntryName" -Value $appEntryContent
|
||||
}
|
||||
}
|
||||
|
||||
for ($i = 0; $i -lt $firstLevelJsonList.Count; $i += 1) {
|
||||
$firstLevelName = $firstLevelJsonList[$i]
|
||||
# Note: Avoid using HTML Entity Codes (for example '”' (stands for "Right Double Quotation Mark")), and use HTML decimal/hex codes instead.
|
||||
# as using HTML Entity Codes will result in XML parse Error when running the compiled script.
|
||||
if ($jsonAsObject.$firstLevelName.content -ne $null) {
|
||||
$jsonAsObject.$firstLevelName.content = $jsonAsObject.$firstLevelName.content.replace('&','&').replace('“','“').replace('”','”').replace("'",''').replace('<','<').replace('>','>')
|
||||
$jsonAsObject.$firstLevelName.content = $jsonAsObject.$firstLevelName.content.replace('''',"'") # resolves the Double Apostrophe caused by the first replace function in the main loop
|
||||
}
|
||||
if ($jsonAsObject.$firstLevelName.description -ne $null) {
|
||||
$jsonAsObject.$firstLevelName.description = $jsonAsObject.$firstLevelName.description.replace('&','&').replace('“','“').replace('”','”').replace("'",''').replace('<','<').replace('>','>')
|
||||
$jsonAsObject.$firstLevelName.description = $jsonAsObject.$firstLevelName.description.replace('''',"'") # resolves the Double Apostrophe caused by the first replace function in the main loop
|
||||
}
|
||||
}
|
||||
# The replace at the end is required, as without it the output of converto-json will be somewhat weird for Multiline String
|
||||
# Most Notably is the scripts in json files, making it harder for users who want to review these scripts that are found in the final compiled script
|
||||
$json = ($jsonAsObject | convertto-json -Depth 3).replace('\r\n',"`r`n")
|
||||
# Line 90 requires no whitespace inside the here-strings, to keep formatting of the JSON in the final script.
|
||||
$json = @"
|
||||
$($jsonAsObject | ConvertTo-Json -Depth 3)
|
||||
"@
|
||||
|
||||
$sync.configs.$($psitem.BaseName) = $json | convertfrom-json
|
||||
$script_content.Add($(Write-output "`$sync.configs.$($psitem.BaseName) = '$json' `| convertfrom-json" ))
|
||||
$sync.configs.$($psitem.BaseName) = $json | ConvertFrom-Json
|
||||
$script_content.Add($(Write-Output "`$sync.configs.$($psitem.BaseName) = @'`r`n$json`r`n'@ `| ConvertFrom-Json" ))
|
||||
}
|
||||
|
||||
$xaml = (Get-Content .\xaml\inputXML.xaml).replace("'","''")
|
||||
# Read the entire XAML file as a single string, preserving line breaks
|
||||
$xaml = Get-Content "$workingdir\xaml\inputXML.xaml" -Raw
|
||||
|
||||
# Dot-source the Get-TabXaml function
|
||||
. .\functions\private\Get-TabXaml.ps1
|
||||
Update-Progress "Adding: Xaml " 90
|
||||
|
||||
Write-Progress -Activity "Compiling" -Status "Building: Xaml " -PercentComplete 75
|
||||
$appXamlContent = Get-TabXaml "applications" 5
|
||||
$tweaksXamlContent = Get-TabXaml "tweaks"
|
||||
$featuresXamlContent = Get-TabXaml "feature"
|
||||
# Add the XAML content to $script_content using a here-string
|
||||
$script_content.Add(@"
|
||||
`$inputXML = @'
|
||||
$xaml
|
||||
'@
|
||||
"@)
|
||||
|
||||
$script_content.Add($(Get-Content "scripts\main.ps1"))
|
||||
|
||||
Write-Progress -Activity "Compiling" -Status "Adding: Xaml " -PercentComplete 90
|
||||
# Replace the placeholder in $inputXML with the content of inputApp.xaml
|
||||
$xaml = $xaml -replace "{{InstallPanel_applications}}", $appXamlContent
|
||||
$xaml = $xaml -replace "{{InstallPanel_tweaks}}", $tweaksXamlContent
|
||||
$xaml = $xaml -replace "{{InstallPanel_features}}", $featuresXamlContent
|
||||
|
||||
$script_content.Add($(Write-output "`$inputXML = '$xaml'"))
|
||||
|
||||
$script_content.Add($(Get-Content .\scripts\main.ps1))
|
||||
|
||||
if ($Debug){
|
||||
Write-Progress -Activity "Compiling" -Status "Writing debug files" -PercentComplete 95
|
||||
$appXamlContent | Out-File -FilePath ".\xaml\inputApp.xaml" -Encoding ascii
|
||||
$tweaksXamlContent | Out-File -FilePath ".\xaml\inputTweaks.xaml" -Encoding ascii
|
||||
$featuresXamlContent | Out-File -FilePath ".\xaml\inputFeatures.xaml" -Encoding ascii
|
||||
}
|
||||
else {
|
||||
Write-Progress -Activity "Compiling" -Status "Removing temporary files" -PercentComplete 99
|
||||
Remove-Item ".\xaml\inputApp.xaml" -ErrorAction SilentlyContinue
|
||||
Remove-Item ".\xaml\inputTweaks.xaml" -ErrorAction SilentlyContinue
|
||||
Remove-Item ".\xaml\inputFeatures.xaml" -ErrorAction SilentlyContinue
|
||||
if ($Debug) {
|
||||
Update-Progress "Writing debug files" 95
|
||||
$appXamlContent | Out-File -FilePath "xaml\inputApp.xaml" -Encoding ascii
|
||||
$tweaksXamlContent | Out-File -FilePath "xaml\inputTweaks.xaml" -Encoding ascii
|
||||
$featuresXamlContent | Out-File -FilePath "xaml\inputFeatures.xaml" -Encoding ascii
|
||||
} else {
|
||||
Update-Progress "Removing temporary files" 99
|
||||
Remove-Item "xaml\inputApp.xaml" -ErrorAction SilentlyContinue
|
||||
Remove-Item "xaml\inputTweaks.xaml" -ErrorAction SilentlyContinue
|
||||
Remove-Item "xaml\inputFeatures.xaml" -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
Set-Content -Path $scriptname -Value ($script_content -join "`r`n") -Encoding ascii
|
||||
Set-Content -Path "$scriptname" -Value ($script_content -join "`r`n") -Encoding ascii
|
||||
Write-Progress -Activity "Compiling" -Completed
|
||||
|
||||
if ($run){
|
||||
try {
|
||||
Start-Process -FilePath "pwsh" -ArgumentList ".\$scriptname"
|
||||
}
|
||||
catch {
|
||||
Start-Process -FilePath "powershell" -ArgumentList ".\$scriptname"
|
||||
}
|
||||
|
||||
}
|
||||
Update-Progress -Activity "Validating" -StatusMessage "Checking winutil.ps1 Syntax" -Percent 0
|
||||
try {
|
||||
Get-Command -Syntax .\winutil.ps1 | Out-Null
|
||||
} catch {
|
||||
Write-Warning "Syntax Validation for 'winutil.ps1' has failed"
|
||||
Write-Host "$($Error[0])" -ForegroundColor Red
|
||||
Pop-Location # Restore previous location before exiting...
|
||||
exit 1
|
||||
}
|
||||
Write-Progress -Activity "Validating" -Completed
|
||||
|
||||
if ($run) {
|
||||
$script = "& '$workingdir\$scriptname' $Arguments"
|
||||
|
||||
$powershellcmd = if (Get-Command pwsh -ErrorAction SilentlyContinue) { "pwsh" } else { "powershell" }
|
||||
$processCmd = if (Get-Command wt.exe -ErrorAction SilentlyContinue) { "wt.exe" } else { $powershellcmd }
|
||||
|
||||
Start-Process $processCmd -ArgumentList "$powershellcmd -NoProfile -Command $script"
|
||||
|
||||
break
|
||||
}
|
||||
Pop-Location
|
||||
|
@ -1,33 +0,0 @@
|
||||
## Known Issues and Fixes
|
||||
- Windows taking longer to shut down:
|
||||
- [#69](https://github.com/ChrisTitusTech/winutil/issues/69) Turn on fast startup: Press Windows key + R, then type:
|
||||
```
|
||||
control /name Microsoft.PowerOptions /page pageGlobalSettings
|
||||
```
|
||||
- If that doesn't work, Disable Hibernation: Press Windows Key+X and select 'PowerShell (Admin)' (Windows 10) or 'Windows Terminal (Admin)' (Windows 11) and enter:
|
||||
```
|
||||
powercfg /H off
|
||||
```
|
||||
- [#69](https://github.com/ChrisTitusTech/winutil/issues/69) [95](https://github.com/ChrisTitusTech/winutil/issues/95) [#232](https://github.com/ChrisTitusTech/winutil/issues/232) Windows Search does not work: Enable Background Apps
|
||||
- [#198](https://github.com/ChrisTitusTech/winutil/issues/198) Xbox Game Bar Activation Broken: Set the Xbox Accessory Management Service to Automatic
|
||||
```
|
||||
Get-Service -Name "XboxGipSvc" | Set-Service -StartupType Automatic
|
||||
```
|
||||
- Windows Insider Builds not installing: Telemetry needs to be enabled
|
||||
```
|
||||
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\DataCollection" -Name "AllowTelemetry" -Type DWord -Value 0
|
||||
Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\DataCollection" -Name "AllowTelemetry" -Type DWord -Value 0
|
||||
```
|
||||
- Winget requires interaction on first run: Manually type 'y' and 'enter' into the PowerShell console to continue
|
||||
- (Windows 11) Quick Settings no longer works: Launch the Script and click 'Enable Action Center'
|
||||
- Explorer no longer launches: Go to Control Panel, File Explorer Options, Change the 'Open File Explorer to' option to 'This PC'.
|
||||
- Script doesn't run/PowerShell crashes:
|
||||
1. Press Windows Key+X and select 'PowerShell (Admin)' (Windows 10) or 'Windows Terminal (Admin)' (Windows 11)
|
||||
2. Run:
|
||||
```
|
||||
Set-ExecutionPolicy Unrestricted -Scope Process -Force
|
||||
```
|
||||
3. Run:
|
||||
```
|
||||
irm christitus.com/win | iex
|
||||
```
|
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Chris Titus
|
||||
Copyright (c) 2022 CT Tech Group LLC
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
164
README.md
164
README.md
@ -1,147 +1,91 @@
|
||||
# Chris Titus Tech's Windows Utility
|
||||
|
||||
This utility is a compilation of Windows tasks I perform on each Windows system I use. It is meant to streamline *installs*, debloat with *tweaks*, troubleshoot with *config*, and fix Windows *updates*. I am extremely picky about any contributions to keep this project clean and efficient.
|
||||
[](https://github.com/ChrisTitusTech/winutil/releases/latest)
|
||||

|
||||
[](https://discord.gg/RUbZUZyByQ)
|
||||
[](https://winutil.christitus.com/)
|
||||
|
||||

|
||||
This utility is a compilation of Windows tasks I perform on each Windows system I use. It is meant to streamline *installs*, debloat with *tweaks*, troubleshoot with *config*, and fix Windows *updates*. I am extremely picky about any contributions to keep this project clean and efficient.
|
||||
|
||||
## Usage
|
||||

|
||||
|
||||
Winutil must be run in Admin mode because it performs system-wide tweaks. To achieve this, open PowerShell or Windows Terminal as an administrator. Here are a few ways to do it:
|
||||
## 💡 Usage
|
||||
|
||||
1. **Right-Click Method:**
|
||||
Winutil must be run in Admin mode because it performs system-wide tweaks. To achieve this, run PowerShell as an administrator. Here are a few ways to do it:
|
||||
|
||||
1. **Start menu Method:**
|
||||
- Right-click on the start menu.
|
||||
- Choose "Windows PowerShell (Admin)" (for Windows 10) or "Terminal (Admin)" (for Windows 11).
|
||||
|
||||
2. **Search and Launch Method:**
|
||||
- Press the Windows key.
|
||||
- Type "PowerShell" or "Terminal" (for Windows 11).
|
||||
- Press `Ctrl + Shift + Enter` to launch it with administrator privileges.
|
||||
|
||||
- Press `Ctrl + Shift + Enter` or Right-click and choose "Run as administrator" to launch it with administrator privileges.
|
||||
|
||||
### Launch Command
|
||||
|
||||
#### Simple way
|
||||
#### Stable Branch (Recommended)
|
||||
|
||||
```ps1
|
||||
irm "https://christitus.com/win" | iex
|
||||
```
|
||||
irm https://christitus.com/win | iex
|
||||
```
|
||||
Courtesy of the issue raised at: [#144](/../../issues/144)
|
||||
#### Dev Branch
|
||||
|
||||
or by executing:
|
||||
```
|
||||
iwr -useb https://christitus.com/win | iex
|
||||
```ps1
|
||||
irm "https://christitus.com/windev" | iex
|
||||
```
|
||||
|
||||
if for some reason this site is not reachable from your country please try running it directly from github (replace `RELEASE_TAG` with current release that you are interested in, for example `v2024.06.05`)
|
||||
```
|
||||
irm "https://github.com/ChrisTitusTech/winutil/releases/download/RELEASE_TAG/winutil.ps1" | iex
|
||||
If you have Issues, refer to [Known Issues](https://winutil.christitus.com/knownissues/)
|
||||
|
||||
## 🎓 Documentation
|
||||
|
||||
> [!NOTE]
|
||||
> To contribute to the documentation, please visit [WinUtil Docs Repo](https://github.com/Chris-Titus-Docs/winutil-docs) for more info.
|
||||
|
||||
### [WinUtil Official Documentation](https://winutil.christitus.com/)
|
||||
|
||||
### [YouTube Tutorial](https://www.youtube.com/watch?v=6UQZ5oQg8XA)
|
||||
|
||||
### [ChrisTitus.com Article](https://christitus.com/windows-tool/)
|
||||
|
||||
## 🛠️ Build & Develop
|
||||
|
||||
> [!NOTE]
|
||||
> Winutil is a relatively large script, so it's split into multiple files which're combined into a single `.ps1` file using a custom compiler. This makes maintaining the project a lot easiler.
|
||||
|
||||
Get a copy of the source code, this can be done using GitHub UI (`Code -> Download ZIP`), or by cloning (downloading) the repo using git.
|
||||
|
||||
If git is installed, run the following commands under a PowerShell window to clone and move into project's directory:
|
||||
```ps1
|
||||
git clone --depth 1 "https://github.com/ChrisTitusTech/winutil.git"
|
||||
cd winutil
|
||||
```
|
||||
|
||||
#### Automation
|
||||
|
||||
Some features are avaliable through automation. This allows you to save your config file pass it to Winutil walk away and come back to a finished system. Here is how you can set it up currently with Winutil >24.01.15
|
||||
|
||||
1. On the Install Tab, click "Get Installed", this will get all installed apps **supported by Winutil** on the system
|
||||

|
||||
2. Click on the Settings cog in the upper right corner and chose Export, chose file file and location, this will export the setting file.
|
||||

|
||||
3. Copy this file to a USB or somewhere you can use after Windows installation.
|
||||
4. Use Microwin tab to create a custom Windows image.
|
||||
5. Install the Windows image.
|
||||
6. In the new Windows, Open PowerShell in the admin mode and run command to automatically apply tweaks and install apps from the config file.
|
||||
```
|
||||
iex "& { $(irm christitus.com/win) } -Config [path-to-your-config] -Run"
|
||||
```
|
||||
7. Have a cup of coffee! Come back when it's done.
|
||||
|
||||
|
||||
## Issues:
|
||||
|
||||
- If you are unable to resolve christitus.com/win and are getting errors launching the tool, it might be due to India blocking GitHub's content domain and preventing downloads. You may use a VPN or change your DNS provider to Google/Cloudflare/etc.
|
||||
|
||||
Source: <https://timesofindia.indiatimes.com/gadgets-news/github-content-domain-blocked-for-these-indian-users-reports/articleshow/96687992.cms>
|
||||
|
||||
- Windows Security (formerly Defender) and other anti-virus software are known to block the script. The script gets flagged due to the fact that it requires administrator privileges & makes drastic system changes.
|
||||
|
||||
- If you are having TLS 1.2 issues, or are having trouble resolving `christitus.com/win` then run with the following command:
|
||||
|
||||
```
|
||||
[Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12;iex(New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/ChrisTitusTech/winutil/main/winutil.ps1')
|
||||
To build the project, run the Compile Script under a PowerShell window (admin permissions IS NOT required):
|
||||
```ps1
|
||||
.\Compile.ps1
|
||||
```
|
||||
|
||||
If you are still having issues try changing your DNS provider to 1.1.1.1 || 1.0.0.1 or 8.8.8.8 || 8.8.4.4
|
||||
You'll see a new file named `winutil.ps1`, which's created by `Compile.ps1` script, now you can run it as admin and a new window will popup, enjoy your own compiled version of WinUtil :)
|
||||
|
||||
## Support
|
||||
> [!TIP]
|
||||
> For more info on using WinUtil and how to develop for it, please consider reading [the Contribution Guidelines](https://winutil.christitus.com/contributing/), if you don't know where to start, or have questions, you can ask over on our [Discord Community Server](https://discord.gg/RUbZUZyByQ) and active project members will answer when they can.
|
||||
|
||||
## 💖 Support
|
||||
- To morally and mentally support the project, make sure to leave a ⭐️!
|
||||
- EXE Wrapper for $10 @ https://www.cttstore.com/windows-toolbox
|
||||
|
||||
## Tutorial
|
||||
## 💖 Sponsors
|
||||
|
||||
[](https://www.youtube.com/watch?v=6UQZ5oQg8XA)
|
||||
These are the sponsors that help keep this project alive with monthly contributions.
|
||||
|
||||
## Overview
|
||||
<!-- sponsors --><a href="https://github.com/TriHydera"><img src="https://github.com/TriHydera.png" width="60px" alt="User avatar: TriHydera" /></a><a href="https://github.com/DelDongo"><img src="https://github.com/DelDongo.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/markamos"><img src="https://github.com/markamos.png" width="60px" alt="User avatar: Mark Amos" /></a><a href="https://github.com/dwelfusius"><img src="https://github.com/dwelfusius.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/mews-se"><img src="https://github.com/mews-se.png" width="60px" alt="User avatar: Martin Stockzell" /></a><a href="https://github.com/jdiegmueller"><img src="https://github.com/jdiegmueller.png" width="60px" alt="User avatar: Jason A. Diegmueller" /></a><a href="https://github.com/robertsandrock"><img src="https://github.com/robertsandrock.png" width="60px" alt="User avatar: RMS" /></a><a href="https://github.com/KenichiQaz"><img src="https://github.com/KenichiQaz.png" width="60px" alt="User avatar: Stefan" /></a><a href="https://github.com/paulsheets"><img src="https://github.com/paulsheets.png" width="60px" alt="User avatar: Paul" /></a><a href="https://github.com/djones369"><img src="https://github.com/djones369.png" width="60px" alt="User avatar: Dave J. - WhamGeek" /></a><a href="https://github.com/anthonymendez"><img src="https://github.com/anthonymendez.png" width="60px" alt="User avatar: Anthony Mendez" /></a><a href="https://github.com/FatBastard0"><img src="https://github.com/FatBastard0.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/DursleyGuy"><img src="https://github.com/DursleyGuy.png" width="60px" alt="User avatar: DursleyGuy" /></a><a href="https://github.com/realmuddy"><img src="https://github.com/realmuddy.png" width="60px" alt="User avatar: Phillip Waters" /></a><a href="https://github.com/quaszi"><img src="https://github.com/quaszi.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/DwayneTheRockLobster1"><img src="https://github.com/DwayneTheRockLobster1.png" width="60px" alt="User avatar: " /></a><a href="https://github.com/KieraKujisawa"><img src="https://github.com/KieraKujisawa.png" width="60px" alt="User avatar: Kiera Meredith" /></a><a href="https://github.com/RoelCrabbe"><img src="https://github.com/RoelCrabbe.png" width="60px" alt="User avatar: Roel Crabbé" /></a><a href="https://github.com/Data-Syd"><img src="https://github.com/Data-Syd.png" width="60px" alt="User avatar: Data Syd" /></a><!-- sponsors -->
|
||||
|
||||
- Install
|
||||
- Install Selection: Organize programs by category and facilitate installation by enabling users to select programs and initiate the installation process with a single click.
|
||||
|
||||
- Upgrade All: Upgrade all existing programs to their latest versions, ensuring users have the most up-to-date and feature-rich software.
|
||||
|
||||
- Uninstall Selection: Effortlessly uninstall selected programs, providing users with a streamlined way to remove unwanted software from their system.
|
||||
|
||||
- Get Installed: Retrieve a comprehensive list of installed programs on the system, offering users visibility into the software currently installed on their computer.
|
||||
|
||||
- Import / Export: Enable users to import or export the selection list of programs, allowing them to save their preferred program configurations or share them with others. This feature promotes convenience and flexibility in managing program selections across different systems.
|
||||
|
||||
- Tweaks
|
||||
- Recommended Selection: Provides pre-defined templates tailored for desktop, laptop, and minimal configurations, allowing users to select recommended settings and optimizations specific to their system type.
|
||||
|
||||
- Essential Tweaks: Offers a collection of essential tweaks aimed at improving system performance, privacy, and resource utilization. These tweaks include creating a system restore point, disabling telemetry, Wi-Fi Sense, setting services to manual, disabling location tracking, and HomeGroup, among others.
|
||||
|
||||
- Advanced Tweaks: Encompasses a range of various advanced power user tweaks to further optimize the system. These tweaks include removing OneDrive and Edge, disabling User Account Control (UAC), notification panel, among others.
|
||||
|
||||
- Toggles: Adds easy to use, one click shortcuts for toggling dark mode, NumLock on startup, file extensions, sticky keys, among others.
|
||||
|
||||
- Additional Tweaks: Introduces various other tweaks such as enabling dark mode, changing DNS settings, adding an Ultimate Performance mode, and creating shortcuts for WinUtil tools. These tweaks provide users with additional customization options to tailor their system to their preferences.
|
||||
|
||||
- Config
|
||||
- Features: Allows users to easily install various essential components and features to enhance their Windows experience. These features include installing .NET Frameworks, enabling Hyper-V virtualization, enabling legacy media support for Windows Media Player and DirectPlay, enabling NFS (Network File System) for network file sharing, and enabling Windows Subsystem for Linux (WSL) for running Linux applications on Windows.
|
||||
|
||||
- Fixes: Provides a range of helpful fixes to address common issues and improve system stability. This includes setting up autologon for seamless login experiences, resetting Windows updates to resolve update-related problems, performing a system corruption scan to detect and repair corrupted files, and resetting network settings to troubleshoot network connectivity issues.
|
||||
|
||||
- Legacy Windows Panels: Includes access to legacy Windows panels from Windows 7, allowing users to access familiar and powerful tools. These panels include Control Panel for managing system settings, Network Connections for configuring network adapters and connections, Power Panel for adjusting power and sleep settings, Sound Settings for managing audio devices and settings, System Properties for viewing and modifying system information, and User Accounts for managing user profiles and account settings.
|
||||
|
||||
|
||||
- Updates:
|
||||
- Default (Out of Box) Settings: Provides the default settings that come with Windows for updates.
|
||||
|
||||
- Security (Recommended) Settings: Offers recommended settings, including a slight delay of feature updates by 2 years and installation of security updates 4 days after release.
|
||||
|
||||
- Disable All Updates (Not Recommended!): Allows users to disable all Windows updates, but it's not recommended due to potential security risks.
|
||||
|
||||
|
||||
Video and Written Article walkthrough @ <https://christitus.com/windows-tool/>
|
||||
|
||||
## Issues
|
||||
|
||||
If you encounter any challenges or problems with the script, I kindly request that you submit them via the "Issues" tab on the GitHub repository. By filling out the provided template, you can provide specific details about the issue, allowing me to promptly address any bugs or consider feature requests.
|
||||
|
||||
## Contribute Code
|
||||
|
||||
Pull Requests are now handled directly on the MAIN branch. This was done since we can now select specific releases to launch via releases in GitHub.
|
||||
|
||||
If doing a code change and you can submit a PR to main branch, but I am very selective about these. Do not use a code formatter, massive amounts of line changes, and make multiple feature changes. EACH FEATURE CHANGE SHOULD BE IT'S OWN Pull Request!
|
||||
|
||||
When creating pull requests, it is essential to thoroughly document all changes made. This includes documenting any additions made to the tweaks section and ensuring that corresponding undo measures are in place to remove the newly added tweaks if necessary. Failure to adhere to this format may result in denial of the pull request. Additionally, comprehensive documentation is required for all code changes. Any code lacking sufficient documentation may also be denied.
|
||||
|
||||
By following these guidelines, we can maintain a high standard of quality and ensure that the codebase remains organized and well-documented.
|
||||
|
||||
NOTE: When creating a function please include "WPF" or "WinUtil" in the name so that it can be loaded into the runspace.
|
||||
|
||||
## Thanks to all Contributors
|
||||
## 🏅 Thanks to all Contributors
|
||||
Thanks a lot for spending your time helping Winutil grow. Thanks a lot! Keep rocking 🍻.
|
||||
|
||||
[](https://github.com/ChrisTitusTech/winutil/graphs/contributors)
|
||||
|
||||
## GitHub Stats
|
||||
## 📊 GitHub Stats
|
||||
|
||||

|
||||
|
16
Test-WingetInstall.ps1
Normal file
16
Test-WingetInstall.ps1
Normal file
@ -0,0 +1,16 @@
|
||||
# Import the function (adjust the path according to your setup)
|
||||
. "./functions/private/Install-WinUtilWinget.ps1"
|
||||
. "./functions/private/Test-WinUtilPackageManager.ps1"
|
||||
|
||||
# Set up Information stream to be visible
|
||||
$InformationPreference = "Continue"
|
||||
|
||||
Write-Host "Starting Winget installation test..." -ForegroundColor Cyan
|
||||
|
||||
try {
|
||||
Install-WinUtilWinget
|
||||
} catch {
|
||||
Write-Host "Error occurred during testing: $($_.Exception.Message)" -ForegroundColor Red
|
||||
Write-Host "Stack Trace:" -ForegroundColor Red
|
||||
$_.ScriptStackTrace
|
||||
}
|
File diff suppressed because it is too large
Load Diff
62
config/appnavigation.json
Normal file
62
config/appnavigation.json
Normal file
@ -0,0 +1,62 @@
|
||||
{
|
||||
"WPFInstall": {
|
||||
"Content": "Install/Upgrade Applications",
|
||||
"Category": "____Actions",
|
||||
"Type": "Button",
|
||||
"Order": "1",
|
||||
"Description": "Install or upgrade the selected applications"
|
||||
},
|
||||
"WPFUninstall": {
|
||||
"Content": "Uninstall Applications",
|
||||
"Category": "____Actions",
|
||||
"Type": "Button",
|
||||
"Order": "2",
|
||||
"Description": "Uninstall the selected applications"
|
||||
},
|
||||
"WPFInstallUpgrade": {
|
||||
"Content": "Upgrade all Applications",
|
||||
"Category": "____Actions",
|
||||
"Type": "Button",
|
||||
"Order": "3",
|
||||
"Description": "Upgrade all applications to the latest version"
|
||||
},
|
||||
"WingetRadioButton": {
|
||||
"Content": "Winget",
|
||||
"Category": "__Package Manager",
|
||||
"Type": "RadioButton",
|
||||
"GroupName": "PackageManagerGroup",
|
||||
"Checked": true,
|
||||
"Order": "1",
|
||||
"Description": "Use Winget for package management"
|
||||
},
|
||||
"ChocoRadioButton": {
|
||||
"Content": "Chocolatey",
|
||||
"Category": "__Package Manager",
|
||||
"Type": "RadioButton",
|
||||
"GroupName": "PackageManagerGroup",
|
||||
"Checked": false,
|
||||
"Order": "2",
|
||||
"Description": "Use Chocolatey for package management"
|
||||
},
|
||||
"WPFClearInstallSelection": {
|
||||
"Content": "Clear Selection",
|
||||
"Category": "__Selection",
|
||||
"Type": "Button",
|
||||
"Order": "1",
|
||||
"Description": "Clear the selection of applications"
|
||||
},
|
||||
"WPFGetInstalled": {
|
||||
"Content": "Get Installed",
|
||||
"Category": "__Selection",
|
||||
"Type": "Button",
|
||||
"Order": "2",
|
||||
"Description": "Show installed applications"
|
||||
},
|
||||
"WPFselectedAppsButton": {
|
||||
"Content": "Selected Apps: 0",
|
||||
"Category": "__Selection",
|
||||
"Type": "Button",
|
||||
"Order": "3",
|
||||
"Description": "Show the selected applications"
|
||||
}
|
||||
}
|
442
config/autounattend.xml
Normal file
442
config/autounattend.xml
Normal file
@ -0,0 +1,442 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<unattend xmlns="urn:schemas-microsoft-com:unattend" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
|
||||
<!--https://schneegans.de/windows/unattend-generator/?LanguageMode=Unattended&UILanguage=en-US&Locale=en-US&Keyboard=00000409&GeoLocation=244&ProcessorArchitecture=amd64&BypassRequirementsCheck=true&BypassNetworkCheck=true&ComputerNameMode=Random&TimeZoneMode=Implicit&PartitionMode=Interactive&WindowsEditionMode=Unattended&WindowsEdition=pro&UserAccountMode=Unattended&AccountName0=User&AccountPassword0=&AccountGroup0=Administrators&AccountName1=&AccountName2=&AccountName3=&AccountName4=&AutoLogonMode=Own&PasswordExpirationMode=Unlimited&LockoutMode=Default&HideFiles=Hidden&DisableWidgets=true&ClassicContextMenu=true&DisableFastStartup=true&EnableLongPaths=true&DisableAppSuggestions=true&PreventDeviceEncryption=true&WifiMode=Skip&ExpressSettings=DisableAll&Remove3DViewer=true&RemoveBingSearch=true&RemoveCamera=true&RemoveClipchamp=true&RemoveClock=true&RemoveCopilot=true&RemoveCortana=true&RemoveDevHome=true&RemoveFamily=true&RemoveFeedbackHub=true&RemoveGetHelp=true&RemoveInternetExplorer=true&RemoveMailCalendar=true&RemoveMaps=true&RemoveMathInputPanel=true&RemoveZuneVideo=true&RemoveNews=true&RemoveNotepad=true&RemoveOffice365=true&RemoveOneDrive=true&RemoveOneNote=true&RemoveOpenSSHClient=true&RemoveOutlook=true&RemovePaint3D=true&RemovePeople=true&RemovePowerAutomate=true&RemoveQuickAssist=true&RemoveSkype=true&RemoveSolitaire=true&RemoveStepsRecorder=true&RemoveStickyNotes=true&RemoveTeams=true&RemoveGetStarted=true&RemoveToDo=true&RemoveVoiceRecorder=true&RemoveWeather=true&RemoveWindowsMediaPlayer=true&RemoveZuneMusic=true&RemoveWordPad=true&WdacMode=Skip-->
|
||||
<settings pass="offlineServicing"></settings>
|
||||
<settings pass="windowsPE">
|
||||
<component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<SetupUILanguage>
|
||||
<UILanguage>en-US</UILanguage>
|
||||
</SetupUILanguage>
|
||||
<InputLocale>0409:00000409</InputLocale>
|
||||
<SystemLocale>en-US</SystemLocale>
|
||||
<UILanguage>en-US</UILanguage>
|
||||
<UserLocale>en-US</UserLocale>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<UserData>
|
||||
<ProductKey>
|
||||
<Key>VK7JG-NPHTM-C97JM-9MPGT-3V66T</Key>
|
||||
</ProductKey>
|
||||
<AcceptEula>true</AcceptEula>
|
||||
</UserData>
|
||||
<RunSynchronous>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>1</Order>
|
||||
<Path>reg.exe add "HKLM\SYSTEM\Setup\LabConfig" /v BypassTPMCheck /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>2</Order>
|
||||
<Path>reg.exe add "HKLM\SYSTEM\Setup\LabConfig" /v BypassSecureBootCheck /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>3</Order>
|
||||
<Path>reg.exe add "HKLM\SYSTEM\Setup\LabConfig" /v BypassRAMCheck /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
</RunSynchronous>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="generalize"></settings>
|
||||
<settings pass="specialize">
|
||||
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<RunSynchronous>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>1</Order>
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE" /v BypassNRO /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>2</Order>
|
||||
<Path>reg.exe load "HKU\DefaultUser" "C:\Users\Default\NTUSER.DAT"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>3</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\Runonce" /v "UninstallCopilot" /t REG_SZ /d "powershell.exe -NoProfile -Command \"Get-AppxPackage -Name 'Microsoft.Windows.Ai.Copilot.Provider' | Remove-AppxPackage;\"" /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>4</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Policies\Microsoft\Windows\WindowsCopilot" /v TurnOffWindowsCopilot /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>5</Order>
|
||||
<Path>reg.exe unload "HKU\DefaultUser"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>6</Order>
|
||||
<Path>reg.exe delete "HKLM\SOFTWARE\Microsoft\WindowsUpdate\Orchestrator\UScheduler_Oobe\DevHomeUpdate" /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>7</Order>
|
||||
<Path>reg.exe load "HKU\DefaultUser" "C:\Users\Default\NTUSER.DAT"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>8</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Notepad" /v ShowStoreBanner /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>9</Order>
|
||||
<Path>reg.exe unload "HKU\DefaultUser"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>10</Order>
|
||||
<Path>cmd.exe /c "del "C:\Users\Default\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\OneDrive.lnk""</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>11</Order>
|
||||
<Path>cmd.exe /c "del "C:\Windows\System32\OneDriveSetup.exe""</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>12</Order>
|
||||
<Path>cmd.exe /c "del "C:\Windows\SysWOW64\OneDriveSetup.exe""</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>13</Order>
|
||||
<Path>reg.exe load "HKU\DefaultUser" "C:\Users\Default\NTUSER.DAT"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>14</Order>
|
||||
<Path>reg.exe delete "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\Run" /v OneDriveSetup /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>15</Order>
|
||||
<Path>reg.exe unload "HKU\DefaultUser"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>16</Order>
|
||||
<Path>reg.exe delete "HKLM\SOFTWARE\Microsoft\WindowsUpdate\Orchestrator\UScheduler_Oobe\OutlookUpdate" /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>17</Order>
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Communications" /v ConfigureChatAutoInstall /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>18</Order>
|
||||
<Path>powershell.exe -NoProfile -Command "$xml = [xml]::new(); $xml.Load('C:\Windows\Panther\unattend.xml'); $sb = [scriptblock]::Create( $xml.unattend.Extensions.ExtractScript ); Invoke-Command -ScriptBlock $sb -ArgumentList $xml;"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>19</Order>
|
||||
<Path>powershell.exe -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Temp\Microwin-RemovePackages.ps1' -Raw | Invoke-Expression;"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>20</Order>
|
||||
<Path>powershell.exe -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Temp\remove-caps.ps1' -Raw | Invoke-Expression;"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>21</Order>
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Microsoft\PolicyManager\current\device\Start" /v ConfigureStartPins /t REG_SZ /d "{ \"pinnedList\": [] }" /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>22</Order>
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Microsoft\PolicyManager\current\device\Start" /v ConfigureStartPins_ProviderSet /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>23</Order>
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Microsoft\PolicyManager\current\device\Start" /v ConfigureStartPins_WinningProvider /t REG_SZ /d B5292708-1619-419B-9923-E5D9F3925E71 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>24</Order>
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Microsoft\PolicyManager\providers\B5292708-1619-419B-9923-E5D9F3925E71\default\Device\Start" /v ConfigureStartPins /t REG_SZ /d "{ \"pinnedList\": [] }" /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>25</Order>
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Microsoft\PolicyManager\providers\B5292708-1619-419B-9923-E5D9F3925E71\default\Device\Start" /v ConfigureStartPins_LastWrite /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>26</Order>
|
||||
<Path>net.exe accounts /maxpwage:UNLIMITED</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>27</Order>
|
||||
<Path>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>28</Order>
|
||||
<Path>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Power" /v HiberbootEnabled /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>29</Order>
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Dsh" /v AllowNewsAndInterests /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>30</Order>
|
||||
<Path>reg.exe load "HKU\DefaultUser" "C:\Users\Default\NTUSER.DAT"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>31</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "ContentDeliveryAllowed" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>32</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "FeatureManagementEnabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>33</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "OEMPreInstalledAppsEnabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>34</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "PreInstalledAppsEnabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>35</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "PreInstalledAppsEverEnabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>36</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SilentInstalledAppsEnabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>37</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SoftLandingEnabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>38</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContentEnabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>39</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-310093Enabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>40</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338387Enabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>41</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338388Enabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>42</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338389Enabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>43</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338393Enabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>44</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-353698Enabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>45</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SystemPaneSuggestionsEnabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>46</Order>
|
||||
<Path>reg.exe unload "HKU\DefaultUser"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>47</Order>
|
||||
<Path>reg.exe add "HKLM\Software\Policies\Microsoft\Windows\CloudContent" /v "DisableWindowsConsumerFeatures" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>48</Order>
|
||||
<Path>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\BitLocker" /v "PreventDeviceEncryption" /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>49</Order>
|
||||
<Path>reg.exe load "HKU\DefaultUser" "C:\Users\Default\NTUSER.DAT"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>50</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\Runonce" /v "ClassicContextMenu" /t REG_SZ /d "reg.exe add \"HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32\" /ve /f" /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>51</Order>
|
||||
<Path>reg.exe unload "HKU\DefaultUser"</Path>
|
||||
</RunSynchronousCommand>
|
||||
</RunSynchronous>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="auditSystem"></settings>
|
||||
<settings pass="auditUser"></settings>
|
||||
<settings pass="oobeSystem">
|
||||
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<InputLocale>0409:00000409</InputLocale>
|
||||
<SystemLocale>en-US</SystemLocale>
|
||||
<UILanguage>en-US</UILanguage>
|
||||
<UserLocale>en-US</UserLocale>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<UserAccounts>
|
||||
<LocalAccounts>
|
||||
<LocalAccount wcm:action="add">
|
||||
<Name>User</Name>
|
||||
<Group>Administrators</Group>
|
||||
<Password>
|
||||
<Value></Value>
|
||||
<PlainText>true</PlainText>
|
||||
</Password>
|
||||
</LocalAccount>
|
||||
</LocalAccounts>
|
||||
</UserAccounts>
|
||||
<AutoLogon>
|
||||
<Username>User</Username>
|
||||
<Enabled>true</Enabled>
|
||||
<LogonCount>1</LogonCount>
|
||||
<Password>
|
||||
<Value></Value>
|
||||
<PlainText>true</PlainText>
|
||||
</Password>
|
||||
</AutoLogon>
|
||||
<OOBE>
|
||||
<ProtectYourPC>3</ProtectYourPC>
|
||||
<HideEULAPage>true</HideEULAPage>
|
||||
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
|
||||
</OOBE>
|
||||
<FirstLogonCommands>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>1</Order>
|
||||
<CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoLogonCount /t REG_DWORD /d 0 /f</CommandLine>
|
||||
</SynchronousCommand>
|
||||
</FirstLogonCommands>
|
||||
</component>
|
||||
</settings>
|
||||
<Extensions xmlns="https://schneegans.de/windows/unattend-generator/">
|
||||
<ExtractScript>
|
||||
param(
|
||||
[xml]$Document
|
||||
);
|
||||
|
||||
$scriptsDir = 'C:\Windows\Setup\Scripts\';
|
||||
foreach( $file in $Document.unattend.Extensions.File ) {
|
||||
$path = [System.Environment]::ExpandEnvironmentVariables(
|
||||
$file.GetAttribute( 'path' )
|
||||
);
|
||||
if( $path.StartsWith( $scriptsDir ) ) {
|
||||
mkdir -Path $scriptsDir -ErrorAction 'SilentlyContinue';
|
||||
}
|
||||
$encoding = switch( [System.IO.Path]::GetExtension( $path ) ) {
|
||||
{ $_ -in '.ps1', '.xml' } { [System.Text.Encoding]::UTF8; }
|
||||
{ $_ -in '.reg', '.vbs', '.js' } { [System.Text.UnicodeEncoding]::new( $false, $true ); }
|
||||
default { [System.Text.Encoding]::Default; }
|
||||
};
|
||||
[System.IO.File]::WriteAllBytes( $path, ( $encoding.GetPreamble() + $encoding.GetBytes( $file.InnerText.Trim() ) ) );
|
||||
}
|
||||
</ExtractScript>
|
||||
<File path="C:\Windows\Temp\Microwin-RemovePackages.ps1">
|
||||
$selectors = @(
|
||||
'Microsoft.Microsoft3DViewer';
|
||||
'Microsoft.BingSearch';
|
||||
'Microsoft.WindowsCamera';
|
||||
'Clipchamp.Clipchamp';
|
||||
'Microsoft.WindowsAlarms';
|
||||
'Microsoft.549981C3F5F10';
|
||||
'Microsoft.Windows.DevHome';
|
||||
'MicrosoftCorporationII.MicrosoftFamily';
|
||||
'Microsoft.WindowsFeedbackHub';
|
||||
'Microsoft.GetHelp';
|
||||
'Microsoft.Getstarted';
|
||||
'microsoft.windowscommunicationsapps';
|
||||
'Microsoft.WindowsMaps';
|
||||
'Microsoft.BingNews';
|
||||
'Microsoft.WindowsNotepad';
|
||||
'Microsoft.MicrosoftOfficeHub';
|
||||
'Microsoft.Office.OneNote';
|
||||
'Microsoft.OutlookForWindows';
|
||||
'Microsoft.MSPaint';
|
||||
'Microsoft.People';
|
||||
'Microsoft.PowerAutomateDesktop';
|
||||
'MicrosoftCorporationII.QuickAssist';
|
||||
'Microsoft.SkypeApp';
|
||||
'Microsoft.MicrosoftSolitaireCollection';
|
||||
'Microsoft.MicrosoftStickyNotes';
|
||||
'MSTeams';
|
||||
'Microsoft.Todos';
|
||||
'Microsoft.WindowsSoundRecorder';
|
||||
'Microsoft.BingWeather';
|
||||
'Microsoft.ZuneMusic';
|
||||
'Microsoft.ZuneVideo';
|
||||
);
|
||||
$getCommand = { Get-AppxProvisionedPackage -Online; };
|
||||
$filterCommand = { $_.DisplayName -eq $selector; };
|
||||
$removeCommand = {
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter( Mandatory, ValueFromPipeline )]
|
||||
$InputObject
|
||||
);
|
||||
process {
|
||||
$InputObject | Remove-AppxProvisionedPackage -AllUsers -Online -ErrorAction 'Continue';
|
||||
}
|
||||
};
|
||||
$type = 'Package';
|
||||
$logfile = 'C:\Windows\Temp\Microwin-RemovePackages.log';
|
||||
& {
|
||||
$installed = & $getCommand;
|
||||
foreach( $selector in $selectors ) {
|
||||
$result = [ordered] @{
|
||||
Selector = $selector;
|
||||
};
|
||||
$found = $installed | Where-Object -FilterScript $filterCommand;
|
||||
if( $found ) {
|
||||
$result.Output = $found | & $removeCommand;
|
||||
if( $? ) {
|
||||
$result.Message = "$type removed.";
|
||||
} else {
|
||||
$result.Message = "$type not removed.";
|
||||
$result.Error = $Error[0];
|
||||
}
|
||||
} else {
|
||||
$result.Message = "$type not installed.";
|
||||
}
|
||||
$result | ConvertTo-Json -Depth 3 -Compress;
|
||||
}
|
||||
} *>&1 >> $logfile;
|
||||
</File>
|
||||
<File path="C:\Windows\Temp\remove-caps.ps1">
|
||||
$selectors = @(
|
||||
'Browser.InternetExplorer';
|
||||
'MathRecognizer';
|
||||
'OpenSSH.Client';
|
||||
'App.Support.QuickAssist';
|
||||
'App.StepsRecorder';
|
||||
'Media.WindowsMediaPlayer';
|
||||
'Microsoft.Windows.WordPad';
|
||||
);
|
||||
$getCommand = { Get-WindowsCapability -Online; };
|
||||
$filterCommand = { ($_.Name -split '~')[0] -eq $selector; };
|
||||
$removeCommand = {
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter( Mandatory, ValueFromPipeline )]
|
||||
$InputObject
|
||||
);
|
||||
process {
|
||||
$InputObject | Remove-WindowsCapability -Online -ErrorAction 'Continue';
|
||||
}
|
||||
};
|
||||
$type = 'Capability';
|
||||
$logfile = 'C:\Windows\Temp\remove-caps.log';
|
||||
& {
|
||||
$installed = & $getCommand;
|
||||
foreach( $selector in $selectors ) {
|
||||
$result = [ordered] @{
|
||||
Selector = $selector;
|
||||
};
|
||||
$found = $installed | Where-Object -FilterScript $filterCommand;
|
||||
if( $found ) {
|
||||
$result.Output = $found | & $removeCommand;
|
||||
if( $? ) {
|
||||
$result.Message = "$type removed.";
|
||||
} else {
|
||||
$result.Message = "$type not removed.";
|
||||
$result.Error = $Error[0];
|
||||
}
|
||||
} else {
|
||||
$result.Message = "$type not installed.";
|
||||
}
|
||||
$result | ConvertTo-Json -Depth 3 -Compress;
|
||||
}
|
||||
} *>&1 >> $logfile;
|
||||
</File>
|
||||
<File path="C:\Users\Default\AppData\Local\Microsoft\Windows\Shell\LayoutModification.xml"><![CDATA[
|
||||
<LayoutModificationTemplate Version="1" xmlns="http://schemas.microsoft.com/Start/2014/LayoutModification">
|
||||
<LayoutOptions StartTileGroupCellWidth="6" />
|
||||
<DefaultLayoutOverride>
|
||||
<StartLayoutCollection>
|
||||
<StartLayout GroupCellWidth="6" xmlns="http://schemas.microsoft.com/Start/2014/FullDefaultLayout" />
|
||||
</StartLayoutCollection>
|
||||
</DefaultLayoutOverride>
|
||||
</LayoutModificationTemplate>
|
||||
]]></File>
|
||||
</Extensions>
|
||||
</unattend>
|
@ -1,30 +1,68 @@
|
||||
{
|
||||
"Google":{
|
||||
"Primary": "8.8.8.8",
|
||||
"Secondary": "8.8.4.4"
|
||||
"Secondary": "8.8.4.4",
|
||||
"Primary6": "2001:4860:4860::8888",
|
||||
"Secondary6": "2001:4860:4860::8844"
|
||||
},
|
||||
"Cloudflare":{
|
||||
"Primary": "1.1.1.1",
|
||||
"Secondary": "1.0.0.1"
|
||||
"Secondary": "1.0.0.1",
|
||||
"Primary6": "2606:4700:4700::1111",
|
||||
"Secondary6": "2606:4700:4700::1001"
|
||||
},
|
||||
"Cloudflare_Malware":{
|
||||
"Primary": "1.1.1.2",
|
||||
"Secondary": "1.0.0.2"
|
||||
"Secondary": "1.0.0.2",
|
||||
"Primary6": "2606:4700:4700::1112",
|
||||
"Secondary6": "2606:4700:4700::1002"
|
||||
},
|
||||
"Cloudflare_Malware_Adult":{
|
||||
"Primary": "1.1.1.3",
|
||||
"Secondary": "1.0.0.3"
|
||||
},
|
||||
"Level3":{
|
||||
"Primary": "4.2.2.2",
|
||||
"Secondary": "4.2.2.1"
|
||||
"Secondary": "1.0.0.3",
|
||||
"Primary6": "2606:4700:4700::1113",
|
||||
"Secondary6": "2606:4700:4700::1003"
|
||||
},
|
||||
"Open_DNS":{
|
||||
"Primary": "208.67.222.222",
|
||||
"Secondary": "208.67.220.220"
|
||||
"Secondary": "208.67.220.220",
|
||||
"Primary6": "2620:119:35::35",
|
||||
"Secondary6": "2620:119:53::53"
|
||||
},
|
||||
"Quad9":{
|
||||
"Primary": "9.9.9.9",
|
||||
"Secondary": "149.112.112.112"
|
||||
"Secondary": "149.112.112.112",
|
||||
"Primary6": "2620:fe::fe",
|
||||
"Secondary6": "2620:fe::9"
|
||||
},
|
||||
"AdGuard_Ads_Trackers":{
|
||||
"Primary": "94.140.14.14",
|
||||
"Secondary": "94.140.15.15",
|
||||
"Primary6": "2a10:50c0::ad1:ff",
|
||||
"Secondary6": "2a10:50c0::ad2:ff"
|
||||
},
|
||||
"AdGuard_Ads_Trackers_Malware_Adult":{
|
||||
"Primary": "94.140.14.15",
|
||||
"Secondary": "94.140.15.16",
|
||||
"Primary6": "2a10:50c0::bad1:ff",
|
||||
"Secondary6": "2a10:50c0::bad2:ff"
|
||||
},
|
||||
"dns0.eu_Open":{
|
||||
"Primary": "193.110.81.254",
|
||||
"Secondary": "185.253.5.254",
|
||||
"Primary6": "2a0f:fc80::ffff",
|
||||
"Secondary6": "2a0f:fc81::ffff"
|
||||
},
|
||||
"dns0.eu_ZERO":{
|
||||
"Primary": "193.110.81.9",
|
||||
"Secondary": "185.253.5.9",
|
||||
"Primary6": "2a0f:fc80::9",
|
||||
"Secondary6": "2a0f:fc81::9"
|
||||
},
|
||||
"dns0.eu_KIDS":{
|
||||
"Primary": "193.110.81.1",
|
||||
"Secondary": "185.253.5.1",
|
||||
"Primary6": "2a0f:fc80::1",
|
||||
"Secondary6": "2a0f:fc81::1"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,9 +9,8 @@
|
||||
"NetFx4-AdvSrvs",
|
||||
"NetFx3"
|
||||
],
|
||||
"InvokeScript": [
|
||||
|
||||
]
|
||||
"InvokeScript": [],
|
||||
"link": "https://winutil.christitus.com/dev/features/features/dotnet"
|
||||
},
|
||||
"WPFFeatureshyperv": {
|
||||
"Content": "HyperV Virtualization",
|
||||
@ -31,7 +30,8 @@
|
||||
],
|
||||
"InvokeScript": [
|
||||
"Start-Process -FilePath cmd.exe -ArgumentList '/c bcdedit /set hypervisorschedulertype classic' -Wait"
|
||||
]
|
||||
],
|
||||
"link": "https://winutil.christitus.com/dev/features/features/hyperv"
|
||||
},
|
||||
"WPFFeatureslegacymedia": {
|
||||
"Content": "Legacy Media (WMP, DirectPlay)",
|
||||
@ -45,9 +45,8 @@
|
||||
"DirectPlay",
|
||||
"LegacyComponents"
|
||||
],
|
||||
"InvokeScript": [
|
||||
|
||||
]
|
||||
"InvokeScript": [],
|
||||
"link": "https://winutil.christitus.com/dev/features/features/legacymedia"
|
||||
},
|
||||
"WPFFeaturewsl": {
|
||||
"Content": "Windows Subsystem for Linux",
|
||||
@ -59,9 +58,8 @@
|
||||
"VirtualMachinePlatform",
|
||||
"Microsoft-Windows-Subsystem-Linux"
|
||||
],
|
||||
"InvokeScript": [
|
||||
|
||||
]
|
||||
"InvokeScript": [],
|
||||
"link": "https://winutil.christitus.com/dev/features/features/wsl"
|
||||
},
|
||||
"WPFFeaturenfs": {
|
||||
"Content": "NFS - Network File System",
|
||||
@ -80,7 +78,8 @@
|
||||
"Set-ItemProperty -Path 'HKLM:\\SOFTWARE\\Microsoft\\ClientForNFS\\CurrentVersion\\Default' -Name 'AnonymousGID' -Type DWord -Value 0",
|
||||
"nfsadmin client start",
|
||||
"nfsadmin client localhost config fileaccess=755 SecFlavors=+sys -krb5 -krb5i"
|
||||
]
|
||||
],
|
||||
"link": "https://winutil.christitus.com/dev/features/features/nfs"
|
||||
},
|
||||
"WPFFeatureEnableSearchSuggestions": {
|
||||
"Content": "Enable Search Box Web Suggestions in Registry(explorer restart)",
|
||||
@ -88,8 +87,7 @@
|
||||
"category": "Features",
|
||||
"panel": "1",
|
||||
"Order": "a015_",
|
||||
"feature": [
|
||||
],
|
||||
"feature": [],
|
||||
"InvokeScript": [
|
||||
"
|
||||
If (!(Test-Path 'HKCU:\\SOFTWARE\\Policies\\Microsoft\\Windows\\Explorer')) {
|
||||
@ -98,7 +96,8 @@
|
||||
New-ItemProperty -Path 'HKCU:\\SOFTWARE\\Policies\\Microsoft\\Windows\\Explorer' -Name 'DisableSearchBoxSuggestions' -Type DWord -Value 0 -Force
|
||||
Stop-Process -name explorer -force
|
||||
"
|
||||
]
|
||||
],
|
||||
"link": "https://winutil.christitus.com/dev/features/features/enablesearchsuggestions"
|
||||
},
|
||||
"WPFFeatureDisableSearchSuggestions": {
|
||||
"Content": "Disable Search Box Web Suggestions in Registry(explorer restart)",
|
||||
@ -106,8 +105,7 @@
|
||||
"category": "Features",
|
||||
"panel": "1",
|
||||
"Order": "a016_",
|
||||
"feature": [
|
||||
],
|
||||
"feature": [],
|
||||
"InvokeScript": [
|
||||
"
|
||||
If (!(Test-Path 'HKCU:\\SOFTWARE\\Policies\\Microsoft\\Windows\\Explorer')) {
|
||||
@ -116,7 +114,8 @@
|
||||
New-ItemProperty -Path 'HKCU:\\SOFTWARE\\Policies\\Microsoft\\Windows\\Explorer' -Name 'DisableSearchBoxSuggestions' -Type DWord -Value 1 -Force
|
||||
Stop-Process -name explorer -force
|
||||
"
|
||||
]
|
||||
],
|
||||
"link": "https://winutil.christitus.com/dev/features/features/disablesearchsuggestions"
|
||||
},
|
||||
"WPFFeatureRegBackup": {
|
||||
"Content": "Enable Daily Registry Backup Task 12.30am",
|
||||
@ -124,8 +123,7 @@
|
||||
"category": "Features",
|
||||
"panel": "1",
|
||||
"Order": "a017_",
|
||||
"feature": [
|
||||
],
|
||||
"feature": [],
|
||||
"InvokeScript": [
|
||||
"
|
||||
New-ItemProperty -Path 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Configuration Manager' -Name 'EnablePeriodicBackup' -Type DWord -Value 1 -Force
|
||||
@ -134,7 +132,8 @@
|
||||
$trigger = New-ScheduledTaskTrigger -Daily -At 00:30
|
||||
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName 'AutoRegBackup' -Description 'Create System Registry Backups' -User 'System'
|
||||
"
|
||||
]
|
||||
],
|
||||
"link": "https://winutil.christitus.com/dev/features/features/regbackup"
|
||||
},
|
||||
"WPFFeatureEnableLegacyRecovery": {
|
||||
"Content": "Enable Legacy F8 Boot Recovery",
|
||||
@ -142,8 +141,7 @@
|
||||
"category": "Features",
|
||||
"panel": "1",
|
||||
"Order": "a018_",
|
||||
"feature": [
|
||||
],
|
||||
"feature": [],
|
||||
"InvokeScript": [
|
||||
"
|
||||
If (!(Test-Path 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Configuration Manager\\LastKnownGood')) {
|
||||
@ -152,7 +150,8 @@
|
||||
New-ItemProperty -Path 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Configuration Manager\\LastKnownGood' -Name 'Enabled' -Type DWord -Value 1 -Force
|
||||
Start-Process -FilePath cmd.exe -ArgumentList '/c bcdedit /Set {Current} BootMenuPolicy Legacy' -Wait
|
||||
"
|
||||
]
|
||||
],
|
||||
"link": "https://winutil.christitus.com/dev/features/features/enablelegacyrecovery"
|
||||
},
|
||||
"WPFFeatureDisableLegacyRecovery": {
|
||||
"Content": "Disable Legacy F8 Boot Recovery",
|
||||
@ -160,8 +159,7 @@
|
||||
"category": "Features",
|
||||
"panel": "1",
|
||||
"Order": "a019_",
|
||||
"feature": [
|
||||
],
|
||||
"feature": [],
|
||||
"InvokeScript": [
|
||||
"
|
||||
If (!(Test-Path 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Configuration Manager\\LastKnownGood')) {
|
||||
@ -170,104 +168,181 @@
|
||||
New-ItemProperty -Path 'HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Configuration Manager\\LastKnownGood' -Name 'Enabled' -Type DWord -Value 0 -Force
|
||||
Start-Process -FilePath cmd.exe -ArgumentList '/c bcdedit /Set {Current} BootMenuPolicy Standard' -Wait
|
||||
"
|
||||
]
|
||||
],
|
||||
"link": "https://winutil.christitus.com/dev/features/features/disablelegacyrecovery"
|
||||
},
|
||||
"WPFFeaturesandbox": {
|
||||
"WPFFeaturesSandbox": {
|
||||
"Content": "Windows Sandbox",
|
||||
"category": "Features",
|
||||
"panel": "1",
|
||||
"Order": "a021_",
|
||||
"Description": "Windows Sandbox is a lightweight virtual machine that provides a temporary desktop environment to safely run applications and programs in isolation."
|
||||
"Description": "Windows Sandbox is a lightweight virtual machine that provides a temporary desktop environment to safely run applications and programs in isolation.",
|
||||
"link": "https://winutil.christitus.com/dev/features/features/sandbox"
|
||||
},
|
||||
"WPFFeatureInstall": {
|
||||
"Content": "Install Features",
|
||||
"category": "Features",
|
||||
"panel": "1",
|
||||
"Order": "a060_",
|
||||
"Type": "150"
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300",
|
||||
"link": "https://winutil.christitus.com/dev/features/features/install"
|
||||
},
|
||||
"WPFPanelAutologin": {
|
||||
"Content": "Set Up Autologin",
|
||||
"category": "Fixes",
|
||||
"Order": "a040_",
|
||||
"panel": "1",
|
||||
"Type": "300"
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300",
|
||||
"link": "https://winutil.christitus.com/dev/features/fixes/autologin"
|
||||
},
|
||||
"WPFFixesUpdate": {
|
||||
"Content": "Reset Windows Update",
|
||||
"category": "Fixes",
|
||||
"panel": "1",
|
||||
"Order": "a041_",
|
||||
"Type": "300"
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300",
|
||||
"link": "https://winutil.christitus.com/dev/features/fixes/update"
|
||||
},
|
||||
"WPFFixesNetwork": {
|
||||
"Content": "Reset Network",
|
||||
"category": "Fixes",
|
||||
"Order": "a042_",
|
||||
"panel": "1",
|
||||
"Type": "300"
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300",
|
||||
"link": "https://winutil.christitus.com/dev/features/fixes/network"
|
||||
},
|
||||
"WPFPanelDISM": {
|
||||
"Content": "System Corruption Scan",
|
||||
"category": "Fixes",
|
||||
"panel": "1",
|
||||
"Order": "a043_",
|
||||
"Type": "300"
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300",
|
||||
"link": "https://winutil.christitus.com/dev/features/fixes/dism"
|
||||
},
|
||||
"WPFFixesWinget": {
|
||||
"Content": "WinGet Reinstall",
|
||||
"category": "Fixes",
|
||||
"panel": "1",
|
||||
"Order": "a044_",
|
||||
"Type": "300"
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300",
|
||||
"link": "https://winutil.christitus.com/dev/features/fixes/winget"
|
||||
},
|
||||
"WPFRunAdobeCCCleanerTool": {
|
||||
"Content": "Remove Adobe Creative Cloud",
|
||||
"category": "Fixes",
|
||||
"panel": "1",
|
||||
"Order": "a045_",
|
||||
"Type": "300"
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300",
|
||||
"link": "https://winutil.christitus.com/dev/features/fixes/runadobecccleanertool"
|
||||
},
|
||||
"WPFPanelnetwork": {
|
||||
"Content": "Network Connections",
|
||||
"category": "Legacy Windows Panels",
|
||||
"panel": "2",
|
||||
"Type": "200"
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300",
|
||||
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/network"
|
||||
},
|
||||
"WPFPanelcontrol": {
|
||||
"Content": "Control Panel",
|
||||
"category": "Legacy Windows Panels",
|
||||
"panel": "2",
|
||||
"Type": "200"
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300",
|
||||
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/control"
|
||||
},
|
||||
"WPFPanelcomputer": {
|
||||
"Content": "Computer Management",
|
||||
"category": "Legacy Windows Panels",
|
||||
"panel": "2",
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300",
|
||||
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/computer"
|
||||
},
|
||||
"WPFPanelpower": {
|
||||
"Content": "Power Panel",
|
||||
"category": "Legacy Windows Panels",
|
||||
"panel": "2",
|
||||
"Type": "200"
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300",
|
||||
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/power"
|
||||
},
|
||||
"WPFPanelregion": {
|
||||
"Content": "Region",
|
||||
"category": "Legacy Windows Panels",
|
||||
"panel": "2",
|
||||
"Type": "200"
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300",
|
||||
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/region"
|
||||
},
|
||||
"WPFPanelsound": {
|
||||
"Content": "Sound Settings",
|
||||
"category": "Legacy Windows Panels",
|
||||
"panel": "2",
|
||||
"Type": "200"
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300",
|
||||
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/sound"
|
||||
},
|
||||
"WPFPanelprinter": {
|
||||
"Content": "Printer Panel",
|
||||
"category": "Legacy Windows Panels",
|
||||
"panel": "2",
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300",
|
||||
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/printer"
|
||||
},
|
||||
"WPFPanelsystem": {
|
||||
"Content": "System Properties",
|
||||
"category": "Legacy Windows Panels",
|
||||
"panel": "2",
|
||||
"Type": "200"
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300",
|
||||
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/system"
|
||||
},
|
||||
"WPFPaneluser": {
|
||||
"Content": "User Accounts",
|
||||
"category": "Legacy Windows Panels",
|
||||
"panel": "2",
|
||||
"Type": "200"
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300",
|
||||
"link": "https://winutil.christitus.com/dev/features/legacy-windows-panels/user"
|
||||
},
|
||||
"WPFPanelGodMode": {
|
||||
"Content": "God Mode",
|
||||
"category": "Legacy Windows Panels",
|
||||
"panel": "2",
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300"
|
||||
},
|
||||
"WPFWinUtilInstallPSProfile": {
|
||||
"Content": "Install CTT PowerShell Profile",
|
||||
"category": "Powershell Profile",
|
||||
"panel": "2",
|
||||
"Order": "a083_",
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300"
|
||||
},
|
||||
"WPFWinUtilUninstallPSProfile": {
|
||||
"Content": "Uninstall CTT PowerShell Profile",
|
||||
"category": "Powershell Profile",
|
||||
"panel": "2",
|
||||
"Order": "a084_",
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300"
|
||||
},
|
||||
"WPFWinUtilSSHServer": {
|
||||
"Content": "Enable OpenSSH Server",
|
||||
"category": "Remote Access",
|
||||
"panel": "2",
|
||||
"Order": "a084_",
|
||||
"Type": "Button",
|
||||
"ButtonWidth": "300"
|
||||
}
|
||||
}
|
||||
|
@ -1,399 +0,0 @@
|
||||
# This file is meant to assist in building out the json files inside this folder.
|
||||
|
||||
#===========================================================================
|
||||
# applications.json
|
||||
#===========================================================================
|
||||
|
||||
<#
|
||||
Applications.json
|
||||
-----------------
|
||||
This file holds all the install commands to install the applications.
|
||||
This file has the ability to expect multiple frameworks per checkbox.
|
||||
You can also add multiple install commands by separating them with ;
|
||||
|
||||
The structure of the json is as follows
|
||||
|
||||
{
|
||||
"Name of Button": {
|
||||
"winget": "Winget command"
|
||||
"choco": "Chocolatey command"
|
||||
},
|
||||
}
|
||||
|
||||
Example:
|
||||
|
||||
{
|
||||
"WPFInstalladobe": {
|
||||
"winget": "Adobe.Acrobat.Reader.64-bit"
|
||||
"choco": "adobereader"
|
||||
},
|
||||
"WPFInstalladvancedip": {
|
||||
"winget": "Famatech.AdvancedIPScanner"
|
||||
"choco": "advanced-ip-scanner"
|
||||
}
|
||||
}
|
||||
|
||||
#>
|
||||
|
||||
# Modify the variables and run his code. It will import the current file and add your addition. From there you can create a pull request.
|
||||
#------Do not delete WPF------
|
||||
|
||||
$NameofButton = "WPF" + ""
|
||||
$WingetCommand = ""
|
||||
$ChocoCommand = ""
|
||||
|
||||
$ButtonToAdd = New-Object psobject
|
||||
$jsonfile = Get-Content ./config/applications.json | ConvertFrom-Json
|
||||
|
||||
# Remove if already exists
|
||||
if($jsonfile.$NameofButton){
|
||||
$jsonfile.psobject.Properties.remove($NameofButton)
|
||||
}
|
||||
|
||||
Add-Member -InputObject $ButtonToAdd -MemberType NoteProperty -Name "Winget" -Value $WingetCommand
|
||||
Add-Member -InputObject $ButtonToAdd -MemberType NoteProperty -Name "choco" -Value $ChocoCommand
|
||||
Add-Member -InputObject $jsonfile.install -MemberType NoteProperty -Name $NameofButton -Value $ButtonToAdd
|
||||
|
||||
$jsonfile | ConvertTo-Json | Out-File ./config/applications.json
|
||||
|
||||
#===========================================================================
|
||||
# feature.json
|
||||
#===========================================================================
|
||||
|
||||
<#
|
||||
feature.json
|
||||
-----------------
|
||||
This file holds all the windows commands to install specific features (IE Hyper-v)
|
||||
|
||||
The structure of the json is as follows
|
||||
|
||||
{
|
||||
"Name of Button": [
|
||||
"Array of",
|
||||
"commands"
|
||||
]
|
||||
}
|
||||
|
||||
Example:
|
||||
{
|
||||
"Featurewsl": [
|
||||
"VirtualMachinePlatform",
|
||||
"Microsoft-Windows-Subsystem-Linux"
|
||||
],
|
||||
"Featurenfs": [
|
||||
"ServicesForNFS-ClientOnly",
|
||||
"ClientForNFS-Infrastructure",
|
||||
"NFS-Administration"
|
||||
]
|
||||
}
|
||||
#>
|
||||
|
||||
# Modify the variables and run his code. It will import the current file and add your addition. From there you can create a pull request.
|
||||
|
||||
$NameofButton = ""
|
||||
$commands = @(
|
||||
|
||||
)
|
||||
|
||||
$jsonfile = Get-Content ./config/feature.json | ConvertFrom-Json
|
||||
|
||||
# Remove if already exists
|
||||
if($jsonfile.$NameofButton){
|
||||
$jsonfile.psobject.Properties.remove($NameofButton)
|
||||
}
|
||||
|
||||
Add-Member -InputObject $jsonfile -MemberType NoteProperty -Name $NameofButton -Value $commands
|
||||
|
||||
$jsonfile | ConvertTo-Json | Out-File ./config/feature.json
|
||||
|
||||
#===========================================================================
|
||||
# preset.json
|
||||
#===========================================================================
|
||||
|
||||
<#
|
||||
preset.json
|
||||
-----------------
|
||||
This file holds all check boxes you wish to check when clicking a preset button in the tweaks section.
|
||||
|
||||
The structure of the json is as follows
|
||||
|
||||
{
|
||||
"Name of Button": [
|
||||
"Array of",
|
||||
"checkboxes to check"
|
||||
]
|
||||
}
|
||||
|
||||
Example:
|
||||
{
|
||||
"laptop": [
|
||||
"EssTweaksAH",
|
||||
"EssTweaksDVR",
|
||||
"EssTweaksHome",
|
||||
"EssTweaksLoc",
|
||||
"EssTweaksOO",
|
||||
"EssTweaksRP",
|
||||
"EssTweaksServices",
|
||||
"EssTweaksStorage",
|
||||
"EssTweaksTele",
|
||||
"EssTweaksWifi",
|
||||
"MiscTweaksLapPower",
|
||||
"MiscTweaksLapNum"
|
||||
],
|
||||
"minimal": [
|
||||
"EssTweaksHome",
|
||||
"EssTweaksOO",
|
||||
"EssTweaksRP",
|
||||
"EssTweaksServices",
|
||||
"EssTweaksTele"
|
||||
]
|
||||
}
|
||||
#>
|
||||
|
||||
# Modify the variables and run his code. It will import the current file and add your addition. From there you can create a pull request.
|
||||
|
||||
$NameofButton = "WPF" + ""
|
||||
$commands = @(
|
||||
|
||||
)
|
||||
|
||||
$jsonfile = Get-Content ./config/preset.json | ConvertFrom-Json
|
||||
|
||||
# Remove if already exists
|
||||
if($jsonfile.$NameofButton){
|
||||
$jsonfile.psobject.Properties.remove($NameofButton)
|
||||
}
|
||||
|
||||
Add-Member -InputObject $jsonfile -MemberType NoteProperty -Name $NameofButton -Value $commands
|
||||
|
||||
$jsonfile | ConvertTo-Json | Out-File ./config/preset.json
|
||||
|
||||
#===========================================================================
|
||||
# tweaks.json
|
||||
#===========================================================================
|
||||
|
||||
<#
|
||||
tweaks.json
|
||||
-----------------
|
||||
This file holds all the tweaks needed to make modifications to windows. This file is the most complicated so modify with care.
|
||||
|
||||
The structure of the json is as follows
|
||||
|
||||
{
|
||||
"Name of button": {
|
||||
"registry" : [
|
||||
{
|
||||
"Path": "Path in registry",
|
||||
"Name": "Name of Registry key",
|
||||
"Type": "Item type",
|
||||
"Value": "Value to modify",
|
||||
"OriginalValue": "value to reset"
|
||||
}
|
||||
],
|
||||
"service" : [
|
||||
{
|
||||
"Name": "Name of service",
|
||||
"StartupType": "Startup type to set",
|
||||
"OriginalType": "Startup type to reset"
|
||||
}
|
||||
],
|
||||
"ScheduledTask" : [
|
||||
{
|
||||
"Name": "Path to scheduled task",
|
||||
"State": "State to set",
|
||||
"OriginalState": "State to reset"
|
||||
}
|
||||
],
|
||||
"appx": [
|
||||
List of appx,
|
||||
files to uninstall
|
||||
],
|
||||
"InvokeScript": [
|
||||
"Script to make modifications not possible with the above types
|
||||
Special care needs to be taken here as converting from json to a scriptblock
|
||||
can cause weird issues. Please look at the example below to get an idea of how things should work"
|
||||
],
|
||||
"UndoScript": [
|
||||
"Same as above however is meant to undo what you did above"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Example:
|
||||
|
||||
{
|
||||
EssTweaksAH": {
|
||||
"registry" : [
|
||||
{
|
||||
"Path": "HKLM:\\SOFTWARE\\Policies\\Microsoft\\Windows\\System",
|
||||
"Name": "EnableActivityFeed",
|
||||
"Type": "DWord",
|
||||
"Value": "0",
|
||||
"OriginalValue": "1"
|
||||
},
|
||||
{
|
||||
"Path": "HKLM:\\SOFTWARE\\Policies\\Microsoft\\Windows\\System",
|
||||
"Name": "PublishUserActivities",
|
||||
"Type": "DWord",
|
||||
"Value": "0",
|
||||
"OriginalValue": "1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"EssTweaksHome": {
|
||||
"service" : [
|
||||
{
|
||||
"Name": "HomeGroupListener",
|
||||
"StartupType": "Manual",
|
||||
"OriginalType": "Automatic"
|
||||
},
|
||||
{
|
||||
"Name": "HomeGroupProvider",
|
||||
"StartupType": "Manual",
|
||||
"OriginalType": "Automatic"
|
||||
}
|
||||
]
|
||||
},
|
||||
"EssTweaksTele": {
|
||||
"ScheduledTask" : [
|
||||
{
|
||||
"Name": "Microsoft\\Windows\\Application Experience\\Microsoft Compatibility Appraiser",
|
||||
"State": "Disabled",
|
||||
"OriginalState": "Enabled"
|
||||
},
|
||||
{
|
||||
"Name": "Microsoft\\Windows\\Application Experience\\ProgramDataUpdater",
|
||||
"State": "Disabled",
|
||||
"OriginalState": "Enabled"
|
||||
}
|
||||
]
|
||||
},
|
||||
"EssTweaksDeBloat": {
|
||||
"appx": [
|
||||
"Microsoft.Microsoft3DViewer",
|
||||
"Microsoft.AppConnector"
|
||||
]
|
||||
},
|
||||
"EssTweaksOO": {
|
||||
"InvokeScript": [
|
||||
"Import-Module BitsTransfer
|
||||
Start-BitsTransfer -Source \"https://raw.githubusercontent.com/ChrisTitusTech/win10script/master/ooshutup10.cfg\" -Destination C:\\Windows\\Temp\\ooshutup10.cfg
|
||||
Start-BitsTransfer -Source \"https://dl5.oo-software.com/files/ooshutup10/OOSU10.exe\" -Destination C:\\Windows\\Temp\\OOSU10.exe
|
||||
C:\\Windows\\Temp\\OOSU10.exe C:\\Windows\\Temp\\ooshutup10.cfg /quiet"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
#>
|
||||
|
||||
# Modify the variables and run his code. It will import the current file and add your addition. From there you can create a pull request.
|
||||
# Make sure to uncomment the sections you which to add.
|
||||
|
||||
#$Registry = @(
|
||||
# # To add more repeat this separated by a comma
|
||||
# @{
|
||||
# Path = ""
|
||||
# Name = ""
|
||||
# Type = ""
|
||||
# Value = ""
|
||||
# OriginalValue = ""
|
||||
# }
|
||||
#)
|
||||
|
||||
#$Service = @(
|
||||
# # To add more repeat this separated by a comma
|
||||
# @{
|
||||
# Name = ""
|
||||
# StartupType = ""
|
||||
# OriginalType = ""
|
||||
# }
|
||||
#)
|
||||
|
||||
#$ScheduledTask = @(
|
||||
# # To add more repeat this separated by a comma
|
||||
# @{
|
||||
# Name = ""
|
||||
# State = ""
|
||||
# OriginalState = ""
|
||||
# }
|
||||
#)
|
||||
|
||||
#$Appx = @(
|
||||
# ""
|
||||
#)
|
||||
|
||||
#$InvokeScript = @(
|
||||
# ""
|
||||
#)
|
||||
|
||||
#$UndoScript = @(
|
||||
# ""
|
||||
#)
|
||||
|
||||
$NameofButton = "WPF" + ""
|
||||
|
||||
$ButtonToAdd = New-Object psobject
|
||||
$jsonfile = Get-Content ./config/tweaks.json | ConvertFrom-Json
|
||||
|
||||
# Remove if already exists
|
||||
if($jsonfile.$NameofButton){
|
||||
$jsonfile.psobject.Properties.remove($NameofButton)
|
||||
}
|
||||
|
||||
if($Registry){Add-Member -InputObject $ButtonToAdd -MemberType NoteProperty -Name "registry" -Value $Registry}
|
||||
if($Service){Add-Member -InputObject $ButtonToAdd -MemberType NoteProperty -Name "service" -Value $Service}
|
||||
if($ScheduledTask){Add-Member -InputObject $ButtonToAdd -MemberType NoteProperty -Name "ScheduledTask" -Value $ScheduledTask}
|
||||
if($Appx){Add-Member -InputObject $ButtonToAdd -MemberType NoteProperty -Name "Appx" -Value $Appx}
|
||||
if($InvokeScript){Add-Member -InputObject $ButtonToAdd -MemberType NoteProperty -Name "InvokeScript" -Value $InvokeScript}
|
||||
if($UndoScript){Add-Member -InputObject $ButtonToAdd -MemberType NoteProperty -Name "UndoScript" -Value $UndoScript}
|
||||
|
||||
Add-Member -InputObject $jsonfile -MemberType NoteProperty -Name $NameofButton -Value $ButtonToAdd
|
||||
|
||||
($jsonfile | ConvertTo-Json -Depth 5).replace('\r\n',"`r`n") | Out-File ./config/tweaks.json
|
||||
|
||||
#===========================================================================
|
||||
# dns.json
|
||||
#===========================================================================
|
||||
|
||||
<#
|
||||
dns.json
|
||||
-----------------
|
||||
This file holds all the DNS entries.
|
||||
|
||||
The structure of the json is as follows
|
||||
|
||||
{
|
||||
"DNS Provider": [
|
||||
"Primary": "IP address",
|
||||
"Secondary": "IP address"
|
||||
]
|
||||
}
|
||||
|
||||
Example:
|
||||
{
|
||||
"Cloudflare":{
|
||||
"Primary": "1.1.1.1",
|
||||
"Secondary": "1.0.0.1"
|
||||
}
|
||||
}
|
||||
#>
|
||||
|
||||
# Modify the variables and run his code. It will import the current file and add your addition. From there you can create a pull request.
|
||||
|
||||
$NameofProvider = "" -replace " ","_"
|
||||
$IPAddress = @{
|
||||
"Primary" = "0.0.0.0"
|
||||
"Secondary" = "0.0.0.0"
|
||||
}
|
||||
|
||||
$ButtonToAdd = New-Object psobject
|
||||
$jsonfile = Get-Content ./config/dns.json | ConvertFrom-Json
|
||||
|
||||
# Remove if already exists
|
||||
if($jsonfile.$NameofProvider){
|
||||
$jsonfile.psobject.Properties.remove($NameofProvider)
|
||||
}
|
||||
|
||||
Add-Member -InputObject $jsonfile -MemberType NoteProperty -Name $NameofProvider -Value $IPAddress
|
||||
|
||||
($jsonfile | ConvertTo-Json -Depth 5).replace('\r\n',"`r`n") | Out-File ./config/dns.json
|
@ -1,8 +1,9 @@
|
||||
{
|
||||
"Standard": [
|
||||
"WPFTweaksAH",
|
||||
"WPFTweaksConsumerFeatures",
|
||||
"WPFTweaksDisableExplorerAutoDiscovery",
|
||||
"WPFTweaksDVR",
|
||||
"WPFTweaksHiber",
|
||||
"WPFTweaksHome",
|
||||
"WPFTweaksLoc",
|
||||
"WPFTweaksServices",
|
||||
@ -13,9 +14,11 @@
|
||||
"WPFTweaksDeleteTempFiles",
|
||||
"WPFTweaksEndTaskOnTaskbar",
|
||||
"WPFTweaksRestorePoint",
|
||||
"WPFTweaksTeredo"
|
||||
"WPFTweaksPowershell7Tele"
|
||||
],
|
||||
"Minimal": [
|
||||
"WPFTweaksConsumerFeatures",
|
||||
"WPFTweaksDisableExplorerAutoDiscovery",
|
||||
"WPFTweaksHome",
|
||||
"WPFTweaksServices",
|
||||
"WPFTweaksTele"
|
||||
|
@ -1,97 +1,126 @@
|
||||
{
|
||||
"Classic": {
|
||||
"ComboBoxBackgroundColor": "#FFFFFF",
|
||||
"LabelboxForegroundColor": "#000000",
|
||||
"MainForegroundColor": "#000000",
|
||||
"MainBackgroundColor": "#FFFFFF",
|
||||
"LabelBackgroundColor": "#FAFAFA",
|
||||
"LinkForegroundColor": "#000000",
|
||||
"LinkHoverForegroundColor": "#000000",
|
||||
"GroupBorderBackgroundColor": "#000000",
|
||||
"ComboBoxForegroundColor": "#000000",
|
||||
"ButtonInstallBackgroundColor": "#FFFFFF",
|
||||
"ButtonTweaksBackgroundColor": "#FFFFFF",
|
||||
"ButtonConfigBackgroundColor": "#FFFFFF",
|
||||
"ButtonUpdatesBackgroundColor": "#FFFFFF",
|
||||
"ButtonInstallForegroundColor": "#000000",
|
||||
"ButtonTweaksForegroundColor": "#000000",
|
||||
"ButtonConfigForegroundColor": "#000000",
|
||||
"ButtonUpdatesForegroundColor": "#000000",
|
||||
"ButtonBackgroundColor": "#F5F5F5",
|
||||
"ButtonBackgroundPressedColor": "#1A1A1A",
|
||||
"CheckboxMouseOverColor": "#999999",
|
||||
"ButtonBackgroundMouseoverColor": "#C2C2C2",
|
||||
"ButtonBackgroundSelectedColor": "#F0F0F0",
|
||||
"ButtonForegroundColor": "#000000",
|
||||
"ToggleButtonOnColor": "#2e77ff",
|
||||
"ButtonBorderThickness": "1",
|
||||
"ButtonMargin": "1",
|
||||
"ButtonCornerRadius": "2",
|
||||
"ToggleButtonHeight": "25",
|
||||
"BorderColor": "#000000",
|
||||
"BorderOpacity": "0.2",
|
||||
"ShadowPulse": "Forever"
|
||||
},
|
||||
"Matrix": {
|
||||
"ComboBoxBackgroundColor": "#000000",
|
||||
"LabelboxForegroundColor": "#FFEE58",
|
||||
"MainForegroundColor": "#9CCC65",
|
||||
"MainBackgroundColor": "#000000",
|
||||
"LabelBackgroundColor": "#000000",
|
||||
"LinkForegroundColor": "#add8e6",
|
||||
"LinkHoverForegroundColor": "#FFFFFF",
|
||||
"ComboBoxForegroundColor": "#FFEE58",
|
||||
"ButtonInstallBackgroundColor": "#222222",
|
||||
"ButtonTweaksBackgroundColor": "#333333",
|
||||
"ButtonConfigBackgroundColor": "#444444",
|
||||
"ButtonUpdatesBackgroundColor": "#555555",
|
||||
"ButtonInstallForegroundColor": "#FFFFFF",
|
||||
"ButtonTweaksForegroundColor": "#FFFFFF",
|
||||
"ButtonConfigForegroundColor": "#FFFFFF",
|
||||
"ButtonUpdatesForegroundColor": "#FFFFFF",
|
||||
"ButtonBackgroundColor": "#000019",
|
||||
"ButtonBackgroundPressedColor": "#FFFFFF",
|
||||
"ButtonBackgroundMouseoverColor": "#A55A64",
|
||||
"ButtonBackgroundSelectedColor": "#FF5733",
|
||||
"ButtonForegroundColor": "#9CCC65",
|
||||
"ToggleButtonOnColor": "#2e77ff",
|
||||
"ButtonBorderThickness": "1",
|
||||
"ButtonMargin": "1",
|
||||
"ButtonCornerRadius": "2",
|
||||
"ToggleButtonHeight": "25",
|
||||
"BorderColor": "#FFAC1C",
|
||||
"BorderOpacity": "0.8",
|
||||
"ShadowPulse": "0:0:3"
|
||||
},
|
||||
"Dark": {
|
||||
"ComboBoxBackgroundColor": "#000000",
|
||||
"LabelboxForegroundColor": "#FFEE58",
|
||||
"MainForegroundColor": "#9CCC65",
|
||||
"MainBackgroundColor": "#000000",
|
||||
"LabelBackgroundColor": "#000000",
|
||||
"LinkForegroundColor": "#add8e6",
|
||||
"LinkHoverForegroundColor": "#FFFFFF",
|
||||
"ComboBoxForegroundColor": "#FFEE58",
|
||||
"ButtonInstallBackgroundColor": "#222222",
|
||||
"ButtonTweaksBackgroundColor": "#333333",
|
||||
"ButtonConfigBackgroundColor": "#444444",
|
||||
"ButtonUpdatesBackgroundColor": "#555555",
|
||||
"ButtonInstallForegroundColor": "#FFFFFF",
|
||||
"ButtonTweaksForegroundColor": "#FFFFFF",
|
||||
"ButtonConfigForegroundColor": "#FFFFFF",
|
||||
"ButtonUpdatesForegroundColor": "#FFFFFF",
|
||||
"ButtonBackgroundColor": "#000019",
|
||||
"ButtonBackgroundPressedColor": "#9CCC65",
|
||||
"ButtonBackgroundMouseoverColor": "#FF5733",
|
||||
"ButtonBackgroundSelectedColor": "#FF5733",
|
||||
"ButtonForegroundColor": "#9CCC65",
|
||||
"ToggleButtonOnColor": "#2e77ff",
|
||||
"ButtonBorderThickness": "1",
|
||||
"ButtonMargin": "1",
|
||||
"ButtonCornerRadius": "2",
|
||||
"ToggleButtonHeight": "25",
|
||||
"BorderColor": "#FFAC1C",
|
||||
"BorderOpacity": "0.2",
|
||||
"ShadowPulse": "Forever"
|
||||
}
|
||||
}
|
||||
"shared":{
|
||||
"AppEntryWidth": "130",
|
||||
"AppEntryFontSize": "11",
|
||||
"AppEntryMargin": "1,1,1,1",
|
||||
"AppEntryBorderTickness": "0",
|
||||
"CustomDialogFontSize": "12",
|
||||
"CustomDialogFontSizeHeader": "14",
|
||||
"CustomDialogLogoSize": "25",
|
||||
"CustomDialogWidth": "400",
|
||||
"CustomDialogHeight": "200",
|
||||
"FontSize": "12",
|
||||
"FontFamily": "Arial",
|
||||
"HeaderFontSize": "16",
|
||||
"HeaderFontFamily": "Consolas, Monaco",
|
||||
"CheckBoxBulletDecoratorSize": "14",
|
||||
"CheckBoxMargin": "15,0,0,2",
|
||||
"TabContentMargin": "5",
|
||||
"TabButtonFontSize": "14",
|
||||
"TabButtonWidth": "110",
|
||||
"TabButtonHeight": "26",
|
||||
"TabRowHeightInPixels": "50",
|
||||
"ToolTipWidth": "300",
|
||||
"IconFontSize": "14",
|
||||
"IconButtonSize": "35",
|
||||
"SettingsIconFontSize": "18",
|
||||
"CloseIconFontSize": "18",
|
||||
"MicroWinLogoSize": "10",
|
||||
"MicrowinCheckBoxMargin": "-10,5,0,0",
|
||||
"GroupBorderBackgroundColor": "#232629",
|
||||
"ButtonFontSize": "12",
|
||||
"ButtonFontFamily": "Arial",
|
||||
"ButtonWidth": "200",
|
||||
"ButtonHeight": "25",
|
||||
"ConfigUpdateButtonFontSize": "14",
|
||||
"SearchBarWidth": "200",
|
||||
"SearchBarHeight": "26",
|
||||
"SearchBarTextBoxFontSize": "12",
|
||||
"SearchBarClearButtonFontSize": "14",
|
||||
"CheckboxMouseOverColor": "#999999",
|
||||
"ButtonBorderThickness": "1",
|
||||
"ButtonMargin": "1",
|
||||
"ButtonCornerRadius": "2"
|
||||
},
|
||||
"Light": {
|
||||
"AppInstallUnselectedColor": "#F7F7F7",
|
||||
"AppInstallHighlightedColor": "#CFCFCF",
|
||||
"AppInstallSelectedColor": "#C2C2C2",
|
||||
"AppInstallOverlayBackgroundColor":"#6A6D72",
|
||||
"ComboBoxForegroundColor": "#232629",
|
||||
"ComboBoxBackgroundColor": "#F7F7F7",
|
||||
"LabelboxForegroundColor": "#232629",
|
||||
"MainForegroundColor": "#232629",
|
||||
"MainBackgroundColor": "#F7F7F7",
|
||||
"LabelBackgroundColor": "#F7F7F7",
|
||||
"LinkForegroundColor": "#484848",
|
||||
"LinkHoverForegroundColor": "#232629",
|
||||
"ScrollBarBackgroundColor": "#4A4D52",
|
||||
"ScrollBarHoverColor": "#5A5D62",
|
||||
"ScrollBarDraggingColor": "#6A6D72",
|
||||
|
||||
"MicrowinBusyColor": "#2e77ff",
|
||||
"ProgressBarForegroundColor": "#2e77ff",
|
||||
"ProgressBarBackgroundColor": "Transparent",
|
||||
"ProgressBarTextColor": "#232629",
|
||||
"ButtonInstallBackgroundColor": "#F7F7F7",
|
||||
"ButtonTweaksBackgroundColor": "#F7F7F7",
|
||||
"ButtonConfigBackgroundColor": "#F7F7F7",
|
||||
"ButtonUpdatesBackgroundColor": "#F7F7F7",
|
||||
"ButtonInstallForegroundColor": "#232629",
|
||||
"ButtonTweaksForegroundColor": "#232629",
|
||||
"ButtonConfigForegroundColor": "#232629",
|
||||
"ButtonUpdatesForegroundColor": "#232629",
|
||||
"ButtonBackgroundColor": "#F5F5F5",
|
||||
"ButtonBackgroundPressedColor": "#1A1A1A",
|
||||
"ButtonBackgroundMouseoverColor": "#C2C2C2",
|
||||
"ButtonBackgroundSelectedColor": "#F0F0F0",
|
||||
"ButtonForegroundColor": "#232629",
|
||||
"ToggleButtonOnColor": "#2e77ff",
|
||||
"ToggleButtonOffColor": "#707070",
|
||||
"ToolTipBackgroundColor": "#F7F7F7",
|
||||
"BorderColor": "#232629",
|
||||
"BorderOpacity": "0.2"
|
||||
|
||||
},
|
||||
"Dark": {
|
||||
"AppInstallUnselectedColor": "#232629",
|
||||
"AppInstallHighlightedColor": "#3C3C3C",
|
||||
"AppInstallSelectedColor": "#4C4C4C",
|
||||
"AppInstallOverlayBackgroundColor":"#2E3135",
|
||||
"ComboBoxForegroundColor": "#F7F7F7",
|
||||
"ComboBoxBackgroundColor": "#1E3747",
|
||||
"LabelboxForegroundColor": "#0567ff",
|
||||
"MainForegroundColor": "#F7F7F7",
|
||||
"MainBackgroundColor": "#232629",
|
||||
"LabelBackgroundColor": "#232629",
|
||||
"LinkForegroundColor": "#add8e6",
|
||||
"LinkHoverForegroundColor": "#F7F7F7",
|
||||
"ScrollBarBackgroundColor": "#2E3135",
|
||||
"ScrollBarHoverColor": "#3B4252",
|
||||
"ScrollBarDraggingColor": "#5E81AC",
|
||||
|
||||
"MicrowinBusyColor": "#2e77ff",
|
||||
"ProgressBarForegroundColor": "#222222",
|
||||
"ProgressBarBackgroundColor": "Transparent",
|
||||
"ProgressBarTextColor": "#232629",
|
||||
"ButtonInstallBackgroundColor": "#222222",
|
||||
"ButtonTweaksBackgroundColor": "#333333",
|
||||
"ButtonConfigBackgroundColor": "#444444",
|
||||
"ButtonUpdatesBackgroundColor": "#555555",
|
||||
"ButtonInstallForegroundColor": "#F7F7F7",
|
||||
"ButtonTweaksForegroundColor": "#F7F7F7",
|
||||
"ButtonConfigForegroundColor": "#F7F7F7",
|
||||
"ButtonUpdatesForegroundColor": "#F7F7F7",
|
||||
"ButtonBackgroundColor": "#1E3747",
|
||||
"ButtonBackgroundPressedColor": "#F7F7F7",
|
||||
"ButtonBackgroundMouseoverColor": "#3B4252",
|
||||
"ButtonBackgroundSelectedColor": "#5E81AC",
|
||||
"ButtonForegroundColor": "#F7F7F7",
|
||||
"ToggleButtonOnColor": "#2e77ff",
|
||||
"ToggleButtonOffColor": "#707070",
|
||||
"ToolTipBackgroundColor": "#2F373D",
|
||||
"BorderColor": "#2F373D",
|
||||
"BorderOpacity": "0.2"
|
||||
}
|
||||
}
|
||||
|
1385
config/tweaks.json
1385
config/tweaks.json
File diff suppressed because it is too large
Load Diff
236
edgeremoval.bat
236
edgeremoval.bat
@ -1,236 +0,0 @@
|
||||
@(set "0=%~f0"^)#) & powershell -nop -c iex([io.file]::ReadAllText($env:0)) & exit /b
|
||||
#:: made by AveYo source: https://raw.githubusercontent.com/AveYo/fox/main/Edge_Removal.bat
|
||||
sp 'HKCU:\Volatile Environment' 'Edge_Removal' @'
|
||||
|
||||
$also_remove_webview = 0
|
||||
|
||||
$host.ui.RawUI.WindowTitle = 'Edge Removal - AveYo, 2023.09.09'
|
||||
$remove_win32 = @("Microsoft Edge","Microsoft Edge Update"); $remove_appx = @("MicrosoftEdge"); $skip = @() # @("DevTools")
|
||||
if ($also_remove_webview -eq 1) {$remove_win32 += "Microsoft EdgeWebView"; $remove_appx += "WebExperience","Win32WebViewHost"}
|
||||
|
||||
## 1 bonus! enter into powershell console: firefox / edge / webview to install a browser / reinstall edge or webview after removal
|
||||
function global:firefox { $url = 'https://download.mozilla.org/?product=firefox-stub'
|
||||
$setup = "$((new-object -ComObject Shell.Application).NameSpace('shell:Downloads').Self.Path)\Firefox Installer.exe"
|
||||
write-host $url; Invoke-WebRequest $url -OutFile $setup; start $setup
|
||||
}
|
||||
function global:edge { $url = 'https://go.microsoft.com/fwlink/?linkid=2108834&Channel=Stable&language=en'
|
||||
$setup = "$((new-object -ComObject Shell.Application).NameSpace('shell:Downloads').Self.Path)\MicrosoftEdgeSetup.exe"
|
||||
write-host $url; Invoke-WebRequest $url -OutFile $setup; prepare_edge; start $setup
|
||||
}
|
||||
function global:webview { $url = 'https://go.microsoft.com/fwlink/p/?LinkId=2124703'
|
||||
$setup = "$((new-object -ComObject Shell.Application).NameSpace('shell:Downloads').Self.Path)\MicrosoftEdgeWebview2Setup.exe"
|
||||
write-host $url; Invoke-WebRequest $url -OutFile $setup; prepare_webview; start $setup
|
||||
}
|
||||
## helper for set-itemproperty remove-itemproperty new-item remove-item with auto test-path
|
||||
function global:sp_test_path { if (test-path $args[0]) {Microsoft.PowerShell.Management\Set-ItemProperty @args} else {
|
||||
Microsoft.PowerShell.Management\New-Item $args[0] -force -ea 0 >''; Microsoft.PowerShell.Management\Set-ItemProperty @args} }
|
||||
function global:rp_test_path { if (test-path $args[0]) {Microsoft.PowerShell.Management\Remove-ItemProperty @args} }
|
||||
function global:ni_test_path { if (-not (test-path $args[0])) {Microsoft.PowerShell.Management\New-Item @args} }
|
||||
function global:ri_test_path { if (test-path $args[0]) {Microsoft.PowerShell.Management\Remove-Item @args} }
|
||||
foreach ($f in 'sp','rp','ni','ri') {set-alias -Name $f -Value "${f}_test_path" -Scope Local -Option AllScope -force -ea 0}
|
||||
## helper for edge reinstall - remove bundled OpenWebSearch redirector and edgeupdate policies
|
||||
function global:prepare_edge {
|
||||
foreach ($f in 'ni','ri','sp','rp') {set-alias -Name $f -Value "${f}_test_path" -Scope Local -Option AllScope -force -ea 0}
|
||||
$MS=($env:ProgramFiles,${env:ProgramFiles(x86)})[[Environment]::Is64BitOperatingSystem]+'\Microsoft\Edge\Application\msedge.exe'
|
||||
ri "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\msedge.exe" -recurse -force -ea 0
|
||||
ri "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ie_to_edge_stub.exe" -recurse -force -ea 0
|
||||
ri 'Registry::HKEY_Users\S-1-5-21*\Software\Classes\microsoft-edge' -recurse -force -ea 0
|
||||
ri 'Registry::HKEY_Users\S-1-5-21*\Software\Classes\MSEdgeHTM' -recurse -force -ea 0
|
||||
ni "HKLM:\SOFTWARE\Classes\microsoft-edge\shell\open\command" -force -ea 0 >''
|
||||
sp "HKLM:\SOFTWARE\Classes\microsoft-edge\shell\open\command" '(Default)' "`"$MS`" --single-argument %%1" -force -ea 0
|
||||
ni "HKLM:\SOFTWARE\Classes\MSEdgeHTM\shell\open\command" -force -ea 0 >''
|
||||
sp "HKLM:\SOFTWARE\Classes\MSEdgeHTM\shell\open\command" '(Default)' "`"$MS`" --single-argument %%1" -force -ea 0
|
||||
foreach ($p in 'HKLM:\SOFTWARE\Policies','HKLM:\SOFTWARE','HKLM:\SOFTWARE\WOW6432Node') {
|
||||
rp "$p\Microsoft\EdgeUpdate" 'InstallDefault' -force -ea 0
|
||||
rp "$p\Microsoft\EdgeUpdate" 'Install{56EB18F8-B008-4CBD-B6D2-8C97FE7E9062}' -force -ea 0
|
||||
rp "$p\Microsoft\EdgeUpdate" 'Install{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}' -force -ea 0
|
||||
}
|
||||
$edgeupdate='Microsoft\EdgeUpdate\Clients\{56EB18F8-B008-4CBD-B6D2-8C97FE7E9062}'
|
||||
$webvupdate='Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}'
|
||||
$on_actions='on-os-upgrade','on-logon','on-logon-autolaunch','on-logon-startup-boost'
|
||||
foreach ($p in 'HKLM:\SOFTWARE','HKLM:\SOFTWARE\Wow6432Node') { foreach ($launch in $on_actions) {
|
||||
ri "$p\$edgeupdate\Commands\$launch" -force -ea 0; ri "$p\$webvupdate\Commands\$launch" -force -ea 0
|
||||
}}
|
||||
}
|
||||
## helper for webview reinstall - restore webexperience (widgets) if available
|
||||
function global:prepare_webview {
|
||||
$cfg = @{Register=$true; ForceApplicationShutdown=$true; ForceUpdateFromAnyVersion=$true; DisableDevelopmentMode=$true}
|
||||
dir "$env:ProgramFiles\WindowsApps\MicrosoftWindows.Client.WebExperience*\AppxManifest.xml" -rec -ea 0 | Add-AppxPackage @cfg
|
||||
dir "$env:SystemRoot\SystemApps\Microsoft.Win32WebViewHost*\AppxManifest.xml" -rec -ea 0 | Add-AppxPackage @cfg
|
||||
kill -name explorer -ea 0; if ((get-process -name 'explorer' -ea 0) -eq $null) {start explorer}
|
||||
}
|
||||
|
||||
## 2 enable admin privileges
|
||||
$D1=[uri].module.gettype('System.Diagnostics.Process')."GetM`ethods"(42) |where {$_.Name -eq 'SetPrivilege'} #`:no-ev-warn
|
||||
'SeSecurityPrivilege','SeTakeOwnershipPrivilege','SeBackupPrivilege','SeRestorePrivilege'|foreach {$D1.Invoke($null, @("$_",2))}
|
||||
|
||||
## 3 shut edge & webview clone stuff down and gather install paths
|
||||
$shut = 'explorer','Widgets','widgetservice','msedgewebview2','MicrosoftEdge*','chredge','msedge','edge'
|
||||
$shut+= 'msteams','msfamily','WebViewHost','Clipchamp'
|
||||
cd $env:systemdrive; taskkill /im explorer.exe /f 2>&1 >''; foreach ($p in $shut) {kill -name $p -force -ea 0}
|
||||
prepare_edge
|
||||
## clear win32 uninstall block
|
||||
foreach ($hk in 'HKCU:','HKLM:') { foreach ($wow in '','\Wow6432Node') { foreach ($i in $remove_win32) {
|
||||
rp "$hk\SOFTWARE${wow}\Microsoft\Windows\CurrentVersion\Uninstall\$i" 'NoRemove' -force -ea 0
|
||||
ni "$hk\SOFTWARE${wow}\Microsoft\EdgeUpdateDev" -force >''
|
||||
sp "$hk\SOFTWARE${wow}\Microsoft\EdgeUpdateDev" 'AllowUninstall' 1 -type Dword -force
|
||||
}}}
|
||||
## find all Edge setup.exe and gather BHO paths for OpenWebSearch / MSEdgeRedirect usage
|
||||
$edges = @(); $bho = @(); 'LocalApplicationData','ProgramFilesX86','ProgramFiles' |foreach {
|
||||
$folder = [Environment]::GetFolderPath($_); $bho += dir "$folder\Microsoft\Edge*\ie_to_edge_stub.exe" -rec -ea 0
|
||||
if ($also_remove_webview -eq 1) {$edges += dir "$folder\Microsoft\Edge*\setup.exe" -rec -ea 0 |where {$_ -like '*EdgeWebView*'}}
|
||||
$edges += dir "$folder\Microsoft\Edge*\setup.exe" -rec -ea 0 |where {$_ -notlike '*EdgeWebView*'}
|
||||
}
|
||||
## use dedicated C:\Scripts path to save OpenWebSearch (due to Sigma rules FUD)
|
||||
$DIR = "$env:SystemDrive\Scripts"; mkdir $DIR -ea 0 >''
|
||||
## export OpenWebSearch innovative redirector - used by MSEdgeRedirect as well
|
||||
foreach ($b in $bho) { if (test-path $b) { try {copy $b "$DIR\ie_to_edge_stub.exe" -force -ea 0} catch{} } }
|
||||
|
||||
## 4 remove found *Edge* appx packages with unblock tricks
|
||||
$provisioned = get-appxprovisionedpackage -online; $appxpackage = get-appxpackage -allusers; $eol = @()
|
||||
$store = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Appx\AppxAllUserStore'
|
||||
$users = @('S-1-5-18'); if (test-path $store) {$users += $((dir $store -ea 0 |where {$_ -like '*S-1-5-21*'}).PSChildName)}
|
||||
foreach ($choice in $remove_appx) { if ('' -eq $choice.Trim()) {continue}
|
||||
foreach ($appx in $($provisioned |where {$_.PackageName -like "*$choice*"})) {
|
||||
$next = !1; foreach ($no in $skip) {if ($appx.PackageName -like "*$no*") {$next = !0}} ; if ($next) {continue}
|
||||
$PackageName = $appx.PackageName; $PackageFamilyName = ($appxpackage |where {$_.Name -eq $appx.DisplayName}).PackageFamilyName
|
||||
ni "$store\Deprovisioned\$PackageFamilyName" -force >''; $PackageFamilyName
|
||||
foreach ($sid in $users) {ni "$store\EndOfLife\$sid\$PackageName" -force >''} ; $eol += $PackageName
|
||||
dism /online /set-nonremovableapppolicy /packagefamily:$PackageFamilyName /nonremovable:0 >''
|
||||
remove-appxprovisionedpackage -packagename $PackageName -online -allusers >''
|
||||
}
|
||||
foreach ($appx in $($appxpackage |where {$_.PackageFullName -like "*$choice*"})) {
|
||||
$next = !1; foreach ($no in $skip) {if ($appx.PackageFullName -like "*$no*") {$next = !0}} ; if ($next) {continue}
|
||||
$PackageFullName = $appx.PackageFullName;
|
||||
ni "$store\Deprovisioned\$appx.PackageFamilyName" -force >''; $PackageFullName
|
||||
foreach ($sid in $users) {ni "$store\EndOfLife\$sid\$PackageFullName" -force >''} ; $eol += $PackageFullName
|
||||
dism /online /set-nonremovableapppolicy /packagefamily:$PackageFamilyName /nonremovable:0 >''
|
||||
remove-appxpackage -package $PackageFullName -allusers >''
|
||||
}
|
||||
}
|
||||
|
||||
## 5 run found *Edge* setup.exe with uninstall args and wait in-between
|
||||
foreach ($setup in $edges) { if (test-path $setup) {
|
||||
if ($setup -like '*EdgeWebView*') {$target = "--msedgewebview"} else {$target = "--msedge"}
|
||||
$removal = "--uninstall $target --system-level --verbose-logging --force-uninstall"
|
||||
try {write-host $setup $removal; start -wait $setup -args $removal} catch {}
|
||||
do {sleep 3} while ((get-process -name 'setup','MicrosoftEdge*' -ea 0).Path -like '*\Microsoft\Edge*')
|
||||
}}
|
||||
|
||||
## 6 extra cleanup
|
||||
foreach ($PF in $env:ProgramFiles,${env:ProgramFiles(x86)}) { if (test-path "$PF\Microsoft\EdgeUpdate\MicrosoftEdgeUpdate.exe") {
|
||||
write-host "$PF\Microsoft\EdgeUpdate\MicrosoftEdgeUpdate.exe /uninstall"
|
||||
start -wait "$PF\Microsoft\EdgeUpdate\MicrosoftEdgeUpdate.exe" -args '/uninstall'
|
||||
do {sleep 3} while ((get-process -name 'setup','MicrosoftEdge*' -ea 0).Path -like '*\Microsoft\Edge*')
|
||||
if ($also_remove_webview -eq 1) { foreach ($hk in 'HKCU:','HKLM:') { foreach ($wow in '','\Wow6432Node') {
|
||||
ri "$hk\SOFTWARE${wow}\Microsoft\Windows\CurrentVersion\Uninstall\Microsoft Edge Update" -rec -force -ea 0 }}
|
||||
ri "$PF\Microsoft\EdgeUpdate" -rec -force -ea 0; Unregister-ScheduledTask -TaskName MicrosoftEdgeUpdate* -Confirm:$false -ea 0
|
||||
}
|
||||
}}
|
||||
$appdata = $([Environment]::GetFolderPath('ApplicationData'))
|
||||
ri "$appdata\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Tombstones\Microsoft Edge.lnk" -force
|
||||
ri "$appdata\Microsoft\Internet Explorer\Quick Launch\Microsoft Edge.lnk" -force
|
||||
|
||||
## undo eol unblock trick to prevent latest cumulative update (LCU) failing
|
||||
foreach ($sid in $users) { foreach ($PackageName in $eol) {ri "$store\EndOfLife\$sid\$PackageName" -force >''} }
|
||||
|
||||
## set (almost) useless policies to prevent unsolicited reinstalls
|
||||
foreach ($p in 'HKLM:\SOFTWARE\Policies','HKLM:\SOFTWARE','HKLM:\SOFTWARE\WOW6432Node') {
|
||||
ni "$p\Microsoft\EdgeUpdate" -force >''
|
||||
sp "$p\Microsoft\EdgeUpdate" 'InstallDefault' 0 -type Dword -force
|
||||
sp "$p\Microsoft\EdgeUpdate" 'Install{56EB18F8-B008-4CBD-B6D2-8C97FE7E9062}' 0 -type Dword -force
|
||||
sp "$p\Microsoft\EdgeUpdate" 'Install{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}' 1 -type Dword -force
|
||||
sp "$p\Microsoft\EdgeUpdate" 'DoNotUpdateToEdgeWithChromium' 1 -type Dword -force
|
||||
}
|
||||
$edgeupdate='Microsoft\EdgeUpdate\Clients\{56EB18F8-B008-4CBD-B6D2-8C97FE7E9062}'
|
||||
$webvupdate='Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}'
|
||||
$on_actions='on-os-upgrade','on-logon','on-logon-autolaunch','on-logon-startup-boost'
|
||||
foreach ($p in 'HKLM:\SOFTWARE','HKLM:\SOFTWARE\Wow6432Node') { foreach ($launch in $on_actions) {
|
||||
ni "$p\$edgeupdate\Commands\$launch" -force >''; sp "$p\$edgeupdate\Commands\$launch" 'CommandLine' 'systray.exe' -force
|
||||
ni "$p\$webvupdate\Commands\$launch" -force >''; sp "$p\$webvupdate\Commands\$launch" 'CommandLine' 'systray.exe' -force
|
||||
}}
|
||||
|
||||
## 7 add bundled OpenWebSearch script to redirect microsoft-edge: anti-competitive links to the default browser
|
||||
$MSEP = ($env:ProgramFiles,${env:ProgramFiles(x86)})[[Environment]::Is64BitOperatingSystem] + '\Microsoft\Edge\Application'
|
||||
$IFEO = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options'
|
||||
$MIN = ('--headless','--width 1 --height 1')[([environment]::OSVersion.Version.Build) -gt 25179]
|
||||
$CMD = "$env:systemroot\system32\conhost.exe $MIN" # AveYo: minimize prompt - see Terminal issue #13914
|
||||
ni "HKLM:\SOFTWARE\Classes\microsoft-edge\shell\open\command" -force >''
|
||||
sp "HKLM:\SOFTWARE\Classes\microsoft-edge" '(Default)' 'URL:microsoft-edge' -force
|
||||
sp "HKLM:\SOFTWARE\Classes\microsoft-edge" 'URL Protocol' '' -force
|
||||
sp "HKLM:\SOFTWARE\Classes\microsoft-edge" 'NoOpenWith' '' -force
|
||||
sp "HKLM:\SOFTWARE\Classes\microsoft-edge\shell\open\command" '(Default)' "`"$DIR\ie_to_edge_stub.exe`" %1" -force
|
||||
ni "HKLM:\SOFTWARE\Classes\MSEdgeHTM\shell\open\command" -force >''
|
||||
sp "HKLM:\SOFTWARE\Classes\MSEdgeHTM" 'NoOpenWith' '' -force
|
||||
sp "HKLM:\SOFTWARE\Classes\MSEdgeHTM\shell\open\command" '(Default)' "`"$DIR\ie_to_edge_stub.exe`" %1" -force
|
||||
ni "$IFEO\ie_to_edge_stub.exe\0" -force >''
|
||||
sp "$IFEO\ie_to_edge_stub.exe" 'UseFilter' 1 -type Dword -force
|
||||
sp "$IFEO\ie_to_edge_stub.exe\0" 'FilterFullPath' "$DIR\ie_to_edge_stub.exe" -force
|
||||
sp "$IFEO\ie_to_edge_stub.exe\0" 'Debugger' "$CMD $DIR\OpenWebSearch.cmd" -force
|
||||
ni "$IFEO\msedge.exe\0" -force >''
|
||||
sp "$IFEO\msedge.exe" 'UseFilter' 1 -type Dword -force
|
||||
sp "$IFEO\msedge.exe\0" 'FilterFullPath' "$MSEP\msedge.exe" -force
|
||||
sp "$IFEO\msedge.exe\0" 'Debugger' "$CMD $DIR\OpenWebSearch.cmd" -force
|
||||
|
||||
$OpenWebSearch = @$
|
||||
@title OpenWebSearch Redux & echo off & set ?= open start menu web search, widgets links or help in your chosen browser - by AveYo
|
||||
for /f %%E in ('"prompt $E$S& for %%e in (1) do rem"') do echo;%%E[2t 2>nul & rem AveYo: minimize prompt
|
||||
call :reg_var "HKCU\SOFTWARE\Microsoft\Windows\Shell\Associations\UrlAssociations\https\UserChoice" ProgID ProgID
|
||||
if /i "%ProgID%" equ "MSEdgeHTM" echo;Default browser is set to Edge! Change it or remove OpenWebSearch script. & pause & exit /b
|
||||
call :reg_var "HKCR\%ProgID%\shell\open\command" "" Browser
|
||||
set Choice=& for %%. in (%Browser%) do if not defined Choice set "Choice=%%~."
|
||||
call :reg_var "HKCR\MSEdgeMHT\shell\open\command" "" FallBack
|
||||
set "Edge=" & for %%. in (%FallBack%) do if not defined Edge set "Edge=%%~."
|
||||
set "URI=" & set "URL=" & set "NOOP=" & set "PassTrough=%Edge:msedge=edge%"
|
||||
set "CLI=%CMDCMDLINE:"=``% "
|
||||
if defined CLI set "CLI=%CLI:*ie_to_edge_stub.exe`` =%"
|
||||
if defined CLI set "CLI=%CLI:*ie_to_edge_stub.exe =%"
|
||||
if defined CLI set "CLI=%CLI:*msedge.exe`` =%"
|
||||
if defined CLI set "CLI=%CLI:*msedge.exe =%"
|
||||
set "FIX=%CLI:~-1%"
|
||||
if defined CLI if "%FIX%"==" " set "CLI=%CLI:~0,-1%"
|
||||
if defined CLI set "RED=%CLI:microsoft-edge=%"
|
||||
if defined CLI set "URL=%CLI:http=%"
|
||||
if defined CLI set "ARG=%CLI:``="%"
|
||||
if "%CLI%" equ "%RED%" (set NOOP=1) else if "%CLI%" equ "%URL%" (set NOOP=1)
|
||||
if defined NOOP if exist "%PassTrough%" start "" "%PassTrough%" %ARG%
|
||||
if defined NOOP exit /b
|
||||
set "URL=%CLI:*microsoft-edge=%"
|
||||
set "URL=http%URL:*http=%"
|
||||
set "FIX=%URL:~-2%"
|
||||
if defined URL if "%FIX%"=="``" set "URL=%URL:~0,-2%"
|
||||
call :dec_url
|
||||
start "" "%Choice%" "%URL%"
|
||||
exit
|
||||
|
||||
:reg_var [USAGE] call :reg_var "HKCU\Volatile Environment" value-or-"" variable [extra options]
|
||||
set {var}=& set {reg}=reg query "%~1" /v %2 /z /se "," /f /e& if %2=="" set {reg}=reg query "%~1" /ve /z /se "," /f /e
|
||||
for /f "skip=2 tokens=* delims=" %%V in ('%{reg}% %4 %5 %6 %7 %8 %9 2^>nul') do if not defined {var} set "{var}=%%V"
|
||||
if not defined {var} (set {reg}=& set "%~3="& exit /b) else if %2=="" set "{var}=%{var}:*) =%"& rem AveYo: v3
|
||||
if not defined {var} (set {reg}=& set "%~3="& exit /b) else set {reg}=& set "%~3=%{var}:*) =%"& set {var}=& exit /b
|
||||
|
||||
:dec_url brute url percent decoding by AveYo
|
||||
set ".=%URL:!=}%"&setlocal enabledelayedexpansion& rem brute url percent decoding
|
||||
set ".=!.:%%={!" &set ".=!.:{3A=:!" &set ".=!.:{2F=/!" &set ".=!.:{3F=?!" &set ".=!.:{23=#!" &set ".=!.:{5B=[!" &set ".=!.:{5D=]!"
|
||||
set ".=!.:{40=@!"&set ".=!.:{21=}!" &set ".=!.:{24=$!" &set ".=!.:{26=&!" &set ".=!.:{27='!" &set ".=!.:{28=(!" &set ".=!.:{29=)!"
|
||||
set ".=!.:{2A=*!"&set ".=!.:{2B=+!" &set ".=!.:{2C=,!" &set ".=!.:{3B=;!" &set ".=!.:{3D==!" &set ".=!.:{25=%%!"&set ".=!.:{20= !"
|
||||
set ".=!.:{=%%!" &rem set ",=!.:%%=!" & if "!,!" neq "!.!" endlocal& set "URL=%.:}=!%" & call :dec_url
|
||||
endlocal& set "URL=%.:}=!%" & exit /b
|
||||
rem done
|
||||
|
||||
$@
|
||||
[io.file]::WriteAllText("$DIR\OpenWebSearch.cmd", $OpenWebSearch)
|
||||
|
||||
## 8 done
|
||||
$done = gp 'Registry::HKEY_Users\S-1-5-21*\Volatile*' Edge_Removal -ea 0; if ($done) {rp $done.PSPath Edge_Removal -force -ea 0}
|
||||
if ((get-process -name 'explorer' -ea 0) -eq $null) {start explorer}
|
||||
|
||||
## 9 bonus enter into powershell console: firefox / edge / webview to install a browser / reinstall edge or webview after removal
|
||||
${.} = [char]27; $firefox = "${.}[38;2;255;165;0m firefox"; $edge = "${.}[94m edge${.}[97m"; $webview = "${.}[94mwebview ${.}[97m"
|
||||
write-host "`n${.}[40;32m EDGE REMOVED! ${.}[97m -GET-ANOTHER-BROWSER? ENTER:$firefox ${.}[97m -REINSTALL? ENTER:$edge / $webview"
|
||||
|
||||
## 0 ask to run script as admin
|
||||
'@.replace("$@","'@").replace("@$","@'") -force -ea 0; $code='gp ''Registry::HKEY_Users\S-1-5-21*\Volatile*'' Edge_Removal -ea 0'
|
||||
start powershell -args "-nop -noe -c & {iex(($code)[0].Edge_Removal)}" -verb runas
|
||||
$_Press_Enter
|
||||
#::
|
253
edgeremoval.ps1
253
edgeremoval.ps1
@ -1,253 +0,0 @@
|
||||
# Script Metadata
|
||||
# Created by AveYo, source: https://raw.githubusercontent.com/AveYo/fox/main/Edge_Removal.bat
|
||||
# Powershell Conversion and Refactor done by Chris Titus Tech
|
||||
|
||||
# Initial Configuration
|
||||
$host.ui.RawUI.WindowTitle = 'Edge Removal - Chris Titus Tech 2023.05.10'
|
||||
$remove_win32 = @("Microsoft Edge", "Microsoft Edge Update")
|
||||
$remove_appx = @("MicrosoftEdge")
|
||||
$skip = @() # Optional: @("DevTools")
|
||||
|
||||
$also_remove_webview = 0
|
||||
if ($also_remove_webview -eq 1) {
|
||||
$remove_win32 += "Microsoft EdgeWebView"
|
||||
$remove_appx += "WebExperience", "Win32WebViewHost"
|
||||
}
|
||||
|
||||
# Administrative Privileges Check
|
||||
$privileges = @(
|
||||
'SeSecurityPrivilege',
|
||||
'SeTakeOwnershipPrivilege',
|
||||
'SeBackupPrivilege',
|
||||
'SeRestorePrivilege'
|
||||
)
|
||||
|
||||
foreach ($privilege in $privileges) {
|
||||
[System.Diagnostics.Process]::SetPrivilege($privilege, 2)
|
||||
}
|
||||
|
||||
# Edge Removal Procedures
|
||||
$processesToShutdown = @(
|
||||
'explorer', 'Widgets', 'widgetservice', 'msedgewebview2', 'MicrosoftEdge*', 'chredge',
|
||||
'msedge', 'edge', 'msteams', 'msfamily', 'WebViewHost', 'Clipchamp'
|
||||
)
|
||||
|
||||
Stop-Process -Name "explorer" -Force -ErrorAction SilentlyContinue
|
||||
$processesToShutdown | ForEach-Object {
|
||||
Stop-Process -Name $_ -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
$MS = ($env:ProgramFiles, ${env:ProgramFiles(x86)})[[Environment]::Is64BitOperatingSystem] + '\Microsoft\Edge\Application\msedge.exe'
|
||||
|
||||
Remove-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\msedge.exe" -Recurse -ErrorAction SilentlyContinue
|
||||
Remove-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ie_to_edge_stub.exe" -Recurse -ErrorAction SilentlyContinue
|
||||
Remove-Item -Path 'Registry::HKEY_Users\S-1-5-21*\Software\Classes\microsoft-edge' -Recurse -ErrorAction SilentlyContinue
|
||||
Remove-Item -Path 'Registry::HKEY_Users\S-1-5-21*\Software\Classes\MSEdgeHTM' -Recurse -ErrorAction SilentlyContinue
|
||||
|
||||
New-Item -Path "HKLM:\SOFTWARE\Classes\microsoft-edge\shell\open\command" -Force -ErrorAction SilentlyContinue
|
||||
Set-ItemProperty -Path "HKLM:\SOFTWARE\Classes\microsoft-edge\shell\open\command" -Name '(Default)' -Value "`"$MS`" --single-argument %%1" -Force -ErrorAction SilentlyContinue
|
||||
|
||||
New-Item -Path "HKLM:\SOFTWARE\Classes\MSEdgeHTM\shell\open\command" -Force -ErrorAction SilentlyContinue
|
||||
Set-ItemProperty -Path "HKLM:\SOFTWARE\Classes\MSEdgeHTM\shell\open\command" -Name '(Default)' -Value "`"$MS`" --single-argument %%1" -Force -ErrorAction SilentlyContinue
|
||||
|
||||
$registryPaths = @('HKLM:\SOFTWARE\Policies', 'HKLM:\SOFTWARE', 'HKLM:\SOFTWARE\WOW6432Node')
|
||||
$edgeProperties = @('InstallDefault', 'Install{56EB18F8-B008-4CBD-B6D2-8C97FE7E9062}', 'Install{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}')
|
||||
foreach ($path in $registryPaths) {
|
||||
foreach ($prop in $edgeProperties) {
|
||||
Remove-ItemProperty -Path "$path\Microsoft\EdgeUpdate" -Name $prop -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
$edgeupdate = 'Microsoft\EdgeUpdate\Clients\{56EB18F8-B008-4CBD-B6D2-8C97FE7E9062}'
|
||||
$webvupdate = 'Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}'
|
||||
$on_actions = @('on-os-upgrade', 'on-logon', 'on-logon-autolaunch', 'on-logon-startup-boost')
|
||||
$registryBases = @('HKLM:\SOFTWARE', 'HKLM:\SOFTWARE\Wow6432Node')
|
||||
foreach ($base in $registryBases) {
|
||||
foreach ($launch in $on_actions) {
|
||||
Remove-Item -Path "$base\$edgeupdate\Commands\$launch" -Force -ErrorAction SilentlyContinue
|
||||
Remove-Item -Path "$base\$webvupdate\Commands\$launch" -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
$registryPaths = @('HKCU:', 'HKLM:')
|
||||
$nodes = @('', '\Wow6432Node')
|
||||
foreach ($regPath in $registryPaths) {
|
||||
foreach ($node in $nodes) {
|
||||
foreach ($i in $remove_win32) {
|
||||
Remove-ItemProperty -Path "$regPath\SOFTWARE${node}\Microsoft\Windows\CurrentVersion\Uninstall\$i" -Name 'NoRemove' -Force -ErrorAction SilentlyContinue
|
||||
New-Item -Path "$regPath\SOFTWARE${node}\Microsoft\EdgeUpdateDev" -Force | Out-Null
|
||||
Set-ItemProperty -Path "$regPath\SOFTWARE${node}\Microsoft\EdgeUpdateDev" -Name 'AllowUninstall' -Value 1 -Type Dword -Force
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$foldersToSearch = @('LocalApplicationData', 'ProgramFilesX86', 'ProgramFiles') | ForEach-Object {
|
||||
[Environment]::GetFolderPath($_)
|
||||
}
|
||||
|
||||
$edges = @()
|
||||
$bhoFiles = @()
|
||||
|
||||
foreach ($folder in $foldersToSearch) {
|
||||
$bhoFiles += Get-ChildItem -Path "$folder\Microsoft\Edge*\ie_to_edge_stub.exe" -Recurse -ErrorAction SilentlyContinue
|
||||
|
||||
$edges += Get-ChildItem -Path "$folder\Microsoft\Edge*\setup.exe" -Recurse -ErrorAction SilentlyContinue |
|
||||
Where-Object { $_.FullName -notlike '*EdgeWebView*' }
|
||||
}
|
||||
|
||||
$destinationDir = "$env:SystemDrive\Scripts"
|
||||
New-Item -Path $destinationDir -ItemType Directory -ErrorAction SilentlyContinue | Out-Null
|
||||
|
||||
foreach ($bhoFile in $bhoFiles) {
|
||||
if (Test-Path $bhoFile) {
|
||||
try {
|
||||
Copy-Item -Path $bhoFile -Destination "$destinationDir\ie_to_edge_stub.exe" -Force
|
||||
} catch { }
|
||||
}
|
||||
}
|
||||
|
||||
## Work on Appx Removals
|
||||
$provisioned = Get-AppxProvisionedPackage -Online
|
||||
$appxpackage = Get-AppxPackage -AllUsers
|
||||
$eol = @()
|
||||
|
||||
$store = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Store'
|
||||
$storeP = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Store\InstalledApplications'
|
||||
foreach ($app in $appxpackage) {
|
||||
$name = $app.Name
|
||||
if ($app.Name -eq "Microsoft.Edge") {
|
||||
$eol += $name
|
||||
} elseif ($app.Name -eq "Microsoft.EdgeBeta" -or $app.Name -eq "Microsoft.EdgeDev" -or $app.Name -eq "Microsoft.EdgeCanary" -or $app.Name -eq "Microsoft.MicrosoftEdge") {
|
||||
$eol += $name
|
||||
}
|
||||
}
|
||||
|
||||
$eolApps = $provisioned | Where-Object { $eol -contains $_.DisplayName }
|
||||
|
||||
foreach ($edge in $eolApps) {
|
||||
$edgeName = $edge.DisplayName
|
||||
if (-not ($skip -contains $edgeName)) {
|
||||
try {
|
||||
Remove-AppxProvisionedPackage -Online -PackageName $edgeName -ErrorAction SilentlyContinue
|
||||
} catch { }
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($edge in $appxpackage) {
|
||||
$edgeName = $edge.Name
|
||||
if ($eol -contains $edgeName) {
|
||||
if (-not ($skip -contains $edgeName)) {
|
||||
try {
|
||||
Remove-AppxPackage -Package $edgeName -AllUsers -ErrorAction SilentlyContinue
|
||||
} catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
## Redirect shortcuts
|
||||
$shortcut_path = "$env:Public\Desktop"
|
||||
$shortcut_file = 'Microsoft Edge.lnk'
|
||||
$full_path = Join-Path -Path $shortcut_path -ChildPath $shortcut_file
|
||||
|
||||
if (Test-Path $full_path) {
|
||||
Remove-Item -Path $full_path -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
$shortcut_path = "$env:ProgramData\Microsoft\Windows\Start Menu\Programs"
|
||||
$shortcut_file = 'Microsoft Edge.lnk'
|
||||
$full_path = Join-Path -Path $shortcut_path -ChildPath $shortcut_file
|
||||
|
||||
if (Test-Path $full_path) {
|
||||
Remove-Item -Path $full_path -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
$edgePolicy = 'HKLM:\SOFTWARE\Policies\Microsoft\Edge'
|
||||
if (-not (Test-Path $edgePolicy)) {
|
||||
New-Item -Path $edgePolicy -Force | Out-Null
|
||||
}
|
||||
|
||||
$edgePrefs = @{
|
||||
'Dword' = @{
|
||||
'BrowserReplacementEnabled' = 1
|
||||
'HideFirstRunExperience' = 1
|
||||
'HideImportEdgeFavoritesPrompt' = 1
|
||||
'HideSyncSetupExperience' = 1
|
||||
'FavoritesBarVisibility' = 1
|
||||
}
|
||||
'String' = @{
|
||||
'AutoplayAllowed' = 'AllowOnce'
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($entryType in $edgePrefs.Keys) {
|
||||
foreach ($prefName in $edgePrefs[$entryType].Keys) {
|
||||
Set-ItemProperty -Path $edgePolicy -Name $prefName -Value $edgePrefs[$entryType][$prefName] -Type $entryType -Force
|
||||
}
|
||||
}
|
||||
|
||||
# Output Results
|
||||
Write-Host "Edge Removal Complete" -ForegroundColor Green
|
||||
|
||||
# Define constants and initial configuration
|
||||
$ScriptVersion = "2023.05.10"
|
||||
$EdgeProcessesToShutdown = @('explorer', 'Widgets', 'widgetservice', 'msedgewebview2', 'MicrosoftEdge*', 'chredge', 'msedge', 'edge', 'msteams', 'msfamily', 'WebViewHost', 'Clipchamp')
|
||||
$EdgeRemovalOptions = @{
|
||||
RemoveWin32 = @("Microsoft Edge", "Microsoft Edge Update")
|
||||
RemoveAppx = @("MicrosoftEdge")
|
||||
Skip = @() # Optional: @("DevTools")
|
||||
AlsoRemoveWebView = $false
|
||||
}
|
||||
|
||||
# Define main function to remove Microsoft Edge components
|
||||
function Remove-MicrosoftEdge {
|
||||
[CmdletBinding()]
|
||||
param()
|
||||
|
||||
# Function to shutdown processes related to Microsoft Edge
|
||||
function Stop-EdgeProcesses {
|
||||
$EdgeProcessesToShutdown | ForEach-Object {
|
||||
Stop-Process -Name $_ -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
# Function to remove registry entries related to Microsoft Edge
|
||||
function Remove-EdgeRegistryEntries {
|
||||
# Clean up certain registry entries
|
||||
Remove-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\msedge.exe" -Recurse -ErrorAction SilentlyContinue
|
||||
Remove-Item -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\ie_to_edge_stub.exe" -Recurse -ErrorAction SilentlyContinue
|
||||
Remove-Item -Path 'Registry::HKEY_Users\S-1-5-21*\Software\Classes\microsoft-edge' -Recurse -ErrorAction SilentlyContinue
|
||||
Remove-Item -Path 'Registry::HKEY_Users\S-1-5-21*\Software\Classes\MSEdgeHTM' -Recurse -ErrorAction SilentlyContinue
|
||||
|
||||
# Create new registry entries
|
||||
$EdgeExecutablePath = ($env:ProgramFiles, ${env:ProgramFiles(x86)})[[Environment]::Is64BitOperatingSystem] + '\Microsoft\Edge\Application\msedge.exe'
|
||||
New-Item -Path "HKLM:\SOFTWARE\Classes\microsoft-edge\shell\open\command" -Force -ErrorAction SilentlyContinue
|
||||
Set-ItemProperty -Path "HKLM:\SOFTWARE\Classes\microsoft-edge\shell\open\command" -Name '(Default)' -Value "`"$EdgeExecutablePath`" --single-argument %%1" -Force -ErrorAction SilentlyContinue
|
||||
|
||||
New-Item -Path "HKLM:\SOFTWARE\Classes\MSEdgeHTM\shell\open\command" -Force -ErrorAction SilentlyContinue
|
||||
Set-ItemProperty -Path "HKLM:\SOFTWARE\Classes\MSEdgeHTM\shell\open\command" -Name '(Default)' -Value "`"$EdgeExecutablePath`" --single-argument %%1" -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
# Function to remove Microsoft Edge AppX packages
|
||||
function Remove-EdgeAppxPackages {
|
||||
$EdgeRemovalOptions.RemoveAppx | ForEach-Object {
|
||||
# Remove provisioned packages
|
||||
Get-AppxProvisionedPackage -Online | Where-Object { $_.PackageName -like "*$_*" -and $EdgeRemovalOptions.Skip -notcontains $_.PackageName } | Remove-AppxProvisionedPackage -Online -AllUsers -ErrorAction SilentlyContinue
|
||||
|
||||
# Remove installed packages
|
||||
Get-AppxPackage -AllUsers | Where-Object { $_.PackageFullName -like "*$_*" -and $EdgeRemovalOptions.Skip -notcontains $_.PackageFullName } | Remove-AppxPackage -AllUsers -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
# Function to remove Microsoft Edge processes, registry entries, and AppX packages
|
||||
try {
|
||||
Stop-EdgeProcesses
|
||||
Remove-EdgeRegistryEntries
|
||||
Remove-EdgeAppxPackages
|
||||
Write-Output "Microsoft Edge components have been successfully removed."
|
||||
} catch {
|
||||
Write-Error "Failed to remove Microsoft Edge components: $_"
|
||||
}
|
||||
}
|
||||
|
||||
# Execute the main function
|
||||
Remove-MicrosoftEdge
|
497
functions/microwin/Invoke-Microwin.ps1
Normal file
497
functions/microwin/Invoke-Microwin.ps1
Normal file
@ -0,0 +1,497 @@
|
||||
function Invoke-Microwin {
|
||||
<#
|
||||
.DESCRIPTION
|
||||
Invoke MicroWin routines...
|
||||
#>
|
||||
|
||||
|
||||
if($sync.ProcessRunning) {
|
||||
$msg = "GetIso process is currently running."
|
||||
[System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
|
||||
return
|
||||
}
|
||||
|
||||
# Define the constants for Windows API
|
||||
Add-Type @"
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
public class PowerManagement {
|
||||
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
|
||||
public static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);
|
||||
|
||||
[FlagsAttribute]
|
||||
public enum EXECUTION_STATE : uint {
|
||||
ES_SYSTEM_REQUIRED = 0x00000001,
|
||||
ES_DISPLAY_REQUIRED = 0x00000002,
|
||||
ES_CONTINUOUS = 0x80000000,
|
||||
}
|
||||
}
|
||||
"@
|
||||
|
||||
# Prevent the machine from sleeping
|
||||
[PowerManagement]::SetThreadExecutionState([PowerManagement]::EXECUTION_STATE::ES_CONTINUOUS -bor [PowerManagement]::EXECUTION_STATE::ES_SYSTEM_REQUIRED -bor [PowerManagement]::EXECUTION_STATE::ES_DISPLAY_REQUIRED)
|
||||
|
||||
# Ask the user where to save the file
|
||||
$SaveDialog = New-Object System.Windows.Forms.SaveFileDialog
|
||||
$SaveDialog.InitialDirectory = [Environment]::GetFolderPath('Desktop')
|
||||
$SaveDialog.Filter = "ISO images (*.iso)|*.iso"
|
||||
$SaveDialog.ShowDialog() | Out-Null
|
||||
|
||||
if ($SaveDialog.FileName -eq "") {
|
||||
$msg = "No file name for the target image was specified"
|
||||
Write-Host $msg
|
||||
Invoke-MicrowinBusyInfo -action "warning" -message $msg
|
||||
Set-WinUtilTaskbaritem -state "Error" -value 1 -overlay "warning"
|
||||
return
|
||||
}
|
||||
|
||||
Set-WinUtilTaskbaritem -state "Indeterminate" -overlay "logo"
|
||||
Invoke-MicrowinBusyInfo -action "wip" -message "Busy..." -interactive $false
|
||||
|
||||
Write-Host "Target ISO location: $($SaveDialog.FileName)"
|
||||
|
||||
$index = $sync.MicrowinWindowsFlavors.SelectedValue.Split(":")[0].Trim()
|
||||
Write-Host "Index chosen: '$index' from $($sync.MicrowinWindowsFlavors.SelectedValue)"
|
||||
|
||||
$copyToUSB = $sync.WPFMicrowinCopyToUsb.IsChecked
|
||||
$injectDrivers = $sync.MicrowinInjectDrivers.IsChecked
|
||||
$importDrivers = $sync.MicrowinImportDrivers.IsChecked
|
||||
|
||||
$importVirtIO = $sync.MicrowinCopyVirtIO.IsChecked
|
||||
|
||||
$mountDir = $sync.MicrowinMountDir.Text
|
||||
$scratchDir = $sync.MicrowinScratchDir.Text
|
||||
|
||||
# Detect if the Windows image is an ESD file and convert it to WIM
|
||||
if (-not (Test-Path -Path "$mountDir\sources\install.wim" -PathType Leaf) -and (Test-Path -Path "$mountDir\sources\install.esd" -PathType Leaf)) {
|
||||
Write-Host "Exporting Windows image to a WIM file, keeping the index we want to work on. This can take several minutes, depending on the performance of your computer..."
|
||||
Export-WindowsImage -SourceImagePath $mountDir\sources\install.esd -SourceIndex $index -DestinationImagePath $mountDir\sources\install.wim -CompressionType "Max"
|
||||
if ($?) {
|
||||
Remove-Item -Path "$mountDir\sources\install.esd" -Force
|
||||
# Since we've already exported the image index we wanted, switch to the first one
|
||||
$index = 1
|
||||
} else {
|
||||
$msg = "The export process has failed and MicroWin processing cannot continue"
|
||||
Write-Host $msg
|
||||
Set-WinUtilTaskbaritem -state "Error" -value 1 -overlay "warning"
|
||||
Invoke-MicrowinBusyInfo -action "warning" -message $msg
|
||||
[System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Error)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
$imgVersion = (Get-WindowsImage -ImagePath $mountDir\sources\install.wim -Index $index).Version
|
||||
Write-Host "The Windows Image Build Version is: $imgVersion"
|
||||
|
||||
# Detect image version to avoid performing MicroWin processing on Windows 8 and earlier
|
||||
if ((Microwin-TestCompatibleImage $imgVersion $([System.Version]::new(10,0,10240,0))) -eq $false) {
|
||||
$msg = "This image is not compatible with MicroWin processing. Make sure it isn't a Windows 8 or earlier image."
|
||||
$dlg_msg = $msg + "`n`nIf you want more information, the version of the image selected is $($imgVersion)`n`nIf an image has been incorrectly marked as incompatible, report an issue to the developers."
|
||||
Write-Host $msg
|
||||
[System.Windows.MessageBox]::Show($dlg_msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Exclamation)
|
||||
Set-WinUtilTaskbaritem -state "Error" -value 1 -overlay "warning"
|
||||
Invoke-MicrowinBusyInfo -action "warning" -message $msg
|
||||
return
|
||||
}
|
||||
|
||||
# Detect whether the image to process contains Windows 10 and show warning
|
||||
if ((Microwin-TestCompatibleImage $imgVersion $([System.Version]::new(10,0,21996,1))) -eq $false) {
|
||||
$msg = "Windows 10 has been detected in the image you want to process. While you can continue, Windows 10 is not a recommended target for MicroWin, and you may not get the full experience."
|
||||
$dlg_msg = $msg
|
||||
Write-Host $msg
|
||||
[System.Windows.MessageBox]::Show($dlg_msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Exclamation)
|
||||
}
|
||||
|
||||
$mountDirExists = Test-Path $mountDir
|
||||
$scratchDirExists = Test-Path $scratchDir
|
||||
if (-not $mountDirExists -or -not $scratchDirExists) {
|
||||
$msg = "Required directories '$mountDirExists' '$scratchDirExists' and do not exist."
|
||||
Write-Error $msg
|
||||
Set-WinUtilTaskbaritem -state "Error" -value 1 -overlay "warning"
|
||||
Invoke-MicrowinBusyInfo -action "warning" -message $msg
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Write-Host "Mounting Windows image. This may take a while."
|
||||
Mount-WindowsImage -ImagePath "$mountDir\sources\install.wim" -Index $index -Path "$scratchDir"
|
||||
if ($?) {
|
||||
Write-Host "The Windows image has been mounted successfully. Continuing processing..."
|
||||
} else {
|
||||
$msg = "Could not mount image. Exiting..."
|
||||
Write-Host $msg
|
||||
Set-WinUtilTaskbaritem -state "Error" -value 1 -overlay "warning"
|
||||
Invoke-MicrowinBusyInfo -action "warning" -message $msg
|
||||
return
|
||||
}
|
||||
|
||||
if ($importDrivers) {
|
||||
Write-Host "Exporting drivers from active installation..."
|
||||
if (Test-Path "$env:TEMP\DRV_EXPORT") {
|
||||
Remove-Item "$env:TEMP\DRV_EXPORT" -Recurse -Force
|
||||
}
|
||||
if (($injectDrivers -and (Test-Path "$($sync.MicrowinDriverLocation.Text)"))) {
|
||||
Write-Host "Using specified driver source..."
|
||||
dism /english /online /export-driver /destination="$($sync.MicrowinDriverLocation.Text)" | Out-Host
|
||||
if ($?) {
|
||||
# Don't add exported drivers yet, that is run later
|
||||
Write-Host "Drivers have been exported successfully."
|
||||
} else {
|
||||
Write-Host "Failed to export drivers."
|
||||
}
|
||||
} else {
|
||||
New-Item -Path "$env:TEMP\DRV_EXPORT" -ItemType Directory -Force
|
||||
dism /english /online /export-driver /destination="$env:TEMP\DRV_EXPORT" | Out-Host
|
||||
if ($?) {
|
||||
Write-Host "Adding exported drivers..."
|
||||
dism /english /image="$scratchDir" /add-driver /driver="$env:TEMP\DRV_EXPORT" /recurse | Out-Host
|
||||
} else {
|
||||
Write-Host "Failed to export drivers. Continuing without importing them..."
|
||||
}
|
||||
if (Test-Path "$env:TEMP\DRV_EXPORT") {
|
||||
Remove-Item "$env:TEMP\DRV_EXPORT" -Recurse -Force
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($injectDrivers) {
|
||||
$driverPath = $sync.MicrowinDriverLocation.Text
|
||||
if (Test-Path $driverPath) {
|
||||
Write-Host "Adding Windows Drivers image($scratchDir) drivers($driverPath) "
|
||||
dism /English /image:$scratchDir /add-driver /driver:$driverPath /recurse | Out-Host
|
||||
} else {
|
||||
Write-Host "Path to drivers is invalid continuing without driver injection"
|
||||
}
|
||||
}
|
||||
|
||||
if ($importVirtIO) {
|
||||
Write-Host "Copying VirtIO drivers..."
|
||||
Microwin-CopyVirtIO
|
||||
}
|
||||
|
||||
Write-Host "Remove Features from the image"
|
||||
Microwin-RemoveFeatures -UseCmdlets $true
|
||||
Write-Host "Removing features complete!"
|
||||
Write-Host "Removing OS packages"
|
||||
Microwin-RemovePackages -UseCmdlets $true
|
||||
Write-Host "Removing Appx Bloat"
|
||||
Microwin-RemoveProvisionedPackages -UseCmdlets $true
|
||||
|
||||
# Detect Windows 11 24H2 and add dependency to FileExp to prevent Explorer look from going back - thanks @WitherOrNot and @thecatontheceiling
|
||||
if ((Microwin-TestCompatibleImage $imgVersion $([System.Version]::new(10,0,26100,1))) -eq $true) {
|
||||
try {
|
||||
if (Test-Path "$scratchDir\Windows\SystemApps\MicrosoftWindows.Client.FileExp_cw5n1h2txyewy\appxmanifest.xml" -PathType Leaf) {
|
||||
# Found the culprit. Do the following:
|
||||
# 1. Take ownership of the file, from TrustedInstaller to Administrators
|
||||
takeown /F "$scratchDir\Windows\SystemApps\MicrosoftWindows.Client.FileExp_cw5n1h2txyewy\appxmanifest.xml" /A
|
||||
# 2. Set ACLs so that we can write to it
|
||||
icacls "$scratchDir\Windows\SystemApps\MicrosoftWindows.Client.FileExp_cw5n1h2txyewy\appxmanifest.xml" /grant "$(Microwin-GetLocalizedUsers -admins $true):(M)" | Out-Host
|
||||
# 3. Open the file and do the modification
|
||||
$appxManifest = Get-Content -Path "$scratchDir\Windows\SystemApps\MicrosoftWindows.Client.FileExp_cw5n1h2txyewy\appxmanifest.xml"
|
||||
$originalLine = $appxManifest[13]
|
||||
$dependency = "`n <PackageDependency Name=`"Microsoft.WindowsAppRuntime.CBS`" MinVersion=`"1.0.0.0`" Publisher=`"CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US`" />"
|
||||
$appxManifest[13] = "$originalLine$dependency"
|
||||
Set-Content -Path "$scratchDir\Windows\SystemApps\MicrosoftWindows.Client.FileExp_cw5n1h2txyewy\appxmanifest.xml" -Value $appxManifest -Force -Encoding utf8
|
||||
}
|
||||
}
|
||||
catch {
|
||||
# Fall back to what we used to do: delayed disablement
|
||||
Enable-WindowsOptionalFeature -Path "$scratchDir" -FeatureName "Recall"
|
||||
}
|
||||
}
|
||||
|
||||
Microwin-RemoveFileOrDirectory -pathToDelete "$($scratchDir)\Windows\System32\LogFiles\WMI\RtBackup" -Directory
|
||||
Microwin-RemoveFileOrDirectory -pathToDelete "$($scratchDir)\Windows\DiagTrack" -Directory
|
||||
Microwin-RemoveFileOrDirectory -pathToDelete "$($scratchDir)\Windows\InboxApps" -Directory
|
||||
Microwin-RemoveFileOrDirectory -pathToDelete "$($scratchDir)\Windows\System32\LocationNotificationWindows.exe"
|
||||
Microwin-RemoveFileOrDirectory -pathToDelete "$($scratchDir)\Program Files (x86)\Windows Media Player" -Directory
|
||||
Microwin-RemoveFileOrDirectory -pathToDelete "$($scratchDir)\Program Files\Windows Media Player" -Directory
|
||||
Microwin-RemoveFileOrDirectory -pathToDelete "$($scratchDir)\Program Files (x86)\Windows Mail" -Directory
|
||||
Microwin-RemoveFileOrDirectory -pathToDelete "$($scratchDir)\Program Files\Windows Mail" -Directory
|
||||
Microwin-RemoveFileOrDirectory -pathToDelete "$($scratchDir)\Program Files (x86)\Internet Explorer" -Directory
|
||||
Microwin-RemoveFileOrDirectory -pathToDelete "$($scratchDir)\Program Files\Internet Explorer" -Directory
|
||||
Microwin-RemoveFileOrDirectory -pathToDelete "$($scratchDir)\Windows\GameBarPresenceWriter"
|
||||
Microwin-RemoveFileOrDirectory -pathToDelete "$($scratchDir)\Windows\System32\OneDriveSetup.exe"
|
||||
Microwin-RemoveFileOrDirectory -pathToDelete "$($scratchDir)\Windows\System32\OneDrive.ico"
|
||||
Microwin-RemoveFileOrDirectory -pathToDelete "$($scratchDir)\Windows\SystemApps" -mask "*narratorquickstart*" -Directory
|
||||
Microwin-RemoveFileOrDirectory -pathToDelete "$($scratchDir)\Windows\SystemApps" -mask "*ParentalControls*" -Directory
|
||||
Write-Host "Removal complete!"
|
||||
|
||||
Write-Host "Create unattend.xml"
|
||||
|
||||
if ($sync.MicrowinUserName.Text -eq "")
|
||||
{
|
||||
Microwin-NewUnattend -userName "User"
|
||||
}
|
||||
else
|
||||
{
|
||||
if ($sync.MicrowinUserPassword.Password -eq "")
|
||||
{
|
||||
Microwin-NewUnattend -userName "$($sync.MicrowinUserName.Text)"
|
||||
}
|
||||
else
|
||||
{
|
||||
Microwin-NewUnattend -userName "$($sync.MicrowinUserName.Text)" -userPassword "$($sync.MicrowinUserPassword.Password)"
|
||||
}
|
||||
}
|
||||
Write-Host "Done Create unattend.xml"
|
||||
Write-Host "Copy unattend.xml file into the ISO"
|
||||
New-Item -ItemType Directory -Force -Path "$($scratchDir)\Windows\Panther"
|
||||
Copy-Item "$env:temp\unattend.xml" "$($scratchDir)\Windows\Panther\unattend.xml" -force
|
||||
New-Item -ItemType Directory -Force -Path "$($scratchDir)\Windows\System32\Sysprep"
|
||||
Copy-Item "$env:temp\unattend.xml" "$($scratchDir)\Windows\System32\Sysprep\unattend.xml" -force
|
||||
Copy-Item "$env:temp\unattend.xml" "$($scratchDir)\unattend.xml" -force
|
||||
Write-Host "Done Copy unattend.xml"
|
||||
|
||||
Write-Host "Create FirstRun"
|
||||
Microwin-NewFirstRun
|
||||
Write-Host "Done create FirstRun"
|
||||
Write-Host "Copy FirstRun.ps1 into the ISO"
|
||||
Copy-Item "$env:temp\FirstStartup.ps1" "$($scratchDir)\Windows\FirstStartup.ps1" -force
|
||||
Write-Host "Done copy FirstRun.ps1"
|
||||
|
||||
Write-Host "Copy link to winutil.ps1 into the ISO"
|
||||
$desktopDir = "$($scratchDir)\Windows\Users\Default\Desktop"
|
||||
New-Item -ItemType Directory -Force -Path "$desktopDir"
|
||||
dism /English /image:$($scratchDir) /set-profilepath:"$($scratchDir)\Windows\Users\Default"
|
||||
|
||||
Write-Host "Copy checkinstall.cmd into the ISO"
|
||||
Microwin-NewCheckInstall
|
||||
Copy-Item "$env:temp\checkinstall.cmd" "$($scratchDir)\Windows\checkinstall.cmd" -force
|
||||
Write-Host "Done copy checkinstall.cmd"
|
||||
|
||||
Write-Host "Creating a directory that allows to bypass Wifi setup"
|
||||
New-Item -ItemType Directory -Force -Path "$($scratchDir)\Windows\System32\OOBE\BYPASSNRO"
|
||||
|
||||
Write-Host "Loading registry"
|
||||
reg load HKLM\zCOMPONENTS "$($scratchDir)\Windows\System32\config\COMPONENTS"
|
||||
reg load HKLM\zDEFAULT "$($scratchDir)\Windows\System32\config\default"
|
||||
reg load HKLM\zNTUSER "$($scratchDir)\Users\Default\ntuser.dat"
|
||||
reg load HKLM\zSOFTWARE "$($scratchDir)\Windows\System32\config\SOFTWARE"
|
||||
reg load HKLM\zSYSTEM "$($scratchDir)\Windows\System32\config\SYSTEM"
|
||||
|
||||
Write-Host "Disabling Teams"
|
||||
reg add "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Communications" /v "ConfigureChatAutoInstall" /t REG_DWORD /d 0 /f >$null 2>&1
|
||||
reg add "HKLM\zSOFTWARE\Policies\Microsoft\Windows\Windows Chat" /v ChatIcon /t REG_DWORD /d 2 /f >$null 2>&1
|
||||
reg add "HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "TaskbarMn" /t REG_DWORD /d 0 /f >$null 2>&1
|
||||
reg query "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Communications" /v "ConfigureChatAutoInstall" >$null 2>&1
|
||||
# Write-Host Error code $LASTEXITCODE
|
||||
Write-Host "Done disabling Teams"
|
||||
|
||||
Write-Host "Fix Windows Volume Mixer Issue"
|
||||
reg add "HKLM\zNTUSER\Software\Microsoft\Internet Explorer\LowRegistry\Audio\PolicyConfig\PropertyStore" /f
|
||||
|
||||
Write-Host "Bypassing system requirements (system image)"
|
||||
reg add "HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache" /v "SV1" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache" /v "SV2" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache" /v "SV1" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache" /v "SV2" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassCPUCheck" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassRAMCheck" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassSecureBootCheck" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassStorageCheck" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassTPMCheck" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\zSYSTEM\Setup\MoSetup" /v "AllowUpgradesWithUnsupportedTPMOrCPU" /t REG_DWORD /d 1 /f
|
||||
|
||||
# Prevent Windows Update Installing so called Expedited Apps - 24H2 and newer
|
||||
if ((Microwin-TestCompatibleImage $imgVersion $([System.Version]::new(10,0,26100,1))) -eq $true) {
|
||||
@(
|
||||
'EdgeUpdate',
|
||||
'DevHomeUpdate',
|
||||
'OutlookUpdate',
|
||||
'CrossDeviceUpdate'
|
||||
) | ForEach-Object {
|
||||
Write-Host "Removing Windows Expedited App: $_"
|
||||
|
||||
# Copied here After Installation (Online)
|
||||
# reg delete "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler\$_" /f | Out-Null
|
||||
|
||||
# When in Offline Image
|
||||
reg delete "HKLM\zSOFTWARE\Microsoft\WindowsUpdate\Orchestrator\UScheduler_Oobe\$_" /f | Out-Null
|
||||
}
|
||||
}
|
||||
|
||||
reg add "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Search" /v "SearchboxTaskbarMode" /t REG_DWORD /d 0 /f
|
||||
Write-Host "Setting all services to start manually"
|
||||
reg add "HKLM\zSOFTWARE\CurrentControlSet\Services" /v Start /t REG_DWORD /d 3 /f
|
||||
# Write-Host $LASTEXITCODE
|
||||
|
||||
Write-Host "Enabling Local Accounts on OOBE"
|
||||
reg add "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\OOBE" /v "BypassNRO" /t REG_DWORD /d "1" /f
|
||||
|
||||
Write-Host "Disabling Sponsored Apps"
|
||||
reg add "HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "OemPreInstalledAppsEnabled" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "PreInstalledAppsEnabled" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SilentInstalledAppsEnabled" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\zSOFTWARE\Policies\Microsoft\Windows\CloudContent" /v "DisableWindowsConsumerFeatures" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\zSOFTWARE\Microsoft\PolicyManager\current\device\Start" /v "ConfigureStartPins" /t REG_SZ /d '{\"pinnedList\": [{}]}' /f
|
||||
Write-Host "Done removing Sponsored Apps"
|
||||
|
||||
Write-Host "Disabling Reserved Storage"
|
||||
reg add "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\ReserveManager" /v "ShippedWithReserves" /t REG_DWORD /d 0 /f
|
||||
|
||||
Write-Host "Changing theme to dark. This only works on Activated Windows"
|
||||
reg add "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize" /v "AppsUseLightTheme" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize" /v "SystemUsesLightTheme" /t REG_DWORD /d 0 /f
|
||||
|
||||
if ((Microwin-TestCompatibleImage $imgVersion $([System.Version]::new(10,0,21996,1))) -eq $false) {
|
||||
# We're dealing with Windows 10. Configure sane desktop settings. NOTE: even though stuff to disable News and Interests is there,
|
||||
# it doesn't seem to work, and I don't want to waste more time dealing with an operating system that will lose support in a year (2025)
|
||||
|
||||
# I invite anyone to work on improving stuff for News and Interests, but that won't be me!
|
||||
|
||||
Write-Host "Disabling Search Highlights..."
|
||||
reg add "HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\Feeds\DSB" /v "ShowDynamicContent" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\SearchSettings" /v "IsDynamicSearchBoxEnabled" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\zSOFTWARE\Policies\Microsoft\Dsh" /v "AllowNewsAndInterests" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\zNTUSER\SOFTWARE\Microsoft\Windows\CurrentVersion\Search" /v "TraySearchBoxVisible" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\zSOFTWARE\Policies\Microsoft\Windows\Windows Feeds" /v "EnableFeeds" /t REG_DWORD /d 0 /f
|
||||
}
|
||||
|
||||
} catch {
|
||||
Write-Error "An unexpected error occurred: $_"
|
||||
} finally {
|
||||
Write-Host "Unmounting Registry..."
|
||||
reg unload HKLM\zCOMPONENTS
|
||||
reg unload HKLM\zDEFAULT
|
||||
reg unload HKLM\zNTUSER
|
||||
reg unload HKLM\zSOFTWARE
|
||||
reg unload HKLM\zSYSTEM
|
||||
|
||||
Write-Host "Cleaning up image..."
|
||||
dism /English /image:$scratchDir /Cleanup-Image /StartComponentCleanup /ResetBase
|
||||
Write-Host "Cleanup complete."
|
||||
|
||||
Write-Host "Unmounting image..."
|
||||
Dismount-WindowsImage -Path "$scratchDir" -Save
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
Write-Host "Exporting image into $mountDir\sources\install2.wim"
|
||||
Export-WindowsImage -SourceImagePath "$mountDir\sources\install.wim" -SourceIndex $index -DestinationImagePath "$mountDir\sources\install2.wim" -CompressionType "Max"
|
||||
Write-Host "Remove old '$mountDir\sources\install.wim' and rename $mountDir\sources\install2.wim"
|
||||
Remove-Item "$mountDir\sources\install.wim"
|
||||
Rename-Item "$mountDir\sources\install2.wim" "$mountDir\sources\install.wim"
|
||||
|
||||
if (-not (Test-Path -Path "$mountDir\sources\install.wim")) {
|
||||
$msg = "Something went wrong. Please report this bug to the devs."
|
||||
Write-Error "$($msg) '$($mountDir)\sources\install.wim' doesn't exist"
|
||||
Invoke-MicrowinBusyInfo -action "warning" -message $msg
|
||||
Set-WinUtilTaskbaritem -state "Error" -value 1 -overlay "warning"
|
||||
return
|
||||
}
|
||||
Write-Host "Windows image completed. Continuing with boot.wim."
|
||||
|
||||
# Next step boot image
|
||||
Write-Host "Mounting boot image $mountDir\sources\boot.wim into $scratchDir"
|
||||
Mount-WindowsImage -ImagePath "$mountDir\sources\boot.wim" -Index 2 -Path "$scratchDir"
|
||||
|
||||
if ($injectDrivers) {
|
||||
$driverPath = $sync.MicrowinDriverLocation.Text
|
||||
if (Test-Path $driverPath) {
|
||||
Write-Host "Adding Windows Drivers image($scratchDir) drivers($driverPath) "
|
||||
dism /English /image:$scratchDir /add-driver /driver:$driverPath /recurse | Out-Host
|
||||
} else {
|
||||
Write-Host "Path to drivers is invalid continuing without driver injection"
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Loading registry..."
|
||||
reg load HKLM\zCOMPONENTS "$($scratchDir)\Windows\System32\config\COMPONENTS" >$null
|
||||
reg load HKLM\zDEFAULT "$($scratchDir)\Windows\System32\config\default" >$null
|
||||
reg load HKLM\zNTUSER "$($scratchDir)\Users\Default\ntuser.dat" >$null
|
||||
reg load HKLM\zSOFTWARE "$($scratchDir)\Windows\System32\config\SOFTWARE" >$null
|
||||
reg load HKLM\zSYSTEM "$($scratchDir)\Windows\System32\config\SYSTEM" >$null
|
||||
Write-Host "Bypassing system requirements on the setup image"
|
||||
reg add "HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache" /v "SV1" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache" /v "SV2" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache" /v "SV1" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache" /v "SV2" /t REG_DWORD /d 0 /f
|
||||
reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassCPUCheck" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassRAMCheck" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassSecureBootCheck" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassStorageCheck" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\zSYSTEM\Setup\LabConfig" /v "BypassTPMCheck" /t REG_DWORD /d 1 /f
|
||||
reg add "HKLM\zSYSTEM\Setup\MoSetup" /v "AllowUpgradesWithUnsupportedTPMOrCPU" /t REG_DWORD /d 1 /f
|
||||
# Fix Computer Restarted Unexpectedly Error on New Bare Metal Install
|
||||
reg add "HKLM\zSYSTEM\Setup\Status\ChildCompletion" /v "setup.exe" /t REG_DWORD /d 3 /f
|
||||
} catch {
|
||||
Write-Error "An unexpected error occurred: $_"
|
||||
} finally {
|
||||
Write-Host "Unmounting Registry..."
|
||||
reg unload HKLM\zCOMPONENTS
|
||||
reg unload HKLM\zDEFAULT
|
||||
reg unload HKLM\zNTUSER
|
||||
reg unload HKLM\zSOFTWARE
|
||||
reg unload HKLM\zSYSTEM
|
||||
|
||||
Write-Host "Unmounting image..."
|
||||
Dismount-WindowsImage -Path "$scratchDir" -Save
|
||||
|
||||
Write-Host "Creating ISO image"
|
||||
|
||||
# if we downloaded oscdimg from github it will be in the temp directory so use it
|
||||
# if it is not in temp it is part of ADK and is in global PATH so just set it to oscdimg.exe
|
||||
$oscdimgPath = Join-Path $env:TEMP 'oscdimg.exe'
|
||||
$oscdImgFound = Test-Path $oscdimgPath -PathType Leaf
|
||||
if (!$oscdImgFound) {
|
||||
$oscdimgPath = "oscdimg.exe"
|
||||
}
|
||||
|
||||
Write-Host "[INFO] Using oscdimg.exe from: $oscdimgPath"
|
||||
|
||||
$oscdimgProc = Start-Process -FilePath "$oscdimgPath" -ArgumentList "-m -o -u2 -udfver102 -bootdata:2#p0,e,b`"$mountDir\boot\etfsboot.com`"#pEF,e,b`"$mountDir\efi\microsoft\boot\efisys.bin`" `"$mountDir`" `"$($SaveDialog.FileName)`"" -Wait -PassThru -NoNewWindow
|
||||
|
||||
$LASTEXITCODE = $oscdimgProc.ExitCode
|
||||
|
||||
Write-Host "OSCDIMG Error Level : $($oscdimgProc.ExitCode)"
|
||||
|
||||
if ($copyToUSB) {
|
||||
Write-Host "Copying target ISO to the USB drive"
|
||||
Microwin-CopyToUSB("$($SaveDialog.FileName)")
|
||||
if ($?) { Write-Host "Done Copying target ISO to USB drive!" } else { Write-Host "ISO copy failed." }
|
||||
}
|
||||
|
||||
Write-Host " _____ "
|
||||
Write-Host "(____ \ "
|
||||
Write-Host " _ \ \ ___ ____ ____ "
|
||||
Write-Host "| | | / _ \| _ \ / _ ) "
|
||||
Write-Host "| |__/ / |_| | | | ( (/ / "
|
||||
Write-Host "|_____/ \___/|_| |_|\____) "
|
||||
|
||||
# Check if the ISO was successfully created - CTT edit
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-Host "`n`nPerforming Cleanup..."
|
||||
Remove-Item -Recurse -Force "$($scratchDir)"
|
||||
Remove-Item -Recurse -Force "$($mountDir)"
|
||||
$msg = "Done. ISO image is located here: $($SaveDialog.FileName)"
|
||||
Write-Host $msg
|
||||
Set-WinUtilTaskbaritem -state "None" -overlay "checkmark"
|
||||
Invoke-MicrowinBusyInfo -action "done" -message "Finished!"
|
||||
[System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Information)
|
||||
} else {
|
||||
Write-Host "ISO creation failed. The "$($mountDir)" directory has not been removed."
|
||||
try {
|
||||
# This creates a new Win32 exception from which we can extract a message in the system language.
|
||||
# Now, this will NOT throw an exception
|
||||
$exitCode = New-Object System.ComponentModel.Win32Exception($LASTEXITCODE)
|
||||
Write-Host "Reason: $($exitCode.Message)"
|
||||
Invoke-MicrowinBusyInfo -action "warning" -message $exitCode.Message
|
||||
Set-WinUtilTaskbaritem -state "Error" -value 1 -overlay "warning"
|
||||
} catch {
|
||||
# Could not get error description from Windows APIs
|
||||
}
|
||||
}
|
||||
|
||||
Toggle-MicrowinPanel 1
|
||||
|
||||
#$sync.MicrowinFinalIsoLocation.Text = "$env:temp\microwin.iso"
|
||||
$sync.MicrowinFinalIsoLocation.Text = "$($SaveDialog.FileName)"
|
||||
# Allow the machine to sleep again (optional)
|
||||
[PowerManagement]::SetThreadExecutionState(0)
|
||||
$sync.ProcessRunning = $false
|
||||
}
|
||||
}
|
65
functions/microwin/Invoke-MicrowinBusyInfo.ps1
Normal file
65
functions/microwin/Invoke-MicrowinBusyInfo.ps1
Normal file
@ -0,0 +1,65 @@
|
||||
function Invoke-MicrowinBusyInfo {
|
||||
<#
|
||||
.DESCRIPTION
|
||||
Function to display the busy info for the Microwin process
|
||||
#>
|
||||
[CmdletBinding(DefaultParameterSetName='done')]
|
||||
param(
|
||||
[Parameter(ParameterSetName='wip', Mandatory, Position = 0)]
|
||||
[Parameter(ParameterSetName='warning', Mandatory, Position = 0)]
|
||||
[Parameter(ParameterSetName='done', Mandatory, Position = 0)]
|
||||
[Parameter(ParameterSetName='hide', Mandatory, Position = 0)]
|
||||
[ValidateSet('wip', 'warning', 'done', 'hide')]
|
||||
[string]$action,
|
||||
|
||||
[Parameter(ParameterSetName='wip', Mandatory, Position = 1)]
|
||||
[Parameter(ParameterSetName='warning', Mandatory, Position = 1)]
|
||||
[Parameter(ParameterSetName='done', Mandatory, Position = 1)]
|
||||
[string]$message,
|
||||
|
||||
[Parameter(ParameterSetName='wip', Position = 2)] [bool]$interactive = $false
|
||||
)
|
||||
|
||||
switch ($action) {
|
||||
"wip" {
|
||||
$sync.form.Dispatcher.BeginInvoke([action]{
|
||||
$sync.MicrowinBusyIndicator.Visibility="Visible"
|
||||
$finalMessage = ""
|
||||
if ($interactive -eq $false) {
|
||||
$finalMessage += "Please wait. "
|
||||
}
|
||||
$finalMessage += $message
|
||||
$sync.BusyText.Text = $finalMessage
|
||||
$sync.BusyIcon.Foreground="#FFA500"
|
||||
$sync.BusyText.Foreground="#FFA500"
|
||||
})
|
||||
}
|
||||
"warning" {
|
||||
$sync.form.Dispatcher.BeginInvoke([action]{
|
||||
$sync.MicrowinBusyIndicator.Visibility="Visible"
|
||||
$sync.BusyText.Text=$message
|
||||
$sync.BusyText.Foreground="#FF0000"
|
||||
$sync.BusyIcon.Foreground="#FF0000"
|
||||
})
|
||||
}
|
||||
"done" {
|
||||
$sync.form.Dispatcher.BeginInvoke([action]{
|
||||
$sync.MicrowinBusyIndicator.Visibility="Visible"
|
||||
$sync.BusyText.Text=$message
|
||||
$sync.BusyText.Foreground="#00FF00"
|
||||
$sync.BusyIcon.Foreground="#00FF00"
|
||||
})
|
||||
}
|
||||
"hide" {
|
||||
$sync.form.Dispatcher.BeginInvoke([action]{
|
||||
$sync.MicrowinBusyIndicator.Visibility="Hidden"
|
||||
$sync.BusyText.Foreground=$sync.Form.Resources.MicrowinBusyColor
|
||||
$sync.BusyIcon.Foreground=$sync.Form.Resources.MicrowinBusyColor
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
# Force the UI to process pending messages
|
||||
[System.Windows.Forms.Application]::DoEvents()
|
||||
Start-Sleep -Milliseconds 50
|
||||
}
|
339
functions/microwin/Invoke-MicrowinGetIso.ps1
Normal file
339
functions/microwin/Invoke-MicrowinGetIso.ps1
Normal file
@ -0,0 +1,339 @@
|
||||
function Invoke-MicrowinGetIso {
|
||||
<#
|
||||
.DESCRIPTION
|
||||
Function to get the path to Iso file for MicroWin, unpack that isom=, read basic information and populate the UI Options
|
||||
#>
|
||||
|
||||
Write-Host "Invoking WPFGetIso"
|
||||
|
||||
if($sync.ProcessRunning) {
|
||||
$msg = "GetIso process is currently running."
|
||||
[System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Warning)
|
||||
return
|
||||
}
|
||||
|
||||
# Provide immediate feedback to user
|
||||
Invoke-MicrowinBusyInfo -action "wip" -message "Initializing MicroWin process..." -interactive $false
|
||||
|
||||
Write-Host " _ __ __ _ "
|
||||
Write-Host " /\/\ (_) ___ _ __ ___ / / /\ \ \(_) _ __ "
|
||||
Write-Host " / \ | | / __|| '__| / _ \ \ \/ \/ /| || '_ \ "
|
||||
Write-Host "/ /\/\ \| || (__ | | | (_) | \ /\ / | || | | | "
|
||||
Write-Host "\/ \/|_| \___||_| \___/ \/ \/ |_||_| |_| "
|
||||
|
||||
if ($sync["ISOmanual"].IsChecked) {
|
||||
# Open file dialog to let user choose the ISO file
|
||||
Invoke-MicrowinBusyInfo -action "wip" -message "Please select an ISO file..." -interactive $true
|
||||
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
|
||||
$openFileDialog = New-Object System.Windows.Forms.OpenFileDialog
|
||||
$openFileDialog.initialDirectory = $initialDirectory
|
||||
$openFileDialog.filter = "ISO files (*.iso)| *.iso"
|
||||
$openFileDialog.ShowDialog() | Out-Null
|
||||
$filePath = $openFileDialog.FileName
|
||||
|
||||
if ([string]::IsNullOrEmpty($filePath)) {
|
||||
Write-Host "No ISO is chosen"
|
||||
Invoke-MicrowinBusyInfo -action "hide" -message " "
|
||||
return
|
||||
}
|
||||
|
||||
} elseif ($sync["ISOdownloader"].IsChecked) {
|
||||
# Create folder browsers for user-specified locations
|
||||
Invoke-MicrowinBusyInfo -action "wip" -message "Please select download location..." -interactive $true
|
||||
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
|
||||
$isoDownloaderFBD = New-Object System.Windows.Forms.FolderBrowserDialog
|
||||
$isoDownloaderFBD.Description = "Please specify the path to download the ISO file to:"
|
||||
$isoDownloaderFBD.ShowNewFolderButton = $true
|
||||
if ($isoDownloaderFBD.ShowDialog() -ne [System.Windows.Forms.DialogResult]::OK)
|
||||
{
|
||||
Invoke-MicrowinBusyInfo -action "hide" -message " "
|
||||
return
|
||||
}
|
||||
|
||||
Set-WinUtilTaskbaritem -state "Indeterminate" -overlay "logo"
|
||||
Invoke-MicrowinBusyInfo -action "wip" -message "Preparing to download ISO..." -interactive $false
|
||||
|
||||
# Grab the location of the selected path
|
||||
$targetFolder = $isoDownloaderFBD.SelectedPath
|
||||
|
||||
# Auto download newest ISO
|
||||
# Credit: https://github.com/pbatard/Fido
|
||||
$fidopath = "$env:temp\Fido.ps1"
|
||||
$originalLocation = $PSScriptRoot
|
||||
|
||||
Invoke-MicrowinBusyInfo -action "wip" -message "Downloading Fido script..." -interactive $false
|
||||
Invoke-WebRequest "https://github.com/pbatard/Fido/raw/master/Fido.ps1" -OutFile $fidopath
|
||||
|
||||
Set-Location -Path $env:temp
|
||||
# Detect if the first option ("System language") has been selected and get a Fido-approved language from the current culture
|
||||
$lang = if ($sync["ISOLanguage"].SelectedIndex -eq 0) {
|
||||
Microwin-GetLangFromCulture -langName (Get-Culture).Name
|
||||
} else {
|
||||
$sync["ISOLanguage"].SelectedItem
|
||||
}
|
||||
|
||||
Invoke-MicrowinBusyInfo -action "wip" -message "Downloading Windows ISO... (This may take a long time)" -interactive $false
|
||||
& $fidopath -Win 'Windows 11' -Rel $sync["ISORelease"].SelectedItem -Arch "x64" -Lang $lang -Ed "Windows 11 Home/Pro/Edu"
|
||||
if (-not $?)
|
||||
{
|
||||
Write-Host "Could not download the ISO file. Look at the output of the console for more information."
|
||||
$msg = "The ISO file could not be downloaded"
|
||||
Invoke-MicrowinBusyInfo -action "warning" -message $msg
|
||||
Set-WinUtilTaskbaritem -state "Error" -value 1 -overlay "warning"
|
||||
[System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Error)
|
||||
return
|
||||
}
|
||||
Set-Location $originalLocation
|
||||
# Use the FullName property to only grab the file names. Using this property is necessary as, without it, you're passing the usual output of Get-ChildItem
|
||||
# to the variable, and let's be honest, that does NOT exist in the file system
|
||||
$filePath = (Get-ChildItem -Path "$env:temp" -Filter "Win11*.iso").FullName | Sort-Object LastWriteTime -Descending | Select-Object -First 1
|
||||
$fileName = [IO.Path]::GetFileName("$filePath")
|
||||
|
||||
if (($targetFolder -ne "") -and (Test-Path "$targetFolder"))
|
||||
{
|
||||
try
|
||||
{
|
||||
# "Let it download to $env:TEMP and then we **move** it to the file path." - CodingWonders
|
||||
$destinationFilePath = "$targetFolder\$fileName"
|
||||
Write-Host "Moving ISO file. Please wait..."
|
||||
Move-Item -Path "$filePath" -Destination "$destinationFilePath" -Force
|
||||
$filePath = $destinationFilePath
|
||||
}
|
||||
catch
|
||||
{
|
||||
$msg = "Unable to move the ISO file to the location you specified. The downloaded ISO is in the `"$env:TEMP`" folder"
|
||||
Write-Host $msg
|
||||
Write-Host "Error information: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
Invoke-MicrowinBusyInfo -action "warning" -message $msg
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "File path $($filePath)"
|
||||
if (-not (Test-Path -Path "$filePath" -PathType Leaf)) {
|
||||
$msg = "File you've chosen doesn't exist"
|
||||
Invoke-MicrowinBusyInfo -action "warning" -message $msg
|
||||
[System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Error)
|
||||
return
|
||||
}
|
||||
|
||||
Set-WinUtilTaskbaritem -state "Indeterminate" -overlay "logo"
|
||||
Invoke-MicrowinBusyInfo -action "wip" -message "Checking system requirements..." -interactive $false
|
||||
|
||||
$oscdimgPath = Join-Path $env:TEMP 'oscdimg.exe'
|
||||
$oscdImgFound = [bool] (Get-Command -ErrorAction Ignore -Type Application oscdimg.exe) -or (Test-Path $oscdimgPath -PathType Leaf)
|
||||
Write-Host "oscdimg.exe on system: $oscdImgFound"
|
||||
|
||||
if (!$oscdImgFound) {
|
||||
$downloadFromGitHub = $sync.WPFMicrowinDownloadFromGitHub.IsChecked
|
||||
|
||||
if (!$downloadFromGitHub) {
|
||||
# only show the message to people who did check the box to download from github, if you check the box
|
||||
# you consent to downloading it, no need to show extra dialogs
|
||||
[System.Windows.MessageBox]::Show("oscdimge.exe is not found on the system, winutil will now attempt do download and install it using choco. This might take a long time.")
|
||||
# the step below needs choco to download oscdimg
|
||||
# Install Choco if not already present
|
||||
Install-WinUtilChoco
|
||||
$chocoFound = [bool] (Get-Command -ErrorAction Ignore -Type Application choco)
|
||||
Write-Host "choco on system: $chocoFound"
|
||||
if (!$chocoFound) {
|
||||
[System.Windows.MessageBox]::Show("choco.exe is not found on the system, you need choco to download oscdimg.exe")
|
||||
return
|
||||
}
|
||||
|
||||
Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "choco install windows-adk-oscdimg"
|
||||
$msg = "oscdimg is installed, now close, reopen PowerShell terminal and re-launch winutil.ps1"
|
||||
Invoke-MicrowinBusyInfo -action "done" -message $msg # We set it to done because it immediately returns from this function
|
||||
[System.Windows.MessageBox]::Show($msg)
|
||||
return
|
||||
} else {
|
||||
[System.Windows.MessageBox]::Show("oscdimge.exe is not found on the system, winutil will now attempt do download and install it from github. This might take a long time.")
|
||||
Invoke-MicrowinBusyInfo -action "wip" -message "Downloading oscdimg.exe..." -interactive $false
|
||||
Microwin-GetOscdimg -oscdimgPath $oscdimgPath
|
||||
$oscdImgFound = Test-Path $oscdimgPath -PathType Leaf
|
||||
if (!$oscdImgFound) {
|
||||
$msg = "oscdimg was not downloaded can not proceed"
|
||||
Invoke-MicrowinBusyInfo -action "warning" -message $msg
|
||||
[System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Error)
|
||||
return
|
||||
} else {
|
||||
Write-Host "oscdimg.exe was successfully downloaded from github"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Invoke-MicrowinBusyInfo -action "wip" -message "Checking disk space..." -interactive $false
|
||||
|
||||
# Detect the file size of the ISO and compare it with the free space of the system drive
|
||||
$isoSize = (Get-Item -Path "$filePath").Length
|
||||
Write-Debug "Size of ISO file: $($isoSize) bytes"
|
||||
# Use this procedure to get the free space of the drive depending on where the user profile folder is stored.
|
||||
# This is done to guarantee a dynamic solution, as the installation drive may be mounted to a letter different than C
|
||||
$driveSpace = (Get-Volume -DriveLetter ([IO.Path]::GetPathRoot([Environment]::GetFolderPath([Environment+SpecialFolder]::UserProfile)).Replace(":\", "").Trim())).SizeRemaining
|
||||
Write-Debug "Free space on installation drive: $($driveSpace) bytes"
|
||||
if ($driveSpace -lt ($isoSize * 2)) {
|
||||
# It's not critical and we _may_ continue. Output a warning
|
||||
Write-Warning "You may not have enough space for this operation. Proceed at your own risk."
|
||||
}
|
||||
elseif ($driveSpace -lt $isoSize) {
|
||||
# It's critical and we can't continue. Output an error
|
||||
$msg = "You don't have enough space for this operation. You need at least $([Math]::Round(($isoSize / ([Math]::Pow(1024, 2))) * 2, 2)) MB of free space to copy the ISO files to a temp directory and to be able to perform additional operations."
|
||||
Write-Host $msg
|
||||
Set-WinUtilTaskbaritem -state "Error" -value 1 -overlay "warning"
|
||||
Invoke-MicrowinBusyInfo -action "warning" -message $msg
|
||||
return
|
||||
} else {
|
||||
Write-Host "You have enough space for this operation."
|
||||
}
|
||||
|
||||
try {
|
||||
Invoke-MicrowinBusyInfo -action "wip" -message "Mounting ISO file..." -interactive $false
|
||||
Write-Host "Mounting Iso. Please wait."
|
||||
$mountedISO = Mount-DiskImage -PassThru "$filePath"
|
||||
Write-Host "Done mounting Iso `"$($mountedISO.ImagePath)`""
|
||||
$driveLetter = (Get-Volume -DiskImage $mountedISO).DriveLetter
|
||||
Write-Host "Iso mounted to '$driveLetter'"
|
||||
} catch {
|
||||
# @ChrisTitusTech please copy this wiki and change the link below to your copy of the wiki
|
||||
$msg = "Failed to mount the image. Error: $($_.Exception.Message)"
|
||||
Write-Error $msg
|
||||
Write-Error "This is NOT winutil's problem, your ISO might be corrupt, or there is a problem on the system"
|
||||
Write-Host "Please refer to this wiki for more details: https://christitustech.github.io/winutil/KnownIssues/#troubleshoot-errors-during-microwin-usage" -ForegroundColor Red
|
||||
Set-WinUtilTaskbaritem -state "Error" -value 1 -overlay "warning"
|
||||
Invoke-MicrowinBusyInfo -action "warning" -message $msg
|
||||
return
|
||||
}
|
||||
# storing off values in hidden fields for further steps
|
||||
# there is probably a better way of doing this, I don't have time to figure this out
|
||||
$sync.MicrowinIsoDrive.Text = $driveLetter
|
||||
|
||||
$mountedISOPath = (Split-Path -Path "$filePath")
|
||||
if ($sync.MicrowinScratchDirBox.Text.Trim() -eq "Scratch") {
|
||||
$sync.MicrowinScratchDirBox.Text =""
|
||||
}
|
||||
|
||||
$UseISOScratchDir = $sync.WPFMicrowinISOScratchDir.IsChecked
|
||||
|
||||
if ($UseISOScratchDir) {
|
||||
$sync.MicrowinScratchDirBox.Text=$mountedISOPath
|
||||
}
|
||||
|
||||
if( -Not $sync.MicrowinScratchDirBox.Text.EndsWith('\') -And $sync.MicrowinScratchDirBox.Text.Length -gt 1) {
|
||||
|
||||
$sync.MicrowinScratchDirBox.Text = Join-Path $sync.MicrowinScratchDirBox.Text.Trim() '\'
|
||||
|
||||
}
|
||||
|
||||
# Detect if the folders already exist and remove them
|
||||
if (($sync.MicrowinMountDir.Text -ne "") -and (Test-Path -Path $sync.MicrowinMountDir.Text)) {
|
||||
try {
|
||||
Write-Host "Deleting temporary files from previous run. Please wait..."
|
||||
Remove-Item -Path $sync.MicrowinMountDir.Text -Recurse -Force
|
||||
Remove-Item -Path $sync.MicrowinScratchDir.Text -Recurse -Force
|
||||
} catch {
|
||||
Write-Host "Could not delete temporary files. You need to delete those manually."
|
||||
}
|
||||
}
|
||||
|
||||
Write-Host "Setting up mount dir and scratch dirs"
|
||||
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
|
||||
$randomNumber = Get-Random -Minimum 1 -Maximum 9999
|
||||
$randomMicrowin = "Microwin_${timestamp}_${randomNumber}"
|
||||
$randomMicrowinScratch = "MicrowinScratch_${timestamp}_${randomNumber}"
|
||||
$sync.BusyText.Text=" - Mounting"
|
||||
Write-Host "Mounting Iso. Please wait."
|
||||
if ($sync.MicrowinScratchDirBox.Text -eq "") {
|
||||
$mountDir = Join-Path $env:TEMP $randomMicrowin
|
||||
$scratchDir = Join-Path $env:TEMP $randomMicrowinScratch
|
||||
} else {
|
||||
$scratchDir = $sync.MicrowinScratchDirBox.Text+"Scratch"
|
||||
$mountDir = $sync.MicrowinScratchDirBox.Text+"micro"
|
||||
}
|
||||
|
||||
$sync.MicrowinMountDir.Text = $mountDir
|
||||
$sync.MicrowinScratchDir.Text = $scratchDir
|
||||
Write-Host "Done setting up mount dir and scratch dirs"
|
||||
Write-Host "Scratch dir is $scratchDir"
|
||||
Write-Host "Image dir is $mountDir"
|
||||
|
||||
try {
|
||||
|
||||
#$data = @($driveLetter, $filePath)
|
||||
Invoke-MicrowinBusyInfo -action "wip" -message "Creating directories..." -interactive $false
|
||||
New-Item -ItemType Directory -Force -Path "$($mountDir)" | Out-Null
|
||||
New-Item -ItemType Directory -Force -Path "$($scratchDir)" | Out-Null
|
||||
|
||||
Invoke-MicrowinBusyInfo -action "wip" -message "Copying Windows files... (This may take several minutes)" -interactive $false
|
||||
Write-Host "Copying Windows image. This will take awhile, please don't use UI or cancel this step!"
|
||||
|
||||
# xcopy we can verify files and also not copy files that already exist, but hard to measure
|
||||
# xcopy.exe /E /I /H /R /Y /J $DriveLetter":" $mountDir >$null
|
||||
$totalTime = Measure-Command {
|
||||
Copy-Files "$($driveLetter):" "$mountDir" -Recurse -Force
|
||||
# Force UI update during long operation
|
||||
[System.Windows.Forms.Application]::DoEvents()
|
||||
}
|
||||
Write-Host "Copy complete! Total Time: $($totalTime.Minutes) minutes, $($totalTime.Seconds) seconds"
|
||||
|
||||
Invoke-MicrowinBusyInfo -action "wip" -message "Processing Windows image..." -interactive $false
|
||||
$wimFile = "$mountDir\sources\install.wim"
|
||||
Write-Host "Getting image information $wimFile"
|
||||
|
||||
if ((-not (Test-Path -Path "$wimFile" -PathType Leaf)) -and (-not (Test-Path -Path "$($wimFile.Replace(".wim", ".esd").Trim())" -PathType Leaf))) {
|
||||
$msg = "Neither install.wim nor install.esd exist in the image, this could happen if you use unofficial Windows images. Please don't use shady images from the internet."
|
||||
Write-Host "$($msg) Only use official images. Here are instructions how to download ISO images if the Microsoft website is not showing the link to download and ISO. https://www.techrepublic.com/article/how-to-download-a-windows-10-iso-file-without-using-the-media-creation-tool/"
|
||||
Invoke-MicrowinBusyInfo -action "warning" -message $msg
|
||||
Set-WinUtilTaskbaritem -state "Error" -value 1 -overlay "warning"
|
||||
[System.Windows.MessageBox]::Show($msg, "Winutil", [System.Windows.MessageBoxButton]::OK, [System.Windows.MessageBoxImage]::Error)
|
||||
throw
|
||||
}
|
||||
elseif ((-not (Test-Path -Path $wimFile -PathType Leaf)) -and (Test-Path -Path $wimFile.Replace(".wim", ".esd").Trim() -PathType Leaf)) {
|
||||
Write-Host "Install.esd found on the image. It needs to be converted to a WIM file in order to begin processing"
|
||||
$wimFile = $wimFile.Replace(".wim", ".esd").Trim()
|
||||
}
|
||||
$sync.MicrowinWindowsFlavors.Items.Clear()
|
||||
Get-WindowsImage -ImagePath $wimFile | ForEach-Object {
|
||||
$imageIdx = $_.ImageIndex
|
||||
$imageName = $_.ImageName
|
||||
$sync.MicrowinWindowsFlavors.Items.Add("$imageIdx : $imageName")
|
||||
}
|
||||
[System.Windows.Forms.Application]::DoEvents()
|
||||
|
||||
$sync.MicrowinWindowsFlavors.SelectedIndex = 0
|
||||
Write-Host "Finding suitable Pro edition. This can take some time. Do note that this is an automatic process that might not select the edition you want."
|
||||
Invoke-MicrowinBusyInfo -action "wip" -message "Finding suitable Pro edition..." -interactive $false
|
||||
|
||||
Get-WindowsImage -ImagePath $wimFile | ForEach-Object {
|
||||
if ((Get-WindowsImage -ImagePath $wimFile -Index $_.ImageIndex).EditionId -eq "Professional") {
|
||||
# We have found the Pro edition
|
||||
$sync.MicrowinWindowsFlavors.SelectedIndex = $_.ImageIndex - 1
|
||||
}
|
||||
# Allow UI updates during this loop
|
||||
[System.Windows.Forms.Application]::DoEvents()
|
||||
}
|
||||
|
||||
Get-Volume $driveLetter | Get-DiskImage | Dismount-DiskImage
|
||||
Write-Host "Selected value '$($sync.MicrowinWindowsFlavors.SelectedValue)'....."
|
||||
|
||||
Toggle-MicrowinPanel 2
|
||||
|
||||
} catch {
|
||||
Write-Host "Dismounting bad image..."
|
||||
Get-Volume $driveLetter | Get-DiskImage | Dismount-DiskImage
|
||||
Remove-Item -Recurse -Force "$($scratchDir)"
|
||||
Remove-Item -Recurse -Force "$($mountDir)"
|
||||
Invoke-MicrowinBusyInfo -action "warning" -message "Failed to read and unpack ISO"
|
||||
Set-WinUtilTaskbaritem -state "Error" -value 1 -overlay "warning"
|
||||
|
||||
}
|
||||
|
||||
Write-Host "Done reading and unpacking ISO"
|
||||
Write-Host ""
|
||||
Write-Host "*********************************"
|
||||
Write-Host "Check the UI for further steps!!!"
|
||||
|
||||
Invoke-MicrowinBusyInfo -action "done" -message "Done! Proceed with customization."
|
||||
$sync.ProcessRunning = $false
|
||||
Set-WinUtilTaskbaritem -state "None" -overlay "checkmark"
|
||||
}
|
10
functions/microwin/Microwin-Classes.ps1
Normal file
10
functions/microwin/Microwin-Classes.ps1
Normal file
@ -0,0 +1,10 @@
|
||||
class ErroredPackage {
|
||||
[string]$PackageName
|
||||
[string]$ErrorMessage
|
||||
ErroredPackage() { $this.Init(@{} )}
|
||||
# Constructor for packages that have errored out
|
||||
ErroredPackage([string]$pkgName, [string]$reason) {
|
||||
$this.PackageName = $pkgName
|
||||
$this.ErrorMessage = $reason
|
||||
}
|
||||
}
|
71
functions/microwin/Microwin-CopyToUSB.ps1
Normal file
71
functions/microwin/Microwin-CopyToUSB.ps1
Normal file
@ -0,0 +1,71 @@
|
||||
function Microwin-CopyToUSB([string]$fileToCopy) {
|
||||
foreach ($volume in Get-Volume) {
|
||||
if ($volume -and $volume.FileSystemLabel -ieq "ventoy") {
|
||||
$destinationPath = "$($volume.DriveLetter):\"
|
||||
#Copy-Item -Path $fileToCopy -Destination $destinationPath -Force
|
||||
# Get the total size of the file
|
||||
$totalSize = (Get-Item "$fileToCopy").length
|
||||
|
||||
Copy-Item -Path "$fileToCopy" -Destination "$destinationPath" -Verbose -Force -Recurse -Container -PassThru |
|
||||
ForEach-Object {
|
||||
# Calculate the percentage completed
|
||||
$completed = ($_.BytesTransferred / $totalSize) * 100
|
||||
|
||||
# Display the progress bar
|
||||
Write-Progress -Activity "Copying File" -Status "Progress" -PercentComplete $completed -CurrentOperation ("{0:N2} MB / {1:N2} MB" -f ($_.BytesTransferred / 1MB), ($totalSize / 1MB))
|
||||
}
|
||||
|
||||
Write-Host "File copied to Ventoy drive $($volume.DriveLetter)"
|
||||
|
||||
# Detect if config files are present, move them if they are, and configure the Ventoy drive to not bypass the requirements
|
||||
$customVentoyConfig = @'
|
||||
{
|
||||
"control":[
|
||||
{ "VTOY_WIN11_BYPASS_CHECK": "0" },
|
||||
{ "VTOY_WIN11_BYPASS_NRO": "0" }
|
||||
],
|
||||
"control_legacy":[
|
||||
{ "VTOY_WIN11_BYPASS_CHECK": "0" },
|
||||
{ "VTOY_WIN11_BYPASS_NRO": "0" }
|
||||
],
|
||||
"control_uefi":[
|
||||
{ "VTOY_WIN11_BYPASS_CHECK": "0" },
|
||||
{ "VTOY_WIN11_BYPASS_NRO": "0" }
|
||||
],
|
||||
"control_ia32":[
|
||||
{ "VTOY_WIN11_BYPASS_CHECK": "0" },
|
||||
{ "VTOY_WIN11_BYPASS_NRO": "0" }
|
||||
],
|
||||
"control_aa64":[
|
||||
{ "VTOY_WIN11_BYPASS_CHECK": "0" },
|
||||
{ "VTOY_WIN11_BYPASS_NRO": "0" }
|
||||
],
|
||||
"control_mips":[
|
||||
{ "VTOY_WIN11_BYPASS_CHECK": "0" },
|
||||
{ "VTOY_WIN11_BYPASS_NRO": "0" }
|
||||
]
|
||||
}
|
||||
'@
|
||||
|
||||
try {
|
||||
Write-Host "Writing custom Ventoy configuration. Please wait..."
|
||||
if (Test-Path -Path "$($volume.DriveLetter):\ventoy\ventoy.json" -PathType Leaf) {
|
||||
Write-Host "A Ventoy configuration file exists. Moving it..."
|
||||
Move-Item -Path "$($volume.DriveLetter):\ventoy\ventoy.json" -Destination "$($volume.DriveLetter):\ventoy\ventoy.json.old" -Force
|
||||
Write-Host "Existing Ventoy configuration has been moved to `"ventoy.json.old`". Feel free to put your config back into the `"ventoy.json`" file."
|
||||
}
|
||||
if (-not (Test-Path -Path "$($volume.DriveLetter):\ventoy")) {
|
||||
New-Item -Path "$($volume.DriveLetter):\ventoy" -ItemType Directory -Force | Out-Null
|
||||
}
|
||||
$customVentoyConfig | Out-File -FilePath "$($volume.DriveLetter):\ventoy\ventoy.json" -Encoding utf8 -Force
|
||||
Write-Host "The Ventoy drive has been successfully configured."
|
||||
} catch {
|
||||
Write-Host "Could not configure Ventoy drive. Error: $($_.Exception.Message)`n"
|
||||
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"
|
||||
Write-Host "Failure to do this will cause conflicts with your target ISO file."
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
Write-Host "Ventoy USB Key is not inserted"
|
||||
}
|
40
functions/microwin/Microwin-CopyVirtIO.ps1
Normal file
40
functions/microwin/Microwin-CopyVirtIO.ps1
Normal file
@ -0,0 +1,40 @@
|
||||
function Microwin-CopyVirtIO {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Downloads and copies the VirtIO Guest Tools drivers to the target MicroWin ISO
|
||||
.NOTES
|
||||
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.
|
||||
#>
|
||||
|
||||
try {
|
||||
Write-Host "Checking existing files..."
|
||||
if (Test-Path -Path "$($env:TEMP)\virtio.iso" -PathType Leaf) {
|
||||
Write-Host "VirtIO ISO has been detected. Deleting..."
|
||||
Remove-Item -Path "$($env:TEMP)\virtio.iso" -Force
|
||||
}
|
||||
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..."
|
||||
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..."
|
||||
# Do everything else if the VirtIO ISO exists
|
||||
if (Test-Path -Path "$($env:TEMP)\virtio.iso" -PathType Leaf) {
|
||||
Write-Host "Mounting ISO. Please wait."
|
||||
$virtIO_ISO = Mount-DiskImage -PassThru "$($env:TEMP)\virtio.iso"
|
||||
$driveLetter = (Get-Volume -DiskImage $virtIO_ISO).DriveLetter
|
||||
# Create new directory for VirtIO on ISO
|
||||
New-Item -Path "$mountDir\VirtIO" -ItemType Directory | Out-Null
|
||||
$totalTime = Measure-Command { Copy-Files "$($driveLetter):" "$mountDir\VirtIO" -Recurse -Force }
|
||||
Write-Host "VirtIO contents have been successfully copied. Time taken: $($totalTime.Minutes) minutes, $($totalTime.Seconds) seconds`n"
|
||||
Get-Volume $driveLetter | Get-DiskImage | Dismount-DiskImage
|
||||
Remove-Item -Path "$($env:TEMP)\virtio.iso" -Force -ErrorAction SilentlyContinue
|
||||
Write-Host "To proceed with installation of the MicroWin image in QEMU/Proxmox VE:"
|
||||
Write-Host "1. Proceed with Setup until you reach the disk selection screen, in which you won't see any drives"
|
||||
Write-Host "2. Click `"Load Driver`" and click Browse"
|
||||
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"
|
||||
Write-Host "4. Select all drivers that will appear in the list box and click OK"
|
||||
} else {
|
||||
throw "Could not download VirtIO drivers"
|
||||
}
|
||||
} catch {
|
||||
Write-Host "We could not download and/or prepare the VirtIO drivers. Error information: $_`n"
|
||||
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"
|
||||
}
|
||||
}
|
49
functions/microwin/Microwin-GetLangFromCulture.ps1
Normal file
49
functions/microwin/Microwin-GetLangFromCulture.ps1
Normal file
@ -0,0 +1,49 @@
|
||||
function Microwin-GetLangFromCulture {
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory, Position = 0)] [string]$langName
|
||||
)
|
||||
|
||||
switch -Wildcard ($langName)
|
||||
{
|
||||
"ar*" { return "Arabic" }
|
||||
"pt-BR" { return "Brazilian Portuguese" }
|
||||
"bg*" { return "Bulgarian" }
|
||||
{($_ -eq "zh-CH") -or ($_ -like "zh-Hans*") -or ($_ -eq "zh-SG") -or ($_ -eq "zh-CHS")} { return "Chinese (Simplified)" }
|
||||
{($_ -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)" }
|
||||
"hr*" { return "Croatian" }
|
||||
"cs*" { return "Czech" }
|
||||
"da*" { return "Danish" }
|
||||
"nl*" { return "Dutch" }
|
||||
"en-US" { return "English" }
|
||||
{($_ -like "en*") -and ($_ -ne "en-US")} { return "English International" }
|
||||
"et*" { return "Estonian" }
|
||||
"fi*" { return "Finnish" }
|
||||
{($_ -like "fr*") -and ($_ -ne "fr-CA")} { return "French" }
|
||||
"fr-CA" { return "French Canadian" }
|
||||
"de*" { return "German" }
|
||||
"el*" { return "Greek" }
|
||||
"he*" { return "Hebrew" }
|
||||
"hu*" { return "Hungarian" }
|
||||
"it*" { return "Italian" }
|
||||
"ja*" { return "Japanese" }
|
||||
"ko*" { return "Korean" }
|
||||
"lv*" { return "Latvian" }
|
||||
"lt*" { return "Lituanian" }
|
||||
"nb*" { return "Norwegian" }
|
||||
"pl*" { return "Polish" }
|
||||
{($_ -like "pt*") -and ($_ -ne "pt-BR")} { return "Portuguese" }
|
||||
"ro*" { return "Romanian" }
|
||||
"ru*" { return "Russian" }
|
||||
"sr-Latn*" { return "Serbian Latin" }
|
||||
"sk*" { return "Slovak" }
|
||||
"sl*" { return "Slovenian" }
|
||||
{($_ -like "es*") -and ($_ -ne "es-MX")} { return "Spanish" }
|
||||
"es-MX" { return "Spanish (Mexico)" }
|
||||
"sv*" { return "Swedish" }
|
||||
"th*" { return "Thai" }
|
||||
"tr*" { return "Turkish" }
|
||||
"uk*" { return "Ukrainian" }
|
||||
default { return "English" }
|
||||
}
|
||||
}
|
21
functions/microwin/Microwin-GetLocalizedUsers.ps1
Normal file
21
functions/microwin/Microwin-GetLocalizedUsers.ps1
Normal file
@ -0,0 +1,21 @@
|
||||
function Microwin-GetLocalizedUsers
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Gets a localized user group representation for ICACLS commands (Port from DISMTools PE Helper)
|
||||
.PARAMETER admins
|
||||
Determines whether to get a localized user group representation for the Administrators user group
|
||||
.OUTPUTS
|
||||
A string containing the localized user group
|
||||
.EXAMPLE
|
||||
Microwin-GetLocalizedUsers -admins $true
|
||||
#>
|
||||
param (
|
||||
[Parameter(Mandatory = $true, Position = 0)] [bool]$admins
|
||||
)
|
||||
if ($admins) {
|
||||
return (Get-LocalGroup | Where-Object { $_.SID.Value -like "S-1-5-32-544" }).Name
|
||||
} else {
|
||||
return (Get-LocalGroup | Where-Object { $_.SID.Value -like "S-1-5-32-545" }).Name
|
||||
}
|
||||
}
|
@ -1,15 +1,17 @@
|
||||
function Get-Oscdimg {
|
||||
function Microwin-GetOscdimg {
|
||||
<#
|
||||
|
||||
.DESCRIPTION
|
||||
This function will download oscdimg file from github Release folders and put it into env:temp folder
|
||||
|
||||
.EXAMPLE
|
||||
Get-Oscdimg
|
||||
Microwin-GetOscdimg
|
||||
#>
|
||||
param( [Parameter(Mandatory=$true)]
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory, position=0)]
|
||||
[string]$oscdimgPath
|
||||
)
|
||||
|
||||
$oscdimgPath = "$env:TEMP\oscdimg.exe"
|
||||
$downloadUrl = "https://github.com/ChrisTitusTech/winutil/raw/main/releases/oscdimg.exe"
|
||||
Invoke-RestMethod -Uri $downloadUrl -OutFile $oscdimgPath
|
||||
@ -24,4 +26,4 @@ function Get-Oscdimg {
|
||||
} else {
|
||||
Write-Host "Hashes do not match. File may be corrupted or tampered with."
|
||||
}
|
||||
}
|
||||
}
|
73
functions/microwin/Microwin-NewCheckInstall.ps1
Normal file
73
functions/microwin/Microwin-NewCheckInstall.ps1
Normal file
@ -0,0 +1,73 @@
|
||||
function Microwin-NewCheckInstall {
|
||||
|
||||
# using here string to embedd firstrun
|
||||
$checkInstall = @'
|
||||
@echo off
|
||||
if exist "%HOMEDRIVE%\windows\cpu.txt" (
|
||||
echo %HOMEDRIVE%\windows\cpu.txt exists
|
||||
) else (
|
||||
echo %HOMEDRIVE%\windows\cpu.txt does not exist
|
||||
)
|
||||
if exist "%HOMEDRIVE%\windows\SerialNumber.txt" (
|
||||
echo %HOMEDRIVE%\windows\SerialNumber.txt exists
|
||||
) else (
|
||||
echo %HOMEDRIVE%\windows\SerialNumber.txt does not exist
|
||||
)
|
||||
if exist "%HOMEDRIVE%\unattend.xml" (
|
||||
echo %HOMEDRIVE%\unattend.xml exists
|
||||
) else (
|
||||
echo %HOMEDRIVE%\unattend.xml does not exist
|
||||
)
|
||||
if exist "%HOMEDRIVE%\Windows\Setup\Scripts\SetupComplete.cmd" (
|
||||
echo %HOMEDRIVE%\Windows\Setup\Scripts\SetupComplete.cmd exists
|
||||
) else (
|
||||
echo %HOMEDRIVE%\Windows\Setup\Scripts\SetupComplete.cmd does not exist
|
||||
)
|
||||
if exist "%HOMEDRIVE%\Windows\Panther\unattend.xml" (
|
||||
echo %HOMEDRIVE%\Windows\Panther\unattend.xml exists
|
||||
) else (
|
||||
echo %HOMEDRIVE%\Windows\Panther\unattend.xml does not exist
|
||||
)
|
||||
if exist "%HOMEDRIVE%\Windows\System32\Sysprep\unattend.xml" (
|
||||
echo %HOMEDRIVE%\Windows\System32\Sysprep\unattend.xml exists
|
||||
) else (
|
||||
echo %HOMEDRIVE%\Windows\System32\Sysprep\unattend.xml does not exist
|
||||
)
|
||||
if exist "%HOMEDRIVE%\Windows\FirstStartup.ps1" (
|
||||
echo %HOMEDRIVE%\Windows\FirstStartup.ps1 exists
|
||||
) else (
|
||||
echo %HOMEDRIVE%\Windows\FirstStartup.ps1 does not exist
|
||||
)
|
||||
if exist "%HOMEDRIVE%\Windows\winutil.ps1" (
|
||||
echo %HOMEDRIVE%\Windows\winutil.ps1 exists
|
||||
) else (
|
||||
echo %HOMEDRIVE%\Windows\winutil.ps1 does not exist
|
||||
)
|
||||
if exist "%HOMEDRIVE%\Windows\LogSpecialize.txt" (
|
||||
echo %HOMEDRIVE%\Windows\LogSpecialize.txt exists
|
||||
) else (
|
||||
echo %HOMEDRIVE%\Windows\LogSpecialize.txt does not exist
|
||||
)
|
||||
if exist "%HOMEDRIVE%\Windows\LogAuditUser.txt" (
|
||||
echo %HOMEDRIVE%\Windows\LogAuditUser.txt exists
|
||||
) else (
|
||||
echo %HOMEDRIVE%\Windows\LogAuditUser.txt does not exist
|
||||
)
|
||||
if exist "%HOMEDRIVE%\Windows\LogOobeSystem.txt" (
|
||||
echo %HOMEDRIVE%\Windows\LogOobeSystem.txt exists
|
||||
) else (
|
||||
echo %HOMEDRIVE%\Windows\LogOobeSystem.txt does not exist
|
||||
)
|
||||
if exist "%HOMEDRIVE%\windows\csup.txt" (
|
||||
echo %HOMEDRIVE%\windows\csup.txt exists
|
||||
) else (
|
||||
echo %HOMEDRIVE%\windows\csup.txt does not exist
|
||||
)
|
||||
if exist "%HOMEDRIVE%\windows\LogFirstRun.txt" (
|
||||
echo %HOMEDRIVE%\windows\LogFirstRun.txt exists
|
||||
) else (
|
||||
echo %HOMEDRIVE%\windows\LogFirstRun.txt does not exist
|
||||
)
|
||||
'@
|
||||
$checkInstall | Out-File -FilePath "$env:temp\checkinstall.cmd" -Force -Encoding Ascii
|
||||
}
|
91
functions/microwin/Microwin-NewFirstRun.ps1
Normal file
91
functions/microwin/Microwin-NewFirstRun.ps1
Normal file
@ -0,0 +1,91 @@
|
||||
function Microwin-NewFirstRun {
|
||||
|
||||
# using here string to embedd firstrun
|
||||
$firstRun = @'
|
||||
# Set the global error action preference to continue
|
||||
$ErrorActionPreference = "Continue"
|
||||
function Remove-RegistryValue {
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$RegistryPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$ValueName
|
||||
)
|
||||
|
||||
# Check if the registry path exists
|
||||
if (Test-Path -Path $RegistryPath) {
|
||||
$registryValue = Get-ItemProperty -Path $RegistryPath -Name $ValueName -ErrorAction SilentlyContinue
|
||||
|
||||
# Check if the registry value exists
|
||||
if ($registryValue) {
|
||||
# Remove the registry value
|
||||
Remove-ItemProperty -Path $RegistryPath -Name $ValueName -Force
|
||||
Write-Host "Registry value '$ValueName' removed from '$RegistryPath'."
|
||||
} else {
|
||||
Write-Host "Registry value '$ValueName' not found in '$RegistryPath'."
|
||||
}
|
||||
} else {
|
||||
Write-Host "Registry path '$RegistryPath' not found."
|
||||
}
|
||||
}
|
||||
|
||||
"FirstStartup has worked" | Out-File -FilePath "$env:HOMEDRIVE\windows\LogFirstRun.txt" -Append -NoClobber
|
||||
|
||||
$taskbarPath = "$env:AppData\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar"
|
||||
# Delete all files on the Taskbar
|
||||
Get-ChildItem -Path $taskbarPath -File | Remove-Item -Force
|
||||
Remove-RegistryValue -RegistryPath "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband" -ValueName "FavoritesRemovedChanges"
|
||||
Remove-RegistryValue -RegistryPath "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband" -ValueName "FavoritesChanges"
|
||||
Remove-RegistryValue -RegistryPath "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband" -ValueName "Favorites"
|
||||
|
||||
# Delete Edge Icon from the desktop
|
||||
$edgeShortcutFiles = Get-ChildItem -Path $desktopPath -Filter "*Edge*.lnk"
|
||||
# Check if Edge shortcuts exist on the desktop
|
||||
if ($edgeShortcutFiles) {
|
||||
foreach ($shortcutFile in $edgeShortcutFiles) {
|
||||
# Remove each Edge shortcut
|
||||
Remove-Item -Path $shortcutFile.FullName -Force
|
||||
Write-Host "Edge shortcut '$($shortcutFile.Name)' removed from the desktop."
|
||||
}
|
||||
}
|
||||
Remove-Item -Path "$env:USERPROFILE\Desktop\*.lnk"
|
||||
Remove-Item -Path "$env:HOMEDRIVE\Users\Default\Desktop\*.lnk"
|
||||
|
||||
try
|
||||
{
|
||||
if ((Get-WindowsOptionalFeature -Online | Where-Object { $_.State -eq 'Enabled' -and $_.FeatureName -like "Recall" }).Count -gt 0)
|
||||
{
|
||||
Disable-WindowsOptionalFeature -Online -FeatureName "Recall" -Remove
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
# Get BCD entries and set bootmgr timeout accordingly
|
||||
try
|
||||
{
|
||||
# Check if the number of occurrences of "path" is 2 - this fixes the Boot Manager screen issue (#2562)
|
||||
if ((bcdedit | Select-String "path").Count -eq 2)
|
||||
{
|
||||
# Set bootmgr timeout to 0
|
||||
bcdedit /set `{bootmgr`} timeout 0
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.Suggested" /f
|
||||
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.Suggested" /v Enabled /t REG_DWORD /d 0 /f
|
||||
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.StartupApp" /f
|
||||
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Windows.SystemToast.StartupApp" /v Enabled /t REG_DWORD /d 0 /f
|
||||
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Microsoft.SkyDrive.Desktop" /f
|
||||
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Notifications\Settings\Microsoft.SkyDrive.Desktop" /v Enabled /t REG_DWORD /d 0 /f
|
||||
|
||||
'@
|
||||
$firstRun | Out-File -FilePath "$env:temp\FirstStartup.ps1" -Force
|
||||
}
|
327
functions/microwin/Microwin-NewUnattend.ps1
Normal file
327
functions/microwin/Microwin-NewUnattend.ps1
Normal file
@ -0,0 +1,327 @@
|
||||
function Microwin-NewUnattend {
|
||||
|
||||
param (
|
||||
[Parameter(Mandatory, Position = 0)] [string]$userName,
|
||||
[Parameter(Position = 1)] [string]$userPassword
|
||||
)
|
||||
|
||||
$unattend = @'
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<unattend xmlns="urn:schemas-microsoft-com:unattend"
|
||||
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<#REPLACEME#>
|
||||
<settings pass="auditUser">
|
||||
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<RunSynchronous>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>1</Order>
|
||||
<CommandLine>CMD /C echo LAU GG>C:\Windows\LogAuditUser.txt</CommandLine>
|
||||
<Description>StartMenu</Description>
|
||||
</RunSynchronousCommand>
|
||||
</RunSynchronous>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="oobeSystem">
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<UserAccounts>
|
||||
<LocalAccounts>
|
||||
<LocalAccount wcm:action="add">
|
||||
<Name>USER-REPLACEME</Name>
|
||||
<Group>Administrators</Group>
|
||||
<Password>
|
||||
<Value>PW-REPLACEME</Value>
|
||||
<PlainText>PT-STATUS</PlainText>
|
||||
</Password>
|
||||
</LocalAccount>
|
||||
</LocalAccounts>
|
||||
</UserAccounts>
|
||||
<AutoLogon>
|
||||
<Username>USER-REPLACEME</Username>
|
||||
<Enabled>true</Enabled>
|
||||
<LogonCount>1</LogonCount>
|
||||
<Password>
|
||||
<Value>PW-REPLACEME</Value>
|
||||
<PlainText>PT-STATUS</PlainText>
|
||||
</Password>
|
||||
</AutoLogon>
|
||||
<OOBE>
|
||||
<HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
|
||||
<SkipUserOOBE>true</SkipUserOOBE>
|
||||
<SkipMachineOOBE>true</SkipMachineOOBE>
|
||||
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
|
||||
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
|
||||
<HideEULAPage>true</HideEULAPage>
|
||||
<ProtectYourPC>3</ProtectYourPC>
|
||||
</OOBE>
|
||||
<FirstLogonCommands>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>1</Order>
|
||||
<CommandLine>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AutoLogonCount /t REG_DWORD /d 0 /f</CommandLine>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>2</Order>
|
||||
<CommandLine>cmd.exe /c echo 23>c:\windows\csup.txt</CommandLine>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>3</Order>
|
||||
<CommandLine>CMD /C echo GG>C:\Windows\LogOobeSystem.txt</CommandLine>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>4</Order>
|
||||
<CommandLine>powershell -ExecutionPolicy Bypass -File c:\windows\FirstStartup.ps1</CommandLine>
|
||||
</SynchronousCommand>
|
||||
</FirstLogonCommands>
|
||||
</component>
|
||||
</settings>
|
||||
</unattend>
|
||||
'@
|
||||
$specPass = @'
|
||||
<settings pass="specialize">
|
||||
<component name="Microsoft-Windows-SQMApi" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<CEIPEnabled>0</CEIPEnabled>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<ConfigureChatAutoInstall>false</ConfigureChatAutoInstall>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||
<RunSynchronous>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>1</Order>
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE" /v BypassNRO /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>2</Order>
|
||||
<Path>reg.exe load "HKU\DefaultUser" "C:\Users\Default\NTUSER.DAT"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>3</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\Runonce" /v "UninstallCopilot" /t REG_SZ /d "powershell.exe -NoProfile -Command \"Get-AppxPackage -Name 'Microsoft.Windows.Ai.Copilot.Provider' | Remove-AppxPackage;\"" /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>4</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Policies\Microsoft\Windows\WindowsCopilot" /v TurnOffWindowsCopilot /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>5</Order>
|
||||
<Path>reg.exe unload "HKU\DefaultUser"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>6</Order>
|
||||
<Path>reg.exe delete "HKLM\SOFTWARE\Microsoft\WindowsUpdate\Orchestrator\UScheduler_Oobe\DevHomeUpdate" /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>7</Order>
|
||||
<Path>reg.exe load "HKU\DefaultUser" "C:\Users\Default\NTUSER.DAT"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>8</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Notepad" /v ShowStoreBanner /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>9</Order>
|
||||
<Path>reg.exe unload "HKU\DefaultUser"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>10</Order>
|
||||
<Path>cmd.exe /c "del "C:\Users\Default\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\OneDrive.lnk""</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>11</Order>
|
||||
<Path>cmd.exe /c "del "C:\Windows\System32\OneDriveSetup.exe""</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>12</Order>
|
||||
<Path>cmd.exe /c "del "C:\Windows\SysWOW64\OneDriveSetup.exe""</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>13</Order>
|
||||
<Path>reg.exe load "HKU\DefaultUser" "C:\Users\Default\NTUSER.DAT"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>14</Order>
|
||||
<Path>reg.exe delete "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\Run" /v OneDriveSetup /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>15</Order>
|
||||
<Path>reg.exe unload "HKU\DefaultUser"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>16</Order>
|
||||
<Path>reg.exe delete "HKLM\SOFTWARE\Microsoft\WindowsUpdate\Orchestrator\UScheduler_Oobe\OutlookUpdate" /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>17</Order>
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Communications" /v ConfigureChatAutoInstall /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>18</Order>
|
||||
<Path>powershell.exe -NoProfile -Command "$xml = [xml]::new(); $xml.Load('C:\Windows\Panther\unattend.xml'); $sb = [scriptblock]::Create( $xml.unattend.Extensions.ExtractScript ); Invoke-Command -ScriptBlock $sb -ArgumentList $xml;"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>19</Order>
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Microsoft\PolicyManager\current\device\Start" /v ConfigureStartPins /t REG_SZ /d "{ \"pinnedList\": [] }" /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>20</Order>
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Microsoft\PolicyManager\current\device\Start" /v ConfigureStartPins_ProviderSet /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>21</Order>
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Microsoft\PolicyManager\current\device\Start" /v ConfigureStartPins_WinningProvider /t REG_SZ /d B5292708-1619-419B-9923-E5D9F3925E71 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>22</Order>
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Microsoft\PolicyManager\providers\B5292708-1619-419B-9923-E5D9F3925E71\default\Device\Start" /v ConfigureStartPins /t REG_SZ /d "{ \"pinnedList\": [] }" /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>23</Order>
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Microsoft\PolicyManager\providers\B5292708-1619-419B-9923-E5D9F3925E71\default\Device\Start" /v ConfigureStartPins_LastWrite /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>24</Order>
|
||||
<Path>net.exe accounts /maxpwage:UNLIMITED</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>25</Order>
|
||||
<Path>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>26</Order>
|
||||
<Path>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Power" /v HiberbootEnabled /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>27</Order>
|
||||
<Path>reg.exe add "HKLM\SOFTWARE\Policies\Microsoft\Dsh" /v AllowNewsAndInterests /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>28</Order>
|
||||
<Path>reg.exe load "HKU\DefaultUser" "C:\Users\Default\NTUSER.DAT"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>29</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "ContentDeliveryAllowed" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>30</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "FeatureManagementEnabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>31</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "OEMPreInstalledAppsEnabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>32</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "PreInstalledAppsEnabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>33</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "PreInstalledAppsEverEnabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>34</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SilentInstalledAppsEnabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>35</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SoftLandingEnabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>36</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContentEnabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>37</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-310093Enabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>38</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338387Enabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>39</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338388Enabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>40</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338389Enabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>41</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-338393Enabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>42</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SubscribedContent-353698Enabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>43</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\ContentDeliveryManager" /v "SystemPaneSuggestionsEnabled" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>44</Order>
|
||||
<Path>reg.exe unload "HKU\DefaultUser"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>45</Order>
|
||||
<Path>reg.exe add "HKLM\Software\Policies\Microsoft\Windows\CloudContent" /v "DisableWindowsConsumerFeatures" /t REG_DWORD /d 0 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>46</Order>
|
||||
<Path>reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\BitLocker" /v "PreventDeviceEncryption" /t REG_DWORD /d 1 /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>47</Order>
|
||||
<Path>reg.exe load "HKU\DefaultUser" "C:\Users\Default\NTUSER.DAT"</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>48</Order>
|
||||
<Path>reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\Runonce" /v "ClassicContextMenu" /t REG_SZ /d "reg.exe add \"HKCU\Software\Classes\CLSID\{86ca1aa0-34aa-4e8b-a509-50c905bae2a2}\InprocServer32\" /ve /f" /f</Path>
|
||||
</RunSynchronousCommand>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>49</Order>
|
||||
<Path>reg.exe unload "HKU\DefaultUser"</Path>
|
||||
</RunSynchronousCommand>
|
||||
</RunSynchronous>
|
||||
</component>
|
||||
</settings>
|
||||
'@
|
||||
if ((Microwin-TestCompatibleImage $imgVersion $([System.Version]::new(10,0,22000,1))) -eq $false) {
|
||||
# Replace the placeholder text with an empty string to make it valid for Windows 10 Setup
|
||||
$unattend = $unattend.Replace("<#REPLACEME#>", "").Trim()
|
||||
} else {
|
||||
# Replace the placeholder text with the Specialize pass
|
||||
$unattend = $unattend.Replace("<#REPLACEME#>", $specPass).Trim()
|
||||
}
|
||||
|
||||
# User password in Base64. According to Microsoft, this is the way you can hide this sensitive information.
|
||||
# More information can be found here: https://learn.microsoft.com/en-us/windows-hardware/customize/desktop/wsim/hide-sensitive-data-in-an-answer-file
|
||||
# Yeah, I know this is not the best way to protect this kind of data, but we all know how Microsoft is - "the Apple of security" (in a sense, it takes them
|
||||
# an eternity to implement basic security features right. Just look at the NTLM and Kerberos situation!)
|
||||
|
||||
$b64pass = ""
|
||||
|
||||
# Replace default User and Password values with the provided parameters
|
||||
$unattend = $unattend.Replace("USER-REPLACEME", $userName).Trim()
|
||||
try {
|
||||
# I want to play it safe here - I don't want encoding mismatch problems like last time
|
||||
|
||||
# NOTE: "Password" needs to be appended to the password specified by the user. Otherwise, a parse error will occur when processing oobeSystem.
|
||||
# This will not be added to the actual password stored in the target system's SAM file - only the provided password
|
||||
$b64pass = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes("$($userPassword)Password"))
|
||||
} catch {
|
||||
$b64pass = ""
|
||||
}
|
||||
if ($b64pass -ne "") {
|
||||
# If we could encode the password with Base64, put it in the answer file and indicate that it's NOT in plain text
|
||||
$unattend = $unattend.Replace("PW-REPLACEME", $b64pass).Trim()
|
||||
$unattend = $unattend.Replace("PT-STATUS", "false").Trim()
|
||||
$b64pass = ""
|
||||
} else {
|
||||
$unattend = $unattend.Replace("PW-REPLACEME", $userPassword).Trim()
|
||||
$unattend = $unattend.Replace("PT-STATUS", "true").Trim()
|
||||
}
|
||||
|
||||
# Save unattended answer file with UTF-8 encoding
|
||||
$unattend | Out-File -FilePath "$env:temp\unattend.xml" -Force -Encoding utf8
|
||||
}
|
82
functions/microwin/Microwin-RemoveFeatures.ps1
Normal file
82
functions/microwin/Microwin-RemoveFeatures.ps1
Normal file
@ -0,0 +1,82 @@
|
||||
function Microwin-RemoveFeatures() {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Removes certain features from ISO image
|
||||
|
||||
.PARAMETER UseCmdlets
|
||||
Determines whether or not to use the DISM cmdlets for processing.
|
||||
- If true, DISM cmdlets will be used
|
||||
- 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
|
||||
the DISM conversion to cmdlets)
|
||||
|
||||
.EXAMPLE
|
||||
Microwin-RemoveFeatures -UseCmdlets $true
|
||||
#>
|
||||
param (
|
||||
[Parameter(Mandatory = $true, Position = 0)] [bool]$UseCmdlets
|
||||
)
|
||||
try {
|
||||
if ($UseCmdlets) {
|
||||
$featlist = (Get-WindowsOptionalFeature -Path "$scratchDir")
|
||||
|
||||
$featlist = $featlist | Where-Object {
|
||||
$_.FeatureName -NotLike "*Defender*" -AND
|
||||
$_.FeatureName -NotLike "*Printing*" -AND
|
||||
$_.FeatureName -NotLike "*TelnetClient*" -AND
|
||||
$_.FeatureName -NotLike "*PowerShell*" -AND
|
||||
$_.FeatureName -NotLike "*NetFx*" -AND
|
||||
$_.FeatureName -NotLike "*Media*" -AND
|
||||
$_.FeatureName -NotLike "*NFS*" -AND
|
||||
$_.FeatureName -NotLike "*SearchEngine*" -AND
|
||||
$_.FeatureName -NotLike "*RemoteDesktop*" -AND
|
||||
$_.State -ne "Disabled"
|
||||
}
|
||||
} else {
|
||||
$featList = dism /english /image="$scratchDir" /get-features | Select-String -Pattern "Feature Name : " -CaseSensitive -SimpleMatch
|
||||
if ($?) {
|
||||
$featList = $featList -split "Feature Name : " | Where-Object {$_}
|
||||
# Exclude the same items. Note: for now, this doesn't exclude those features that are disabled.
|
||||
# This will appear in the future
|
||||
$featList = $featList | Where-Object {
|
||||
$_ -NotLike "*Defender*" -AND
|
||||
$_ -NotLike "*Printing*" -AND
|
||||
$_ -NotLike "*TelnetClient*" -AND
|
||||
$_ -NotLike "*PowerShell*" -AND
|
||||
$_ -NotLike "*NetFx*" -AND
|
||||
$_ -NotLike "*Media*" -AND
|
||||
$_ -NotLike "*NFS*" -AND
|
||||
$_ -NotLike "*SearchEngine*" -AND
|
||||
$_ -NotLike "*RemoteDesktop*"
|
||||
}
|
||||
} else {
|
||||
Write-Host "Features could not be obtained with DISM. MicroWin processing will continue, but features will be skipped."
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if ($UseCmdlets) {
|
||||
foreach ($feature in $featList) {
|
||||
$status = "Removing feature $($feature.FeatureName)"
|
||||
Write-Progress -Activity "Removing features" -Status $status -PercentComplete ($counter++/$featlist.Count*100)
|
||||
Write-Debug "Removing feature $($feature.FeatureName)"
|
||||
Disable-WindowsOptionalFeature -Path "$scratchDir" -FeatureName $($feature.FeatureName) -Remove -ErrorAction SilentlyContinue -NoRestart
|
||||
}
|
||||
} else {
|
||||
foreach ($feature in $featList) {
|
||||
$status = "Removing feature $feature"
|
||||
Write-Progress -Activity "Removing features" -Status $status -PercentComplete ($counter++/$featlist.Count*100)
|
||||
Write-Debug "Removing feature $feature"
|
||||
dism /english /image="$scratchDir" /disable-feature /featurename=$feature /remove /quiet /norestart | Out-Null
|
||||
if ($? -eq $false) {
|
||||
Write-Host "Feature $feature could not be disabled."
|
||||
}
|
||||
}
|
||||
}
|
||||
Write-Progress -Activity "Removing features" -Status "Ready" -Completed
|
||||
Write-Host "You can re-enable the disabled features at any time, using either Windows Update or the SxS folder in <installation media>\Sources."
|
||||
} catch {
|
||||
Write-Host "Unable to get information about the features. A fallback will be used..."
|
||||
Write-Host "Error information: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
Microwin-RemoveFeatures -UseCmdlets $false
|
||||
}
|
||||
}
|
46
functions/microwin/Microwin-RemoveFileOrDirectory.ps1
Normal file
46
functions/microwin/Microwin-RemoveFileOrDirectory.ps1
Normal file
@ -0,0 +1,46 @@
|
||||
function Microwin-RemoveFileOrDirectory([string]$pathToDelete, [string]$mask = "", [switch]$Directory = $false) {
|
||||
if(([string]::IsNullOrEmpty($pathToDelete))) { return }
|
||||
if (-not (Test-Path -Path "$($pathToDelete)")) { return }
|
||||
|
||||
$yesNo = Get-LocalizedYesNo
|
||||
Write-Host "[INFO] In Your local takeown expects '$($yesNo[0])' as a Yes answer."
|
||||
|
||||
$itemsToDelete = [System.Collections.ArrayList]::new()
|
||||
|
||||
if ($mask -eq "") {
|
||||
Write-Debug "Adding $($pathToDelete) to array."
|
||||
[void]$itemsToDelete.Add($pathToDelete)
|
||||
} else {
|
||||
Write-Debug "Adding $($pathToDelete) to array and mask is $($mask)"
|
||||
if ($Directory) {
|
||||
$itemsToDelete = Get-ChildItem $pathToDelete -Include $mask -Recurse -Directory
|
||||
} else {
|
||||
$itemsToDelete = Get-ChildItem $pathToDelete -Include $mask -Recurse
|
||||
}
|
||||
}
|
||||
|
||||
foreach($itemToDelete in $itemsToDelete) {
|
||||
$status = "Deleting $($itemToDelete)"
|
||||
Write-Progress -Activity "Removing Items" -Status $status -PercentComplete ($counter++/$itemsToDelete.Count*100)
|
||||
|
||||
if (Test-Path -Path "$($itemToDelete)" -PathType Container) {
|
||||
$status = "Deleting directory: $($itemToDelete)"
|
||||
|
||||
takeown /r /d $yesNo[0] /a /f "$($itemToDelete)"
|
||||
icacls "$($itemToDelete)" /q /c /t /reset
|
||||
icacls $itemToDelete /setowner "*S-1-5-32-544"
|
||||
icacls $itemToDelete /grant "*S-1-5-32-544:(OI)(CI)F" /t /c /q
|
||||
Remove-Item -Force -Recurse "$($itemToDelete)"
|
||||
}
|
||||
elseif (Test-Path -Path "$($itemToDelete)" -PathType Leaf) {
|
||||
$status = "Deleting file: $($itemToDelete)"
|
||||
|
||||
takeown /a /f "$($itemToDelete)"
|
||||
icacls "$($itemToDelete)" /q /c /t /reset
|
||||
icacls "$($itemToDelete)" /setowner "*S-1-5-32-544"
|
||||
icacls "$($itemToDelete)" /grant "*S-1-5-32-544:(OI)(CI)F" /t /c /q
|
||||
Remove-Item -Force "$($itemToDelete)"
|
||||
}
|
||||
}
|
||||
Write-Progress -Activity "Removing Items" -Status "Ready" -Completed
|
||||
}
|
129
functions/microwin/Microwin-RemovePackages.ps1
Normal file
129
functions/microwin/Microwin-RemovePackages.ps1
Normal file
@ -0,0 +1,129 @@
|
||||
function Microwin-RemovePackages {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Removes certain packages from ISO image
|
||||
|
||||
.PARAMETER UseCmdlets
|
||||
Determines whether or not to use the DISM cmdlets for processing.
|
||||
- If true, DISM cmdlets will be used
|
||||
- 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
|
||||
the DISM conversion to cmdlets)
|
||||
|
||||
.EXAMPLE
|
||||
Microwin-RemovePackages -UseCmdlets $true
|
||||
#>
|
||||
param (
|
||||
[Parameter(Mandatory = $true, Position = 0)] [bool]$UseCmdlets
|
||||
)
|
||||
try {
|
||||
if ($useCmdlets) {
|
||||
$pkglist = (Get-WindowsPackage -Path "$scratchDir").PackageName
|
||||
|
||||
$pkglist = $pkglist | Where-Object {
|
||||
$_ -NotLike "*ApplicationModel*" -AND
|
||||
$_ -NotLike "*indows-Client-LanguagePack*" -AND
|
||||
$_ -NotLike "*LanguageFeatures-Basic*" -AND
|
||||
$_ -NotLike "*Package_for_ServicingStack*" -AND
|
||||
$_ -NotLike "*DotNet*" -AND
|
||||
$_ -NotLike "*Notepad*" -AND
|
||||
$_ -NotLike "*WMIC*" -AND
|
||||
$_ -NotLike "*Ethernet*" -AND
|
||||
$_ -NotLike "*Wifi*" -AND
|
||||
$_ -NotLike "*FodMetadata*" -AND
|
||||
$_ -NotLike "*Foundation*" -AND
|
||||
$_ -NotLike "*LanguageFeatures*" -AND
|
||||
$_ -NotLike "*VBSCRIPT*" -AND
|
||||
$_ -NotLike "*License*" -AND
|
||||
$_ -NotLike "*Hello-Face*" -AND
|
||||
$_ -NotLike "*ISE*" -AND
|
||||
$_ -NotLike "*OpenSSH*"
|
||||
}
|
||||
} else {
|
||||
$pkgList = dism /english /image="$scratchDir" /get-packages | Select-String -Pattern "Package Identity : " -CaseSensitive -SimpleMatch
|
||||
if ($?) {
|
||||
$pkgList = $pkgList -split "Package Identity : " | Where-Object {$_}
|
||||
# Exclude the same items.
|
||||
$pkgList = $pkgList | Where-Object {
|
||||
$_ -NotLike "*ApplicationModel*" -AND
|
||||
$_ -NotLike "*indows-Client-LanguagePack*" -AND
|
||||
$_ -NotLike "*LanguageFeatures-Basic*" -AND
|
||||
$_ -NotLike "*Package_for_ServicingStack*" -AND
|
||||
$_ -NotLike "*DotNet*" -AND
|
||||
$_ -NotLike "*Notepad*" -AND
|
||||
$_ -NotLike "*WMIC*" -AND
|
||||
$_ -NotLike "*Ethernet*" -AND
|
||||
$_ -NotLike "*Wifi*" -AND
|
||||
$_ -NotLike "*FodMetadata*" -AND
|
||||
$_ -NotLike "*Foundation*" -AND
|
||||
$_ -NotLike "*LanguageFeatures*" -AND
|
||||
$_ -NotLike "*VBSCRIPT*" -AND
|
||||
$_ -NotLike "*License*" -AND
|
||||
$_ -NotLike "*Hello-Face*" -AND
|
||||
$_ -NotLike "*ISE*" -AND
|
||||
$_ -NotLike "*OpenSSH*"
|
||||
}
|
||||
} else {
|
||||
Write-Host "Packages could not be obtained with DISM. MicroWin processing will continue, but packages will be skipped."
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if ($UseCmdlets) {
|
||||
$failedCount = 0
|
||||
|
||||
$erroredPackages = [System.Collections.Generic.List[ErroredPackage]]::new()
|
||||
|
||||
foreach ($pkg in $pkglist) {
|
||||
try {
|
||||
$status = "Removing $pkg"
|
||||
Write-Progress -Activity "Removing Packages" -Status $status -PercentComplete ($counter++/$pkglist.Count*100)
|
||||
Remove-WindowsPackage -Path "$scratchDir" -PackageName $pkg -NoRestart -ErrorAction SilentlyContinue
|
||||
} catch {
|
||||
# This can happen if the package that is being removed is a permanent one
|
||||
$erroredPackages.Add([ErroredPackage]::new($pkg, $_.Exception.Message))
|
||||
$failedCount += 1
|
||||
continue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($package in $pkgList) {
|
||||
$status = "Removing package $package"
|
||||
Write-Progress -Activity "Removing Packages" -Status $status -PercentComplete ($counter++/$pkglist.Count*100)
|
||||
Write-Debug "Removing package $package"
|
||||
dism /english /image="$scratchDir" /remove-package /packagename=$package /quiet /norestart | Out-Null
|
||||
if ($? -eq $false) {
|
||||
Write-Host "Package $package could not be removed."
|
||||
}
|
||||
}
|
||||
}
|
||||
Write-Progress -Activity "Removing Packages" -Status "Ready" -Completed
|
||||
if ($UseCmdlets -and $failedCount -gt 0)
|
||||
{
|
||||
Write-Host "$failedCount package(s) could not be removed. Your image will still work fine, however. Below is information on what packages failed to be removed and why."
|
||||
if ($erroredPackages.Count -gt 0)
|
||||
{
|
||||
$erroredPackages = $erroredPackages | Sort-Object -Property ErrorMessage
|
||||
|
||||
$previousErroredPackage = $erroredPackages[0]
|
||||
$counter = 0
|
||||
Write-Host ""
|
||||
Write-Host "- $($previousErroredPackage.ErrorMessage)"
|
||||
foreach ($erroredPackage in $erroredPackages) {
|
||||
if ($erroredPackage.ErrorMessage -ne $previousErroredPackage.ErrorMessage) {
|
||||
Write-Host ""
|
||||
$counter = 0
|
||||
Write-Host "- $($erroredPackage.ErrorMessage)"
|
||||
}
|
||||
$counter += 1
|
||||
Write-Host " $counter) $($erroredPackage.PackageName)"
|
||||
$previousErroredPackage = $erroredPackage
|
||||
}
|
||||
Write-Host ""
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Unable to get information about the packages. A fallback will be used..."
|
||||
Write-Host "Error information: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
Microwin-RemovePackages -UseCmdlets $false
|
||||
}
|
||||
}
|
96
functions/microwin/Microwin-RemoveProvisionedPackages.ps1
Normal file
96
functions/microwin/Microwin-RemoveProvisionedPackages.ps1
Normal file
@ -0,0 +1,96 @@
|
||||
function Microwin-RemoveProvisionedPackages() {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Removes AppX packages from a Windows image during MicroWin processing
|
||||
|
||||
.PARAMETER UseCmdlets
|
||||
Determines whether or not to use the DISM cmdlets for processing.
|
||||
- If true, DISM cmdlets will be used
|
||||
- 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
|
||||
the DISM conversion to cmdlets)
|
||||
|
||||
.EXAMPLE
|
||||
Microwin-RemoveProvisionedPackages
|
||||
#>
|
||||
param (
|
||||
[Parameter(Mandatory = $true, Position = 0)] [bool]$UseCmdlets
|
||||
)
|
||||
try
|
||||
{
|
||||
if ($UseCmdlets) {
|
||||
$appxProvisionedPackages = Get-AppxProvisionedPackage -Path "$($scratchDir)" | Where-Object {
|
||||
$_.PackageName -NotLike "*AppInstaller*" -AND
|
||||
$_.PackageName -NotLike "*Store*" -and
|
||||
$_.PackageName -NotLike "*Notepad*" -and
|
||||
$_.PackageName -NotLike "*Printing*" -and
|
||||
$_.PackageName -NotLike "*YourPhone*" -and
|
||||
$_.PackageName -NotLike "*Xbox*" -and
|
||||
$_.PackageName -NotLike "*WindowsTerminal*" -and
|
||||
$_.PackageName -NotLike "*Calculator*" -and
|
||||
$_.PackageName -NotLike "*Photos*" -and
|
||||
$_.PackageName -NotLike "*VCLibs*" -and
|
||||
$_.PackageName -NotLike "*Paint*" -and
|
||||
$_.PackageName -NotLike "*Gaming*" -and
|
||||
$_.PackageName -NotLike "*Extension*" -and
|
||||
$_.PackageName -NotLike "*SecHealthUI*" -and
|
||||
$_.PackageName -NotLike "*ScreenSketch*"
|
||||
}
|
||||
} else {
|
||||
$appxProvisionedPackages = dism /english /image="$scratchDir" /get-provisionedappxpackages | Select-String -Pattern "PackageName : " -CaseSensitive -SimpleMatch
|
||||
if ($?) {
|
||||
$appxProvisionedPackages = $appxProvisionedPackages -split "PackageName : " | Where-Object {$_}
|
||||
# Exclude the same items.
|
||||
$appxProvisionedPackages = $appxProvisionedPackages | Where-Object {
|
||||
$_ -NotLike "*AppInstaller*" -AND
|
||||
$_ -NotLike "*Store*" -and
|
||||
$_ -NotLike "*Notepad*" -and
|
||||
$_ -NotLike "*Printing*" -and
|
||||
$_ -NotLike "*YourPhone*" -and
|
||||
$_ -NotLike "*Xbox*" -and
|
||||
$_ -NotLike "*WindowsTerminal*" -and
|
||||
$_ -NotLike "*Calculator*" -and
|
||||
$_ -NotLike "*Photos*" -and
|
||||
$_ -NotLike "*VCLibs*" -and
|
||||
$_ -NotLike "*Paint*" -and
|
||||
$_ -NotLike "*Gaming*" -and
|
||||
$_ -NotLike "*Extension*" -and
|
||||
$_ -NotLike "*SecHealthUI*" -and
|
||||
$_ -NotLike "*ScreenSketch*"
|
||||
}
|
||||
} else {
|
||||
Write-Host "AppX packages could not be obtained with DISM. MicroWin processing will continue, but AppX packages will be skipped."
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
$counter = 0
|
||||
if ($UseCmdlets) {
|
||||
foreach ($appx in $appxProvisionedPackages) {
|
||||
$status = "Removing Provisioned $($appx.PackageName)"
|
||||
Write-Progress -Activity "Removing Provisioned Apps" -Status $status -PercentComplete ($counter++/$appxProvisionedPackages.Count*100)
|
||||
try {
|
||||
Remove-AppxProvisionedPackage -Path "$scratchDir" -PackageName $appx.PackageName -ErrorAction SilentlyContinue
|
||||
} catch {
|
||||
Write-Host "Application $($appx.PackageName) could not be removed"
|
||||
continue
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach ($appx in $appxProvisionedPackages) {
|
||||
$status = "Removing Provisioned $appx"
|
||||
Write-Progress -Activity "Removing Provisioned Apps" -Status $status -PercentComplete ($counter++/$appxProvisionedPackages.Count*100)
|
||||
dism /english /image="$scratchDir" /remove-provisionedappxpackage /packagename=$appx /quiet /norestart | Out-Null
|
||||
if ($? -eq $false) {
|
||||
Write-Host "AppX package $appx could not be removed."
|
||||
}
|
||||
}
|
||||
}
|
||||
Write-Progress -Activity "Removing Provisioned Apps" -Status "Ready" -Completed
|
||||
}
|
||||
catch
|
||||
{
|
||||
Write-Host "Unable to get information about the AppX packages. A fallback will be used..."
|
||||
Write-Host "Error information: $($_.Exception.Message)" -ForegroundColor Yellow
|
||||
Microwin-RemoveProvisionedPackages -UseCmdlets $false
|
||||
}
|
||||
}
|
26
functions/microwin/Microwin-TestCompatibleImage.ps1
Normal file
26
functions/microwin/Microwin-TestCompatibleImage.ps1
Normal file
@ -0,0 +1,26 @@
|
||||
function Microwin-TestCompatibleImage() {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Checks the version of a Windows image and determines whether or not it is compatible with a specific feature depending on a desired version
|
||||
|
||||
.PARAMETER Name
|
||||
imgVersion - The version of the Windows image
|
||||
desiredVersion - The version to compare the image version with
|
||||
#>
|
||||
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory, position=0)]
|
||||
[string]$imgVersion,
|
||||
|
||||
[Parameter(Mandatory, position=1)]
|
||||
[Version]$desiredVersion
|
||||
)
|
||||
|
||||
try {
|
||||
$version = [Version]$imgVersion
|
||||
return $version -ge $desiredVersion
|
||||
} catch {
|
||||
return $False
|
||||
}
|
||||
}
|
28
functions/microwin/Toggle-MicrowinPanel.ps1
Normal file
28
functions/microwin/Toggle-MicrowinPanel.ps1
Normal file
@ -0,0 +1,28 @@
|
||||
function Toggle-MicrowinPanel {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Toggles the visibility of the Microwin options and ISO panels in the GUI.
|
||||
.DESCRIPTION
|
||||
This function toggles the visibility of the Microwin options and ISO panels in the GUI.
|
||||
.PARAMETER MicrowinOptionsPanel
|
||||
The panel containing Microwin options.
|
||||
.PARAMETER MicrowinISOPanel
|
||||
The panel containing the Microwin ISO options.
|
||||
.EXAMPLE
|
||||
Toggle-MicrowinPanel 1
|
||||
#>
|
||||
param (
|
||||
[Parameter(Mandatory = $true, Position = 0)]
|
||||
[ValidateSet(1, 2)]
|
||||
[int]$PanelNumber
|
||||
)
|
||||
|
||||
if ($PanelNumber -eq 1) {
|
||||
$sync.MicrowinISOPanel.Visibility = 'Visible'
|
||||
$sync.MicrowinOptionsPanel.Visibility = 'Collapsed'
|
||||
|
||||
} elseif ($PanelNumber -eq 2) {
|
||||
$sync.MicrowinOptionsPanel.Visibility = 'Visible'
|
||||
$sync.MicrowinISOPanel.Visibility = 'Collapsed'
|
||||
}
|
||||
}
|
50
functions/private/Add-SelectedAppsMenuItem.ps1
Normal file
50
functions/private/Add-SelectedAppsMenuItem.ps1
Normal file
@ -0,0 +1,50 @@
|
||||
function Add-SelectedAppsMenuItem {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This is a helper function that generates and adds the Menu Items to the Selected Apps Popup.
|
||||
|
||||
.Parameter name
|
||||
The actual Name of an App like "Chrome" or "Brave"
|
||||
This name is contained in the "Content" property inside the applications.json
|
||||
.PARAMETER key
|
||||
The key which identifies an app object in applications.json
|
||||
For Chrome this would be "WPFInstallchrome" because "WPFInstall" is prepended automatically for each key in applications.json
|
||||
#>
|
||||
|
||||
param ([string]$name, [string]$key)
|
||||
|
||||
$selectedAppGrid = New-Object Windows.Controls.Grid
|
||||
|
||||
$selectedAppGrid.ColumnDefinitions.Add((New-Object System.Windows.Controls.ColumnDefinition -Property @{Width = "*"}))
|
||||
$selectedAppGrid.ColumnDefinitions.Add((New-Object System.Windows.Controls.ColumnDefinition -Property @{Width = "30"}))
|
||||
|
||||
# Sets the name to the Content as well as the Tooltip, because the parent Popup Border has a fixed width and text could "overflow".
|
||||
# With the tooltip, you can still read the whole entry on hover
|
||||
$selectedAppLabel = New-Object Windows.Controls.Label
|
||||
$selectedAppLabel.Content = $name
|
||||
$selectedAppLabel.ToolTip = $name
|
||||
$selectedAppLabel.HorizontalAlignment = "Left"
|
||||
$selectedAppLabel.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor")
|
||||
[System.Windows.Controls.Grid]::SetColumn($selectedAppLabel, 0)
|
||||
$selectedAppGrid.Children.Add($selectedAppLabel)
|
||||
|
||||
$selectedAppRemoveButton = New-Object Windows.Controls.Button
|
||||
$selectedAppRemoveButton.FontFamily = "Segoe MDL2 Assets"
|
||||
$selectedAppRemoveButton.Content = [string]([char]0xE711)
|
||||
$selectedAppRemoveButton.HorizontalAlignment = "Center"
|
||||
$selectedAppRemoveButton.Tag = $key
|
||||
$selectedAppRemoveButton.ToolTip = "Remove the App from Selection"
|
||||
$selectedAppRemoveButton.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor")
|
||||
$selectedAppRemoveButton.SetResourceReference([Windows.Controls.Control]::StyleProperty, "HoverButtonStyle")
|
||||
|
||||
# Highlight the Remove icon on Hover
|
||||
$selectedAppRemoveButton.Add_MouseEnter({ $this.Foreground = "Red" })
|
||||
$selectedAppRemoveButton.Add_MouseLeave({ $this.SetResourceReference([Windows.Controls.Control]::ForegroundProperty, "MainForegroundColor") })
|
||||
$selectedAppRemoveButton.Add_Click({
|
||||
$sync.($this.Tag).isChecked = $false # On click of the remove button, we only have to uncheck the corresponding checkbox. This will kick of all neccessary changes to update the UI
|
||||
})
|
||||
[System.Windows.Controls.Grid]::SetColumn($selectedAppRemoveButton, 1)
|
||||
$selectedAppGrid.Children.Add($selectedAppRemoveButton)
|
||||
# Add new Element to Popup
|
||||
$sync.selectedAppsstackPanel.Children.Add($selectedAppGrid)
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
function ConvertTo-Icon {
|
||||
<#
|
||||
|
||||
.DESCRIPTION
|
||||
This function will convert PNG to ICO file
|
||||
|
||||
.EXAMPLE
|
||||
ConvertTo-Icon -bitmapPath "$env:TEMP\cttlogo.png" -iconPath $iconPath
|
||||
#>
|
||||
param( [Parameter(Mandatory=$true)]
|
||||
$bitmapPath,
|
||||
$iconPath = "$env:temp\newicon.ico"
|
||||
)
|
||||
|
||||
Add-Type -AssemblyName System.Drawing
|
||||
|
||||
if (Test-Path $bitmapPath) {
|
||||
$b = [System.Drawing.Bitmap]::FromFile($bitmapPath)
|
||||
$icon = [System.Drawing.Icon]::FromHandle($b.GetHicon())
|
||||
$file = New-Object System.IO.FileStream($iconPath, 'OpenOrCreate')
|
||||
$icon.Save($file)
|
||||
$file.Close()
|
||||
$icon.Dispose()
|
||||
#explorer "/SELECT,$iconpath"
|
||||
}
|
||||
else { Write-Warning "$BitmapPath does not exist" }
|
||||
}
|
@ -1,48 +1,53 @@
|
||||
function Copy-Files {
|
||||
<#
|
||||
|
||||
|
||||
.DESCRIPTION
|
||||
This function will make all modifications to the registry
|
||||
|
||||
Copies the contents of a given ISO file to a given destination
|
||||
.PARAMETER Path
|
||||
The source of the files to copy
|
||||
.PARAMETER Destination
|
||||
The destination to copy the files to
|
||||
.PARAMETER Recurse
|
||||
Determines whether or not to copy all files of the ISO file, including those in subdirectories
|
||||
.PARAMETER Force
|
||||
Determines whether or not to overwrite existing files
|
||||
.EXAMPLE
|
||||
Copy-Files "D:" "C:\ISOFile" -Recurse -Force
|
||||
|
||||
Set-WinUtilRegistry -Name "PublishUserActivities" -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\System" -Type "DWord" -Value "0"
|
||||
|
||||
#>
|
||||
#>
|
||||
param (
|
||||
[string] $Path,
|
||||
[string] $Destination,
|
||||
[switch] $Recurse = $false,
|
||||
[switch] $Force = $false
|
||||
[string]$Path,
|
||||
[string]$Destination,
|
||||
[switch]$Recurse = $false,
|
||||
[switch]$Force = $false
|
||||
)
|
||||
|
||||
try {
|
||||
try {
|
||||
|
||||
$files = Get-ChildItem -Path $path -Recurse:$recurse
|
||||
Write-Host "Copy $($files.Count)(s) from $path to $destination"
|
||||
$files = Get-ChildItem -Path $path -Recurse:$recurse
|
||||
Write-Host "Copy $($files.Count) file(s) from $path to $destination"
|
||||
|
||||
foreach($file in $files)
|
||||
{
|
||||
$status = "Copy files {0} on {1}: {2}" -f $counter, $files.Count, $file.Name
|
||||
Write-Progress -Activity "Copy Windows files" -Status $status -PercentComplete ($counter++/$files.count*100)
|
||||
foreach ($file in $files) {
|
||||
$status = "Copying file {0} of {1}: {2}" -f $counter, $files.Count, $file.Name
|
||||
Write-Progress -Activity "Copy disc image files" -Status $status -PercentComplete ($counter++/$files.count*100)
|
||||
$restpath = $file.FullName -Replace $path, ''
|
||||
|
||||
if($file.PSIsContainer -eq $true)
|
||||
{
|
||||
if ($file.PSIsContainer -eq $true) {
|
||||
Write-Debug "Creating $($destination + $restpath)"
|
||||
New-Item ($destination+$restpath) -Force:$force -Type Directory -ErrorAction SilentlyContinue
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
Write-Debug "Copy from $($file.FullName) to $($destination+$restpath)"
|
||||
Copy-Item $file.FullName ($destination+$restpath) -ErrorAction SilentlyContinue -Force:$force
|
||||
Copy-Item $file.FullName ($destination+$restpath) -ErrorAction SilentlyContinue -Force:$force
|
||||
Set-ItemProperty -Path ($destination+$restpath) -Name IsReadOnly -Value $false
|
||||
}
|
||||
}
|
||||
}
|
||||
Write-Progress -Activity "Copy Windows files" -Status "Ready" -Completed
|
||||
Write-Progress -Activity "Copy disc image files" -Status "Ready" -Completed
|
||||
} catch {
|
||||
Write-Host "Unable to Copy all the files due to an unhandled exception" -ForegroundColor Yellow
|
||||
Write-Host "Error information: $($_.Exception.Message)`n" -ForegroundColor Yellow
|
||||
Write-Host "Additional information:" -ForegroundColor Yellow
|
||||
Write-Host $PSItem.Exception.StackTrace
|
||||
# Write possible suggestions
|
||||
Write-Host "`nIf you are using an antivirus, try configuring exclusions"
|
||||
}
|
||||
Catch{
|
||||
Write-Warning "Unable to Copy all the files due to unhandled exception"
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
}
|
||||
}
|
||||
}
|
||||
|
49
functions/private/Find-AppsByNameOrDescription.ps1
Normal file
49
functions/private/Find-AppsByNameOrDescription.ps1
Normal file
@ -0,0 +1,49 @@
|
||||
function Find-AppsByNameOrDescription {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Searches through the Apps on the Install Tab and hides all entries that do not match the string
|
||||
|
||||
.PARAMETER SearchString
|
||||
The string to be searched for
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$SearchString = ""
|
||||
)
|
||||
# Reset the visibility if the search string is empty or the search is cleared
|
||||
if ([string]::IsNullOrWhiteSpace($SearchString)) {
|
||||
$sync.ItemsControl.Items | ForEach-Object {
|
||||
$_.Visibility = [Windows.Visibility]::Visible
|
||||
$_.Children | ForEach-Object {
|
||||
if ($null -ne $_) {
|
||||
$_.Visibility = [Windows.Visibility]::Visible
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
$sync.ItemsControl.Items | ForEach-Object {
|
||||
# Ensure ToggleButtons remain visible
|
||||
if ($_.Tag -like "CategoryToggleButton") {
|
||||
$_.Visibility = [Windows.Visibility]::Visible
|
||||
return
|
||||
}
|
||||
# Hide all CategoryWrapPanel and ToggleButton
|
||||
$_.Visibility = [Windows.Visibility]::Collapsed
|
||||
if ($_.Tag -like "CategoryWrapPanel_*") {
|
||||
# Search for Apps that match the search string
|
||||
$_.Children | Foreach-Object {
|
||||
$appEntry = $sync.configs.applicationsHashtable.$($_.Tag)
|
||||
if ($appEntry.Content -like "*$SearchString*" -or $appEntry.Description -like "*$SearchString*") {
|
||||
# Show the App and the parent CategoryWrapPanel if the string is found
|
||||
$_.Visibility = [Windows.Visibility]::Visible
|
||||
$_.parent.Visibility = [Windows.Visibility]::Visible
|
||||
}
|
||||
else {
|
||||
$_.Visibility = [Windows.Visibility]::Collapsed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
100
functions/private/Find-TweaksByNameOrDescription.ps1
Normal file
100
functions/private/Find-TweaksByNameOrDescription.ps1
Normal file
@ -0,0 +1,100 @@
|
||||
function Find-TweaksByNameOrDescription {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Searches through the Tweaks on the Tweaks Tab and hides all entries that do not match the search string
|
||||
|
||||
.PARAMETER SearchString
|
||||
The string to be searched for
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$SearchString = ""
|
||||
)
|
||||
|
||||
# Reset the visibility if the search string is empty or the search is cleared
|
||||
if ([string]::IsNullOrWhiteSpace($SearchString)) {
|
||||
# Show all categories
|
||||
$tweakspanel = $sync.Form.FindName("tweakspanel")
|
||||
$tweakspanel.Children | ForEach-Object {
|
||||
$_.Visibility = [Windows.Visibility]::Visible
|
||||
|
||||
# Foreach category section, show all items
|
||||
if ($_ -is [Windows.Controls.Border]) {
|
||||
$_.Visibility = [Windows.Visibility]::Visible
|
||||
|
||||
# Find ItemsControl
|
||||
$dockPanel = $_.Child
|
||||
if ($dockPanel -is [Windows.Controls.DockPanel]) {
|
||||
$itemsControl = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] }
|
||||
if ($itemsControl) {
|
||||
# Show items in the category
|
||||
foreach ($item in $itemsControl.Items) {
|
||||
if ($item -is [Windows.Controls.Label]) {
|
||||
$item.Visibility = [Windows.Visibility]::Visible
|
||||
} elseif ($item -is [Windows.Controls.DockPanel] -or
|
||||
$item -is [Windows.Controls.StackPanel]) {
|
||||
$item.Visibility = [Windows.Visibility]::Visible
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
# Search for matching tweaks when search string is not null
|
||||
$tweakspanel = $sync.Form.FindName("tweakspanel")
|
||||
|
||||
$tweakspanel.Children | ForEach-Object {
|
||||
$categoryBorder = $_
|
||||
$categoryVisible = $false
|
||||
|
||||
if ($_ -is [Windows.Controls.Border]) {
|
||||
# Find the ItemsControl
|
||||
$dockPanel = $_.Child
|
||||
if ($dockPanel -is [Windows.Controls.DockPanel]) {
|
||||
$itemsControl = $dockPanel.Children | Where-Object { $_ -is [Windows.Controls.ItemsControl] }
|
||||
if ($itemsControl) {
|
||||
$categoryLabel = $null
|
||||
|
||||
# Process all items in the ItemsControl
|
||||
for ($i = 0; $i -lt $itemsControl.Items.Count; $i++) {
|
||||
$item = $itemsControl.Items[$i]
|
||||
|
||||
if ($item -is [Windows.Controls.Label]) {
|
||||
$categoryLabel = $item
|
||||
$item.Visibility = [Windows.Visibility]::Collapsed
|
||||
} elseif ($item -is [Windows.Controls.DockPanel]) {
|
||||
$checkbox = $item.Children | Where-Object { $_ -is [Windows.Controls.CheckBox] } | Select-Object -First 1
|
||||
$label = $item.Children | Where-Object { $_ -is [Windows.Controls.Label] } | Select-Object -First 1
|
||||
|
||||
if ($label -and ($label.Content -like "*$SearchString*" -or $label.ToolTip -like "*$SearchString*")) {
|
||||
$item.Visibility = [Windows.Visibility]::Visible
|
||||
if ($categoryLabel) { $categoryLabel.Visibility = [Windows.Visibility]::Visible }
|
||||
$categoryVisible = $true
|
||||
} else {
|
||||
$item.Visibility = [Windows.Visibility]::Collapsed
|
||||
}
|
||||
} elseif ($item -is [Windows.Controls.StackPanel]) {
|
||||
# StackPanel which contain checkboxes or other elements
|
||||
$checkbox = $item.Children | Where-Object { $_ -is [Windows.Controls.CheckBox] } | Select-Object -First 1
|
||||
|
||||
if ($checkbox -and ($checkbox.Content -like "*$SearchString*" -or $checkbox.ToolTip -like "*$SearchString*")) {
|
||||
$item.Visibility = [Windows.Visibility]::Visible
|
||||
if ($categoryLabel) { $categoryLabel.Visibility = [Windows.Visibility]::Visible }
|
||||
$categoryVisible = $true
|
||||
} else {
|
||||
$item.Visibility = [Windows.Visibility]::Collapsed
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Set the visibility based on if any item matched
|
||||
$categoryBorder.Visibility = if ($categoryVisible) { [Windows.Visibility]::Visible } else { [Windows.Visibility]::Collapsed }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +1,17 @@
|
||||
function Get-LocalizedYesNo {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This function runs choice.exe and captures its output to extract yes no in a localized Windows
|
||||
|
||||
This function runs choice.exe and captures its output to extract yes no in a localized Windows
|
||||
|
||||
.DESCRIPTION
|
||||
The function retrieves the output of the command 'cmd /c "choice <nul 2>nul"' and converts the default output for Yes and No
|
||||
in the localized format, such as "Yes=<first character>, No=<second character>".
|
||||
|
||||
|
||||
.EXAMPLE
|
||||
$yesNoArray = Get-LocalizedYesNo
|
||||
Write-Host "Yes=$($yesNoArray[0]), No=$($yesNoArray[1])"
|
||||
#>
|
||||
|
||||
|
||||
# Run choice and capture its options as output
|
||||
# The output shows the options for Yes and No as "[Y,N]?" in the (partitially) localized format.
|
||||
# eg. English: [Y,N]?
|
||||
@ -21,7 +21,7 @@ function Get-LocalizedYesNo {
|
||||
# Spanish: [S,N]?
|
||||
# Italian: [S,N]?
|
||||
# Russian: [Y,N]?
|
||||
|
||||
|
||||
$line = cmd /c "choice <nul 2>nul"
|
||||
$charactersArray = @()
|
||||
$regexPattern = '([a-zA-Z])'
|
||||
@ -30,4 +30,5 @@ function Get-LocalizedYesNo {
|
||||
Write-Debug "According to takeown.exe local Yes is $charactersArray[0]"
|
||||
# Return the array of characters
|
||||
return $charactersArray
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,131 +0,0 @@
|
||||
function Get-TabXaml {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Generates XAML for a tab in the WinUtil GUI
|
||||
This function is used to generate the XAML for the applications tab in the WinUtil GUI
|
||||
It takes the tabname and the number of columns to display the applications in as input and returns the XAML for the tab as output
|
||||
.PARAMETER tabname
|
||||
The name of the tab to generate XAML for
|
||||
.PARAMETER columncount
|
||||
The number of columns to display the applications in
|
||||
.OUTPUTS
|
||||
The XAML for the tab
|
||||
.EXAMPLE
|
||||
Get-TabXaml "applications" 3
|
||||
#>
|
||||
|
||||
|
||||
param( [Parameter(Mandatory=$true)]
|
||||
$tabname,
|
||||
$columncount = 0
|
||||
)
|
||||
$organizedData = @{}
|
||||
# Iterate through JSON data and organize by panel and category
|
||||
foreach ($appName in $sync.configs.$tabname.PSObject.Properties.Name) {
|
||||
$appInfo = $sync.configs.$tabname.$appName
|
||||
|
||||
# Create an object for the application
|
||||
$appObject = [PSCustomObject]@{
|
||||
Name = $appName
|
||||
Category = $appInfo.Category
|
||||
Content = $appInfo.Content
|
||||
Choco = $appInfo.choco
|
||||
Winget = $appInfo.winget
|
||||
Panel = if ($columncount -gt 0 ) { "0" } else {$appInfo.panel}
|
||||
Link = $appInfo.link
|
||||
Description = $appInfo.description
|
||||
# Type is (Checkbox,Toggle,Button,Combobox ) (Default is Checkbox)
|
||||
Type = $appInfo.type
|
||||
ComboItems = $appInfo.ComboItems
|
||||
# Checked is the property to set startup checked status of checkbox (Default is false)
|
||||
Checked = $appInfo.Checked
|
||||
}
|
||||
|
||||
if (-not $organizedData.ContainsKey($appObject.panel)) {
|
||||
$organizedData[$appObject.panel] = @{}
|
||||
}
|
||||
|
||||
if (-not $organizedData[$appObject.panel].ContainsKey($appObject.Category)) {
|
||||
$organizedData[$appObject.panel][$appObject.Category] = @{}
|
||||
}
|
||||
|
||||
# Store application data in a sub-array under the category
|
||||
# Add Order property to keep the original order of tweaks and features
|
||||
$organizedData[$appObject.panel][$appInfo.Category]["$($appInfo.order)$appName"] = $appObject
|
||||
}
|
||||
$panelcount=0
|
||||
$paneltotal = $organizedData.Keys.Count
|
||||
if ($columncount -gt 0) {
|
||||
$appcount = $sync.configs.$tabname.PSObject.Properties.Name.count + $organizedData["0"].Keys.count
|
||||
$maxcount = [Math]::Round( $appcount / $columncount + 0.5)
|
||||
$paneltotal = $columncount
|
||||
}
|
||||
# add ColumnDefinitions to evenly draw colums
|
||||
$blockXml="<Grid.ColumnDefinitions>`n"+("<ColumnDefinition Width=""*""/>`n"*($paneltotal))+"</Grid.ColumnDefinitions>`n"
|
||||
# Iterate through organizedData by panel, category, and application
|
||||
$count = 0
|
||||
foreach ($panel in ($organizedData.Keys | Sort-Object)) {
|
||||
$blockXml += "<Border Grid.Row=""1"" Grid.Column=""$panelcount"">`n<StackPanel Background=""{MainBackgroundColor}"" SnapsToDevicePixels=""True"">`n"
|
||||
$panelcount++
|
||||
foreach ($category in ($organizedData[$panel].Keys | Sort-Object)) {
|
||||
$count++
|
||||
if ($columncount -gt 0) {
|
||||
$panelcount2 = [Int](($count)/$maxcount-0.5)
|
||||
if ($panelcount -eq $panelcount2 ) {
|
||||
$blockXml +="`n</StackPanel>`n</Border>`n"
|
||||
$blockXml += "<Border Grid.Row=""1"" Grid.Column=""$panelcount"">`n<StackPanel Background=""{MainBackgroundColor}"" SnapsToDevicePixels=""True"">`n"
|
||||
$panelcount++
|
||||
}
|
||||
}
|
||||
|
||||
# Dot-source the Get-WPFObjectName function
|
||||
. .\functions\private\Get-WPFObjectName
|
||||
|
||||
$categorycontent = $($category -replace '^.__', '')
|
||||
$categoryname = Get-WPFObjectName -type "Label" -name $categorycontent
|
||||
$blockXml += "<Label Name=""$categoryname"" Content=""$categorycontent"" FontSize=""16""/>`n"
|
||||
$sortedApps = $organizedData[$panel][$category].Keys | Sort-Object
|
||||
foreach ($appName in $sortedApps) {
|
||||
$count++
|
||||
if ($columncount -gt 0) {
|
||||
$panelcount2 = [Int](($count)/$maxcount-0.5)
|
||||
if ($panelcount -eq $panelcount2 ) {
|
||||
$blockXml +="`n</StackPanel>`n</Border>`n"
|
||||
$blockXml += "<Border Grid.Row=""1"" Grid.Column=""$panelcount"">`n<StackPanel Background=""{MainBackgroundColor}"" SnapsToDevicePixels=""True"">`n"
|
||||
$panelcount++
|
||||
}
|
||||
}
|
||||
$appInfo = $organizedData[$panel][$category][$appName]
|
||||
if ("Toggle" -eq $appInfo.Type) {
|
||||
$blockXml += "<DockPanel LastChildFill=`"True`">`n<Label Content=`"$($appInfo.Content)`" ToolTip=`"$($appInfo.Description)`" HorizontalAlignment=`"Left`"/>`n"
|
||||
$blockXml += "<CheckBox Name=`"$($appInfo.Name)`" Style=`"{StaticResource ColorfulToggleSwitchStyle}`" Margin=`"2.5,0`" HorizontalAlignment=`"Right`"/>`n</DockPanel>`n"
|
||||
} elseif ("Combobox" -eq $appInfo.Type) {
|
||||
$blockXml += "<StackPanel Orientation=`"Horizontal`" Margin=`"0,5,0,0`">`n<Label Content=`"$($appInfo.Content)`" HorizontalAlignment=`"Left`" VerticalAlignment=`"Center`"/>`n"
|
||||
$blockXml += "<ComboBox Name=`"$($appInfo.Name)`" Height=`"32`" Width=`"186`" HorizontalAlignment=`"Left`" VerticalAlignment=`"Center`" Margin=`"5,5`">`n"
|
||||
$addfirst="IsSelected=`"True`""
|
||||
foreach ($comboitem in ($appInfo.ComboItems -split " ")) {
|
||||
$blockXml += "<ComboBoxItem $addfirst Content=`"$comboitem`"/>`n"
|
||||
$addfirst=""
|
||||
}
|
||||
$blockXml += "</ComboBox>`n</StackPanel>"
|
||||
# If it is a digit, type is button and button length is digits
|
||||
} elseif ($appInfo.Type -match "^[\d\.]+$") {
|
||||
$blockXml += "<Button Name=`"$($appInfo.Name)`" Content=`"$($appInfo.Content)`" HorizontalAlignment = `"Left`" Width=`"$($appInfo.Type)`" Margin=`"5`" Padding=`"20,5`" />`n"
|
||||
# else it is a checkbox
|
||||
} else {
|
||||
$checkedStatus = If ($null -eq $appInfo.Checked) {""} Else {"IsChecked=`"$($appInfo.Checked)`" "}
|
||||
if ($null -eq $appInfo.Link)
|
||||
{
|
||||
$blockXml += "<CheckBox Name=`"$($appInfo.Name)`" Content=`"$($appInfo.Content)`" $($checkedStatus)Margin=`"5,0`" ToolTip=`"$($appInfo.Description)`"/>`n"
|
||||
}
|
||||
else
|
||||
{
|
||||
$blockXml += "<StackPanel Orientation=""Horizontal"">`n<CheckBox Name=""$($appInfo.Name)"" Content=""$($appInfo.Content)"" $($checkedStatus)ToolTip=""$($appInfo.Description)"" Margin=""0,0,2,0""/><TextBlock Name=""$($appInfo.Name)Link"" Style=""{StaticResource HoverTextBlockStyle}"" Text=""(?)"" ToolTip=""$($appInfo.Link)"" />`n</StackPanel>`n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$blockXml +="`n</StackPanel>`n</Border>`n"
|
||||
}
|
||||
return ($blockXml)
|
||||
}
|
@ -1,27 +1,31 @@
|
||||
function Get-WPFObjectName {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This is a helper function that generates an objectname with the prefix WPF that can be used as a Powershell Variable after compilation.
|
||||
To achieve this, all characters that are not a-z, A-Z or 0-9 are simply removed from the name.
|
||||
.PARAMETER type
|
||||
The type of object for which the name should be generated. (e.g. Label, Button, CheckBox...)
|
||||
.PARAMETER name
|
||||
The name or description to be used for the object. (invalid characters are removed)
|
||||
.OUTPUTS
|
||||
A string that can be used as a object/variable name in powershell.
|
||||
For example: WPFLabelMicrosoftTools
|
||||
|
||||
.EXAMPLE
|
||||
Get-WPFObjectName -type Label -name "Microsoft Tools"
|
||||
<#
|
||||
.SYNOPSIS
|
||||
This is a helper function that generates an objectname with the prefix WPF that can be used as a Powershell Variable after compilation.
|
||||
To achieve this, all characters that are not a-z, A-Z or 0-9 are simply removed from the name.
|
||||
|
||||
.PARAMETER type
|
||||
The type of object for which the name should be generated. (e.g. Label, Button, CheckBox...)
|
||||
|
||||
.PARAMETER name
|
||||
The name or description to be used for the object. (invalid characters are removed)
|
||||
|
||||
.OUTPUTS
|
||||
A string that can be used as a object/variable name in powershell.
|
||||
For example: WPFLabelMicrosoftTools
|
||||
|
||||
.EXAMPLE
|
||||
Get-WPFObjectName -type Label -name "Microsoft Tools"
|
||||
#>
|
||||
|
||||
param( [Parameter(Mandatory=$true)]
|
||||
$type,
|
||||
$name
|
||||
)
|
||||
param(
|
||||
[Parameter(Mandatory, position=0)]
|
||||
[string]$type,
|
||||
|
||||
$Output = $("WPF"+$type+$name) -replace '[^a-zA-Z0-9]', ''
|
||||
[Parameter(position=1)]
|
||||
[string]$name
|
||||
)
|
||||
|
||||
return $Output
|
||||
|
||||
}
|
||||
$Output = $("WPF"+$type+$name) -replace '[^a-zA-Z0-9]', ''
|
||||
return $Output
|
||||
}
|
||||
|
@ -14,11 +14,11 @@ function Get-WinUtilInstallerProcess {
|
||||
|
||||
param($Process)
|
||||
|
||||
if ($Null -eq $Process){
|
||||
if ($Null -eq $Process) {
|
||||
return $false
|
||||
}
|
||||
if (Get-Process -Id $Process.Id -ErrorAction SilentlyContinue){
|
||||
if (Get-Process -Id $Process.Id -ErrorAction SilentlyContinue) {
|
||||
return $true
|
||||
}
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
59
functions/private/Get-WinUtilSelectedPackages.ps1
Normal file
59
functions/private/Get-WinUtilSelectedPackages.ps1
Normal file
@ -0,0 +1,59 @@
|
||||
function Get-WinUtilSelectedPackages
|
||||
{
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Sorts given packages based on installer preference and availability.
|
||||
|
||||
.OUTPUTS
|
||||
Hashtable. Key = Package Manager, Value = ArrayList of packages to install
|
||||
#>
|
||||
param (
|
||||
[Parameter(Mandatory=$true)]
|
||||
$PackageList,
|
||||
[Parameter(Mandatory=$true)]
|
||||
[PackageManagers]$Preference
|
||||
)
|
||||
|
||||
if ($PackageList.count -eq 1) {
|
||||
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Indeterminate" -value 0.01 -overlay "logo" })
|
||||
} else {
|
||||
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Normal" -value 0.01 -overlay "logo" })
|
||||
}
|
||||
|
||||
$packages = [System.Collections.Hashtable]::new()
|
||||
$packagesWinget = [System.Collections.ArrayList]::new()
|
||||
$packagesChoco = [System.Collections.ArrayList]::new()
|
||||
$packages[[PackageManagers]::Winget] = $packagesWinget
|
||||
$packages[[PackageManagers]::Choco] = $packagesChoco
|
||||
|
||||
Write-Debug "Checking packages using Preference '$($Preference)'"
|
||||
|
||||
foreach ($package in $PackageList) {
|
||||
switch ($Preference) {
|
||||
"Choco" {
|
||||
if ($package.choco -eq "na") {
|
||||
Write-Debug "$($package.content) has no Choco value."
|
||||
$null = $packagesWinget.add($($package.winget))
|
||||
Write-Host "Queueing $($package.winget) for Winget"
|
||||
} else {
|
||||
$null = $packagesChoco.add($package.choco)
|
||||
Write-Host "Queueing $($package.choco) for Chocolatey"
|
||||
}
|
||||
break
|
||||
}
|
||||
"Winget" {
|
||||
if ($package.winget -eq "na") {
|
||||
Write-Debug "$($package.content) has no Winget value."
|
||||
$null = $packagesChoco.add($package.choco)
|
||||
Write-Host "Queueing $($package.choco) for Chocolatey"
|
||||
} else {
|
||||
$null = $packagesWinget.add($($package.winget))
|
||||
Write-Host "Queueing $($package.winget) for Winget"
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $packages
|
||||
}
|
@ -13,107 +13,66 @@ Function Get-WinUtilToggleStatus {
|
||||
#>
|
||||
|
||||
Param($ToggleSwitch)
|
||||
if($ToggleSwitch -eq "WPFToggleDarkMode"){
|
||||
$app = (Get-ItemProperty -path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize').AppsUseLightTheme
|
||||
$system = (Get-ItemProperty -path 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize').SystemUsesLightTheme
|
||||
if($app -eq 0 -and $system -eq 0){
|
||||
return $true
|
||||
}
|
||||
else{
|
||||
return $false
|
||||
}
|
||||
}
|
||||
if($ToggleSwitch -eq "WPFToggleBingSearch"){
|
||||
$bingsearch = (Get-ItemProperty -path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Search').BingSearchEnabled
|
||||
if($bingsearch -eq 0){
|
||||
return $false
|
||||
}
|
||||
else{
|
||||
return $true
|
||||
}
|
||||
}
|
||||
if($ToggleSwitch -eq "WPFToggleNumLock"){
|
||||
$numlockvalue = (Get-ItemProperty -path 'HKCU:\Control Panel\Keyboard').InitialKeyboardIndicators
|
||||
if($numlockvalue -eq 2){
|
||||
return $true
|
||||
}
|
||||
else{
|
||||
return $false
|
||||
}
|
||||
}
|
||||
if($ToggleSwitch -eq "WPFToggleVerboseLogon"){
|
||||
$VerboseStatusvalue = (Get-ItemProperty -path 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System').VerboseStatus
|
||||
if($VerboseStatusvalue -eq 1){
|
||||
return $true
|
||||
}
|
||||
else{
|
||||
return $false
|
||||
}
|
||||
}
|
||||
if($ToggleSwitch -eq "WPFToggleShowExt"){
|
||||
$hideextvalue = (Get-ItemProperty -path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced').HideFileExt
|
||||
if($hideextvalue -eq 0){
|
||||
return $true
|
||||
}
|
||||
else{
|
||||
return $false
|
||||
}
|
||||
}
|
||||
if($ToggleSwitch -eq "WPFToggleSnapWindow"){
|
||||
$hidesnap = (Get-ItemProperty -path 'HKCU:\Control Panel\Desktop').WindowArrangementActive
|
||||
if($hidesnap -eq 0){
|
||||
return $false
|
||||
}
|
||||
else{
|
||||
return $true
|
||||
}
|
||||
}
|
||||
if($ToggleSwitch -eq "WPFToggleSnapFlyout"){
|
||||
$hidesnap = (Get-ItemProperty -path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced').EnableSnapAssistFlyout
|
||||
if($hidesnap -eq 0){
|
||||
return $false
|
||||
}
|
||||
else{
|
||||
return $true
|
||||
}
|
||||
}
|
||||
if($ToggleSwitch -eq "WPFToggleSnapSuggestion"){
|
||||
$hidesnap = (Get-ItemProperty -path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced').SnapAssist
|
||||
if($hidesnap -eq 0){
|
||||
return $false
|
||||
}
|
||||
else{
|
||||
return $true
|
||||
}
|
||||
}
|
||||
if($ToggleSwitch -eq "WPFToggleMouseAcceleration"){
|
||||
$MouseSpeed = (Get-ItemProperty -path 'HKCU:\Control Panel\Mouse').MouseSpeed
|
||||
$MouseThreshold1 = (Get-ItemProperty -path 'HKCU:\Control Panel\Mouse').MouseThreshold1
|
||||
$MouseThreshold2 = (Get-ItemProperty -path 'HKCU:\Control Panel\Mouse').MouseThreshold2
|
||||
|
||||
if($MouseSpeed -eq 1 -and $MouseThreshold1 -eq 6 -and $MouseThreshold2 -eq 10){
|
||||
return $true
|
||||
}
|
||||
else{
|
||||
return $false
|
||||
$ToggleSwitchReg = $sync.configs.tweaks.$ToggleSwitch.registry
|
||||
|
||||
try {
|
||||
if (($ToggleSwitchReg.path -imatch "hku") -and !(Get-PSDrive -Name HKU -ErrorAction SilentlyContinue)) {
|
||||
$null = (New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS)
|
||||
if (Get-PSDrive -Name HKU -ErrorAction SilentlyContinue) {
|
||||
Write-Debug "HKU drive created successfully"
|
||||
} else {
|
||||
Write-Debug "Failed to create HKU drive"
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
Write-Error "An error occurred regarding the HKU Drive: $_"
|
||||
return $false
|
||||
}
|
||||
if ($ToggleSwitch -eq "WPFToggleStickyKeys") {
|
||||
$StickyKeys = (Get-ItemProperty -path 'HKCU:\Control Panel\Accessibility\StickyKeys').Flags
|
||||
if($StickyKeys -eq 58){
|
||||
|
||||
if ($ToggleSwitchReg) {
|
||||
$count = 0
|
||||
|
||||
foreach ($regentry in $ToggleSwitchReg) {
|
||||
try {
|
||||
if (!(Test-Path $regentry.Path)) {
|
||||
New-Item -Path $regentry.Path -Force | Out-Null
|
||||
}
|
||||
$regstate = (Get-ItemProperty -path $regentry.Path).$($regentry.Name)
|
||||
if ($regstate -eq $regentry.Value) {
|
||||
$count += 1
|
||||
Write-Debug "$($regentry.Name) is true (state: $regstate, value: $($regentry.Value), original: $($regentry.OriginalValue))"
|
||||
} else {
|
||||
Write-Debug "$($regentry.Name) is false (state: $regstate, value: $($regentry.Value), original: $($regentry.OriginalValue))"
|
||||
}
|
||||
if (!$regstate) {
|
||||
switch ($regentry.DefaultState) {
|
||||
"true" {
|
||||
$regstate = $regentry.Value
|
||||
$count += 1
|
||||
}
|
||||
"false" {
|
||||
$regstate = $regentry.OriginalValue
|
||||
}
|
||||
default {
|
||||
Write-Error "Entry for $($regentry.Name) does not exist and no DefaultState is defined."
|
||||
$regstate = $regentry.OriginalValue
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
Write-Error "An unexpected error occurred: $_"
|
||||
}
|
||||
}
|
||||
|
||||
if ($count -eq $ToggleSwitchReg.Count) {
|
||||
Write-Debug "$($ToggleSwitchReg.Name) is true (count: $count)"
|
||||
return $true
|
||||
} else {
|
||||
Write-Debug "$($ToggleSwitchReg.Name) is false (count: $count)"
|
||||
return $false
|
||||
}
|
||||
else{
|
||||
return $true
|
||||
}
|
||||
}
|
||||
if ($ToggleSwitch -eq "WPFToggleTaskbarWidgets") {
|
||||
$TaskbarWidgets = (Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced").TaskBarDa
|
||||
if($TaskbarWidgets -eq 0) {
|
||||
return $false
|
||||
}
|
||||
else{
|
||||
return $true
|
||||
}
|
||||
} else {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
@ -11,18 +11,15 @@ function Get-WinUtilVariables {
|
||||
[Parameter()]
|
||||
[string[]]$Type
|
||||
)
|
||||
|
||||
$keys = $sync.keys | Where-Object { $_ -like "WPF*" }
|
||||
|
||||
$keys = ($sync.keys).where{ $_ -like "WPF*" }
|
||||
if ($Type) {
|
||||
$output = $keys | ForEach-Object {
|
||||
Try {
|
||||
try {
|
||||
$objType = $sync["$psitem"].GetType().Name
|
||||
if ($Type -contains $objType) {
|
||||
Write-Output $psitem
|
||||
}
|
||||
}
|
||||
Catch {
|
||||
} catch {
|
||||
<#I am here so errors don't get outputted for a couple variables that don't have the .GetType() attribute#>
|
||||
}
|
||||
}
|
||||
|
@ -1,27 +0,0 @@
|
||||
function Get-WinUtilWingetLatest {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Uses GitHub API to check for the latest release of Winget.
|
||||
.DESCRIPTION
|
||||
This function grabs the latest version of Winget and returns the download path to Install-WinUtilWinget for installation.
|
||||
#>
|
||||
# Invoke-WebRequest is notoriously slow when the byte progress is displayed. The following lines disable the progress bar and reset them at the end of the function
|
||||
$PreviousProgressPreference = $ProgressPreference
|
||||
$ProgressPreference = "silentlyContinue"
|
||||
Try{
|
||||
# Grabs the latest release of Winget from the Github API for the install process.
|
||||
$response = Invoke-RestMethod -Uri "https://api.github.com/repos/microsoft/Winget-cli/releases/latest" -Method Get -ErrorAction Stop
|
||||
$latestVersion = $response.tag_name #Stores version number of latest release.
|
||||
$licenseWingetUrl = $response.assets.browser_download_url | Where-Object {$_ -like "*License1.xml"} #Index value for License file.
|
||||
Write-Host "Latest Version:`t$($latestVersion)`n"
|
||||
Write-Host "Downloading..."
|
||||
$assetUrl = $response.assets.browser_download_url | Where-Object {$_ -like "*Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle"}
|
||||
Invoke-WebRequest -Uri $licenseWingetUrl -OutFile $ENV:TEMP\License1.xml
|
||||
# The only pain is that the msixbundle for winget-cli is 246MB. In some situations this can take a bit, with slower connections.
|
||||
Invoke-WebRequest -Uri $assetUrl -OutFile $ENV:TEMP\Microsoft.DesktopAppInstaller.msixbundle
|
||||
}
|
||||
Catch{
|
||||
throw [WingetFailedInstall]::new('Failed to get latest Winget release and license')
|
||||
}
|
||||
$ProgressPreference = $PreviousProgressPreference
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
function Get-WinUtilWingetPrerequisites {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Downloads the Winget Prereqs.
|
||||
.DESCRIPTION
|
||||
Downloads Prereqs for Winget. Version numbers are coded as variables and can be updated as uncommonly as Microsoft updates the prereqs.
|
||||
#>
|
||||
|
||||
# I don't know of a way to detect the prereqs automatically, so if someone has a better way of defining these, that would be great.
|
||||
# Microsoft.VCLibs version rarely changes, but for future compatibility I made it a variable.
|
||||
$versionVCLibs = "14.00"
|
||||
$fileVCLibs = "https://aka.ms/Microsoft.VCLibs.x64.${versionVCLibs}.Desktop.appx"
|
||||
# Write-Host "$fileVCLibs"
|
||||
# Microsoft.UI.Xaml version changed recently, so I made the version numbers variables.
|
||||
$versionUIXamlMinor = "2.8"
|
||||
$versionUIXamlPatch = "2.8.6"
|
||||
$fileUIXaml = "https://github.com/microsoft/microsoft-ui-xaml/releases/download/v${versionUIXamlPatch}/Microsoft.UI.Xaml.${versionUIXamlMinor}.x64.appx"
|
||||
# Write-Host "$fileUIXaml"
|
||||
|
||||
Try{
|
||||
Write-Host "Downloading Microsoft.VCLibs Dependency..."
|
||||
Invoke-WebRequest -Uri $fileVCLibs -OutFile $ENV:TEMP\Microsoft.VCLibs.x64.Desktop.appx
|
||||
Write-Host "Downloading Microsoft.UI.Xaml Dependency...`n"
|
||||
Invoke-WebRequest -Uri $fileUIXaml -OutFile $ENV:TEMP\Microsoft.UI.Xaml.x64.appx
|
||||
}
|
||||
Catch{
|
||||
throw [WingetFailedInstall]::new('Failed to install prerequsites')
|
||||
}
|
||||
}
|
12
functions/private/Hide-WPFInstallAppBusy.ps1
Normal file
12
functions/private/Hide-WPFInstallAppBusy.ps1
Normal file
@ -0,0 +1,12 @@
|
||||
function Hide-WPFInstallAppBusy {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Hides the busy overlay in the install app area of the WPF form.
|
||||
This is used to indicate that an install or uninstall has finished.
|
||||
#>
|
||||
$sync.form.Dispatcher.Invoke([action]{
|
||||
$sync.InstallAppAreaOverlay.Visibility = [Windows.Visibility]::Collapsed
|
||||
$sync.InstallAppAreaBorder.IsEnabled = $true
|
||||
$sync.InstallAppAreaScrollViewer.Effect.Radius = 0
|
||||
})
|
||||
}
|
74
functions/private/Initalize-InstallAppEntry.ps1
Normal file
74
functions/private/Initalize-InstallAppEntry.ps1
Normal file
@ -0,0 +1,74 @@
|
||||
function Initialize-InstallAppEntry {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Creates the app entry to be placed on the isntall tab for a given app
|
||||
Used to as part of the Install Tab UI generation
|
||||
.PARAMETER TargetElement
|
||||
The Element into which the Apps should be placed
|
||||
.PARAMETER appKey
|
||||
The Key of the app inside the $sync.configs.applicationsHashtable
|
||||
#>
|
||||
param(
|
||||
[Windows.Controls.WrapPanel]$TargetElement,
|
||||
$appKey
|
||||
)
|
||||
|
||||
# Create the outer Border for the application type
|
||||
$border = New-Object Windows.Controls.Border
|
||||
$border.Style = $sync.Form.Resources.AppEntryBorderStyle
|
||||
$border.Tag = $appKey
|
||||
$border.ToolTip = $Apps.$appKey.description
|
||||
$border.Add_MouseLeftButtonUp({
|
||||
$childCheckbox = ($this.Child | Where-Object {$_.Template.TargetType -eq [System.Windows.Controls.Checkbox]})[0]
|
||||
$childCheckBox.isChecked = -not $childCheckbox.IsChecked
|
||||
})
|
||||
$border.Add_MouseEnter({
|
||||
if (($sync.$($this.Tag).IsChecked) -eq $false) {
|
||||
$this.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallHighlightedColor")
|
||||
}
|
||||
})
|
||||
$border.Add_MouseLeave({
|
||||
if (($sync.$($this.Tag).IsChecked) -eq $false) {
|
||||
$this.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor")
|
||||
}
|
||||
})
|
||||
$border.Add_MouseRightButtonUp({
|
||||
# Store the selected app in a global variable so it can be used in the popup
|
||||
$sync.appPopupSelectedApp = $this.Tag
|
||||
# Set the popup position to the current mouse position
|
||||
$sync.appPopup.PlacementTarget = $this
|
||||
$sync.appPopup.IsOpen = $true
|
||||
})
|
||||
|
||||
$checkBox = New-Object Windows.Controls.CheckBox
|
||||
$checkBox.Name = $appKey
|
||||
$checkbox.Style = $sync.Form.Resources.AppEntryCheckboxStyle
|
||||
$checkbox.Add_Checked({
|
||||
Invoke-WPFSelectedAppsUpdate -type "Add" -checkbox $this
|
||||
$borderElement = $this.Parent
|
||||
$borderElement.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallSelectedColor")
|
||||
})
|
||||
|
||||
$checkbox.Add_Unchecked({
|
||||
Invoke-WPFSelectedAppsUpdate -type "Remove" -checkbox $this
|
||||
$borderElement = $this.Parent
|
||||
$borderElement.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallUnselectedColor")
|
||||
})
|
||||
|
||||
# Create the TextBlock for the application name
|
||||
$appName = New-Object Windows.Controls.TextBlock
|
||||
$appName.Style = $sync.Form.Resources.AppEntryNameStyle
|
||||
$appName.Text = $Apps.$appKey.content
|
||||
|
||||
# Add the name to the Checkbox
|
||||
$checkBox.Content = $appName
|
||||
|
||||
# Add accessibility properties to make the elements screen reader friendly
|
||||
$checkBox.SetValue([Windows.Automation.AutomationProperties]::NameProperty, $Apps.$appKey.content)
|
||||
$border.SetValue([Windows.Automation.AutomationProperties]::NameProperty, $Apps.$appKey.content)
|
||||
|
||||
$border.Child = $checkBox
|
||||
# Add the border to the corresponding Category
|
||||
$TargetElement.Children.Add($border) | Out-Null
|
||||
return $checkbox
|
||||
}
|
112
functions/private/Initialize-InstallAppArea.ps1
Normal file
112
functions/private/Initialize-InstallAppArea.ps1
Normal file
@ -0,0 +1,112 @@
|
||||
function Initialize-InstallAppArea {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Creates a [Windows.Controls.ScrollViewer] containing a [Windows.Controls.ItemsControl] which is setup to use Virtualization to only load the visible elements for performance reasons.
|
||||
This is used as the parent object for all category and app entries on the install tab
|
||||
Used to as part of the Install Tab UI generation
|
||||
|
||||
Also creates an overlay with a progress bar and text to indicate that an install or uninstall is in progress
|
||||
|
||||
.PARAMETER TargetElement
|
||||
The element to which the AppArea shoud be added
|
||||
|
||||
#>
|
||||
param($TargetElement)
|
||||
$targetGrid = $sync.Form.FindName($TargetElement)
|
||||
$null = $targetGrid.Children.Clear()
|
||||
|
||||
# Create the outer Border for the aren where the apps will be placed
|
||||
$Border = New-Object Windows.Controls.Border
|
||||
$Border.VerticalAlignment = "Stretch"
|
||||
$Border.SetResourceReference([Windows.Controls.Control]::StyleProperty, "BorderStyle")
|
||||
$sync.InstallAppAreaBorder = $Border
|
||||
|
||||
# Add a ScrollViewer, because the ItemsControl does not support scrolling by itself
|
||||
$scrollViewer = New-Object Windows.Controls.ScrollViewer
|
||||
$scrollViewer.VerticalScrollBarVisibility = 'Auto'
|
||||
$scrollViewer.HorizontalAlignment = 'Stretch'
|
||||
$scrollViewer.VerticalAlignment = 'Stretch'
|
||||
$scrollViewer.CanContentScroll = $true
|
||||
$sync.InstallAppAreaScrollViewer = $scrollViewer
|
||||
$Border.Child = $scrollViewer
|
||||
|
||||
# Initialize the Blur Effect for the ScrollViewer, which will be used to indicate that an install/uninstall is in progress
|
||||
$blurEffect = New-Object Windows.Media.Effects.BlurEffect
|
||||
$blurEffect.Radius = 0
|
||||
$scrollViewer.Effect = $blurEffect
|
||||
|
||||
## Create the ItemsControl, which will be the parent of all the app entries
|
||||
$itemsControl = New-Object Windows.Controls.ItemsControl
|
||||
$itemsControl.HorizontalAlignment = 'Stretch'
|
||||
$itemsControl.VerticalAlignment = 'Stretch'
|
||||
$scrollViewer.Content = $itemsControl
|
||||
|
||||
# Enable virtualization for the ItemsControl to improve performance (It's hard to test if this is actually working, so if you know what you're doing, please check this)
|
||||
$itemsPanelTemplate = New-Object Windows.Controls.ItemsPanelTemplate
|
||||
$factory = New-Object Windows.FrameworkElementFactory ([Windows.Controls.VirtualizingStackPanel])
|
||||
$itemsPanelTemplate.VisualTree = $factory
|
||||
$itemsControl.ItemsPanel = $itemsPanelTemplate
|
||||
$itemsControl.SetValue([Windows.Controls.VirtualizingStackPanel]::IsVirtualizingProperty, $true)
|
||||
$itemsControl.SetValue([Windows.Controls.VirtualizingStackPanel]::VirtualizationModeProperty, [Windows.Controls.VirtualizationMode]::Recycling)
|
||||
|
||||
# Add the Border containing the App Area to the target Grid
|
||||
$targetGrid.Children.Add($Border) | Out-Null
|
||||
|
||||
$overlay = New-Object Windows.Controls.Border
|
||||
$overlay.CornerRadius = New-Object Windows.CornerRadius(10)
|
||||
$overlay.SetResourceReference([Windows.Controls.Control]::BackgroundProperty, "AppInstallOverlayBackgroundColor")
|
||||
$overlay.Visibility = [Windows.Visibility]::Collapsed
|
||||
|
||||
# Also add the overlay to the target Grid on top of the App Area
|
||||
$targetGrid.Children.Add($overlay) | Out-Null
|
||||
$sync.InstallAppAreaOverlay = $overlay
|
||||
|
||||
$overlayText = New-Object Windows.Controls.TextBlock
|
||||
$overlayText.Text = "Installing apps..."
|
||||
$overlayText.HorizontalAlignment = 'Center'
|
||||
$overlayText.VerticalAlignment = 'Center'
|
||||
$overlayText.SetResourceReference([Windows.Controls.TextBlock]::ForegroundProperty, "MainForegroundColor")
|
||||
$overlayText.Background = "Transparent"
|
||||
$overlayText.SetResourceReference([Windows.Controls.TextBlock]::FontSizeProperty, "HeaderFontSize")
|
||||
$overlayText.SetResourceReference([Windows.Controls.TextBlock]::FontFamilyProperty, "MainFontFamily")
|
||||
$overlayText.SetResourceReference([Windows.Controls.TextBlock]::FontWeightProperty, "MainFontWeight")
|
||||
$overlayText.SetResourceReference([Windows.Controls.TextBlock]::MarginProperty, "MainMargin")
|
||||
$sync.InstallAppAreaOverlayText = $overlayText
|
||||
|
||||
$progressbar = New-Object Windows.Controls.ProgressBar
|
||||
$progressbar.Name = "ProgressBar"
|
||||
$progressbar.Width = 250
|
||||
$progressbar.Height = 50
|
||||
$sync.ProgressBar = $progressbar
|
||||
|
||||
# Add a TextBlock overlay for the progress bar text
|
||||
$progressBarTextBlock = New-Object Windows.Controls.TextBlock
|
||||
$progressBarTextBlock.Name = "progressBarTextBlock"
|
||||
$progressBarTextBlock.FontWeight = [Windows.FontWeights]::Bold
|
||||
$progressBarTextBlock.FontSize = 16
|
||||
$progressBarTextBlock.Width = $progressbar.Width
|
||||
$progressBarTextBlock.Height = $progressbar.Height
|
||||
$progressBarTextBlock.SetResourceReference([Windows.Controls.TextBlock]::ForegroundProperty, "ProgressBarTextColor")
|
||||
$progressBarTextBlock.TextTrimming = "CharacterEllipsis"
|
||||
$progressBarTextBlock.Background = "Transparent"
|
||||
$sync.progressBarTextBlock = $progressBarTextBlock
|
||||
|
||||
# Create a Grid to overlay the text on the progress bar
|
||||
$progressGrid = New-Object Windows.Controls.Grid
|
||||
$progressGrid.Width = $progressbar.Width
|
||||
$progressGrid.Height = $progressbar.Height
|
||||
$progressGrid.Margin = "0,10,0,10"
|
||||
$progressGrid.Children.Add($progressbar) | Out-Null
|
||||
$progressGrid.Children.Add($progressBarTextBlock) | Out-Null
|
||||
|
||||
$overlayStackPanel = New-Object Windows.Controls.StackPanel
|
||||
$overlayStackPanel.Orientation = "Vertical"
|
||||
$overlayStackPanel.HorizontalAlignment = 'Center'
|
||||
$overlayStackPanel.VerticalAlignment = 'Center'
|
||||
$overlayStackPanel.Children.Add($overlayText) | Out-Null
|
||||
$overlayStackPanel.Children.Add($progressGrid) | Out-Null
|
||||
|
||||
$overlay.Child = $overlayStackPanel
|
||||
|
||||
return $itemsControl
|
||||
}
|
56
functions/private/Initialize-InstallCategoryAppList.ps1
Normal file
56
functions/private/Initialize-InstallCategoryAppList.ps1
Normal file
@ -0,0 +1,56 @@
|
||||
function Initialize-InstallCategoryAppList {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Clears the Target Element and sets up a "Loading" message. This is done, because loading of all apps can take a bit of time in some scenarios
|
||||
Iterates through all Categories and Apps and adds them to the UI
|
||||
Used to as part of the Install Tab UI generation
|
||||
.PARAMETER TargetElement
|
||||
The Element into which the Categories and Apps should be placed
|
||||
.PARAMETER Apps
|
||||
The Hashtable of Apps to be added to the UI
|
||||
The Categories are also extracted from the Apps Hashtable
|
||||
|
||||
#>
|
||||
param(
|
||||
$TargetElement,
|
||||
$Apps
|
||||
)
|
||||
function Add-Category {
|
||||
param(
|
||||
[string]$Category,
|
||||
[Windows.Controls.ItemsControl]$TargetElement
|
||||
)
|
||||
|
||||
$toggleButton = New-Object Windows.Controls.Label
|
||||
$toggleButton.Content = "$Category"
|
||||
$toggleButton.Tag = "CategoryToggleButton"
|
||||
$sync.$Category = $Category
|
||||
|
||||
$null = $TargetElement.Items.Add($toggleButton)
|
||||
}
|
||||
|
||||
|
||||
# Pre-group apps by category
|
||||
$appsByCategory = @{}
|
||||
foreach ($appKey in $Apps.Keys) {
|
||||
$category = $Apps.$appKey.Category
|
||||
if (-not $appsByCategory.ContainsKey($category)) {
|
||||
$appsByCategory[$category] = @()
|
||||
}
|
||||
$appsByCategory[$category] += $appKey
|
||||
}
|
||||
foreach ($category in $($appsByCategory.Keys | Sort-Object)) {
|
||||
Add-Category -Category $category -TargetElement $TargetElement
|
||||
$wrapPanel = New-Object Windows.Controls.WrapPanel
|
||||
$wrapPanel.Orientation = "Horizontal"
|
||||
$wrapPanel.HorizontalAlignment = "Stretch"
|
||||
$wrapPanel.VerticalAlignment = "Center"
|
||||
$wrapPanel.Margin = New-Object Windows.Thickness(0, 0, 0, 20)
|
||||
$wrapPanel.Visibility = [Windows.Visibility]::Visible
|
||||
$wrapPanel.Tag = "CategoryWrapPanel_$category"
|
||||
$null = $TargetElement.Items.Add($wrapPanel)
|
||||
$appsByCategory[$category] |Sort-Object | ForEach-Object {
|
||||
$sync.$_ = $(Initialize-InstallAppEntry -TargetElement $wrapPanel -AppKey $_)
|
||||
}
|
||||
}
|
||||
}
|
@ -13,13 +13,13 @@ function Install-WinUtilChoco {
|
||||
if((Test-WinUtilPackageManager -choco) -eq "installed") {
|
||||
return
|
||||
}
|
||||
|
||||
# Install logic taken from https://chocolatey.org/install#individual
|
||||
Write-Host "Seems Chocolatey is not installed, installing now."
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force; Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1')) -ErrorAction Stop
|
||||
powershell choco feature enable -n allowGlobalConfirmation
|
||||
Set-ExecutionPolicy Bypass -Scope Process -Force;
|
||||
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072;
|
||||
Invoke-Expression ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))
|
||||
|
||||
}
|
||||
Catch {
|
||||
} catch {
|
||||
Write-Host "===========================================" -Foregroundcolor Red
|
||||
Write-Host "-- Chocolatey failed to install ---" -Foregroundcolor Red
|
||||
Write-Host "===========================================" -Foregroundcolor Red
|
||||
|
@ -1,91 +1,258 @@
|
||||
function Install-WinUtilProgramChoco {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Manages the provided programs using Chocolatey
|
||||
|
||||
.PARAMETER ProgramsToInstall
|
||||
A list of programs to manage
|
||||
|
||||
.PARAMETER manage
|
||||
The action to perform on the programs, can be either 'Installing' or 'Uninstalling'
|
||||
|
||||
.NOTES
|
||||
The triple quotes are required any time you need a " in a normal script block.
|
||||
Manages the installation or uninstallation of a list of Chocolatey packages.
|
||||
|
||||
.PARAMETER Programs
|
||||
A string array containing the programs to be installed or uninstalled.
|
||||
|
||||
.PARAMETER Action
|
||||
Specifies the action to perform: "Install" or "Uninstall". The default value is "Install".
|
||||
|
||||
.DESCRIPTION
|
||||
This function processes a list of programs to be managed using Chocolatey. Depending on the specified action, it either installs or uninstalls each program in the list, updating the taskbar progress accordingly. After all operations are completed, temporary output files are cleaned up.
|
||||
|
||||
.EXAMPLE
|
||||
Install-WinUtilProgramChoco -Programs @("7zip","chrome") -Action "Uninstall"
|
||||
#>
|
||||
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory, Position=0)]
|
||||
[PsCustomObject]$ProgramsToInstall,
|
||||
[Parameter(Mandatory, Position = 0)]
|
||||
[string[]]$Programs,
|
||||
|
||||
[Parameter(Position=1)]
|
||||
[String]$manage = "Installing"
|
||||
[Parameter(Position = 1)]
|
||||
[String]$Action = "Install"
|
||||
)
|
||||
|
||||
$x = 0
|
||||
$count = $ProgramsToInstall.Count
|
||||
|
||||
# This check isn't really necessary, as there's a couple of checks before this Private Function gets called, but just to make sure ;)
|
||||
if($count -le 0) {
|
||||
throw "Private Function 'Install-WinUtilProgramChoco' expected Parameter 'ProgramsToInstall' to be of size 1 or greater, instead got $count,`nPlease double check your code and re-compile WinUtil."
|
||||
function Initialize-OutputFile {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Initializes an output file by removing any existing file and creating a new, empty file at the specified path.
|
||||
|
||||
.PARAMETER filePath
|
||||
The full path to the file to be initialized.
|
||||
|
||||
.DESCRIPTION
|
||||
This function ensures that the specified file is reset by removing any existing file at the provided path and then creating a new, empty file. It is useful when preparing a log or output file for subsequent operations.
|
||||
|
||||
.EXAMPLE
|
||||
Initialize-OutputFile -filePath "C:\temp\output.txt"
|
||||
#>
|
||||
|
||||
param ($filePath)
|
||||
Remove-Item -Path $filePath -Force -ErrorAction SilentlyContinue
|
||||
New-Item -ItemType File -Path $filePath | Out-Null
|
||||
}
|
||||
|
||||
Write-Progress -Activity "$manage Applications" -Status "Starting" -PercentComplete 0
|
||||
Write-Host "==========================================="
|
||||
Write-Host "-- Configuring Chocolatey pacakages ---"
|
||||
Write-Host "==========================================="
|
||||
Foreach ($Program in $ProgramsToInstall){
|
||||
Write-Progress -Activity "$manage Applications" -Status "$manage $($Program.choco) $($x + 1) of $count" -PercentComplete $($x/$count*100)
|
||||
if($manage -eq "Installing"){
|
||||
write-host "Starting install of $($Program.choco) with Chocolatey."
|
||||
try{
|
||||
$tryUpgrade = $false
|
||||
$installOutputFilePath = "$env:TEMP\Install-WinUtilProgramChoco.install-command.output.txt"
|
||||
New-Item -ItemType File -Path $installOutputFilePath
|
||||
$chocoInstallStatus = $(Start-Process -FilePath "choco" -ArgumentList "install $($Program.choco) -y" -Wait -PassThru -RedirectStandardOutput $installOutputFilePath).ExitCode
|
||||
if(($chocoInstallStatus -eq 0) -AND (Test-Path -Path $installOutputFilePath)) {
|
||||
$keywordsFound = Get-Content -Path $installOutputFilePath | Where-Object {$_ -match "reinstall" -OR $_ -match "already installed"}
|
||||
if ($keywordsFound) {
|
||||
$tryUpgrade = $true
|
||||
}
|
||||
}
|
||||
# TODO: Implement the Upgrade part using 'choco upgrade' command, this will make choco consistent with WinGet, as WinGet tries to Upgrade when you use the install command.
|
||||
if ($tryUpgrade) {
|
||||
throw "Automatic Upgrade for Choco isn't implemented yet, a feature to make it consistent with WinGet, the install command using choco simply failed because $($Program.choco) is already installed."
|
||||
}
|
||||
if(($chocoInstallStatus -eq 0) -AND ($tryUpgrade -eq $false)){
|
||||
Write-Host "$($Program.choco) installed successfully using Chocolatey."
|
||||
continue
|
||||
} else {
|
||||
Write-Host "Failed to install $($Program.choco) using Chocolatey, Chocolatey output:`n`n$(Get-Content -Path $installOutputFilePath)."
|
||||
function Invoke-ChocoCommand {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Executes a Chocolatey command with the specified arguments and returns the exit code.
|
||||
|
||||
.PARAMETER arguments
|
||||
The arguments to be passed to the Chocolatey command.
|
||||
|
||||
.DESCRIPTION
|
||||
This function runs a specified Chocolatey command by passing the provided arguments to the `choco` executable. It waits for the process to complete and then returns the exit code, allowing the caller to determine success or failure based on the exit code.
|
||||
|
||||
.RETURNS
|
||||
[int]
|
||||
The exit code of the Chocolatey command.
|
||||
|
||||
.EXAMPLE
|
||||
$exitCode = Invoke-ChocoCommand -arguments "install 7zip -y"
|
||||
#>
|
||||
|
||||
param ($arguments)
|
||||
return (Start-Process -FilePath "choco" -ArgumentList $arguments -Wait -PassThru).ExitCode
|
||||
}
|
||||
|
||||
function Test-UpgradeNeeded {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Checks if an upgrade is needed for a Chocolatey package based on the content of a log file.
|
||||
|
||||
.PARAMETER filePath
|
||||
The path to the log file that contains the output of a Chocolatey install command.
|
||||
|
||||
.DESCRIPTION
|
||||
This function reads the specified log file and checks for keywords that indicate whether an upgrade is needed. It returns a boolean value indicating whether the terms "reinstall" or "already installed" are present, which suggests that the package might need an upgrade.
|
||||
|
||||
.RETURNS
|
||||
[bool]
|
||||
True if the log file indicates that an upgrade is needed; otherwise, false.
|
||||
|
||||
.EXAMPLE
|
||||
$isUpgradeNeeded = Test-UpgradeNeeded -filePath "C:\temp\install-output.txt"
|
||||
#>
|
||||
|
||||
param ($filePath)
|
||||
return Get-Content -Path $filePath | Select-String -Pattern "reinstall|already installed" -Quiet
|
||||
}
|
||||
|
||||
function Update-TaskbarProgress {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Updates the taskbar progress based on the current installation progress.
|
||||
|
||||
.PARAMETER currentIndex
|
||||
The current index of the program being installed or uninstalled.
|
||||
|
||||
.PARAMETER totalPrograms
|
||||
The total number of programs to be installed or uninstalled.
|
||||
|
||||
.DESCRIPTION
|
||||
This function calculates the progress of the installation or uninstallation process and updates the taskbar accordingly. The taskbar is set to "Normal" if all programs have been processed, otherwise, it is set to "Error" as a placeholder.
|
||||
|
||||
.EXAMPLE
|
||||
Update-TaskbarProgress -currentIndex 3 -totalPrograms 10
|
||||
#>
|
||||
|
||||
param (
|
||||
[int]$currentIndex,
|
||||
[int]$totalPrograms
|
||||
)
|
||||
$progressState = if ($currentIndex -eq $totalPrograms) { "Normal" } else { "Error" }
|
||||
$sync.form.Dispatcher.Invoke([action] { Set-WinUtilTaskbaritem -state $progressState -value ($currentIndex / $totalPrograms) })
|
||||
}
|
||||
|
||||
function Install-ChocoPackage {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Installs a Chocolatey package and optionally upgrades it if needed.
|
||||
|
||||
.PARAMETER Program
|
||||
A string containing the name of the Chocolatey package to be installed.
|
||||
|
||||
.PARAMETER currentIndex
|
||||
The current index of the program in the list of programs to be managed.
|
||||
|
||||
.PARAMETER totalPrograms
|
||||
The total number of programs to be installed.
|
||||
|
||||
.DESCRIPTION
|
||||
This function installs a Chocolatey package by running the `choco install` command. If the installation output indicates that an upgrade might be needed, the function will attempt to upgrade the package. The taskbar progress is updated after each package is processed.
|
||||
|
||||
.EXAMPLE
|
||||
Install-ChocoPackage -Program $Program -currentIndex 0 -totalPrograms 5
|
||||
#>
|
||||
|
||||
param (
|
||||
[string]$Program,
|
||||
[int]$currentIndex,
|
||||
[int]$totalPrograms
|
||||
)
|
||||
|
||||
$installOutputFile = "$env:TEMP\Install-WinUtilProgramChoco.install-command.output.txt"
|
||||
Initialize-OutputFile $installOutputFile
|
||||
|
||||
Write-Host "Starting installation of $Program with Chocolatey."
|
||||
|
||||
try {
|
||||
$installStatusCode = Invoke-ChocoCommand "install $Program -y --log-file $installOutputFile"
|
||||
if ($installStatusCode -eq 0) {
|
||||
|
||||
if (Test-UpgradeNeeded $installOutputFile) {
|
||||
$upgradeStatusCode = Invoke-ChocoCommand "upgrade $Program -y"
|
||||
Write-Host "$Program was" $(if ($upgradeStatusCode -eq 0) { "upgraded successfully." } else { "not upgraded." })
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Failed to install $($Program.choco) due to an error: $_"
|
||||
else {
|
||||
Write-Host "$Program installed successfully."
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Host "Failed to install $Program."
|
||||
}
|
||||
}
|
||||
|
||||
if($manage -eq "Uninstalling"){
|
||||
write-host "Starting uninstall of $($Program.choco) with Chocolatey."
|
||||
try{
|
||||
$uninstallOutputFilePath = "$env:TEMP\Install-WinUtilProgramChoco.uninstall-command.output.txt"
|
||||
New-Item -ItemType File -Path $uninstallOutputFilePath
|
||||
$chocoUninstallStatus = $(Start-Process -FilePath "choco" -ArgumentList "uninstall $($Program.choco) -y" -Wait -PassThru).ExitCode
|
||||
if($chocoUninstallStatus -eq 0){
|
||||
Write-Host "$($Program.choco) uninstalled successfully using Chocolatey."
|
||||
continue
|
||||
} else {
|
||||
Write-Host "Failed to uninstall $($Program.choco) using Chocolatey, Chocolatey output:`n`n$(Get-Content -Path $uninstallOutputFilePath)."
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Failed to uninstall $($Program.choco) due to an error: $_"
|
||||
}
|
||||
}
|
||||
$x++
|
||||
catch {
|
||||
Write-Host "Failed to install $Program due to an error: $_"
|
||||
}
|
||||
finally {
|
||||
Update-TaskbarProgress $currentIndex $totalPrograms
|
||||
}
|
||||
}
|
||||
Write-Progress -Activity "$manage Applications" -Status "Finished" -Completed
|
||||
|
||||
# Cleanup leftovers files
|
||||
if(Test-Path -Path $installOutputFilePath){ Remove-Item -Path $installOutputFilePath }
|
||||
if(Test-Path -Path $installOutputFilePath){ Remove-Item -Path $uninstallOutputFilePath }
|
||||
function Uninstall-ChocoPackage {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Uninstalls a Chocolatey package and any related metapackages.
|
||||
|
||||
return;
|
||||
.PARAMETER Program
|
||||
A string containing the name of the Chocolatey package to be uninstalled.
|
||||
|
||||
.PARAMETER currentIndex
|
||||
The current index of the program in the list of programs to be managed.
|
||||
|
||||
.PARAMETER totalPrograms
|
||||
The total number of programs to be uninstalled.
|
||||
|
||||
.DESCRIPTION
|
||||
This function uninstalls a Chocolatey package and any related metapackages (e.g., .install or .portable variants). It updates the taskbar progress after processing each package.
|
||||
|
||||
.EXAMPLE
|
||||
Uninstall-ChocoPackage -Program $Program -currentIndex 0 -totalPrograms 5
|
||||
#>
|
||||
|
||||
param (
|
||||
[string]$Program,
|
||||
[int]$currentIndex,
|
||||
[int]$totalPrograms
|
||||
)
|
||||
|
||||
$uninstallOutputFile = "$env:TEMP\Install-WinUtilProgramChoco.uninstall-command.output.txt"
|
||||
Initialize-OutputFile $uninstallOutputFile
|
||||
|
||||
Write-Host "Searching for metapackages of $Program (.install or .portable)"
|
||||
$chocoPackages = ((choco list | Select-String -Pattern "$Program(\.install|\.portable)?").Matches.Value) -join " "
|
||||
if ($chocoPackages) {
|
||||
Write-Host "Starting uninstallation of $chocoPackages with Chocolatey."
|
||||
try {
|
||||
$uninstallStatusCode = Invoke-ChocoCommand "uninstall $chocoPackages -y"
|
||||
Write-Host "$Program" $(if ($uninstallStatusCode -eq 0) { "uninstalled successfully." } else { "failed to uninstall." })
|
||||
}
|
||||
catch {
|
||||
Write-Host "Failed to uninstall $Program due to an error: $_"
|
||||
}
|
||||
finally {
|
||||
Update-TaskbarProgress $currentIndex $totalPrograms
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Host "$Program is not installed."
|
||||
}
|
||||
}
|
||||
|
||||
$totalPrograms = $Programs.Count
|
||||
if ($totalPrograms -le 0) {
|
||||
throw "Parameter 'Programs' must have at least one item."
|
||||
}
|
||||
|
||||
Write-Host "==========================================="
|
||||
Write-Host "-- Configuring Chocolatey packages ---"
|
||||
Write-Host "==========================================="
|
||||
|
||||
for ($currentIndex = 0; $currentIndex -lt $totalPrograms; $currentIndex++) {
|
||||
$Program = $Programs[$currentIndex]
|
||||
Set-WinUtilProgressBar -label "$Action $($Program)" -percent ($currentIndex / $totalPrograms * 100)
|
||||
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($currentIndex / $totalPrograms)})
|
||||
|
||||
switch ($Action) {
|
||||
"Install" {
|
||||
Install-ChocoPackage -Program $Program -currentIndex $currentIndex -totalPrograms $totalPrograms
|
||||
}
|
||||
"Uninstall" {
|
||||
Uninstall-ChocoPackage -Program $Program -currentIndex $currentIndex -totalPrograms $totalPrograms
|
||||
}
|
||||
default {
|
||||
throw "Invalid action parameter value: '$Action'."
|
||||
}
|
||||
}
|
||||
}
|
||||
Set-WinUtilProgressBar -label "$($Action)ation done" -percent 100
|
||||
# Cleanup Output Files
|
||||
$outputFiles = @("$env:TEMP\Install-WinUtilProgramChoco.install-command.output.txt", "$env:TEMP\Install-WinUtilProgramChoco.uninstall-command.output.txt")
|
||||
foreach ($filePath in $outputFiles) {
|
||||
Remove-Item -Path $filePath -Force -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,103 +1,169 @@
|
||||
Function Install-WinUtilProgramWinget {
|
||||
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Manages the provided programs using Winget
|
||||
|
||||
.PARAMETER ProgramsToInstall
|
||||
A list of programs to manage
|
||||
|
||||
.PARAMETER manage
|
||||
The action to perform on the programs, can be either 'Installing' or 'Uninstalling'
|
||||
|
||||
Runs the designated action on the provided programs using Winget
|
||||
|
||||
.PARAMETER Programs
|
||||
A list of programs to process
|
||||
|
||||
.PARAMETER action
|
||||
The action to perform on the programs, can be either 'Install' or 'Uninstall'
|
||||
|
||||
.NOTES
|
||||
The triple quotes are required any time you need a " in a normal script block.
|
||||
The winget Return codes are documented here: https://github.com/microsoft/winget-cli/blob/master/doc/windows/package-manager/winget/returnCodes.md
|
||||
The winget Return codes are documented here: https://github.com/microsoft/winget-cli/blob/master/doc/windows/package-actionr/winget/returnCodes.md
|
||||
#>
|
||||
|
||||
|
||||
param(
|
||||
[Parameter(Mandatory, Position=0)]
|
||||
[PsCustomObject]$ProgramsToInstall,
|
||||
|
||||
[Parameter(Position=1)]
|
||||
[String]$manage = "Installing"
|
||||
[Parameter(Mandatory, Position=0)]$Programs,
|
||||
|
||||
[Parameter(Mandatory, Position=1)]
|
||||
[ValidateSet("Install", "Uninstall")]
|
||||
[String]$Action
|
||||
)
|
||||
$x = 0
|
||||
$count = $ProgramsToInstall.Count
|
||||
|
||||
Write-Progress -Activity "$manage Applications" -Status "Starting" -PercentComplete 0
|
||||
|
||||
Function Invoke-Winget {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Invokes the winget.exe with the provided arguments and return the exit code
|
||||
|
||||
.PARAMETER wingetId
|
||||
The Id of the Program that Winget should Install/Uninstall
|
||||
|
||||
.PARAMETER scope
|
||||
Determines the installation mode. Can be "user" or "machine" (For more info look at the winget documentation)
|
||||
|
||||
.PARAMETER credential
|
||||
The PSCredential Object of the user that should be used to run winget
|
||||
|
||||
.NOTES
|
||||
Invoke Winget uses the public variable $Action defined outside the function to determine if a Program should be installed or removed
|
||||
#>
|
||||
param (
|
||||
[string]$wingetId,
|
||||
[string]$scope = "",
|
||||
[PScredential]$credential = $null
|
||||
)
|
||||
|
||||
$commonArguments = "--id $wingetId --silent"
|
||||
$arguments = if ($Action -eq "Install") {
|
||||
"install $commonArguments --accept-source-agreements --accept-package-agreements $(if ($scope) {" --scope $scope"})"
|
||||
} else {
|
||||
"uninstall $commonArguments"
|
||||
}
|
||||
|
||||
$processParams = @{
|
||||
FilePath = "winget"
|
||||
ArgumentList = $arguments
|
||||
Wait = $true
|
||||
PassThru = $true
|
||||
NoNewWindow = $true
|
||||
}
|
||||
|
||||
if ($credential) {
|
||||
$processParams.credential = $credential
|
||||
}
|
||||
|
||||
return (Start-Process @processParams).ExitCode
|
||||
}
|
||||
|
||||
Function Invoke-Install {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Contains the Install Logic and return code handling from winget
|
||||
|
||||
.PARAMETER Program
|
||||
The Winget ID of the Program that should be installed
|
||||
#>
|
||||
param (
|
||||
[string]$Program
|
||||
)
|
||||
$status = Invoke-Winget -wingetId $Program
|
||||
if ($status -eq 0) {
|
||||
Write-Host "$($Program) installed successfully."
|
||||
return $true
|
||||
} elseif ($status -eq -1978335189) {
|
||||
Write-Host "$($Program) No applicable update found"
|
||||
return $true
|
||||
}
|
||||
|
||||
Write-Host "Attempt installation of $($Program) with User scope"
|
||||
$status = Invoke-Winget -wingetId $Program -scope "user"
|
||||
if ($status -eq 0) {
|
||||
Write-Host "$($Program) installed successfully with User scope."
|
||||
return $true
|
||||
} elseif ($status -eq -1978335189) {
|
||||
Write-Host "$($Program) No applicable update found"
|
||||
return $true
|
||||
}
|
||||
|
||||
$userChoice = [System.Windows.MessageBox]::Show("Do you want to attempt $($Program) installation with specific user credentials? Select 'Yes' to proceed or 'No' to skip.", "User credential Prompt", [System.Windows.MessageBoxButton]::YesNo)
|
||||
if ($userChoice -eq 'Yes') {
|
||||
$getcreds = Get-Credential
|
||||
$status = Invoke-Winget -wingetId $Program -credential $getcreds
|
||||
if ($status -eq 0) {
|
||||
Write-Host "$($Program) installed successfully with User prompt."
|
||||
return $true
|
||||
}
|
||||
} else {
|
||||
Write-Host "Skipping installation with specific user credentials."
|
||||
}
|
||||
|
||||
Write-Host "Failed to install $($Program)."
|
||||
return $false
|
||||
}
|
||||
|
||||
Function Invoke-Uninstall {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Contains the Uninstall Logic and return code handling from winget
|
||||
|
||||
.PARAMETER Program
|
||||
The Winget ID of the Program that should be uninstalled
|
||||
#>
|
||||
param (
|
||||
[psobject]$Program
|
||||
)
|
||||
|
||||
try {
|
||||
$status = Invoke-Winget -wingetId $Program
|
||||
if ($status -eq 0) {
|
||||
Write-Host "$($Program) uninstalled successfully."
|
||||
return $true
|
||||
} else {
|
||||
Write-Host "Failed to uninstall $($Program)."
|
||||
return $false
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Failed to uninstall $($Program) due to an error: $_"
|
||||
return $false
|
||||
}
|
||||
}
|
||||
|
||||
$count = $Programs.Count
|
||||
$failedPackages = @()
|
||||
|
||||
Write-Host "==========================================="
|
||||
Write-Host "-- Configuring winget packages ---"
|
||||
Write-Host "==========================================="
|
||||
Foreach ($Program in $ProgramsToInstall){
|
||||
$failedPackages = @()
|
||||
Write-Progress -Activity "$manage Applications" -Status "$manage $($Program.winget) $($x + 1) of $count" -PercentComplete $($x/$count*100)
|
||||
if($manage -eq "Installing"){
|
||||
# Install package via ID, if it fails try again with different scope and then with an unelevated prompt.
|
||||
# Since Install-WinGetPackage might not be directly available, we use winget install command as a workaround.
|
||||
# Winget, not all installers honor any of the following: System-wide, User Installs, or Unelevated Prompt OR Silent Install Mode.
|
||||
# This is up to the individual package maintainers to enable these options. Aka. not as clean as Linux Package Managers.
|
||||
Write-Host "Starting install of $($Program.winget) with winget."
|
||||
try {
|
||||
$status = $(Start-Process -FilePath "winget" -ArgumentList "install --id $($Program.winget) --silent --accept-source-agreements --accept-package-agreements" -Wait -PassThru -NoNewWindow).ExitCode
|
||||
if($status -eq 0){
|
||||
Write-Host "$($Program.winget) installed successfully."
|
||||
continue
|
||||
}
|
||||
if ($status -eq -1978335189){
|
||||
Write-Host "$($Program.winget) No applicable update found"
|
||||
continue
|
||||
}
|
||||
Write-Host "Attempt with User scope"
|
||||
$status = $(Start-Process -FilePath "winget" -ArgumentList "install --id $($Program.winget) --scope user --silent --accept-source-agreements --accept-package-agreements" -Wait -PassThru -NoNewWindow).ExitCode
|
||||
if($status -eq 0){
|
||||
Write-Host "$($Program.winget) installed successfully with User scope."
|
||||
continue
|
||||
}
|
||||
if ($status -eq -1978335189){
|
||||
Write-Host "$($Program.winget) No applicable update found"
|
||||
continue
|
||||
}
|
||||
Write-Host "Attempt with User prompt"
|
||||
$userChoice = [System.Windows.MessageBox]::Show("Do you want to attempt $($Program.winget) installation with specific user credentials? Select 'Yes' to proceed or 'No' to skip.", "User Credential Prompt", [System.Windows.MessageBoxButton]::YesNo)
|
||||
if ($userChoice -eq 'Yes') {
|
||||
$getcreds = Get-Credential
|
||||
$process = Start-Process -FilePath "winget" -ArgumentList "install --id $($Program.winget) --silent --accept-source-agreements --accept-package-agreements" -Credential $getcreds -PassThru -NoNewWindow
|
||||
Wait-Process -Id $process.Id
|
||||
$status = $process.ExitCode
|
||||
} else {
|
||||
Write-Host "Skipping installation with specific user credentials."
|
||||
}
|
||||
if($status -eq 0){
|
||||
Write-Host "$($Program.winget) installed successfully with User prompt."
|
||||
continue
|
||||
}
|
||||
if ($status -eq -1978335189){
|
||||
Write-Host "$($Program.winget) No applicable update found"
|
||||
continue
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Failed to install $($Program.winget). With winget"
|
||||
$failedPackages += $Program
|
||||
}
|
||||
|
||||
for ($i = 0; $i -lt $count; $i++) {
|
||||
$Program = $Programs[$i]
|
||||
$result = $false
|
||||
Set-WinUtilProgressBar -label "$Action $($Program)" -percent ($i / $count * 100)
|
||||
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($i / $count)})
|
||||
|
||||
$result = switch ($Action) {
|
||||
"Install" {Invoke-Install -Program $Program}
|
||||
"Uninstall" {Invoke-Uninstall -Program $Program}
|
||||
default {throw "[Install-WinUtilProgramWinget] Invalid action: $Action"}
|
||||
}
|
||||
if($manage -eq "Uninstalling"){
|
||||
# Uninstall package via ID using winget directly.
|
||||
try {
|
||||
$status = $(Start-Process -FilePath "winget" -ArgumentList "uninstall --id $($Program.winget) --silent" -Wait -PassThru -NoNewWindow).ExitCode
|
||||
if($status -ne 0){
|
||||
Write-Host "Failed to uninstall $($Program.winget)."
|
||||
} else {
|
||||
Write-Host "$($Program.winget) uninstalled successfully."
|
||||
$failedPackages += $Program
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Failed to uninstall $($Program.winget) due to an error: $_"
|
||||
$failedPackages += $Program
|
||||
}
|
||||
|
||||
if (-not $result) {
|
||||
$failedPackages += $Program
|
||||
}
|
||||
$X++
|
||||
}
|
||||
Write-Progress -Activity "$manage Applications" -Status "Finished" -Completed
|
||||
return $failedPackages;
|
||||
|
||||
Set-WinUtilProgressBar -label "$($Action)ation done" -percent 100
|
||||
return $failedPackages
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ function Install-WinUtilWinget {
|
||||
#>
|
||||
$isWingetInstalled = Test-WinUtilPackageManager -winget
|
||||
|
||||
Try {
|
||||
try {
|
||||
if ($isWingetInstalled -eq "installed") {
|
||||
Write-Host "`nWinget is already installed.`r" -ForegroundColor Green
|
||||
return
|
||||
@ -19,8 +19,9 @@ function Install-WinUtilWinget {
|
||||
Write-Host "`nWinget is not Installed. Continuing with install.`r" -ForegroundColor Red
|
||||
}
|
||||
|
||||
|
||||
# Gets the computer's information
|
||||
if ($null -eq $sync.ComputerInfo){
|
||||
if ($null -eq $sync.ComputerInfo) {
|
||||
$ComputerInfo = Get-ComputerInfo -ErrorAction Stop
|
||||
} else {
|
||||
$ComputerInfo = $sync.ComputerInfo
|
||||
@ -32,35 +33,44 @@ function Install-WinUtilWinget {
|
||||
return
|
||||
}
|
||||
|
||||
# Install Winget via GitHub method.
|
||||
# Used part of my own script with some modification: ruxunderscore/windows-initialization
|
||||
Write-Host "Downloading Winget Prerequsites`n"
|
||||
Get-WinUtilWingetPrerequisites
|
||||
Write-Host "Downloading Winget and License File`r"
|
||||
Get-WinUtilWingetLatest
|
||||
Write-Host "Installing Winget w/ Prerequsites`r"
|
||||
Add-AppxProvisionedPackage -Online -PackagePath $ENV:TEMP\Microsoft.DesktopAppInstaller.msixbundle -DependencyPackagePath $ENV:TEMP\Microsoft.VCLibs.x64.Desktop.appx, $ENV:TEMP\Microsoft.UI.Xaml.x64.appx -LicensePath $ENV:TEMP\License1.xml
|
||||
Write-Host "Manually adding Winget Sources, from Winget CDN."
|
||||
Add-AppxPackage -Path https://cdn.winget.microsoft.com/cache/source.msix #Seems some installs of Winget don't add the repo source, this should makes sure that it's installed every time.
|
||||
Write-Host "Winget Installed" -ForegroundColor Green
|
||||
Write-Host "Enabling NuGet and Module..."
|
||||
Install-PackageProvider -Name NuGet -Force
|
||||
Install-Module -Name Microsoft.WinGet.Client -Force
|
||||
# Winget only needs a refresh of the environment variables to be used.
|
||||
Write-Output "Refreshing Environment Variables...`n"
|
||||
$ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
|
||||
} Catch {
|
||||
Write-Host "Failure detected while installing via GitHub method. Continuing with Chocolatey method as fallback." -ForegroundColor Red
|
||||
# In case install fails via GitHub method.
|
||||
Try {
|
||||
# Install Choco if not already present
|
||||
Install-WinUtilChoco
|
||||
Start-Process -Verb runas -FilePath powershell.exe -ArgumentList "choco install winget-cli"
|
||||
Write-Host "Winget Installed" -ForegroundColor Green
|
||||
Write-Output "Refreshing Environment Variables...`n"
|
||||
$ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
|
||||
} Catch {
|
||||
throw [WingetFailedInstall]::new('Failed to install!')
|
||||
Write-Host "Attempting to install/update Winget`r"
|
||||
try {
|
||||
$wingetCmd = Get-Command winget -ErrorAction Stop
|
||||
Write-Information "Attempting to update WinGet using WinGet..."
|
||||
$result = Start-Process -FilePath "`"$($wingetCmd.Source)`"" -ArgumentList "install -e --accept-source-agreements --accept-package-agreements Microsoft.AppInstaller" -Wait -NoNewWindow -PassThru
|
||||
if ($result.ExitCode -ne 0) {
|
||||
throw "WinGet update failed with exit code: $($result.ExitCode)"
|
||||
}
|
||||
Write-Output "Refreshing Environment Variables...`n"
|
||||
$ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
|
||||
return
|
||||
} catch {
|
||||
Write-Information "WinGet not found or update failed. Attempting to install from Microsoft Store..."
|
||||
}
|
||||
try {
|
||||
Write-Host "Attempting to repair WinGet using Repair-WinGetPackageManager..." -ForegroundColor Yellow
|
||||
|
||||
# Check if Windows version supports Repair-WinGetPackageManager (24H2 and above)
|
||||
if ([System.Environment]::OSVersion.Version.Build -ge 26100) {
|
||||
Repair-WinGetPackageManager -Force -Latest -Verbose
|
||||
# Verify if repair was successful
|
||||
$wingetCmd = Get-Command winget -ErrorAction Stop
|
||||
Write-Host "WinGet repair successful!" -ForegroundColor Green
|
||||
} else {
|
||||
Write-Host "Repair-WinGetPackageManager is only available on Windows 24H2 and above. Your version doesn't support this method." -ForegroundColor Yellow
|
||||
throw "Windows version not supported for repair method"
|
||||
}
|
||||
|
||||
Write-Output "Refreshing Environment Variables...`n"
|
||||
$ENV:PATH = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
|
||||
return
|
||||
|
||||
} catch {
|
||||
Write-Error "All installation methods failed. Unable to install WinGet."
|
||||
throw
|
||||
}
|
||||
} catch {
|
||||
Write-Error "An error occurred during WinGet installation: $_"
|
||||
throw
|
||||
}
|
||||
}
|
||||
|
@ -1,648 +0,0 @@
|
||||
function Test-CompatibleImage() {
|
||||
<#
|
||||
|
||||
.SYNOPSIS
|
||||
Checks the version of a Windows image and determines whether or not it is compatible with a specific feature depending on a desired version
|
||||
|
||||
.PARAMETER Name
|
||||
imgVersion - The version of the Windows image
|
||||
desiredVersion - The version to compare the image version with
|
||||
|
||||
#>
|
||||
|
||||
param
|
||||
(
|
||||
[Parameter(Mandatory = $true, Position=0)] [string] $imgVersion,
|
||||
[Parameter(Mandatory = $true, Position=1)] [Version] $desiredVersion
|
||||
)
|
||||
|
||||
try {
|
||||
$version = [Version]$imgVersion
|
||||
return $version -ge $desiredVersion
|
||||
} catch {
|
||||
return $False
|
||||
}
|
||||
}
|
||||
|
||||
function Remove-Features([switch] $dumpFeatures = $false, [switch] $keepDefender = $false) {
|
||||
<#
|
||||
|
||||
.SYNOPSIS
|
||||
Removes certain features from ISO image
|
||||
|
||||
.PARAMETER Name
|
||||
dumpFeatures - Dumps all features found in the ISO into a file called allfeaturesdump.txt. This file can be examined and used to decide what to remove.
|
||||
keepDefender - Should Defender be removed from the ISO?
|
||||
|
||||
.EXAMPLE
|
||||
Remove-Features -keepDefender:$false
|
||||
|
||||
#>
|
||||
$featlist = (Get-WindowsOptionalFeature -Path $scratchDir).FeatureName
|
||||
if ($dumpFeatures)
|
||||
{
|
||||
$featlist > allfeaturesdump.txt
|
||||
}
|
||||
|
||||
$featlist = $featlist | Where-Object {
|
||||
$_ -NotLike "*Printing*" -AND
|
||||
$_ -NotLike "*TelnetClient*" -AND
|
||||
$_ -NotLike "*PowerShell*" -AND
|
||||
$_ -NotLike "*NetFx*" -AND
|
||||
$_ -NotLike "*Media*" -AND
|
||||
$_ -NotLike "*NFS*"
|
||||
}
|
||||
|
||||
if ($keepDefender) { $featlist = $featlist | Where-Object { $_ -NotLike "*Defender*" }}
|
||||
|
||||
foreach($feature in $featlist)
|
||||
{
|
||||
$status = "Removing feature $feature"
|
||||
Write-Progress -Activity "Removing features" -Status $status -PercentComplete ($counter++/$featlist.Count*100)
|
||||
Write-Debug "Removing feature $feature"
|
||||
Disable-WindowsOptionalFeature -Path "$scratchDir" -FeatureName $feature -Remove -ErrorAction SilentlyContinue -NoRestart
|
||||
}
|
||||
Write-Progress -Activity "Removing features" -Status "Ready" -Completed
|
||||
Write-Host "You can re-enable the disabled features at any time, using either Windows Update or the SxS folder in <installation media>\Sources."
|
||||
}
|
||||
|
||||
function Remove-Packages
|
||||
{
|
||||
$pkglist = (Get-WindowsPackage -Path "$scratchDir").PackageName
|
||||
|
||||
$pkglist = $pkglist | Where-Object {
|
||||
$_ -NotLike "*ApplicationModel*" -AND
|
||||
$_ -NotLike "*indows-Client-LanguagePack*" -AND
|
||||
$_ -NotLike "*LanguageFeatures-Basic*" -AND
|
||||
$_ -NotLike "*Package_for_ServicingStack*" -AND
|
||||
$_ -NotLike "*.NET*" -AND
|
||||
$_ -NotLike "*Store*" -AND
|
||||
$_ -NotLike "*VCLibs*" -AND
|
||||
$_ -NotLike "*AAD.BrokerPlugin",
|
||||
$_ -NotLike "*LockApp*" -AND
|
||||
$_ -NotLike "*Notepad*" -AND
|
||||
$_ -NotLike "*immersivecontrolpanel*" -AND
|
||||
$_ -NotLike "*ContentDeliveryManager*" -AND
|
||||
$_ -NotLike "*PinningConfirMationDialog*" -AND
|
||||
$_ -NotLike "*SecHealthUI*" -AND
|
||||
$_ -NotLike "*SecureAssessmentBrowser*" -AND
|
||||
$_ -NotLike "*PrintDialog*" -AND
|
||||
$_ -NotLike "*AssignedAccessLockApp*" -AND
|
||||
$_ -NotLike "*OOBENetworkConnectionFlow*" -AND
|
||||
$_ -NotLike "*Apprep.ChxApp*" -AND
|
||||
$_ -NotLike "*CBS*" -AND
|
||||
$_ -NotLike "*OOBENetworkCaptivePortal*" -AND
|
||||
$_ -NotLike "*PeopleExperienceHost*" -AND
|
||||
$_ -NotLike "*ParentalControls*" -AND
|
||||
$_ -NotLike "*Win32WebViewHost*" -AND
|
||||
$_ -NotLike "*InputApp*" -AND
|
||||
$_ -NotLike "*AccountsControl*" -AND
|
||||
$_ -NotLike "*AsyncTextService*" -AND
|
||||
$_ -NotLike "*CapturePicker*" -AND
|
||||
$_ -NotLike "*CredDialogHost*" -AND
|
||||
$_ -NotLike "*BioEnrollMent*" -AND
|
||||
$_ -NotLike "*ShellExperienceHost*" -AND
|
||||
$_ -NotLike "*DesktopAppInstaller*" -AND
|
||||
$_ -NotLike "*WebMediaExtensions*" -AND
|
||||
$_ -NotLike "*WMIC*" -AND
|
||||
$_ -NotLike "*UI.XaML*"
|
||||
}
|
||||
|
||||
foreach ($pkg in $pkglist)
|
||||
{
|
||||
try {
|
||||
$status = "Removing $pkg"
|
||||
Write-Progress -Activity "Removing Apps" -Status $status -PercentComplete ($counter++/$pkglist.Count*100)
|
||||
Remove-WindowsPackage -Path "$scratchDir" -PackageName $pkg -NoRestart -ErrorAction SilentlyContinue
|
||||
}
|
||||
catch {
|
||||
# This can happen if the package that is being removed is a permanent one, like FodMetadata
|
||||
Write-Host "Could not remove OS package $($pkg)"
|
||||
continue
|
||||
}
|
||||
}
|
||||
Write-Progress -Activity "Removing Apps" -Status "Ready" -Completed
|
||||
}
|
||||
|
||||
function Remove-ProvisionedPackages([switch] $keepSecurity = $false)
|
||||
{
|
||||
<#
|
||||
|
||||
.SYNOPSIS
|
||||
Removes AppX packages from a Windows image during MicroWin processing
|
||||
|
||||
.PARAMETER Name
|
||||
keepSecurity - Boolean that determines whether to keep "Microsoft.SecHealthUI" (Windows Security) in the Windows image
|
||||
|
||||
.EXAMPLE
|
||||
Remove-ProvisionedPackages -keepSecurity:$false
|
||||
|
||||
#>
|
||||
$appxProvisionedPackages = Get-AppxProvisionedPackage -Path "$($scratchDir)" | Where-Object {
|
||||
$_.PackageName -NotLike "*AppInstaller*" -AND
|
||||
$_.PackageName -NotLike "*Store*" -and
|
||||
$_.PackageName -NotLike "*dism*" -and
|
||||
$_.PackageName -NotLike "*Foundation*" -and
|
||||
$_.PackageName -NotLike "*FodMetadata*" -and
|
||||
$_.PackageName -NotLike "*LanguageFeatures*" -and
|
||||
$_.PackageName -NotLike "*Notepad*" -and
|
||||
$_.PackageName -NotLike "*Printing*" -and
|
||||
$_.PackageName -NotLike "*Wifi*" -and
|
||||
$_.PackageName -NotLike "*Foundation*"
|
||||
}
|
||||
|
||||
if ($?)
|
||||
{
|
||||
if ($keepSecurity) { $appxProvisionedPackages = $appxProvisionedPackages | Where-Object { $_.PackageName -NotLike "*SecHealthUI*" }}
|
||||
$counter = 0
|
||||
foreach ($appx in $appxProvisionedPackages)
|
||||
{
|
||||
$status = "Removing Provisioned $($appx.PackageName)"
|
||||
Write-Progress -Activity "Removing Provisioned Apps" -Status $status -PercentComplete ($counter++/$appxProvisionedPackages.Count*100)
|
||||
Remove-AppxProvisionedPackage -Path $scratchDir -PackageName $appx.PackageName -ErrorAction SilentlyContinue
|
||||
}
|
||||
Write-Progress -Activity "Removing Provisioned Apps" -Status "Ready" -Completed
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "Could not get Provisioned App information. Skipping process..."
|
||||
}
|
||||
}
|
||||
|
||||
function Copy-ToUSB([string] $fileToCopy)
|
||||
{
|
||||
foreach ($volume in Get-Volume) {
|
||||
if ($volume -and $volume.FileSystemLabel -ieq "ventoy") {
|
||||
$destinationPath = "$($volume.DriveLetter):\"
|
||||
#Copy-Item -Path $fileToCopy -Destination $destinationPath -Force
|
||||
# Get the total size of the file
|
||||
$totalSize = (Get-Item $fileToCopy).length
|
||||
|
||||
Copy-Item -Path $fileToCopy -Destination $destinationPath -Verbose -Force -Recurse -Container -PassThru |
|
||||
ForEach-Object {
|
||||
# Calculate the percentage completed
|
||||
$completed = ($_.BytesTransferred / $totalSize) * 100
|
||||
|
||||
# Display the progress bar
|
||||
Write-Progress -Activity "Copying File" -Status "Progress" -PercentComplete $completed -CurrentOperation ("{0:N2} MB / {1:N2} MB" -f ($_.BytesTransferred / 1MB), ($totalSize / 1MB))
|
||||
}
|
||||
|
||||
Write-Host "File copied to Ventoy drive $($volume.DriveLetter)"
|
||||
return
|
||||
}
|
||||
}
|
||||
Write-Host "Ventoy USB Key is not inserted"
|
||||
}
|
||||
|
||||
function Remove-FileOrDirectory([string] $pathToDelete, [string] $mask = "", [switch] $Directory = $false)
|
||||
{
|
||||
if(([string]::IsNullOrEmpty($pathToDelete))) { return }
|
||||
if (-not (Test-Path -Path "$($pathToDelete)")) { return }
|
||||
|
||||
$yesNo = Get-LocalizedYesNo
|
||||
Write-Host "[INFO] In Your local takeown expects '$($yesNo[0])' as a Yes answer."
|
||||
|
||||
# Specify the path to the directory
|
||||
# $directoryPath = "$($scratchDir)\Windows\System32\LogFiles\WMI\RtBackup"
|
||||
# takeown /a /r /d $yesNo[0] /f "$($directoryPath)" > $null
|
||||
# icacls "$($directoryPath)" /q /c /t /reset > $null
|
||||
# icacls $directoryPath /setowner "*S-1-5-32-544"
|
||||
# icacls $directoryPath /grant "*S-1-5-32-544:(OI)(CI)F" /t /c /q
|
||||
# Remove-Item -Path $directoryPath -Recurse -Force
|
||||
|
||||
# # Grant full control to BUILTIN\Administrators using icacls
|
||||
# $directoryPath = "$($scratchDir)\Windows\System32\WebThreatDefSvc"
|
||||
# takeown /a /r /d $yesNo[0] /f "$($directoryPath)" > $null
|
||||
# icacls "$($directoryPath)" /q /c /t /reset > $null
|
||||
# icacls $directoryPath /setowner "*S-1-5-32-544"
|
||||
# icacls $directoryPath /grant "*S-1-5-32-544:(OI)(CI)F" /t /c /q
|
||||
# Remove-Item -Path $directoryPath -Recurse -Force
|
||||
|
||||
$itemsToDelete = [System.Collections.ArrayList]::new()
|
||||
|
||||
if ($mask -eq "")
|
||||
{
|
||||
Write-Debug "Adding $($pathToDelete) to array."
|
||||
[void]$itemsToDelete.Add($pathToDelete)
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Debug "Adding $($pathToDelete) to array and mask is $($mask)"
|
||||
if ($Directory) { $itemsToDelete = Get-ChildItem $pathToDelete -Include $mask -Recurse -Directory }
|
||||
else { $itemsToDelete = Get-ChildItem $pathToDelete -Include $mask -Recurse }
|
||||
}
|
||||
|
||||
foreach($itemToDelete in $itemsToDelete)
|
||||
{
|
||||
$status = "Deleting $($itemToDelete)"
|
||||
Write-Progress -Activity "Removing Items" -Status $status -PercentComplete ($counter++/$itemsToDelete.Count*100)
|
||||
|
||||
if (Test-Path -Path "$($itemToDelete)" -PathType Container)
|
||||
{
|
||||
$status = "Deleting directory: $($itemToDelete)"
|
||||
|
||||
takeown /r /d $yesNo[0] /a /f "$($itemToDelete)"
|
||||
icacls "$($itemToDelete)" /q /c /t /reset
|
||||
icacls $itemToDelete /setowner "*S-1-5-32-544"
|
||||
icacls $itemToDelete /grant "*S-1-5-32-544:(OI)(CI)F" /t /c /q
|
||||
Remove-Item -Force -Recurse "$($itemToDelete)"
|
||||
}
|
||||
elseif (Test-Path -Path "$($itemToDelete)" -PathType Leaf)
|
||||
{
|
||||
$status = "Deleting file: $($itemToDelete)"
|
||||
|
||||
takeown /a /f "$($itemToDelete)"
|
||||
icacls "$($itemToDelete)" /q /c /t /reset
|
||||
icacls "$($itemToDelete)" /setowner "*S-1-5-32-544"
|
||||
icacls "$($itemToDelete)" /grant "*S-1-5-32-544:(OI)(CI)F" /t /c /q
|
||||
Remove-Item -Force "$($itemToDelete)"
|
||||
}
|
||||
}
|
||||
Write-Progress -Activity "Removing Items" -Status "Ready" -Completed
|
||||
}
|
||||
|
||||
function New-Unattend {
|
||||
|
||||
# later if we wont to remove even more bloat EU requires MS to remove everything from English(world)
|
||||
# Below is an example how to do it we probably should create a drop down with common locals
|
||||
# <settings pass="specialize">
|
||||
# <!-- Specify English (World) locale -->
|
||||
# <component name="Microsoft-Windows-International-Core" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
# <SetupUILanguage>
|
||||
# <UILanguage>en-US</UILanguage>
|
||||
# </SetupUILanguage>
|
||||
# <InputLocale>en-US</InputLocale>
|
||||
# <SystemLocale>en-US</SystemLocale>
|
||||
# <UILanguage>en-US</UILanguage>
|
||||
# <UserLocale>en-US</UserLocale>
|
||||
# </component>
|
||||
# </settings>
|
||||
|
||||
# <settings pass="oobeSystem">
|
||||
# <!-- Specify English (World) locale -->
|
||||
# <component name="Microsoft-Windows-International-Core" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
# <InputLocale>en-US</InputLocale>
|
||||
# <SystemLocale>en-US</SystemLocale>
|
||||
# <UILanguage>en-US</UILanguage>
|
||||
# <UserLocale>en-US</UserLocale>
|
||||
# </component>
|
||||
# </settings>
|
||||
# using here string to embedd unattend
|
||||
# <RunSynchronousCommand wcm:action="add">
|
||||
# <Order>1</Order>
|
||||
# <Path>net user administrator /active:yes</Path>
|
||||
# </RunSynchronousCommand>
|
||||
|
||||
# this section doesn't work in win10/????
|
||||
# <settings pass="specialize">
|
||||
# <component name="Microsoft-Windows-SQMApi" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
# <CEIPEnabled>0</CEIPEnabled>
|
||||
# </component>
|
||||
# <component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
# <ConfigureChatAutoInstall>false</ConfigureChatAutoInstall>
|
||||
# </component>
|
||||
# </settings>
|
||||
|
||||
$unattend = @'
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<unattend xmlns="urn:schemas-microsoft-com:unattend"
|
||||
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<#REPLACEME#>
|
||||
<settings pass="auditUser">
|
||||
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<RunSynchronous>
|
||||
<RunSynchronousCommand wcm:action="add">
|
||||
<Order>1</Order>
|
||||
<CommandLine>CMD /C echo LAU GG>C:\Windows\LogAuditUser.txt</CommandLine>
|
||||
<Description>StartMenu</Description>
|
||||
</RunSynchronousCommand>
|
||||
</RunSynchronous>
|
||||
</component>
|
||||
</settings>
|
||||
<settings pass="oobeSystem">
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<OOBE>
|
||||
<HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
|
||||
<SkipUserOOBE>false</SkipUserOOBE>
|
||||
<SkipMachineOOBE>false</SkipMachineOOBE>
|
||||
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
|
||||
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
|
||||
<HideEULAPage>true</HideEULAPage>
|
||||
<ProtectYourPC>3</ProtectYourPC>
|
||||
</OOBE>
|
||||
<FirstLogonCommands>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>1</Order>
|
||||
<CommandLine>cmd.exe /c echo 23>c:\windows\csup.txt</CommandLine>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>2</Order>
|
||||
<CommandLine>CMD /C echo GG>C:\Windows\LogOobeSystem.txt</CommandLine>
|
||||
</SynchronousCommand>
|
||||
<SynchronousCommand wcm:action="add">
|
||||
<Order>3</Order>
|
||||
<CommandLine>powershell -ExecutionPolicy Bypass -File c:\windows\FirstStartup.ps1</CommandLine>
|
||||
</SynchronousCommand>
|
||||
</FirstLogonCommands>
|
||||
</component>
|
||||
</settings>
|
||||
</unattend>
|
||||
'@
|
||||
$specPass = @'
|
||||
<settings pass="specialize">
|
||||
<component name="Microsoft-Windows-SQMApi" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<CEIPEnabled>0</CEIPEnabled>
|
||||
</component>
|
||||
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<ConfigureChatAutoInstall>false</ConfigureChatAutoInstall>
|
||||
</component>
|
||||
</settings>
|
||||
'@
|
||||
if ((Test-CompatibleImage $imgVersion $([System.Version]::new(10,0,22000,1))) -eq $false)
|
||||
{
|
||||
# Replace the placeholder text with an empty string to make it valid for Windows 10 Setup
|
||||
$unattend = $unattend.Replace("<#REPLACEME#>", "").Trim()
|
||||
}
|
||||
else
|
||||
{
|
||||
# Replace the placeholder text with the Specialize pass
|
||||
$unattend = $unattend.Replace("<#REPLACEME#>", $specPass).Trim()
|
||||
}
|
||||
$unattend | Out-File -FilePath "$env:temp\unattend.xml" -Force -Encoding utf8
|
||||
}
|
||||
|
||||
function New-CheckInstall {
|
||||
|
||||
# using here string to embedd firstrun
|
||||
$checkInstall = @'
|
||||
@echo off
|
||||
if exist "C:\windows\cpu.txt" (
|
||||
echo C:\windows\cpu.txt exists
|
||||
) else (
|
||||
echo C:\windows\cpu.txt does not exist
|
||||
)
|
||||
if exist "C:\windows\SerialNumber.txt" (
|
||||
echo C:\windows\SerialNumber.txt exists
|
||||
) else (
|
||||
echo C:\windows\SerialNumber.txt does not exist
|
||||
)
|
||||
if exist "C:\unattend.xml" (
|
||||
echo C:\unattend.xml exists
|
||||
) else (
|
||||
echo C:\unattend.xml does not exist
|
||||
)
|
||||
if exist "C:\Windows\Setup\Scripts\SetupComplete.cmd" (
|
||||
echo C:\Windows\Setup\Scripts\SetupComplete.cmd exists
|
||||
) else (
|
||||
echo C:\Windows\Setup\Scripts\SetupComplete.cmd does not exist
|
||||
)
|
||||
if exist "C:\Windows\Panther\unattend.xml" (
|
||||
echo C:\Windows\Panther\unattend.xml exists
|
||||
) else (
|
||||
echo C:\Windows\Panther\unattend.xml does not exist
|
||||
)
|
||||
if exist "C:\Windows\System32\Sysprep\unattend.xml" (
|
||||
echo C:\Windows\System32\Sysprep\unattend.xml exists
|
||||
) else (
|
||||
echo C:\Windows\System32\Sysprep\unattend.xml does not exist
|
||||
)
|
||||
if exist "C:\Windows\FirstStartup.ps1" (
|
||||
echo C:\Windows\FirstStartup.ps1 exists
|
||||
) else (
|
||||
echo C:\Windows\FirstStartup.ps1 does not exist
|
||||
)
|
||||
if exist "C:\Windows\winutil.ps1" (
|
||||
echo C:\Windows\winutil.ps1 exists
|
||||
) else (
|
||||
echo C:\Windows\winutil.ps1 does not exist
|
||||
)
|
||||
if exist "C:\Windows\LogSpecialize.txt" (
|
||||
echo C:\Windows\LogSpecialize.txt exists
|
||||
) else (
|
||||
echo C:\Windows\LogSpecialize.txt does not exist
|
||||
)
|
||||
if exist "C:\Windows\LogAuditUser.txt" (
|
||||
echo C:\Windows\LogAuditUser.txt exists
|
||||
) else (
|
||||
echo C:\Windows\LogAuditUser.txt does not exist
|
||||
)
|
||||
if exist "C:\Windows\LogOobeSystem.txt" (
|
||||
echo C:\Windows\LogOobeSystem.txt exists
|
||||
) else (
|
||||
echo C:\Windows\LogOobeSystem.txt does not exist
|
||||
)
|
||||
if exist "c:\windows\csup.txt" (
|
||||
echo c:\windows\csup.txt exists
|
||||
) else (
|
||||
echo c:\windows\csup.txt does not exist
|
||||
)
|
||||
if exist "c:\windows\LogFirstRun.txt" (
|
||||
echo c:\windows\LogFirstRun.txt exists
|
||||
) else (
|
||||
echo c:\windows\LogFirstRun.txt does not exist
|
||||
)
|
||||
'@
|
||||
$checkInstall | Out-File -FilePath "$env:temp\checkinstall.cmd" -Force -Encoding Ascii
|
||||
}
|
||||
|
||||
function New-FirstRun {
|
||||
|
||||
# using here string to embedd firstrun
|
||||
$firstRun = @'
|
||||
# Set the global error action preference to continue
|
||||
$ErrorActionPreference = "Continue"
|
||||
function Remove-RegistryValue
|
||||
{
|
||||
param (
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$RegistryPath,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$ValueName
|
||||
)
|
||||
|
||||
# Check if the registry path exists
|
||||
if (Test-Path -Path $RegistryPath)
|
||||
{
|
||||
$registryValue = Get-ItemProperty -Path $RegistryPath -Name $ValueName -ErrorAction SilentlyContinue
|
||||
|
||||
# Check if the registry value exists
|
||||
if ($registryValue)
|
||||
{
|
||||
# Remove the registry value
|
||||
Remove-ItemProperty -Path $RegistryPath -Name $ValueName -Force
|
||||
Write-Host "Registry value '$ValueName' removed from '$RegistryPath'."
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "Registry value '$ValueName' not found in '$RegistryPath'."
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Write-Host "Registry path '$RegistryPath' not found."
|
||||
}
|
||||
}
|
||||
|
||||
function Stop-UnnecessaryServices
|
||||
{
|
||||
$servicesToExclude = @(
|
||||
"AudioSrv",
|
||||
"AudioEndpointBuilder",
|
||||
"BFE",
|
||||
"BITS",
|
||||
"BrokerInfrastructure",
|
||||
"CDPSvc",
|
||||
"CDPUserSvc_dc2a4",
|
||||
"CoreMessagingRegistrar",
|
||||
"CryptSvc",
|
||||
"DPS",
|
||||
"DcomLaunch",
|
||||
"Dhcp",
|
||||
"DispBrokerDesktopSvc",
|
||||
"Dnscache",
|
||||
"DoSvc",
|
||||
"DusmSvc",
|
||||
"EventLog",
|
||||
"EventSystem",
|
||||
"FontCache",
|
||||
"LSM",
|
||||
"LanmanServer",
|
||||
"LanmanWorkstation",
|
||||
"MapsBroker",
|
||||
"MpsSvc",
|
||||
"OneSyncSvc_dc2a4",
|
||||
"Power",
|
||||
"ProfSvc",
|
||||
"RpcEptMapper",
|
||||
"RpcSs",
|
||||
"SCardSvr",
|
||||
"SENS",
|
||||
"SamSs",
|
||||
"Schedule",
|
||||
"SgrmBroker",
|
||||
"ShellHWDetection",
|
||||
"Spooler",
|
||||
"SysMain",
|
||||
"SystemEventsBroker",
|
||||
"TextInputManagementService",
|
||||
"Themes",
|
||||
"TrkWks",
|
||||
"UserManager",
|
||||
"VGAuthService",
|
||||
"VMTools",
|
||||
"WSearch",
|
||||
"Wcmsvc",
|
||||
"WinDefend",
|
||||
"Winmgmt",
|
||||
"WlanSvc",
|
||||
"WpnService",
|
||||
"WpnUserService_dc2a4",
|
||||
"cbdhsvc_dc2a4",
|
||||
"edgeupdate",
|
||||
"gpsvc",
|
||||
"iphlpsvc",
|
||||
"mpssvc",
|
||||
"nsi",
|
||||
"sppsvc",
|
||||
"tiledatamodelsvc",
|
||||
"vm3dservice",
|
||||
"webthreatdefusersvc_dc2a4",
|
||||
"wscsvc"
|
||||
)
|
||||
|
||||
$runningServices = Get-Service | Where-Object { $servicesToExclude -notcontains $_.Name }
|
||||
foreach($service in $runningServices)
|
||||
{
|
||||
Stop-Service -Name $service.Name -PassThru
|
||||
Set-Service $service.Name -StartupType Manual
|
||||
"Stopping service $($service.Name)" | Out-File -FilePath c:\windows\LogFirstRun.txt -Append -NoClobber
|
||||
}
|
||||
}
|
||||
|
||||
"FirstStartup has worked" | Out-File -FilePath c:\windows\LogFirstRun.txt -Append -NoClobber
|
||||
|
||||
$Theme = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize"
|
||||
Set-ItemProperty -Path $Theme -Name AppsUseLightTheme -Value 1
|
||||
Set-ItemProperty -Path $Theme -Name SystemUsesLightTheme -Value 1
|
||||
|
||||
# figure this out later how to set updates to security only
|
||||
#Import-Module -Name PSWindowsUpdate;
|
||||
#Stop-Service -Name wuauserv
|
||||
#Set-WUSettings -MicrosoftUpdateEnabled -AutoUpdateOption 'Never'
|
||||
#Start-Service -Name wuauserv
|
||||
|
||||
Stop-UnnecessaryServices
|
||||
|
||||
$taskbarPath = "$env:AppData\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar"
|
||||
# Delete all files on the Taskbar
|
||||
Get-ChildItem -Path $taskbarPath -File | Remove-Item -Force
|
||||
Remove-RegistryValue -RegistryPath "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband" -ValueName "FavoritesRemovedChanges"
|
||||
Remove-RegistryValue -RegistryPath "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband" -ValueName "FavoritesChanges"
|
||||
Remove-RegistryValue -RegistryPath "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Taskband" -ValueName "Favorites"
|
||||
|
||||
# Stop-Process -Name explorer -Force
|
||||
|
||||
$process = Get-Process -Name "explorer"
|
||||
Stop-Process -InputObject $process
|
||||
# Wait for the process to exit
|
||||
Wait-Process -InputObject $process
|
||||
Start-Sleep -Seconds 3
|
||||
|
||||
# Delete Edge Icon from the desktop
|
||||
$edgeShortcutFiles = Get-ChildItem -Path $desktopPath -Filter "*Edge*.lnk"
|
||||
# Check if Edge shortcuts exist on the desktop
|
||||
if ($edgeShortcutFiles)
|
||||
{
|
||||
foreach ($shortcutFile in $edgeShortcutFiles)
|
||||
{
|
||||
# Remove each Edge shortcut
|
||||
Remove-Item -Path $shortcutFile.FullName -Force
|
||||
Write-Host "Edge shortcut '$($shortcutFile.Name)' removed from the desktop."
|
||||
}
|
||||
}
|
||||
Remove-Item -Path "$env:USERPROFILE\Desktop\*.lnk"
|
||||
Remove-Item -Path "C:\Users\Default\Desktop\*.lnk"
|
||||
|
||||
# ************************************************
|
||||
# Create WinUtil shortcut on the desktop
|
||||
#
|
||||
$desktopPath = "$($env:USERPROFILE)\Desktop"
|
||||
# Specify the target PowerShell command
|
||||
$command = "powershell.exe -NoProfile -ExecutionPolicy Bypass -Command 'irm https://christitus.com/win | iex'"
|
||||
# Specify the path for the shortcut
|
||||
$shortcutPath = Join-Path $desktopPath 'winutil.lnk'
|
||||
# Create a shell object
|
||||
$shell = New-Object -ComObject WScript.Shell
|
||||
|
||||
# Create a shortcut object
|
||||
$shortcut = $shell.CreateShortcut($shortcutPath)
|
||||
|
||||
if (Test-Path -Path "c:\Windows\cttlogo.png")
|
||||
{
|
||||
$shortcut.IconLocation = "c:\Windows\cttlogo.png"
|
||||
}
|
||||
|
||||
# Set properties of the shortcut
|
||||
$shortcut.TargetPath = "powershell.exe"
|
||||
$shortcut.Arguments = "-NoProfile -ExecutionPolicy Bypass -Command `"$command`""
|
||||
# Save the shortcut
|
||||
$shortcut.Save()
|
||||
|
||||
# Make the shortcut have 'Run as administrator' property on
|
||||
$bytes = [System.IO.File]::ReadAllBytes($shortcutPath)
|
||||
# Set byte value at position 0x15 in hex, or 21 in decimal, from the value 0x00 to 0x20 in hex
|
||||
$bytes[0x15] = $bytes[0x15] -bor 0x20
|
||||
[System.IO.File]::WriteAllBytes($shortcutPath, $bytes)
|
||||
|
||||
Write-Host "Shortcut created at: $shortcutPath"
|
||||
#
|
||||
# Done create WinUtil shortcut on the desktop
|
||||
# ************************************************
|
||||
|
||||
Start-Process explorer
|
||||
|
||||
'@
|
||||
$firstRun | Out-File -FilePath "$env:temp\FirstStartup.ps1" -Force
|
||||
}
|
199
functions/private/Invoke-WinUtilAssets.ps1
Normal file
199
functions/private/Invoke-WinUtilAssets.ps1
Normal file
@ -0,0 +1,199 @@
|
||||
function Invoke-WinUtilAssets {
|
||||
param (
|
||||
$type,
|
||||
$Size,
|
||||
[switch]$render
|
||||
)
|
||||
|
||||
# Create the Viewbox and set its size
|
||||
$LogoViewbox = New-Object Windows.Controls.Viewbox
|
||||
$LogoViewbox.Width = $Size
|
||||
$LogoViewbox.Height = $Size
|
||||
|
||||
# Create a Canvas to hold the paths
|
||||
$canvas = New-Object Windows.Controls.Canvas
|
||||
$canvas.Width = 100
|
||||
$canvas.Height = 100
|
||||
|
||||
# Define a scale factor for the content inside the Canvas
|
||||
$scaleFactor = $Size / 100
|
||||
|
||||
# Apply a scale transform to the Canvas content
|
||||
$scaleTransform = New-Object Windows.Media.ScaleTransform($scaleFactor, $scaleFactor)
|
||||
$canvas.LayoutTransform = $scaleTransform
|
||||
|
||||
switch ($type) {
|
||||
'logo' {
|
||||
$LogoPathData1 = @"
|
||||
M 18.00,14.00
|
||||
C 18.00,14.00 45.00,27.74 45.00,27.74
|
||||
45.00,27.74 57.40,34.63 57.40,34.63
|
||||
57.40,34.63 59.00,43.00 59.00,43.00
|
||||
59.00,43.00 59.00,83.00 59.00,83.00
|
||||
55.35,81.66 46.99,77.79 44.72,74.79
|
||||
41.17,70.10 42.01,59.80 42.00,54.00
|
||||
42.00,51.62 42.20,48.29 40.98,46.21
|
||||
38.34,41.74 25.78,38.60 21.28,33.79
|
||||
16.81,29.02 18.00,20.20 18.00,14.00 Z
|
||||
"@
|
||||
$LogoPath1 = New-Object Windows.Shapes.Path
|
||||
$LogoPath1.Data = [Windows.Media.Geometry]::Parse($LogoPathData1)
|
||||
$LogoPath1.Fill = [System.Windows.Media.BrushConverter]::new().ConvertFromString("#0567ff")
|
||||
|
||||
$LogoPathData2 = @"
|
||||
M 107.00,14.00
|
||||
C 109.01,19.06 108.93,30.37 104.66,34.21
|
||||
100.47,37.98 86.38,43.10 84.60,47.21
|
||||
83.94,48.74 84.01,51.32 84.00,53.00
|
||||
83.97,57.04 84.46,68.90 83.26,72.00
|
||||
81.06,77.70 72.54,81.42 67.00,83.00
|
||||
67.00,83.00 67.00,43.00 67.00,43.00
|
||||
67.00,43.00 67.99,35.63 67.99,35.63
|
||||
67.99,35.63 80.00,28.26 80.00,28.26
|
||||
80.00,28.26 107.00,14.00 107.00,14.00 Z
|
||||
"@
|
||||
$LogoPath2 = New-Object Windows.Shapes.Path
|
||||
$LogoPath2.Data = [Windows.Media.Geometry]::Parse($LogoPathData2)
|
||||
$LogoPath2.Fill = [System.Windows.Media.BrushConverter]::new().ConvertFromString("#0567ff")
|
||||
|
||||
$LogoPathData3 = @"
|
||||
M 19.00,46.00
|
||||
C 21.36,47.14 28.67,50.71 30.01,52.63
|
||||
31.17,54.30 30.99,57.04 31.00,59.00
|
||||
31.04,65.41 30.35,72.16 33.56,78.00
|
||||
38.19,86.45 46.10,89.04 54.00,93.31
|
||||
56.55,94.69 60.10,97.20 63.00,97.22
|
||||
65.50,97.24 68.77,95.36 71.00,94.25
|
||||
76.42,91.55 84.51,87.78 88.82,83.68
|
||||
94.56,78.20 95.96,70.59 96.00,63.00
|
||||
96.01,60.24 95.59,54.63 97.02,52.39
|
||||
98.80,49.60 103.95,47.87 107.00,47.00
|
||||
107.00,47.00 107.00,67.00 107.00,67.00
|
||||
106.90,87.69 96.10,93.85 80.00,103.00
|
||||
76.51,104.98 66.66,110.67 63.00,110.52
|
||||
60.33,110.41 55.55,107.53 53.00,106.25
|
||||
46.21,102.83 36.63,98.57 31.04,93.68
|
||||
16.88,81.28 19.00,62.88 19.00,46.00 Z
|
||||
"@
|
||||
$LogoPath3 = New-Object Windows.Shapes.Path
|
||||
$LogoPath3.Data = [Windows.Media.Geometry]::Parse($LogoPathData3)
|
||||
$LogoPath3.Fill = [System.Windows.Media.BrushConverter]::new().ConvertFromString("#a3a4a6")
|
||||
|
||||
$canvas.Children.Add($LogoPath1) | Out-Null
|
||||
$canvas.Children.Add($LogoPath2) | Out-Null
|
||||
$canvas.Children.Add($LogoPath3) | Out-Null
|
||||
}
|
||||
'checkmark' {
|
||||
$canvas.Width = 512
|
||||
$canvas.Height = 512
|
||||
|
||||
$scaleFactor = $Size / 2.54
|
||||
$scaleTransform = New-Object Windows.Media.ScaleTransform($scaleFactor, $scaleFactor)
|
||||
$canvas.LayoutTransform = $scaleTransform
|
||||
|
||||
# Define the circle path
|
||||
$circlePathData = "M 1.27,0 A 1.27,1.27 0 1,0 1.27,2.54 A 1.27,1.27 0 1,0 1.27,0"
|
||||
$circlePath = New-Object Windows.Shapes.Path
|
||||
$circlePath.Data = [Windows.Media.Geometry]::Parse($circlePathData)
|
||||
$circlePath.Fill = [System.Windows.Media.BrushConverter]::new().ConvertFromString("#39ba00")
|
||||
|
||||
# Define the checkmark path
|
||||
$checkmarkPathData = "M 0.873 1.89 L 0.41 1.391 A 0.17 0.17 0 0 1 0.418 1.151 A 0.17 0.17 0 0 1 0.658 1.16 L 1.016 1.543 L 1.583 1.013 A 0.17 0.17 0 0 1 1.599 1 L 1.865 0.751 A 0.17 0.17 0 0 1 2.105 0.759 A 0.17 0.17 0 0 1 2.097 0.999 L 1.282 1.759 L 0.999 2.022 L 0.874 1.888 Z"
|
||||
$checkmarkPath = New-Object Windows.Shapes.Path
|
||||
$checkmarkPath.Data = [Windows.Media.Geometry]::Parse($checkmarkPathData)
|
||||
$checkmarkPath.Fill = [Windows.Media.Brushes]::White
|
||||
|
||||
# Add the paths to the Canvas
|
||||
$canvas.Children.Add($circlePath) | Out-Null
|
||||
$canvas.Children.Add($checkmarkPath) | Out-Null
|
||||
}
|
||||
'warning' {
|
||||
$canvas.Width = 512
|
||||
$canvas.Height = 512
|
||||
|
||||
# Define a scale factor for the content inside the Canvas
|
||||
$scaleFactor = $Size / 512 # Adjust scaling based on the canvas size
|
||||
$scaleTransform = New-Object Windows.Media.ScaleTransform($scaleFactor, $scaleFactor)
|
||||
$canvas.LayoutTransform = $scaleTransform
|
||||
|
||||
# Define the circle path
|
||||
$circlePathData = "M 256,0 A 256,256 0 1,0 256,512 A 256,256 0 1,0 256,0"
|
||||
$circlePath = New-Object Windows.Shapes.Path
|
||||
$circlePath.Data = [Windows.Media.Geometry]::Parse($circlePathData)
|
||||
$circlePath.Fill = [System.Windows.Media.BrushConverter]::new().ConvertFromString("#f41b43")
|
||||
|
||||
# Define the exclamation mark path
|
||||
$exclamationPathData = "M 256 307.2 A 35.89 35.89 0 0 1 220.14 272.74 L 215.41 153.3 A 35.89 35.89 0 0 1 251.27 116 H 260.73 A 35.89 35.89 0 0 1 296.59 153.3 L 291.86 272.74 A 35.89 35.89 0 0 1 256 307.2 Z"
|
||||
$exclamationPath = New-Object Windows.Shapes.Path
|
||||
$exclamationPath.Data = [Windows.Media.Geometry]::Parse($exclamationPathData)
|
||||
$exclamationPath.Fill = [Windows.Media.Brushes]::White
|
||||
|
||||
# Get the bounds of the exclamation mark path
|
||||
$exclamationBounds = $exclamationPath.Data.Bounds
|
||||
|
||||
# Calculate the center position for the exclamation mark path
|
||||
$exclamationCenterX = ($canvas.Width - $exclamationBounds.Width) / 2 - $exclamationBounds.X
|
||||
$exclamationPath.SetValue([Windows.Controls.Canvas]::LeftProperty, $exclamationCenterX)
|
||||
|
||||
# Define the rounded rectangle at the bottom (dot of exclamation mark)
|
||||
$roundedRectangle = New-Object Windows.Shapes.Rectangle
|
||||
$roundedRectangle.Width = 80
|
||||
$roundedRectangle.Height = 80
|
||||
$roundedRectangle.RadiusX = 30
|
||||
$roundedRectangle.RadiusY = 30
|
||||
$roundedRectangle.Fill = [Windows.Media.Brushes]::White
|
||||
|
||||
# Calculate the center position for the rounded rectangle
|
||||
$centerX = ($canvas.Width - $roundedRectangle.Width) / 2
|
||||
$roundedRectangle.SetValue([Windows.Controls.Canvas]::LeftProperty, $centerX)
|
||||
$roundedRectangle.SetValue([Windows.Controls.Canvas]::TopProperty, 324.34)
|
||||
|
||||
# Add the paths to the Canvas
|
||||
$canvas.Children.Add($circlePath) | Out-Null
|
||||
$canvas.Children.Add($exclamationPath) | Out-Null
|
||||
$canvas.Children.Add($roundedRectangle) | Out-Null
|
||||
}
|
||||
default {
|
||||
Write-Host "Invalid type: $type"
|
||||
}
|
||||
}
|
||||
|
||||
# Add the Canvas to the Viewbox
|
||||
$LogoViewbox.Child = $canvas
|
||||
|
||||
if ($render) {
|
||||
# Measure and arrange the canvas to ensure proper rendering
|
||||
$canvas.Measure([Windows.Size]::new($canvas.Width, $canvas.Height))
|
||||
$canvas.Arrange([Windows.Rect]::new(0, 0, $canvas.Width, $canvas.Height))
|
||||
$canvas.UpdateLayout()
|
||||
|
||||
# Initialize RenderTargetBitmap correctly with dimensions
|
||||
$renderTargetBitmap = New-Object Windows.Media.Imaging.RenderTargetBitmap($canvas.Width, $canvas.Height, 96, 96, [Windows.Media.PixelFormats]::Pbgra32)
|
||||
|
||||
# Render the canvas to the bitmap
|
||||
$renderTargetBitmap.Render($canvas)
|
||||
|
||||
# Create a BitmapFrame from the RenderTargetBitmap
|
||||
$bitmapFrame = [Windows.Media.Imaging.BitmapFrame]::Create($renderTargetBitmap)
|
||||
|
||||
# Create a PngBitmapEncoder and add the frame
|
||||
$bitmapEncoder = [Windows.Media.Imaging.PngBitmapEncoder]::new()
|
||||
$bitmapEncoder.Frames.Add($bitmapFrame)
|
||||
|
||||
# Save to a memory stream
|
||||
$imageStream = New-Object System.IO.MemoryStream
|
||||
$bitmapEncoder.Save($imageStream)
|
||||
$imageStream.Position = 0
|
||||
|
||||
# Load the stream into a BitmapImage
|
||||
$bitmapImage = [Windows.Media.Imaging.BitmapImage]::new()
|
||||
$bitmapImage.BeginInit()
|
||||
$bitmapImage.StreamSource = $imageStream
|
||||
$bitmapImage.CacheOption = [Windows.Media.Imaging.BitmapCacheOption]::OnLoad
|
||||
$bitmapImage.EndInit()
|
||||
|
||||
return $bitmapImage
|
||||
} else {
|
||||
return $LogoViewbox
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
function Invoke-WinUtilBingSearch {
|
||||
<#
|
||||
|
||||
.SYNOPSIS
|
||||
Disables/Enables Bing Search
|
||||
|
||||
.PARAMETER Enabled
|
||||
Indicates whether to enable or disable Bing Search
|
||||
|
||||
#>
|
||||
Param($Enabled)
|
||||
Try{
|
||||
if ($Enabled -eq $false){
|
||||
Write-Host "Enabling Bing Search"
|
||||
$value = 1
|
||||
}
|
||||
else {
|
||||
Write-Host "Disabling Bing Search"
|
||||
$value = 0
|
||||
}
|
||||
$Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Search"
|
||||
Set-ItemProperty -Path $Path -Name BingSearchEnabled -Value $value
|
||||
}
|
||||
Catch [System.Security.SecurityException] {
|
||||
Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception"
|
||||
}
|
||||
Catch [System.Management.Automation.ItemNotFoundException] {
|
||||
Write-Warning $psitem.Exception.ErrorRecord
|
||||
}
|
||||
Catch{
|
||||
Write-Warning "Unable to set $Name due to unhandled exception"
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
}
|
||||
}
|
@ -13,8 +13,18 @@ Function Invoke-WinUtilCurrentSystem {
|
||||
param(
|
||||
$CheckBox
|
||||
)
|
||||
if ($CheckBox -eq "choco") {
|
||||
$apps = (choco list | Select-String -Pattern "^\S+").Matches.Value
|
||||
$filter = Get-WinUtilVariables -Type Checkbox | Where-Object {$psitem -like "WPFInstall*"}
|
||||
$sync.GetEnumerator() | Where-Object {$psitem.Key -in $filter} | ForEach-Object {
|
||||
$dependencies = @($sync.configs.applications.$($psitem.Key).choco -split ";")
|
||||
if ($dependencies -in $apps) {
|
||||
Write-Output $psitem.name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($checkbox -eq "winget"){
|
||||
if ($checkbox -eq "winget") {
|
||||
|
||||
$originalEncoding = [Console]::OutputEncoding
|
||||
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
|
||||
@ -31,9 +41,9 @@ Function Invoke-WinUtilCurrentSystem {
|
||||
}
|
||||
}
|
||||
|
||||
if($CheckBox -eq "tweaks"){
|
||||
if($CheckBox -eq "tweaks") {
|
||||
|
||||
if(!(Test-Path 'HKU:\')){New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS}
|
||||
if(!(Test-Path 'HKU:\')) {$null = (New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS)}
|
||||
$ScheduledTasks = Get-ScheduledTask
|
||||
|
||||
$sync.configs.tweaks | Get-Member -MemberType NoteProperty | ForEach-Object {
|
||||
@ -44,56 +54,57 @@ Function Invoke-WinUtilCurrentSystem {
|
||||
$scheduledtaskKeys = $sync.configs.tweaks.$Config.scheduledtask
|
||||
$serviceKeys = $sync.configs.tweaks.$Config.service
|
||||
|
||||
if($registryKeys -or $scheduledtaskKeys -or $serviceKeys){
|
||||
if($registryKeys -or $scheduledtaskKeys -or $serviceKeys) {
|
||||
$Values = @()
|
||||
|
||||
|
||||
Foreach ($tweaks in $registryKeys){
|
||||
Foreach($tweak in $tweaks){
|
||||
Foreach ($tweaks in $registryKeys) {
|
||||
Foreach($tweak in $tweaks) {
|
||||
|
||||
if(test-path $tweak.Path){
|
||||
if(test-path $tweak.Path) {
|
||||
$actualValue = Get-ItemProperty -Name $tweak.Name -Path $tweak.Path -ErrorAction SilentlyContinue | Select-Object -ExpandProperty $($tweak.Name)
|
||||
$expectedValue = $tweak.Value
|
||||
if ($expectedValue -notlike $actualValue){
|
||||
if ($expectedValue -notlike $actualValue) {
|
||||
$values += $False
|
||||
}
|
||||
} else {
|
||||
$values += $False
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Foreach ($tweaks in $scheduledtaskKeys){
|
||||
Foreach($tweak in $tweaks){
|
||||
Foreach ($tweaks in $scheduledtaskKeys) {
|
||||
Foreach($tweak in $tweaks) {
|
||||
$task = $ScheduledTasks | Where-Object {$($psitem.TaskPath + $psitem.TaskName) -like "\$($tweak.name)"}
|
||||
|
||||
if($task){
|
||||
if($task) {
|
||||
$actualValue = $task.State
|
||||
$expectedValue = $tweak.State
|
||||
if ($expectedValue -ne $actualValue){
|
||||
if ($expectedValue -ne $actualValue) {
|
||||
$values += $False
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Foreach ($tweaks in $serviceKeys){
|
||||
Foreach($tweak in $tweaks){
|
||||
Foreach ($tweaks in $serviceKeys) {
|
||||
Foreach($tweak in $tweaks) {
|
||||
$Service = Get-Service -Name $tweak.Name
|
||||
|
||||
if($Service){
|
||||
if($Service) {
|
||||
$actualValue = $Service.StartType
|
||||
$expectedValue = $tweak.StartupType
|
||||
if ($expectedValue -ne $actualValue){
|
||||
if ($expectedValue -ne $actualValue) {
|
||||
$values += $False
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($values -notcontains $false){
|
||||
if($values -notcontains $false) {
|
||||
Write-Output $Config
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,36 +0,0 @@
|
||||
Function Invoke-WinUtilDarkMode {
|
||||
<#
|
||||
|
||||
.SYNOPSIS
|
||||
Enables/Disables Dark Mode
|
||||
|
||||
.PARAMETER DarkMoveEnabled
|
||||
Indicates the current dark mode state
|
||||
|
||||
#>
|
||||
Param($DarkMoveEnabled)
|
||||
Try{
|
||||
if ($DarkMoveEnabled -eq $false){
|
||||
Write-Host "Enabling Dark Mode"
|
||||
$DarkMoveValue = 0
|
||||
}
|
||||
else {
|
||||
Write-Host "Disabling Dark Mode"
|
||||
$DarkMoveValue = 1
|
||||
}
|
||||
|
||||
$Path = "HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize"
|
||||
Set-ItemProperty -Path $Path -Name AppsUseLightTheme -Value $DarkMoveValue
|
||||
Set-ItemProperty -Path $Path -Name SystemUsesLightTheme -Value $DarkMoveValue
|
||||
}
|
||||
Catch [System.Security.SecurityException] {
|
||||
Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception"
|
||||
}
|
||||
Catch [System.Management.Automation.ItemNotFoundException] {
|
||||
Write-Warning $psitem.Exception.ErrorRecord
|
||||
}
|
||||
Catch{
|
||||
Write-Warning "Unable to set $Name due to unhandled exception"
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
}
|
||||
}
|
43
functions/private/Invoke-WinUtilExplorerUpdate.ps1
Normal file
43
functions/private/Invoke-WinUtilExplorerUpdate.ps1
Normal file
@ -0,0 +1,43 @@
|
||||
function Invoke-WinUtilExplorerUpdate {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Refreshes the Windows Explorer
|
||||
#>
|
||||
|
||||
param (
|
||||
[string]$action = "refresh"
|
||||
)
|
||||
|
||||
if ($action -eq "refresh") {
|
||||
Invoke-WPFRunspace -DebugPreference $DebugPreference -ScriptBlock {
|
||||
# Send the WM_SETTINGCHANGE message to all windows
|
||||
Add-Type -TypeDefinition @"
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
public class Win32 {
|
||||
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]
|
||||
public static extern IntPtr SendMessageTimeout(
|
||||
IntPtr hWnd,
|
||||
uint Msg,
|
||||
IntPtr wParam,
|
||||
string lParam,
|
||||
uint fuFlags,
|
||||
uint uTimeout,
|
||||
out IntPtr lpdwResult);
|
||||
}
|
||||
"@
|
||||
|
||||
$HWND_BROADCAST = [IntPtr]0xffff
|
||||
$WM_SETTINGCHANGE = 0x1A
|
||||
$SMTO_ABORTIFHUNG = 0x2
|
||||
$timeout = 100
|
||||
|
||||
# Send the broadcast message to all windows
|
||||
[Win32]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [IntPtr]::Zero, "ImmersiveColorSet", $SMTO_ABORTIFHUNG, $timeout, [ref]([IntPtr]::Zero))
|
||||
}
|
||||
} elseif ($action -eq "restart") {
|
||||
# Restart the Windows Explorer
|
||||
taskkill.exe /F /IM "explorer.exe"
|
||||
Start-Process "explorer.exe"
|
||||
}
|
||||
}
|
@ -10,44 +10,46 @@ function Invoke-WinUtilFeatureInstall {
|
||||
$CheckBox
|
||||
)
|
||||
|
||||
$x = 0
|
||||
|
||||
$CheckBox | ForEach-Object {
|
||||
if($sync.configs.feature.$psitem.feature){
|
||||
Foreach( $feature in $sync.configs.feature.$psitem.feature ){
|
||||
Try{
|
||||
if($sync.configs.feature.$psitem.feature) {
|
||||
Foreach( $feature in $sync.configs.feature.$psitem.feature ) {
|
||||
try {
|
||||
Write-Host "Installing $feature"
|
||||
Enable-WindowsOptionalFeature -Online -FeatureName $feature -All -NoRestart
|
||||
}
|
||||
Catch{
|
||||
if ($psitem.Exception.Message -like "*requires elevation*"){
|
||||
} catch {
|
||||
if ($psitem.Exception.Message -like "*requires elevation*") {
|
||||
Write-Warning "Unable to Install $feature due to permissions. Are you running as admin?"
|
||||
}
|
||||
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" })
|
||||
} else {
|
||||
|
||||
else{
|
||||
Write-Warning "Unable to Install $feature due to unhandled exception"
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if($sync.configs.feature.$psitem.InvokeScript){
|
||||
Foreach( $script in $sync.configs.feature.$psitem.InvokeScript ){
|
||||
Try{
|
||||
if($sync.configs.feature.$psitem.InvokeScript) {
|
||||
Foreach( $script in $sync.configs.feature.$psitem.InvokeScript ) {
|
||||
try {
|
||||
$Scriptblock = [scriptblock]::Create($script)
|
||||
|
||||
Write-Host "Running Script for $psitem"
|
||||
Invoke-Command $scriptblock -ErrorAction stop
|
||||
}
|
||||
Catch{
|
||||
if ($psitem.Exception.Message -like "*requires elevation*"){
|
||||
} catch {
|
||||
if ($psitem.Exception.Message -like "*requires elevation*") {
|
||||
Write-Warning "Unable to Install $feature due to permissions. Are you running as admin?"
|
||||
}
|
||||
|
||||
else{
|
||||
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" })
|
||||
} else {
|
||||
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -state "Error" })
|
||||
Write-Warning "Unable to Install $feature due to unhandled exception"
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$X++
|
||||
$sync.form.Dispatcher.Invoke([action]{ Set-WinUtilTaskbaritem -value ($x/$CheckBox.Count) })
|
||||
}
|
||||
}
|
||||
|
@ -1,29 +1,23 @@
|
||||
function Invoke-WinUtilGPU {
|
||||
$gpuInfo = Get-CimInstance Win32_VideoController
|
||||
|
||||
foreach ($gpu in $gpuInfo) {
|
||||
$gpuName = $gpu.Name
|
||||
if ($gpuName -like "*NVIDIA*") {
|
||||
return $true # NVIDIA GPU found
|
||||
}
|
||||
}
|
||||
|
||||
# GPUs to blacklist from using Demanding Theming
|
||||
$lowPowerGPUs = (
|
||||
"*NVIDIA GeForce*M*",
|
||||
"*NVIDIA GeForce*Laptop*",
|
||||
"*NVIDIA GeForce*GT*",
|
||||
"*AMD Radeon(TM)*",
|
||||
"*Intel(R) HD Graphics*",
|
||||
"*UHD*"
|
||||
|
||||
)
|
||||
|
||||
foreach ($gpu in $gpuInfo) {
|
||||
$gpuName = $gpu.Name
|
||||
if ($gpuName -like "*AMD Radeon RX*") {
|
||||
return $true # AMD GPU Found
|
||||
foreach ($gpuPattern in $lowPowerGPUs) {
|
||||
if ($gpu.Name -like $gpuPattern) {
|
||||
return $false
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($gpu in $gpuInfo) {
|
||||
$gpuName = $gpu.Name
|
||||
if ($gpuName -like "*UHD*") {
|
||||
return $false # Intel Intergrated GPU Found
|
||||
}
|
||||
}
|
||||
foreach ($gpu in $gpuInfo) {
|
||||
$gpuName = $gpu.Name
|
||||
if ($gpuName -like "*AMD Radeon(TM)*") {
|
||||
return $false # AMD Intergrated GPU Found
|
||||
}
|
||||
}
|
||||
}
|
||||
return $true
|
||||
}
|
||||
|
103
functions/private/Invoke-WinUtilInstallPSProfile.ps1
Normal file
103
functions/private/Invoke-WinUtilInstallPSProfile.ps1
Normal file
@ -0,0 +1,103 @@
|
||||
function Invoke-WinUtilInstallPSProfile {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Backs up your original profile then installs and applies the CTT PowerShell profile.
|
||||
#>
|
||||
|
||||
Invoke-WPFRunspace -ArgumentList $PROFILE -DebugPreference $DebugPreference -ScriptBlock {
|
||||
# Remap the automatic built-in $PROFILE variable to the parameter named $PSProfile.
|
||||
param ($PSProfile)
|
||||
|
||||
function Invoke-PSSetup {
|
||||
# Define the URL used to download Chris Titus Tech's PowerShell profile.
|
||||
$url = "https://raw.githubusercontent.com/ChrisTitusTech/powershell-profile/main/Microsoft.PowerShell_profile.ps1"
|
||||
|
||||
# Get the file hash for the user's current PowerShell profile.
|
||||
$OldHash = Get-FileHash $PSProfile -ErrorAction SilentlyContinue
|
||||
|
||||
# Download Chris Titus Tech's PowerShell profile to the 'TEMP' folder.
|
||||
Invoke-RestMethod $url -OutFile "$env:TEMP/Microsoft.PowerShell_profile.ps1"
|
||||
|
||||
# Get the file hash for Chris Titus Tech's PowerShell profile.
|
||||
$NewHash = Get-FileHash "$env:TEMP/Microsoft.PowerShell_profile.ps1"
|
||||
|
||||
# Store the file hash of Chris Titus Tech's PowerShell profile.
|
||||
if (!(Test-Path "$PSProfile.hash")) {
|
||||
$NewHash.Hash | Out-File "$PSProfile.hash"
|
||||
}
|
||||
|
||||
# Check if the new profile's hash doesn't match the old profile's hash.
|
||||
if ($NewHash.Hash -ne $OldHash.Hash) {
|
||||
# Check if oldprofile.ps1 exists and use it as a profile backup source.
|
||||
if (Test-Path "$env:USERPROFILE\oldprofile.ps1") {
|
||||
Write-Host "===> Backup File Exists... <===" -ForegroundColor Yellow
|
||||
Write-Host "===> Moving Backup File... <===" -ForegroundColor Yellow
|
||||
Copy-Item "$env:USERPROFILE\oldprofile.ps1" "$PSProfile.bak"
|
||||
Write-Host "===> Profile Backup: Done. <===" -ForegroundColor Yellow
|
||||
} else {
|
||||
# If oldprofile.ps1 does not exist use $PSProfile as a profile backup source.
|
||||
# Check if the profile backup file has not already been created on the disk.
|
||||
if ((Test-Path $PSProfile) -and (-not (Test-Path "$PSProfile.bak"))) {
|
||||
# Let the user know their PowerShell profile is being backed up.
|
||||
Write-Host "===> Backing Up Profile... <===" -ForegroundColor Yellow
|
||||
|
||||
# Copy the user's current PowerShell profile to the backup file path.
|
||||
Copy-Item -Path $PSProfile -Destination "$PSProfile.bak"
|
||||
|
||||
# Let the user know the profile backup has been completed successfully.
|
||||
Write-Host "===> Profile Backup: Done. <===" -ForegroundColor Yellow
|
||||
}
|
||||
}
|
||||
|
||||
# Let the user know Chris Titus Tech's PowerShell profile is being installed.
|
||||
Write-Host "===> Installing Profile... <===" -ForegroundColor Yellow
|
||||
|
||||
# Start a new hidden PowerShell instance because setup.ps1 does not work in runspaces.
|
||||
Start-Process -FilePath "pwsh" -ArgumentList "-ExecutionPolicy Bypass -NoProfile -Command `"Invoke-Expression (Invoke-WebRequest `'https://github.com/ChrisTitusTech/powershell-profile/raw/main/setup.ps1`')`"" -WindowStyle Hidden -Wait
|
||||
|
||||
# Let the user know Chris Titus Tech's PowerShell profile has been installed successfully.
|
||||
Write-Host "Profile has been installed. Please restart your shell to reflect the changes!" -ForegroundColor Magenta
|
||||
|
||||
# Let the user know Chris Titus Tech's PowerShell profile has been setup successfully.
|
||||
Write-Host "===> Finished Profile Setup <===" -ForegroundColor Yellow
|
||||
} else {
|
||||
# Let the user know Chris Titus Tech's PowerShell profile is already fully up-to-date.
|
||||
Write-Host "Profile is up to date" -ForegroundColor Magenta
|
||||
}
|
||||
}
|
||||
|
||||
# Check if PowerShell Core is currently installed as a program and is available as a command.
|
||||
if (Get-Command "pwsh" -ErrorAction SilentlyContinue) {
|
||||
# Check if the version of PowerShell Core currently in use is version 7 or higher.
|
||||
if ($PSVersionTable.PSVersion.Major -ge 7) {
|
||||
# Invoke the PowerShell Profile setup script to install Chris Titus Tech's PowerShell Profile.
|
||||
Invoke-PSSetup
|
||||
} else {
|
||||
# Let the user know that PowerShell 7 is installed but is not currently in use.
|
||||
Write-Host "This profile requires Powershell 7, which is currently installed but not used!" -ForegroundColor Red
|
||||
|
||||
# Load the necessary .NET library required to use Windows Forms to show dialog boxes.
|
||||
Add-Type -AssemblyName System.Windows.Forms
|
||||
|
||||
# Display the message box asking if the user wants to install PowerShell 7 or not.
|
||||
$question = [System.Windows.Forms.MessageBox]::Show(
|
||||
"Profile requires Powershell 7, which is currently installed but not used! Do you want to install the profile for Powershell 7?",
|
||||
"Question",
|
||||
[System.Windows.Forms.MessageBoxButtons]::YesNo,
|
||||
[System.Windows.Forms.MessageBoxIcon]::Question
|
||||
)
|
||||
|
||||
# Proceed with the installation and setup of the profile as the user pressed the 'Yes' button.
|
||||
if ($question -eq [System.Windows.Forms.DialogResult]::Yes) {
|
||||
Invoke-PSSetup
|
||||
} else {
|
||||
# Let the user know the setup of the profile will not proceed as they pressed the 'No' button.
|
||||
Write-Host "Not proceeding with the profile setup!" -ForegroundColor Magenta
|
||||
}
|
||||
}
|
||||
} else {
|
||||
# Let the user know that the profile requires PowerShell Core but it is not currently installed.
|
||||
Write-Host "This profile requires Powershell Core, which is currently not installed!" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
Function Invoke-WinUtilMouseAcceleration {
|
||||
<#
|
||||
|
||||
.SYNOPSIS
|
||||
Enables/Disables Mouse Acceleration
|
||||
|
||||
.PARAMETER DarkMoveEnabled
|
||||
Indicates the current Mouse Acceleration State
|
||||
|
||||
#>
|
||||
Param($MouseAccelerationEnabled)
|
||||
Try{
|
||||
if ($MouseAccelerationEnabled -eq $false){
|
||||
Write-Host "Enabling Mouse Acceleration"
|
||||
$MouseSpeed = 1
|
||||
$MouseThreshold1 = 6
|
||||
$MouseThreshold2 = 10
|
||||
}
|
||||
else {
|
||||
Write-Host "Disabling Mouse Acceleration"
|
||||
$MouseSpeed = 0
|
||||
$MouseThreshold1 = 0
|
||||
$MouseThreshold2 = 0
|
||||
|
||||
}
|
||||
|
||||
$Path = "HKCU:\Control Panel\Mouse"
|
||||
Set-ItemProperty -Path $Path -Name MouseSpeed -Value $MouseSpeed
|
||||
Set-ItemProperty -Path $Path -Name MouseThreshold1 -Value $MouseThreshold1
|
||||
Set-ItemProperty -Path $Path -Name MouseThreshold2 -Value $MouseThreshold2
|
||||
}
|
||||
Catch [System.Security.SecurityException] {
|
||||
Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception"
|
||||
}
|
||||
Catch [System.Management.Automation.ItemNotFoundException] {
|
||||
Write-Warning $psitem.Exception.ErrorRecord
|
||||
}
|
||||
Catch{
|
||||
Write-Warning "Unable to set $Name due to unhandled exception"
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
function Invoke-WinUtilNumLock {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Disables/Enables NumLock on startup
|
||||
.PARAMETER Enabled
|
||||
Indicates whether to enable or disable Numlock on startup
|
||||
#>
|
||||
Param($Enabled)
|
||||
Try{
|
||||
if ($Enabled -eq $false){
|
||||
Write-Host "Enabling Numlock on startup"
|
||||
$value = 2
|
||||
}
|
||||
else {
|
||||
Write-Host "Disabling Numlock on startup"
|
||||
$value = 0
|
||||
}
|
||||
New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS
|
||||
$Path = "HKU:\.Default\Control Panel\Keyboard"
|
||||
Set-ItemProperty -Path $Path -Name InitialKeyboardIndicators -Value $value
|
||||
}
|
||||
Catch [System.Security.SecurityException] {
|
||||
Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception"
|
||||
}
|
||||
Catch [System.Management.Automation.ItemNotFoundException] {
|
||||
Write-Warning $psitem.Exception.ErrorRecord
|
||||
}
|
||||
Catch{
|
||||
Write-Warning "Unable to set $Name due to unhandled exception"
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
}
|
||||
}
|
81
functions/private/Invoke-WinUtilSSHServer.ps1
Normal file
81
functions/private/Invoke-WinUtilSSHServer.ps1
Normal file
@ -0,0 +1,81 @@
|
||||
function Invoke-WinUtilSSHServer {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Enables OpenSSH server to remote into your windows device
|
||||
#>
|
||||
|
||||
# Get the latest version of OpenSSH Server
|
||||
$FeatureName = Get-WindowsCapability -Online | Where-Object { $_.Name -like "OpenSSH.Server*" }
|
||||
|
||||
# Install the OpenSSH Server feature if not already installed
|
||||
if ($FeatureName.State -ne "Installed") {
|
||||
Write-Host "Enabling OpenSSH Server"
|
||||
Add-WindowsCapability -Online -Name $FeatureName.Name
|
||||
}
|
||||
|
||||
# Sets up the OpenSSH Server service
|
||||
Write-Host "Starting the services"
|
||||
Start-Service -Name sshd
|
||||
Set-Service -Name sshd -StartupType Automatic
|
||||
|
||||
# Sets up the ssh-agent service
|
||||
Start-Service 'ssh-agent'
|
||||
Set-Service -Name 'ssh-agent' -StartupType 'Automatic'
|
||||
|
||||
# Confirm the required services are running
|
||||
$SSHDaemonService = Get-Service -Name sshd
|
||||
$SSHAgentService = Get-Service -Name 'ssh-agent'
|
||||
|
||||
if ($SSHDaemonService.Status -eq 'Running') {
|
||||
Write-Host "OpenSSH Server is running."
|
||||
} else {
|
||||
try {
|
||||
Write-Host "OpenSSH Server is not running. Attempting to restart..."
|
||||
Restart-Service -Name sshd -Force
|
||||
Write-Host "OpenSSH Server has been restarted successfully."
|
||||
} catch {
|
||||
Write-Host "Failed to restart OpenSSH Server: $_"
|
||||
}
|
||||
}
|
||||
if ($SSHAgentService.Status -eq 'Running') {
|
||||
Write-Host "ssh-agent is running."
|
||||
} else {
|
||||
try {
|
||||
Write-Host "ssh-agent is not running. Attempting to restart..."
|
||||
Restart-Service -Name sshd -Force
|
||||
Write-Host "ssh-agent has been restarted successfully."
|
||||
} catch {
|
||||
Write-Host "Failed to restart ssh-agent : $_"
|
||||
}
|
||||
}
|
||||
|
||||
#Adding Firewall rule for port 22
|
||||
Write-Host "Setting up firewall rules"
|
||||
$firewallRule = (Get-NetFirewallRule -Name 'sshd').Enabled
|
||||
if ($firewallRule) {
|
||||
Write-Host "Firewall rule for OpenSSH Server (sshd) already exists."
|
||||
} else {
|
||||
New-NetFirewallRule -Name sshd -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
|
||||
Write-Host "Firewall rule for OpenSSH Server created and enabled."
|
||||
}
|
||||
|
||||
# Check for the authorized_keys file
|
||||
$sshFolderPath = "$env:HOMEDRIVE\$env:HOMEPATH\.ssh"
|
||||
$authorizedKeysPath = "$sshFolderPath\authorized_keys"
|
||||
|
||||
if (-not (Test-Path -Path $sshFolderPath)) {
|
||||
Write-Host "Creating ssh directory..."
|
||||
New-Item -Path $sshFolderPath -ItemType Directory -Force
|
||||
}
|
||||
|
||||
if (-not (Test-Path -Path $authorizedKeysPath)) {
|
||||
Write-Host "Creating authorized_keys file..."
|
||||
New-Item -Path $authorizedKeysPath -ItemType File -Force
|
||||
Write-Host "authorized_keys file created at $authorizedKeysPath."
|
||||
} else {
|
||||
Write-Host "authorized_keys file already exists at $authorizedKeysPath."
|
||||
}
|
||||
Write-Host "OpenSSH server was successfully enabled."
|
||||
Write-Host "The config file can be located at C:\ProgramData\ssh\sshd_config "
|
||||
Write-Host "Add your public keys to this file -> $authorizedKeysPath"
|
||||
}
|
@ -20,30 +20,25 @@ function Invoke-WinUtilScript {
|
||||
[scriptblock]$scriptblock
|
||||
)
|
||||
|
||||
Try {
|
||||
try {
|
||||
Write-Host "Running Script for $name"
|
||||
Invoke-Command $scriptblock -ErrorAction Stop
|
||||
}
|
||||
Catch [System.Management.Automation.CommandNotFoundException] {
|
||||
} catch [System.Management.Automation.CommandNotFoundException] {
|
||||
Write-Warning "The specified command was not found."
|
||||
Write-Warning $PSItem.Exception.message
|
||||
}
|
||||
Catch [System.Management.Automation.RuntimeException] {
|
||||
} catch [System.Management.Automation.RuntimeException] {
|
||||
Write-Warning "A runtime exception occurred."
|
||||
Write-Warning $PSItem.Exception.message
|
||||
}
|
||||
Catch [System.Security.SecurityException] {
|
||||
} catch [System.Security.SecurityException] {
|
||||
Write-Warning "A security exception occurred."
|
||||
Write-Warning $PSItem.Exception.message
|
||||
}
|
||||
Catch [System.UnauthorizedAccessException] {
|
||||
} catch [System.UnauthorizedAccessException] {
|
||||
Write-Warning "Access denied. You do not have permission to perform this operation."
|
||||
Write-Warning $PSItem.Exception.message
|
||||
}
|
||||
Catch {
|
||||
} catch {
|
||||
# Generic catch block to handle any other type of exception
|
||||
Write-Warning "Unable to run script for $name due to unhandled exception"
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
function Invoke-WinUtilShowExt {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Disables/Enables Show file Extentions
|
||||
.PARAMETER Enabled
|
||||
Indicates whether to enable or disable Show file extentions
|
||||
#>
|
||||
Param($Enabled)
|
||||
Try{
|
||||
if ($Enabled -eq $false){
|
||||
Write-Host "Showing file extentions"
|
||||
$value = 0
|
||||
}
|
||||
else {
|
||||
Write-Host "hiding file extensions"
|
||||
$value = 1
|
||||
}
|
||||
$Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
|
||||
Set-ItemProperty -Path $Path -Name HideFileExt -Value $value
|
||||
}
|
||||
Catch [System.Security.SecurityException] {
|
||||
Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception"
|
||||
}
|
||||
Catch [System.Management.Automation.ItemNotFoundException] {
|
||||
Write-Warning $psitem.Exception.ErrorRecord
|
||||
}
|
||||
Catch{
|
||||
Write-Warning "Unable to set $Name due to unhandled exception"
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
function Invoke-WinUtilSnapFlyout {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Disables/Enables Snap Assist Flyout on startup
|
||||
.PARAMETER Enabled
|
||||
Indicates whether to enable or disable Snap Assist Flyout on startup
|
||||
#>
|
||||
Param($Enabled)
|
||||
Try{
|
||||
if ($Enabled -eq $false){
|
||||
Write-Host "Enabling Snap Assist Flyout On startup"
|
||||
$value = 1
|
||||
}
|
||||
else {
|
||||
Write-Host "Disabling Snap Assist Flyout On startup"
|
||||
$value = 0
|
||||
}
|
||||
# taskkill.exe /F /IM "explorer.exe"
|
||||
$Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
|
||||
taskkill.exe /F /IM "explorer.exe"
|
||||
Set-ItemProperty -Path $Path -Name EnableSnapAssistFlyout -Value $value
|
||||
Start-Process "explorer.exe"
|
||||
}
|
||||
Catch [System.Security.SecurityException] {
|
||||
Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception"
|
||||
}
|
||||
Catch [System.Management.Automation.ItemNotFoundException] {
|
||||
Write-Warning $psitem.Exception.ErrorRecord
|
||||
}
|
||||
Catch{
|
||||
Write-Warning "Unable to set $Name due to unhandled exception"
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
function Invoke-WinUtilSnapSuggestion {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Disables/Enables Snap Assist Suggestions on startup
|
||||
.PARAMETER Enabled
|
||||
Indicates whether to enable or disable Snap Assist Suggestions on startup
|
||||
#>
|
||||
Param($Enabled)
|
||||
Try{
|
||||
if ($Enabled -eq $false){
|
||||
Write-Host "Enabling Snap Assist Suggestion On startup"
|
||||
$value = 1
|
||||
}
|
||||
else {
|
||||
Write-Host "Disabling Snap Assist Suggestion On startup"
|
||||
$value = 0
|
||||
}
|
||||
# taskkill.exe /F /IM "explorer.exe"
|
||||
$Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
|
||||
taskkill.exe /F /IM "explorer.exe"
|
||||
Set-ItemProperty -Path $Path -Name SnapAssist -Value $value
|
||||
Start-Process "explorer.exe"
|
||||
}
|
||||
Catch [System.Security.SecurityException] {
|
||||
Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception"
|
||||
}
|
||||
Catch [System.Management.Automation.ItemNotFoundException] {
|
||||
Write-Warning $psitem.Exception.ErrorRecord
|
||||
}
|
||||
Catch{
|
||||
Write-Warning "Unable to set $Name due to unhandled exception"
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
function Invoke-WinUtilSnapWindow {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Disables/Enables Snapping Windows on startup
|
||||
.PARAMETER Enabled
|
||||
Indicates whether to enable or disable Snapping Windows on startup
|
||||
#>
|
||||
Param($Enabled)
|
||||
Try{
|
||||
if ($Enabled -eq $false){
|
||||
Write-Host "Enabling Snap Windows On startup | Relogin Required"
|
||||
$value = 1
|
||||
}
|
||||
else {
|
||||
Write-Host "Disabling Snap Windows On startup | Relogin Required"
|
||||
$value = 0
|
||||
}
|
||||
$Path = "HKCU:\Control Panel\Desktop"
|
||||
Set-ItemProperty -Path $Path -Name WindowArrangementActive -Value $value
|
||||
}
|
||||
Catch [System.Security.SecurityException] {
|
||||
Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception"
|
||||
}
|
||||
Catch [System.Management.Automation.ItemNotFoundException] {
|
||||
Write-Warning $psitem.Exception.ErrorRecord
|
||||
}
|
||||
Catch{
|
||||
Write-Warning "Unable to set $Name due to unhandled exception"
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
}
|
||||
}
|
44
functions/private/Invoke-WinUtilSponsors.ps1
Normal file
44
functions/private/Invoke-WinUtilSponsors.ps1
Normal file
@ -0,0 +1,44 @@
|
||||
Function Invoke-WinUtilSponsors {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Lists Sponsors from ChrisTitusTech
|
||||
.DESCRIPTION
|
||||
Lists Sponsors from ChrisTitusTech
|
||||
.EXAMPLE
|
||||
Invoke-WinUtilSponsors
|
||||
.NOTES
|
||||
This function is used to list sponsors from ChrisTitusTech
|
||||
#>
|
||||
try {
|
||||
# Define the URL and headers
|
||||
$url = "https://github.com/sponsors/ChrisTitusTech"
|
||||
$headers = @{
|
||||
"User-Agent" = "Chrome/58.0.3029.110"
|
||||
}
|
||||
|
||||
# Fetch the webpage content
|
||||
try {
|
||||
$html = Invoke-RestMethod -Uri $url -Headers $headers
|
||||
} catch {
|
||||
Write-Output $_.Exception.Message
|
||||
exit
|
||||
}
|
||||
|
||||
# Use regex to extract the content between "Current sponsors" and "Past sponsors"
|
||||
$currentSponsorsPattern = '(?s)(?<=Current sponsors).*?(?=Past sponsors)'
|
||||
$currentSponsorsHtml = [regex]::Match($html, $currentSponsorsPattern).Value
|
||||
|
||||
# Use regex to extract the sponsor usernames from the alt attributes in the "Current Sponsors" section
|
||||
$sponsorPattern = '(?<=alt="@)[^"]+'
|
||||
$sponsors = [regex]::Matches($currentSponsorsHtml, $sponsorPattern) | ForEach-Object { $_.Value }
|
||||
|
||||
# Exclude "ChrisTitusTech" from the sponsors
|
||||
$sponsors = $sponsors | Where-Object { $_ -ne "ChrisTitusTech" }
|
||||
|
||||
# Return the sponsors
|
||||
return $sponsors
|
||||
} catch {
|
||||
Write-Error "An error occurred while fetching or processing the sponsors: $_"
|
||||
return $null
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
Function Invoke-WinUtilStickyKeys {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Disables/Enables Sticky Keyss on startup
|
||||
.PARAMETER Enabled
|
||||
Indicates whether to enable or disable Sticky Keys on startup
|
||||
#>
|
||||
Param($Enabled)
|
||||
Try {
|
||||
if ($Enabled -eq $false){
|
||||
Write-Host "Enabling Sticky Keys On startup"
|
||||
$value = 510
|
||||
}
|
||||
else {
|
||||
Write-Host "Disabling Sticky Keys On startup"
|
||||
$value = 58
|
||||
}
|
||||
$Path = "HKCU:\Control Panel\Accessibility\StickyKeys"
|
||||
Set-ItemProperty -Path $Path -Name Flags -Value $value
|
||||
}
|
||||
Catch [System.Security.SecurityException] {
|
||||
Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception"
|
||||
}
|
||||
Catch [System.Management.Automation.ItemNotFoundException] {
|
||||
Write-Warning $psitem.Exception.ErrorRecord
|
||||
}
|
||||
Catch{
|
||||
Write-Warning "Unable to set $Name due to unhandled exception"
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
}
|
||||
}
|
@ -1,34 +0,0 @@
|
||||
function Invoke-WinUtilTaskbarWidgets {
|
||||
<#
|
||||
|
||||
.SYNOPSIS
|
||||
Enable/Disable Taskbar Widgets
|
||||
|
||||
.PARAMETER Enabled
|
||||
Indicates whether to enable or disable Taskbar Widgets
|
||||
|
||||
#>
|
||||
Param($Enabled)
|
||||
Try{
|
||||
if ($Enabled -eq $false){
|
||||
Write-Host "Enabling Taskbar Widgets"
|
||||
$value = 1
|
||||
}
|
||||
else {
|
||||
Write-Host "Disabling Taskbar Widgets"
|
||||
$value = 0
|
||||
}
|
||||
$Path = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
|
||||
Set-ItemProperty -Path $Path -Name TaskbarDa -Value $value
|
||||
}
|
||||
Catch [System.Security.SecurityException] {
|
||||
Write-Warning "Unable to set $Path\$Name to $Value due to a Security Exception"
|
||||
}
|
||||
Catch [System.Management.Automation.ItemNotFoundException] {
|
||||
Write-Warning $psitem.Exception.ErrorRecord
|
||||
}
|
||||
Catch{
|
||||
Write-Warning "Unable to set $Name due to unhandled exception"
|
||||
Write-Warning $psitem.Exception.StackTrace
|
||||
}
|
||||
}
|
@ -21,8 +21,12 @@ function Invoke-WinUtilTweaks {
|
||||
$KeepServiceStartup = $true
|
||||
)
|
||||
|
||||
if ($Checkbox -contains "Toggle") {
|
||||
$CheckBox = $sync.configs.tweaks.$CheckBox
|
||||
}
|
||||
|
||||
Write-Debug "Tweaks: $($CheckBox)"
|
||||
if($undo){
|
||||
if($undo) {
|
||||
$Values = @{
|
||||
Registry = "OriginalValue"
|
||||
ScheduledTask = "OriginalState"
|
||||
@ -30,8 +34,7 @@ function Invoke-WinUtilTweaks {
|
||||
ScriptType = "UndoScript"
|
||||
}
|
||||
|
||||
}
|
||||
Else{
|
||||
} else {
|
||||
$Values = @{
|
||||
Registry = "Value"
|
||||
ScheduledTask = "State"
|
||||
@ -40,18 +43,18 @@ function Invoke-WinUtilTweaks {
|
||||
ScriptType = "InvokeScript"
|
||||
}
|
||||
}
|
||||
if($sync.configs.tweaks.$CheckBox.ScheduledTask){
|
||||
if($sync.configs.tweaks.$CheckBox.ScheduledTask) {
|
||||
$sync.configs.tweaks.$CheckBox.ScheduledTask | ForEach-Object {
|
||||
Write-Debug "$($psitem.Name) and state is $($psitem.$($values.ScheduledTask))"
|
||||
Set-WinUtilScheduledTask -Name $psitem.Name -State $psitem.$($values.ScheduledTask)
|
||||
}
|
||||
}
|
||||
if($sync.configs.tweaks.$CheckBox.service){
|
||||
if($sync.configs.tweaks.$CheckBox.service) {
|
||||
Write-Debug "KeepServiceStartup is $KeepServiceStartup"
|
||||
$sync.configs.tweaks.$CheckBox.service | ForEach-Object {
|
||||
$changeservice = $true
|
||||
|
||||
# The check for !($undo) is required, without it the script will throw an error for accessing unavailable memeber, which's the 'OriginalService' Property
|
||||
|
||||
# The check for !($undo) is required, without it the script will throw an error for accessing unavailable memeber, which's the 'OriginalService' Property
|
||||
if($KeepServiceStartup -AND !($undo)) {
|
||||
try {
|
||||
# Check if the service exists
|
||||
@ -60,8 +63,7 @@ function Invoke-WinUtilTweaks {
|
||||
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))"
|
||||
$changeservice = $false
|
||||
}
|
||||
}
|
||||
catch [System.ServiceProcess.ServiceNotFoundException] {
|
||||
} catch [System.ServiceProcess.ServiceNotFoundException] {
|
||||
Write-Warning "Service $($psitem.Name) was not found"
|
||||
}
|
||||
}
|
||||
@ -72,13 +74,21 @@ function Invoke-WinUtilTweaks {
|
||||
}
|
||||
}
|
||||
}
|
||||
if($sync.configs.tweaks.$CheckBox.registry){
|
||||
if($sync.configs.tweaks.$CheckBox.registry) {
|
||||
$sync.configs.tweaks.$CheckBox.registry | ForEach-Object {
|
||||
Write-Debug "$($psitem.Name) and state is $($psitem.$($values.registry))"
|
||||
if (($psitem.Path -imatch "hku") -and !(Get-PSDrive -Name HKU -ErrorAction SilentlyContinue)) {
|
||||
$null = (New-PSDrive -PSProvider Registry -Name HKU -Root HKEY_USERS)
|
||||
if (Get-PSDrive -Name HKU -ErrorAction SilentlyContinue) {
|
||||
Write-Debug "HKU drive created successfully"
|
||||
} else {
|
||||
Write-Debug "Failed to create HKU drive"
|
||||
}
|
||||
}
|
||||
Set-WinUtilRegistry -Name $psitem.Name -Path $psitem.Path -Type $psitem.Type -Value $psitem.$($values.registry)
|
||||
}
|
||||
}
|
||||
if($sync.configs.tweaks.$CheckBox.$($values.ScriptType)){
|
||||
if($sync.configs.tweaks.$CheckBox.$($values.ScriptType)) {
|
||||
$sync.configs.tweaks.$CheckBox.$($values.ScriptType) | ForEach-Object {
|
||||
Write-Debug "$($psitem) and state is $($psitem.$($values.ScriptType))"
|
||||
$Scriptblock = [scriptblock]::Create($psitem)
|
||||
@ -86,8 +96,8 @@ function Invoke-WinUtilTweaks {
|
||||
}
|
||||
}
|
||||
|
||||
if(!$undo){
|
||||
if($sync.configs.tweaks.$CheckBox.appx){
|
||||
if(!$undo) {
|
||||
if($sync.configs.tweaks.$CheckBox.appx) {
|
||||
$sync.configs.tweaks.$CheckBox.appx | ForEach-Object {
|
||||
Write-Debug "UNDO $($psitem.Name)"
|
||||
Remove-WinUtilAPPX -Name $psitem
|
||||
|
231
functions/private/Invoke-WinUtilUninstallPSProfile.ps1
Normal file
231
functions/private/Invoke-WinUtilUninstallPSProfile.ps1
Normal file
@ -0,0 +1,231 @@
|
||||
function Invoke-WinUtilUninstallPSProfile {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
# Uninstalls the CTT PowerShell profile then restores the original profile.
|
||||
#>
|
||||
|
||||
Invoke-WPFRunspace -ArgumentList $PROFILE -DebugPreference $DebugPreference -ScriptBlock {
|
||||
# Remap the automatic built-in $PROFILE variable to the parameter named $PSProfile.
|
||||
param ($PSProfile)
|
||||
|
||||
# Helper function used to uninstall a specific Nerd Fonts font package.
|
||||
function Uninstall-NerdFonts {
|
||||
# Define the parameters block for the Uninstall-NerdFonts function.
|
||||
param (
|
||||
[string]$FontsPath = "$env:LOCALAPPDATA\Microsoft\Windows\Fonts",
|
||||
[string]$FontFamilyName = "CaskaydiaCoveNerdFont"
|
||||
)
|
||||
|
||||
# Get the list of installed fonts as specified by the FontFamilyName parameter.
|
||||
$Fonts = Get-ChildItem $FontsPath -Recurse -Filter "*.ttf" | Where-Object { $_.Name -match $FontFamilyName }
|
||||
|
||||
# Check if the specified fonts are currently installed on the system.
|
||||
if ($Fonts) {
|
||||
# Let the user know that the Nerd Fonts are currently being uninstalled.
|
||||
Write-Host "===> Uninstalling: Nerd Fonts... <===" -ForegroundColor Yellow
|
||||
|
||||
# Loop over the font files and remove each installed font file one-by-one.
|
||||
$Fonts | ForEach-Object {
|
||||
# Check if the font file exists on the disk before attempting to remove it.
|
||||
if (Test-Path "$($_.FullName)") {
|
||||
# Remove the found font files from the disk; uninstalling the font.
|
||||
Remove-Item "$($_.FullName)"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# Let the user know that the Nerd Fonts package has been uninstalled from the system.
|
||||
if (-not $Fonts) {
|
||||
Write-Host "===> Successfully Uninstalled: Nerd Fonts. <===" -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# Helper function used to uninstall a specific Nerd Fonts font corresponding registry keys.
|
||||
function Uninstall-NerdFontRegKeys {
|
||||
# Define the parameters block for the Uninstall-NerdFontsRegKey function.
|
||||
param (
|
||||
[string]$FontsRegPath = "HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts",
|
||||
[string]$FontFamilyName = "CaskaydiaCove"
|
||||
)
|
||||
|
||||
try {
|
||||
# Get all properties (font registrations) from the registry path
|
||||
$registryProperties = Get-ItemProperty -Path $FontsRegPath
|
||||
|
||||
# Filter and remove properties that match the font family name
|
||||
$registryProperties.PSObject.Properties |
|
||||
Where-Object { $_.Name -match $FontFamilyName } |
|
||||
ForEach-Object {
|
||||
If ($_.Name -like "*$FontFamilyName*") {
|
||||
Remove-ItemProperty -path $FontsRegPath -Name $_.Name -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
Write-Host "Error removing registry keys: $($_.exception.message)" -ForegroundColor Red
|
||||
}
|
||||
}
|
||||
|
||||
# Check if Chris Titus Tech's PowerShell profile is currently available in the PowerShell profile folder.
|
||||
if (Test-Path $PSProfile -PathType Leaf) {
|
||||
# Set the GitHub repo path used for looking up the name of Chris Titus Tech's powershell-profile repo.
|
||||
$GitHubRepoPath = "ChrisTitusTech/powershell-profile"
|
||||
|
||||
# Get the unique identifier used to test for the presence of Chris Titus Tech's PowerShell profile.
|
||||
$PSProfileIdentifier = (Invoke-RestMethod "https://api.github.com/repos/$GitHubRepoPath").full_name
|
||||
|
||||
# Check if Chris Titus Tech's PowerShell profile is currently installed in the PowerShell profile folder.
|
||||
if ((Get-Content $PSProfile) -match $PSProfileIdentifier) {
|
||||
# Attempt to uninstall Chris Titus Tech's PowerShell profile from the PowerShell profile folder.
|
||||
try {
|
||||
# Get the content of the backup PowerShell profile and store it in-memory.
|
||||
$PSProfileContent = Get-Content "$PSProfile.bak"
|
||||
|
||||
# Store the flag used to check if OhMyPosh is in use by the backup PowerShell profile.
|
||||
$OhMyPoshInUse = $PSProfileContent -match "oh-my-posh init"
|
||||
|
||||
# Check if OhMyPosh is not currently in use by the backup PowerShell profile.
|
||||
if (-not $OhMyPoshInUse) {
|
||||
# If OhMyPosh is currently installed attempt to uninstall it from the system.
|
||||
if (Get-Command oh-my-posh -ErrorAction SilentlyContinue) {
|
||||
# Let the user know that OhMyPosh is currently being uninstalled from their system.
|
||||
Write-Host "===> Uninstalling: OhMyPosh... <===" -ForegroundColor Yellow
|
||||
|
||||
# Attempt to uninstall OhMyPosh from the system with the WinGet package manager.
|
||||
winget uninstall -e --id JanDeDobbeleer.OhMyPosh
|
||||
}
|
||||
} else {
|
||||
# Let the user know that the uninstallation of OhMyPosh has been skipped because it is in use.
|
||||
Write-Host "===> Skipped Uninstall: OhMyPosh In-Use. <===" -ForegroundColor Yellow
|
||||
}
|
||||
} catch {
|
||||
# Let the user know that an error was encountered when uninstalling OhMyPosh.
|
||||
Write-Host "Failed to uninstall OhMyPosh. Error: $_" -ForegroundColor Red
|
||||
}
|
||||
|
||||
# Attempt to uninstall the specified Nerd Fonts package from the system.
|
||||
try {
|
||||
# Specify the directory that the specified font package will be uninstalled from.
|
||||
[string]$FontsPath = "$env:LOCALAPPDATA\Microsoft\Windows\Fonts"
|
||||
|
||||
# Specify the name of the font package that is to be uninstalled from the system.
|
||||
[string]$FontFamilyName = "CaskaydiaCoveNerdFont"
|
||||
|
||||
# Call the function used to uninstall the specified Nerd Fonts package from the system.
|
||||
Uninstall-NerdFonts -FontsPath $FontsPath -FontFamilyName $FontFamilyName
|
||||
|
||||
} catch {
|
||||
# Let the user know that an error was encountered when uninstalling Nerd Fonts.
|
||||
Write-Host "Failed to uninstall Nerd Fonts. Error: $_" -ForegroundColor Red
|
||||
}
|
||||
|
||||
# Attempt to uninstall the specified Nerd Fonts registry keys from the system.
|
||||
try {
|
||||
# Specify the registry path that the specified font registry keys will be uninstalled from.
|
||||
[string]$FontsRegPath = "HKCU:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts"
|
||||
|
||||
# Specify the name of the font registry keys that is to be uninstalled from the system.
|
||||
[string]$FontFamilyName = "CaskaydiaCove"
|
||||
|
||||
# Call the function used to uninstall the specified Nerd Fonts registry keys from the system.
|
||||
Uninstall-NerdFontRegKeys -FontsPath $FontsRegPath -FontFamilyName $FontFamilyName
|
||||
|
||||
} catch {
|
||||
# Let the user know that an error was encountered when uninstalling Nerd Font registry keys.
|
||||
Write-Host "Failed to uninstall Nerd Font Registry Keys. Error: $_" -ForegroundColor Red
|
||||
}
|
||||
|
||||
# Attempt to uninstall the Terminal-Icons PowerShell module from the system.
|
||||
try {
|
||||
# Get the content of the backup PowerShell profile and store it in-memory.
|
||||
$PSProfileContent = Get-Content "$PSProfile.bak"
|
||||
|
||||
# Store the flag used to check if Terminal-Icons is in use by the backup PowerShell profile.
|
||||
$TerminalIconsInUse = $PSProfileContent -match "Import-Module" -and $PSProfileContent -match "Terminal-Icons"
|
||||
|
||||
# Check if Terminal-Icons is not currently in use by the backup PowerShell profile.
|
||||
if (-not $TerminalIconsInUse) {
|
||||
# If Terminal-Icons is currently installed attempt to uninstall it from the system.
|
||||
if (Get-Module -ListAvailable Terminal-Icons) {
|
||||
# Let the user know that Terminal-Icons is currently being uninstalled from their system.
|
||||
Write-Host "===> Uninstalling: Terminal-Icons... <===" -ForegroundColor Yellow
|
||||
|
||||
# Attempt to uninstall Terminal-Icons from the system with Uninstall-Module.
|
||||
Uninstall-Module -Name Terminal-Icons
|
||||
}
|
||||
} else {
|
||||
# Let the user know that the uninstallation of Terminal-Icons has been skipped because it is in use.
|
||||
Write-Host "===> Skipped Uninstall: Terminal-Icons In-Use. <===" -ForegroundColor Yellow
|
||||
}
|
||||
} catch {
|
||||
# Let the user know that an error was encountered when uninstalling Terminal-Icons.
|
||||
Write-Host "Failed to uninstall Terminal-Icons. Error: $_" -ForegroundColor Red
|
||||
}
|
||||
|
||||
# Attempt to uninstall the Zoxide application from the system.
|
||||
try {
|
||||
# Get the content of the backup PowerShell profile and store it in-memory.
|
||||
$PSProfileContent = Get-Content "$PSProfile.bak"
|
||||
|
||||
# Store the flag used to check if Zoxide is in use by the backup PowerShell profile.
|
||||
$ZoxideInUse = $PSProfileContent -match "zoxide init"
|
||||
|
||||
# Check if Zoxide is not currently in use by the backup PowerShell profile.
|
||||
if (-not $ZoxideInUse) {
|
||||
# If Zoxide is currently installed attempt to uninstall it from the system.
|
||||
if (Get-Command zoxide -ErrorAction SilentlyContinue) {
|
||||
# Let the user know that Zoxide is currently being uninstalled from their system.
|
||||
Write-Host "===> Uninstalling: Zoxide... <===" -ForegroundColor Yellow
|
||||
|
||||
# Attempt to uninstall Zoxide from the system with the WinGet package manager.
|
||||
winget uninstall -e --id ajeetdsouza.zoxide
|
||||
}
|
||||
} else {
|
||||
# Let the user know that the uninstallation of Zoxide been skipped because it is in use.
|
||||
Write-Host "===> Skipped Uninstall: Zoxide In-Use. <===" -ForegroundColor Yellow
|
||||
}
|
||||
} catch {
|
||||
# Let the user know that an error was encountered when uninstalling Zoxide.
|
||||
Write-Host "Failed to uninstall Zoxide. Error: $_" -ForegroundColor Red
|
||||
}
|
||||
|
||||
# Attempt to uninstall the CTT PowerShell profile from the system.
|
||||
try {
|
||||
# Try and remove the CTT PowerShell Profile file from the disk with Remove-Item.
|
||||
Remove-Item $PSProfile
|
||||
|
||||
# Let the user know that the CTT PowerShell profile has been uninstalled from the system.
|
||||
Write-Host "Profile has been uninstalled. Please restart your shell to reflect the changes!" -ForegroundColor Magenta
|
||||
} catch {
|
||||
# Let the user know that an error was encountered when uninstalling the profile.
|
||||
Write-Host "Failed to uninstall profile. Error: $_" -ForegroundColor Red
|
||||
}
|
||||
|
||||
# Attempt to move the user's original PowerShell profile backup back to its original location.
|
||||
try {
|
||||
# Check if the backup PowerShell profile exists before attempting to restore the backup.
|
||||
if (Test-Path "$PSProfile.bak") {
|
||||
# Restore the backup PowerShell profile and move it to its original location.
|
||||
Move-Item "$PSProfile.bak" $PSProfile
|
||||
|
||||
# Let the user know that their PowerShell profile backup has been successfully restored.
|
||||
Write-Host "===> Restored Profile Backup. <===" -ForegroundColor Yellow
|
||||
}
|
||||
} catch {
|
||||
# Let the user know that an error was encountered when restoring the profile backup.
|
||||
Write-Host "Failed to restore profile backup. Error: $_" -ForegroundColor Red
|
||||
}
|
||||
|
||||
# Silently cleanup the oldprofile.ps1 file that was created when the CTT PowerShell profile was installed.
|
||||
Remove-Item "$env:USERPROFILE\oldprofile.ps1" | Out-Null
|
||||
} else {
|
||||
# Let the user know that the CTT PowerShell profile is not installed and that the uninstallation was skipped.
|
||||
Write-Host "===> Chris Titus Tech's PowerShell Profile Not Found. Skipped Uninstallation. <===" -ForegroundColor Magenta
|
||||
}
|
||||
} else {
|
||||
# Let the user know that no PowerShell profile was found and that the uninstallation was skipped.
|
||||
Write-Host "===> No PowerShell Profile Found. Skipped Uninstallation. <===" -ForegroundColor Magenta
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user