mirror of
https://github.com/ChrisTitusTech/winutil
synced 2026-04-06 06:38:31 +00:00
Compare commits
12 Commits
26.03.03
...
d2dbf03572
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2dbf03572 | ||
|
|
88c68fd411 | ||
|
|
e82aaf03f0 | ||
|
|
9a77fed09b | ||
|
|
336ac6fb8f | ||
|
|
72ad35bbd8 | ||
|
|
df17ca4695 | ||
|
|
7f46e8d60d | ||
|
|
9769cafa7d | ||
|
|
42dfc8c82b | ||
|
|
d13295bdd8 | ||
|
|
5fc566b46f |
32
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
32
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -6,9 +6,6 @@ body:
|
|||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
value: |
|
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**
|
## ⚠️ **IMPORTANT**
|
||||||
- 🛠️ **Supported environments only:** We only support Windows 11.
|
- 🛠️ **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).
|
- 💡 For general questions, use the [Discussions section](https://github.com/Christitustech/winutil/discussions) or join our Community-driven [Discord Server](https://discord.gg/RUbZUZyByQ).
|
||||||
@@ -24,11 +21,16 @@ body:
|
|||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
- type: input
|
- type: dropdown
|
||||||
id: affected_part
|
id: affected_part
|
||||||
attributes:
|
attributes:
|
||||||
label: 📜 What part of Winutil are you having issues with?
|
label: What part of Winutil are you having issues with?
|
||||||
placeholder: "e.g., Tweaks, etc."
|
options:
|
||||||
|
- Program Install Tab
|
||||||
|
- Tweaks Tab
|
||||||
|
- Config Tab
|
||||||
|
- Updates Tab
|
||||||
|
- Win11 Creator Tab
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
@@ -39,24 +41,8 @@ body:
|
|||||||
validations:
|
validations:
|
||||||
required: true
|
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
|
- type: textarea
|
||||||
id: error_output
|
id: error_output
|
||||||
attributes:
|
attributes:
|
||||||
label: ❌ Paste the full error output (if available).
|
label: ❌ Paste the full error output (if available) or Screenshot.
|
||||||
placeholder: "Include any relevant logs or error messages."
|
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
|
|
||||||
|
|||||||
37
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
37
.github/ISSUE_TEMPLATE/feature_request.yaml
vendored
@@ -13,45 +13,10 @@ body:
|
|||||||
- 🛠️ **Supported environments only:** We only support Windows 11.
|
- 🛠️ **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).
|
- 💡 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
|
- type: textarea
|
||||||
id: proposed_solution
|
id: proposed_solution
|
||||||
attributes:
|
attributes:
|
||||||
label: 💡 Describe the solution you'd like
|
label: 💡 Describe the solution you'd like
|
||||||
placeholder: "Provide a clear and concise description of what you want to happen."
|
placeholder: "Provide a clear and concise description."
|
||||||
validations:
|
validations:
|
||||||
required: true
|
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
|
|
||||||
|
|||||||
@@ -128,6 +128,154 @@ winutil/
|
|||||||
- CheckBoxes for options
|
- CheckBoxes for options
|
||||||
- ListBoxes for selections
|
- ListBoxes for selections
|
||||||
|
|
||||||
|
## Win11 Creator Architecture
|
||||||
|
|
||||||
|
The **Win11 Creator** is a specialized subsystem within Winutil that creates customized Windows 11 ISOs. It operates independently from the main package installation and tweak system.
|
||||||
|
|
||||||
|
### Win11 Creator Components
|
||||||
|
|
||||||
|
**Core Functions** (`functions/private/`):
|
||||||
|
- `Invoke-WinUtilISO.ps1`: Main orchestrator containing all Win11 Creator functions
|
||||||
|
- `Invoke-WinUtilISOBrowse`: ISO file selection dialog
|
||||||
|
- `Invoke-WinUtilISOMountAndVerify`: Validates and mounts ISO, verifies it's official Windows 11
|
||||||
|
- `Invoke-WinUtilISOModify`: Launches modification in background runspace
|
||||||
|
- `Invoke-WinUtilISOExport`: Handles ISO and USB export
|
||||||
|
- `Invoke-WinUtilISOCheckExistingWork`: Recovers incomplete work sessions
|
||||||
|
- `Invoke-WinUtilISOCleanAndReset`: Cleans up temp directories and resets UI
|
||||||
|
|
||||||
|
- `Invoke-WinUtilISOScript.ps1`: Applies modifications to mounted install.wim
|
||||||
|
- Removes provisioned AppX packages (40+ bloatware apps)
|
||||||
|
- Injects drivers (optional) from current system
|
||||||
|
- Removes OneDrive setup files
|
||||||
|
- Applies offline registry tweaks (hardware bypass, privacy, telemetry, OOBE)
|
||||||
|
- Deletes telemetry scheduled task definitions
|
||||||
|
- Pre-stages setup scripts from autounattend.xml
|
||||||
|
- Removes unused Windows editions
|
||||||
|
- Cleans component store via DISM
|
||||||
|
|
||||||
|
### Win11 Creator Data Flow
|
||||||
|
|
||||||
|
```
|
||||||
|
User selects official Windows 11 ISO
|
||||||
|
↓
|
||||||
|
Invoke-WinUtilISOBrowse → OpenFileDialog, validates file size
|
||||||
|
↓
|
||||||
|
Invoke-WinUtilISOMountAndVerify
|
||||||
|
├─ Mount ISO via Mount-DiskImage
|
||||||
|
├─ Verify install.wim or install.esd exists
|
||||||
|
├─ Check for "Windows 11" in image metadata
|
||||||
|
├─ Extract available editions (Home, Pro, Enterprise, etc.)
|
||||||
|
└─ Store ISO path, drive letter, WIM path, image info in $sync
|
||||||
|
↓
|
||||||
|
User optionally enables Driver Injection checkbox
|
||||||
|
↓
|
||||||
|
Invoke-WinUtilISOModify (runs in background runspace)
|
||||||
|
├─ Create work directory: ~WinUtil_Win11ISO_[timestamp]
|
||||||
|
├─ Copy ISO contents to disk (~5-6 GB)
|
||||||
|
├─ Mount install.wim at selected edition/index
|
||||||
|
├─ Invoke-WinUtilISOScript:
|
||||||
|
│ ├─ Remove 40+ bloat AppX packages
|
||||||
|
│ ├─ Export and inject drivers (if enabled)
|
||||||
|
│ ├─ Remove OneDrive setup
|
||||||
|
│ ├─ Load offline registry hives
|
||||||
|
│ ├─ Apply 50+ registry tweaks (hardware bypass, privacy, telemetry, OOBE, etc.)
|
||||||
|
│ ├─ Delete telemetry scheduled task files
|
||||||
|
│ ├─ Pre-stage setup scripts from autounattend.xml to C:\Windows\Setup\Scripts\
|
||||||
|
│ └─ Unload registry hives
|
||||||
|
├─ DISM /Cleanup-Image /StartComponentCleanup /ResetBase (saves 300-800 MB)
|
||||||
|
├─ Dismount and save modified install.wim (~10+ minutes, slowest step)
|
||||||
|
├─ Export selected edition only (removes all other editions, saves 1-2 GB each)
|
||||||
|
├─ Dismount source ISO
|
||||||
|
└─ Report completion, enable export options
|
||||||
|
↓
|
||||||
|
Invoke-WinUtilISOExport (user chooses output)
|
||||||
|
├─ Option 1: Save as ISO
|
||||||
|
│ ├─ Build bootable ISO via oscdimg.exe (BIOS/UEFI dual-boot)
|
||||||
|
│ └─ Output: Win11_Modified_[date].iso (2.5-3.5 GB)
|
||||||
|
│
|
||||||
|
└─ Option 2: Write to USB
|
||||||
|
├─ Format USB as GPT
|
||||||
|
├─ Create 512 MB EFI partition
|
||||||
|
├─ Copy modified ISO contents
|
||||||
|
└─ Output: Bootable USB (minimum 8 GB)
|
||||||
|
↓
|
||||||
|
Invoke-WinUtilISOCleanAndReset (optional)
|
||||||
|
└─ Delete temp working directory (~10-15 GB)
|
||||||
|
└─ Reset UI to initial state
|
||||||
|
```
|
||||||
|
|
||||||
|
### Win11 Creator Validation & Safety
|
||||||
|
|
||||||
|
**ISO Validation**:
|
||||||
|
- Only accepts official Microsoft Windows 11 ISOs
|
||||||
|
- Validates presence of install.wim or install.esd
|
||||||
|
- Checks image metadata for "Windows 11" string
|
||||||
|
- Rejects custom, modified, or non-Windows 11 ISOs
|
||||||
|
|
||||||
|
**Work Session Recovery**:
|
||||||
|
- Auto-detects incomplete work from previous sessions
|
||||||
|
- Allows resuming Step 4 (export) without re-running Steps 1-3
|
||||||
|
- Prevents redundant modifications
|
||||||
|
|
||||||
|
**Modification Safety**:
|
||||||
|
- All registry changes are documented in script (reversible)
|
||||||
|
- Original ISO never modified; only working copy
|
||||||
|
- Logged to `WinUtil_Win11ISO.log` for debugging
|
||||||
|
- DISM handles image dismount with automatic cleanup on error
|
||||||
|
|
||||||
|
### Win11 Creator Registry Tweaks
|
||||||
|
|
||||||
|
The `Invoke-WinUtilISOScript` function applies **50+ offline registry tweaks**:
|
||||||
|
|
||||||
|
**Hardware Bypass**:
|
||||||
|
- TPM 2.0 check bypass
|
||||||
|
- Secure Boot requirement bypass
|
||||||
|
- CPU compatibility bypass
|
||||||
|
- RAM requirement bypass
|
||||||
|
- Storage check bypass
|
||||||
|
|
||||||
|
**Privacy & Telemetry**:
|
||||||
|
- Disable advertising ID
|
||||||
|
- Disable tailored experiences
|
||||||
|
- Disable input personalization
|
||||||
|
- Disable speech online privacy
|
||||||
|
- Disable cloud content suggestions
|
||||||
|
- Disable app suggestion subscriptions
|
||||||
|
- Remove CEIP, Appraiser, WaaSMedic, etc.
|
||||||
|
|
||||||
|
**OOBE & Setup**:
|
||||||
|
- Enable local account setup
|
||||||
|
- Skip Microsoft account requirement
|
||||||
|
- Dark mode by default
|
||||||
|
- Empty taskbar and Start Menu
|
||||||
|
|
||||||
|
**Post-Setup Installations**:
|
||||||
|
- Prevent DevHome auto-installation
|
||||||
|
- Prevent new Outlook Mail app installation
|
||||||
|
- Prevent Teams auto-installation
|
||||||
|
|
||||||
|
**System Features**:
|
||||||
|
- Disable BitLocker and device encryption
|
||||||
|
- Disable Chat icon from taskbar
|
||||||
|
- Disable OneDrive folder backup
|
||||||
|
- Disable Copilot
|
||||||
|
- Disable Windows Update during OOBE (re-enabled at first login)
|
||||||
|
|
||||||
|
### Driver Injection Feature
|
||||||
|
|
||||||
|
**Optional Enhancement**: When enabled, exports all drivers from the running system and injects them into both:
|
||||||
|
- `install.wim` (main OS image)
|
||||||
|
- `boot.wim` index 2 (Windows Setup PE environment)
|
||||||
|
|
||||||
|
**Use Case**: Enables offline installation on systems with missing drivers.
|
||||||
|
|
||||||
|
### Disk Space Requirements
|
||||||
|
|
||||||
|
- **Temporary working directory**: ~10-15 GB
|
||||||
|
- **Original ISO**: 4-6 GB
|
||||||
|
- **Modified ISO**: 2.5-3.5 GB
|
||||||
|
- **Total needed**: ~25 GB for safe operation
|
||||||
|
|
||||||
## Data Flow
|
## Data Flow
|
||||||
|
|
||||||
### Application Installation Flow
|
### Application Installation Flow
|
||||||
@@ -514,6 +662,7 @@ Outputs `winutil.ps1` in the root directory.
|
|||||||
|
|
||||||
- [Contributing Guide](../../contributing/) - How to contribute code
|
- [Contributing Guide](../../contributing/) - How to contribute code
|
||||||
- [User Guide](../../userguide/) - End-user documentation
|
- [User Guide](../../userguide/) - End-user documentation
|
||||||
|
- [Win11 Creator Guide](../../userguide/win11Creator/) - Building customized Windows 11 ISOs
|
||||||
- [FAQ](../../faq/) - Common questions
|
- [FAQ](../../faq/) - Common questions
|
||||||
|
|
||||||
## Additional Resources
|
## Additional Resources
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ weight: 5
|
|||||||
Winutil includes a built-in **Win11 Creator** tool that lets you take any official Windows 11 ISO and produce a customized, debloated version — with telemetry removed, hardware requirement checks bypassed, and local account setup enabled out of the box. You can export the result as a new ISO file or write it directly to a USB drive.
|
Winutil includes a built-in **Win11 Creator** tool that lets you take any official Windows 11 ISO and produce a customized, debloated version — with telemetry removed, hardware requirement checks bypassed, and local account setup enabled out of the box. You can export the result as a new ISO file or write it directly to a USB drive.
|
||||||
|
|
||||||
> [!IMPORTANT]
|
> [!IMPORTANT]
|
||||||
> You need a valid Windows 11 ISO before starting. Download one from [Microsoft's official site](https://www.microsoft.com/en-us/software-download/windows11) or use [UUP Dump](https://uupdump.net/). The process uses ~10–15 GB of temporary disk space, so make sure you have room.
|
> You need an **official Windows 11 ISO** from [Microsoft's website](https://www.microsoft.com/en-us/software-download/windows11) before starting. Custom, modified, or non-official ISOs are not supported. The process uses ~10–15 GB of temporary disk space, so make sure you have room.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
### Step 1 — Select Your ISO
|
### Step 1 — Select Your Official Windows 11 ISO
|
||||||
|
|
||||||
1. Open Winutil and go to the **Win11 Creator** tab.
|
1. Open Winutil and go to the **Win11 Creator** tab.
|
||||||
2. Click **Browse** and select your Windows 11 ISO file (must be 4 GB or larger).
|
2. Click **Browse** and select your **official Windows 11 ISO file** from Microsoft (must be 4 GB or larger). Custom or modified ISOs are not supported.
|
||||||
3. The file path and size will appear on screen once selected.
|
3. The file path and size will appear on screen once selected.
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -35,14 +35,31 @@ Winutil includes a built-in **Win11 Creator** tool that lets you take any offici
|
|||||||
|
|
||||||
Click **Run Windows ISO Modification and Creator** to start the customization process. Winutil will:
|
Click **Run Windows ISO Modification and Creator** to start the customization process. Winutil will:
|
||||||
|
|
||||||
|
**App & Component Removal:**
|
||||||
- **Remove 40+ bloat apps** — Clipchamp, Teams, Copilot, Dev Home, new Outlook, Bing apps, Solitaire, and more
|
- **Remove 40+ bloat apps** — Clipchamp, Teams, Copilot, Dev Home, new Outlook, Bing apps, Solitaire, and more
|
||||||
- **Delete OneDrive setup** from the image
|
- **Delete OneDrive setup** from the image
|
||||||
- **Apply registry tweaks** — disables telemetry, advertising ID, tailored experiences, and cloud content features
|
|
||||||
|
**System Customization:**
|
||||||
- **Bypass hardware checks** — removes TPM, Secure Boot, CPU, and RAM requirement enforcement so the ISO installs on unsupported hardware
|
- **Bypass hardware checks** — removes TPM, Secure Boot, CPU, and RAM requirement enforcement so the ISO installs on unsupported hardware
|
||||||
- **Enable local account setup** — injects an `autounattend.xml` that skips the Microsoft account screen during OOBE
|
- **Enable local account setup** — injects an `autounattend.xml` that skips the Microsoft account screen during OOBE
|
||||||
|
- **Disable BitLocker and device encryption** — removes startup overhead
|
||||||
|
- **Disable Chat icon** — removes chat taskbar button
|
||||||
- **Strip unused editions** — keeps only your selected edition, saving 1–2 GB per removed edition
|
- **Strip unused editions** — keeps only your selected edition, saving 1–2 GB per removed edition
|
||||||
- **Clean the component store** — runs DISM cleanup to reclaim another 300–800 MB
|
- **Clean the component store** — runs DISM cleanup to reclaim another 300–800 MB
|
||||||
|
|
||||||
|
**Privacy & Telemetry Tweaks:**
|
||||||
|
- **Disable telemetry** — advertising ID, tailored experiences, input personalization, speech online privacy
|
||||||
|
- **Disable cloud content features** — app suggestions, Microsoft Store recommendations
|
||||||
- **Remove telemetry scheduled tasks** — CEIP, Appraiser, WaaSMedic, and others
|
- **Remove telemetry scheduled tasks** — CEIP, Appraiser, WaaSMedic, and others
|
||||||
|
- **Disable OneDrive folder backup** — prevents automatic backups to cloud
|
||||||
|
- **Prevent DevHome and Outlook post-setup installation**
|
||||||
|
- **Prevent Teams installation** — blocks auto-install after OOBE
|
||||||
|
- **Prevent new Outlook Mail app installation**
|
||||||
|
- **Disable Windows Update during OOBE** — re-enabled automatically on first login
|
||||||
|
- **Disable Copilot and search box suggestions**
|
||||||
|
|
||||||
|
**Optional: Driver Injection**
|
||||||
|
- If enabled, injects all drivers from your current system into the install.wim and boot.wim — useful for offline installations on machines with missing drivers. This is an optional checkbox in Step 3.
|
||||||
|
|
||||||
A live log shows progress as each step completes. This stage takes **10–30 minutes** depending on your disk speed — the WIM dismount near the end is the slowest part, so don't close Winutil while it's running.
|
A live log shows progress as each step completes. This stage takes **10–30 minutes** depending on your disk speed — the WIM dismount near the end is the slowest part, so don't close Winutil while it's running.
|
||||||
|
|
||||||
@@ -94,9 +111,9 @@ When you install Windows 11 from your modified ISO:
|
|||||||
- **No Microsoft account required** — create a local account directly during setup
|
- **No Microsoft account required** — create a local account directly during setup
|
||||||
- **No hardware checks** — installs on machines without TPM 2.0, Secure Boot, or supported CPUs
|
- **No hardware checks** — installs on machines without TPM 2.0, Secure Boot, or supported CPUs
|
||||||
- **Dark mode enabled by default**
|
- **Dark mode enabled by default**
|
||||||
- **Empty taskbar and Start Menu** — no pinned apps
|
- **Empty taskbar and Start Menu** — no pinned apps, Chat icon removed
|
||||||
- **Windows Update re-enabled automatically** after first login (it's paused during OOBE to prevent interruption)
|
- **Windows Update disabled during OOBE** — automatically re-enabled on first login to prevent setup interruptions
|
||||||
- **BitLocker disabled**, Recall disabled, desktop shortcuts removed
|
- **BitLocker disabled** — removes startup overhead on first boot
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -103,13 +103,24 @@ function Invoke-WinUtilISOWriteUSB {
|
|||||||
try {
|
try {
|
||||||
SetProgress "Formatting USB drive..." 10
|
SetProgress "Formatting USB drive..." 10
|
||||||
|
|
||||||
# Phase 1: Clean disk via diskpart
|
# Phase 1: Clean disk via diskpart (retry once if the drive is not yet ready)
|
||||||
$dpFile1 = Join-Path $env:TEMP "winutil_diskpart_$(Get-Random).txt"
|
$dpFile1 = Join-Path $env:TEMP "winutil_diskpart_$(Get-Random).txt"
|
||||||
"select disk $diskNum`nclean`nexit" | Set-Content -Path $dpFile1 -Encoding ASCII
|
"select disk $diskNum`nclean`nexit" | Set-Content -Path $dpFile1 -Encoding ASCII
|
||||||
Log "Running diskpart clean on Disk $diskNum..."
|
Log "Running diskpart clean on Disk $diskNum..."
|
||||||
diskpart /s $dpFile1 2>&1 | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" }
|
$dpCleanOut = diskpart /s $dpFile1 2>&1
|
||||||
|
$dpCleanOut | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" }
|
||||||
Remove-Item $dpFile1 -Force -ErrorAction SilentlyContinue
|
Remove-Item $dpFile1 -Force -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
if (($dpCleanOut -join ' ') -match 'device is not ready') {
|
||||||
|
Log "Disk $diskNum was not ready; waiting 5 seconds and retrying clean..."
|
||||||
|
Start-Sleep -Seconds 5
|
||||||
|
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue
|
||||||
|
$dpFile1b = Join-Path $env:TEMP "winutil_diskpart_$(Get-Random).txt"
|
||||||
|
"select disk $diskNum`nclean`nexit" | Set-Content -Path $dpFile1b -Encoding ASCII
|
||||||
|
diskpart /s $dpFile1b 2>&1 | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" }
|
||||||
|
Remove-Item $dpFile1b -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
|
||||||
# Phase 2: Initialize as GPT
|
# Phase 2: Initialize as GPT
|
||||||
Start-Sleep -Seconds 2
|
Start-Sleep -Seconds 2
|
||||||
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue
|
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue
|
||||||
@@ -122,7 +133,8 @@ function Invoke-WinUtilISOWriteUSB {
|
|||||||
Log "Disk $diskNum converted to GPT (was $($diskObj.PartitionStyle))."
|
Log "Disk $diskNum converted to GPT (was $($diskObj.PartitionStyle))."
|
||||||
}
|
}
|
||||||
|
|
||||||
# Phase 3: Create FAT32 partition via diskpart
|
# Phase 3: Create FAT32 partition via diskpart, then format with Format-Volume
|
||||||
|
# (diskpart's 'format' command can fail with "no volume selected" on fresh/never-formatted drives)
|
||||||
$volLabel = "W11-" + (Get-Date).ToString('yyMMdd')
|
$volLabel = "W11-" + (Get-Date).ToString('yyMMdd')
|
||||||
$dpFile2 = Join-Path $env:TEMP "winutil_diskpart2_$(Get-Random).txt"
|
$dpFile2 = Join-Path $env:TEMP "winutil_diskpart2_$(Get-Random).txt"
|
||||||
$maxFat32PartitionMB = 32768
|
$maxFat32PartitionMB = 32768
|
||||||
@@ -136,28 +148,38 @@ function Invoke-WinUtilISOWriteUSB {
|
|||||||
@(
|
@(
|
||||||
"select disk $diskNum"
|
"select disk $diskNum"
|
||||||
$createPartitionCommand
|
$createPartitionCommand
|
||||||
"format quick fs=fat32 label=`"$volLabel`""
|
|
||||||
"exit"
|
"exit"
|
||||||
) | Set-Content -Path $dpFile2 -Encoding ASCII
|
) | Set-Content -Path $dpFile2 -Encoding ASCII
|
||||||
Log "Creating partitions on Disk $diskNum..."
|
Log "Creating partitions on Disk $diskNum..."
|
||||||
diskpart /s $dpFile2 2>&1 | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" }
|
diskpart /s $dpFile2 2>&1 | Where-Object { $_ -match '\S' } | ForEach-Object { Log " diskpart: $_" }
|
||||||
Remove-Item $dpFile2 -Force -ErrorAction SilentlyContinue
|
Remove-Item $dpFile2 -Force -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
SetProgress "Assigning drive letters..." 30
|
SetProgress "Formatting USB partition..." 25
|
||||||
Start-Sleep -Seconds 3
|
Start-Sleep -Seconds 3
|
||||||
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue
|
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
$partitions = Get-Partition -DiskNumber $diskNum -ErrorAction Stop
|
$partitions = Get-Partition -DiskNumber $diskNum -ErrorAction Stop
|
||||||
Log "Partitions on Disk $diskNum after format: $($partitions.Count)"
|
Log "Partitions on Disk $diskNum after creation: $($partitions.Count)"
|
||||||
foreach ($p in $partitions) {
|
foreach ($p in $partitions) {
|
||||||
Log " Partition $($p.PartitionNumber) Type=$($p.Type) Letter=$($p.DriveLetter) Size=$([math]::Round($p.Size/1MB))MB"
|
Log " Partition $($p.PartitionNumber) Type=$($p.Type) Letter=$($p.DriveLetter) Size=$([math]::Round($p.Size/1MB))MB"
|
||||||
}
|
}
|
||||||
|
|
||||||
$winpePart = $partitions | Where-Object { $_.Type -eq "Basic" } | Select-Object -Last 1
|
$winpePart = $partitions | Where-Object { $_.Type -eq "Basic" } | Select-Object -Last 1
|
||||||
if (-not $winpePart) {
|
if (-not $winpePart) {
|
||||||
throw "Could not find the WINPE (Basic) partition on Disk $diskNum after format."
|
throw "Could not find the Basic partition on Disk $diskNum after creation."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Format using Format-Volume (reliable on fresh drives; diskpart format fails
|
||||||
|
# with 'no volume selected' when the partition has never been formatted before)
|
||||||
|
Log "Formatting Partition $($winpePart.PartitionNumber) as FAT32 (label: $volLabel)..."
|
||||||
|
Get-Partition -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber |
|
||||||
|
Format-Volume -FileSystem FAT32 -NewFileSystemLabel $volLabel -Force -Confirm:$false | Out-Null
|
||||||
|
Log "Partition $($winpePart.PartitionNumber) formatted as FAT32."
|
||||||
|
|
||||||
|
SetProgress "Assigning drive letters..." 30
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
Update-Disk -Number $diskNum -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
try { Remove-PartitionAccessPath -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber -AccessPath "$($winpePart.DriveLetter):" -ErrorAction SilentlyContinue } catch {}
|
try { Remove-PartitionAccessPath -DiskNumber $diskNum -PartitionNumber $winpePart.PartitionNumber -AccessPath "$($winpePart.DriveLetter):" -ErrorAction SilentlyContinue } catch {}
|
||||||
$usbLetter = Get-FreeDriveLetter
|
$usbLetter = Get-FreeDriveLetter
|
||||||
if (-not $usbLetter) { throw "No free drive letters (D-Z) available to assign to the USB data partition." }
|
if (-not $usbLetter) { throw "No free drive letters (D-Z) available to assign to the USB data partition." }
|
||||||
@@ -166,6 +188,12 @@ function Invoke-WinUtilISOWriteUSB {
|
|||||||
Start-Sleep -Seconds 2
|
Start-Sleep -Seconds 2
|
||||||
|
|
||||||
$usbDrive = "${usbLetter}:"
|
$usbDrive = "${usbLetter}:"
|
||||||
|
$retries = 0
|
||||||
|
while (-not (Test-Path $usbDrive) -and $retries -lt 6) {
|
||||||
|
$retries++
|
||||||
|
Log "Waiting for $usbDrive to become accessible (attempt $retries/6)..."
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
}
|
||||||
if (-not (Test-Path $usbDrive)) { throw "Drive $usbDrive is not accessible after letter assignment." }
|
if (-not (Test-Path $usbDrive)) { throw "Drive $usbDrive is not accessible after letter assignment." }
|
||||||
Log "USB data partition: $usbDrive"
|
Log "USB data partition: $usbDrive"
|
||||||
|
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
function Test-WinUtilInternetConnection {
|
|
||||||
<#
|
|
||||||
.SYNOPSIS
|
|
||||||
Tests if the computer has internet connectivity
|
|
||||||
.OUTPUTS
|
|
||||||
Boolean - True if connected, False if offline
|
|
||||||
#>
|
|
||||||
try {
|
|
||||||
# Test multiple reliable endpoints
|
|
||||||
$testSites = @(
|
|
||||||
"8.8.8.8", # Google DNS
|
|
||||||
"1.1.1.1", # Cloudflare DNS
|
|
||||||
"208.67.222.222" # OpenDNS
|
|
||||||
)
|
|
||||||
|
|
||||||
foreach ($site in $testSites) {
|
|
||||||
if (Test-Connection -ComputerName $site -Count 1 -Quiet -ErrorAction SilentlyContinue) {
|
|
||||||
return $true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
return $false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,7 +11,7 @@ function Invoke-WPFFixesWinget {
|
|||||||
try {
|
try {
|
||||||
Set-WinUtilTaskbaritem -state "Indeterminate" -overlay "logo"
|
Set-WinUtilTaskbaritem -state "Indeterminate" -overlay "logo"
|
||||||
Write-Host "==> Starting Winget Repair"
|
Write-Host "==> Starting Winget Repair"
|
||||||
Install-WinUtilWinget -Force
|
Install-WinUtilWinget
|
||||||
} catch {
|
} catch {
|
||||||
Write-Error "Failed to install winget: $_"
|
Write-Error "Failed to install winget: $_"
|
||||||
Set-WinUtilTaskbaritem -state "Error" -overlay "warning"
|
Set-WinUtilTaskbaritem -state "Error" -overlay "warning"
|
||||||
|
|||||||
@@ -15,12 +15,14 @@ $maxthreads = [int]$env:NUMBER_OF_PROCESSORS
|
|||||||
$hashVars = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'sync',$sync,$Null
|
$hashVars = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'sync',$sync,$Null
|
||||||
$debugVar = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'DebugPreference',$DebugPreference,$Null
|
$debugVar = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'DebugPreference',$DebugPreference,$Null
|
||||||
$uiVar = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'PARAM_NOUI',$PARAM_NOUI,$Null
|
$uiVar = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'PARAM_NOUI',$PARAM_NOUI,$Null
|
||||||
|
$offlineVar = New-object System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList 'PARAM_OFFLINE',$PARAM_OFFLINE,$Null
|
||||||
$InitialSessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
|
$InitialSessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault()
|
||||||
|
|
||||||
# Add the variable to the session state
|
# Add the variable to the session state
|
||||||
$InitialSessionState.Variables.Add($hashVars)
|
$InitialSessionState.Variables.Add($hashVars)
|
||||||
$InitialSessionState.Variables.Add($debugVar)
|
$InitialSessionState.Variables.Add($debugVar)
|
||||||
$InitialSessionState.Variables.Add($uiVar)
|
$InitialSessionState.Variables.Add($uiVar)
|
||||||
|
$InitialSessionState.Variables.Add($offlineVar)
|
||||||
|
|
||||||
# Get every private function and add them to the session state
|
# Get every private function and add them to the session state
|
||||||
$functions = Get-ChildItem function:\ | Where-Object { $_.Name -imatch 'winutil|WPF' }
|
$functions = Get-ChildItem function:\ | Where-Object { $_.Name -imatch 'winutil|WPF' }
|
||||||
@@ -350,11 +352,10 @@ $sync["Form"].Add_ContentRendered({
|
|||||||
Write-Debug "Unable to retrieve information about the primary monitor."
|
Write-Debug "Unable to retrieve information about the primary monitor."
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check internet connectivity and disable install tab if offline
|
if ($PARAM_OFFLINE) {
|
||||||
#$isOnline = Test-WinUtilInternetConnection
|
# Show offline banner
|
||||||
$isOnline = $true # Temporarily force online mode until we can resolve false negatives
|
$sync.WPFOfflineBanner.Visibility = [System.Windows.Visibility]::Visible
|
||||||
|
|
||||||
if (-not $isOnline) {
|
|
||||||
# Disable the install tab
|
# Disable the install tab
|
||||||
$sync.WPFTab1BT.IsEnabled = $false
|
$sync.WPFTab1BT.IsEnabled = $false
|
||||||
$sync.WPFTab1BT.Opacity = 0.5
|
$sync.WPFTab1BT.Opacity = 0.5
|
||||||
|
|||||||
@@ -9,7 +9,8 @@
|
|||||||
param (
|
param (
|
||||||
[string]$Config,
|
[string]$Config,
|
||||||
[switch]$Run,
|
[switch]$Run,
|
||||||
[switch]$Noui
|
[switch]$Noui,
|
||||||
|
[switch]$Offline
|
||||||
)
|
)
|
||||||
|
|
||||||
if ($Config) {
|
if ($Config) {
|
||||||
@@ -27,25 +28,10 @@ if ($Noui) {
|
|||||||
$PARAM_NOUI = $true
|
$PARAM_NOUI = $true
|
||||||
}
|
}
|
||||||
|
|
||||||
# Load DLLs
|
$PARAM_OFFLINE = $false
|
||||||
Add-Type -AssemblyName PresentationFramework
|
if ($Offline) {
|
||||||
Add-Type -AssemblyName System.Windows.Forms
|
$PARAM_OFFLINE = $true
|
||||||
|
}
|
||||||
# Variable to sync between runspaces
|
|
||||||
$sync = [Hashtable]::Synchronized(@{})
|
|
||||||
$sync.PSScriptRoot = $PSScriptRoot
|
|
||||||
$sync.version = "#{replaceme}"
|
|
||||||
$sync.configs = @{}
|
|
||||||
$sync.Buttons = [System.Collections.Generic.List[PSObject]]::new()
|
|
||||||
$sync.preferences = @{}
|
|
||||||
$sync.ProcessRunning = $false
|
|
||||||
$sync.selectedApps = [System.Collections.Generic.List[string]]::new()
|
|
||||||
$sync.selectedTweaks = [System.Collections.Generic.List[string]]::new()
|
|
||||||
$sync.selectedToggles = [System.Collections.Generic.List[string]]::new()
|
|
||||||
$sync.selectedFeatures = [System.Collections.Generic.List[string]]::new()
|
|
||||||
$sync.currentTab = "Install"
|
|
||||||
$sync.selectedAppsStackPanel
|
|
||||||
$sync.selectedAppsPopup
|
|
||||||
|
|
||||||
|
|
||||||
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
||||||
@@ -80,6 +66,26 @@ if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]:
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Load DLLs
|
||||||
|
Add-Type -AssemblyName PresentationFramework
|
||||||
|
Add-Type -AssemblyName System.Windows.Forms
|
||||||
|
|
||||||
|
# Variable to sync between runspaces
|
||||||
|
$sync = [Hashtable]::Synchronized(@{})
|
||||||
|
$sync.PSScriptRoot = $PSScriptRoot
|
||||||
|
$sync.version = "#{replaceme}"
|
||||||
|
$sync.configs = @{}
|
||||||
|
$sync.Buttons = [System.Collections.Generic.List[PSObject]]::new()
|
||||||
|
$sync.preferences = @{}
|
||||||
|
$sync.ProcessRunning = $false
|
||||||
|
$sync.selectedApps = [System.Collections.Generic.List[string]]::new()
|
||||||
|
$sync.selectedTweaks = [System.Collections.Generic.List[string]]::new()
|
||||||
|
$sync.selectedToggles = [System.Collections.Generic.List[string]]::new()
|
||||||
|
$sync.selectedFeatures = [System.Collections.Generic.List[string]]::new()
|
||||||
|
$sync.currentTab = "Install"
|
||||||
|
$sync.selectedAppsStackPanel
|
||||||
|
$sync.selectedAppsPopup
|
||||||
|
|
||||||
$dateTime = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
|
$dateTime = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
|
||||||
|
|
||||||
# Set the path for the winutil directory
|
# Set the path for the winutil directory
|
||||||
|
|||||||
@@ -5,10 +5,6 @@
|
|||||||
<settings pass="windowsPE">
|
<settings pass="windowsPE">
|
||||||
<component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
<component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
|
||||||
<UserData>
|
<UserData>
|
||||||
<ProductKey>
|
|
||||||
<Key>00000-00000-00000-00000-00000</Key>
|
|
||||||
<WillShowUI>Always</WillShowUI>
|
|
||||||
</ProductKey>
|
|
||||||
<AcceptEula>true</AcceptEula>
|
<AcceptEula>true</AcceptEula>
|
||||||
</UserData>
|
</UserData>
|
||||||
<UseConfigurationSet>false</UseConfigurationSet>
|
<UseConfigurationSet>false</UseConfigurationSet>
|
||||||
|
|||||||
@@ -943,13 +943,19 @@
|
|||||||
</Window.Resources>
|
</Window.Resources>
|
||||||
<Grid Background="{DynamicResource MainBackgroundColor}" ShowGridLines="False" Name="WPFMainGrid" Width="Auto" Height="Auto" HorizontalAlignment="Stretch">
|
<Grid Background="{DynamicResource MainBackgroundColor}" ShowGridLines="False" Name="WPFMainGrid" Width="Auto" Height="Auto" HorizontalAlignment="Stretch">
|
||||||
<Grid.RowDefinitions>
|
<Grid.RowDefinitions>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
<Grid Grid.Row="0" Background="{DynamicResource MainBackgroundColor}">
|
<!-- Offline banner -->
|
||||||
|
<Border Name="WPFOfflineBanner" Grid.Row="0" Background="#8B0000" Visibility="Collapsed" Padding="6,4">
|
||||||
|
<TextBlock Text="⚠ Offline Mode - No Internet Connection" Foreground="White" FontWeight="Bold"
|
||||||
|
HorizontalAlignment="Center" FontSize="13" Background="Transparent"/>
|
||||||
|
</Border>
|
||||||
|
<Grid Grid.Row="1" Background="{DynamicResource MainBackgroundColor}">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto"/> <!-- Navigation buttons -->
|
<ColumnDefinition Width="Auto"/> <!-- Navigation buttons -->
|
||||||
<ColumnDefinition Width="*"/> <!-- Search bar and buttons -->
|
<ColumnDefinition Width="*"/> <!-- Search bar and buttons -->
|
||||||
@@ -1192,7 +1198,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<TabControl Name="WPFTabNav" Background="Transparent" Width="Auto" Height="Auto" BorderBrush="Transparent" BorderThickness="0" Grid.Row="1" Grid.Column="0" Padding="-1">
|
<TabControl Name="WPFTabNav" Background="Transparent" Width="Auto" Height="Auto" BorderBrush="Transparent" BorderThickness="0" Grid.Row="2" Grid.Column="0" Padding="-1">
|
||||||
<TabItem Header="Install" Visibility="Collapsed" Name="WPFTab1">
|
<TabItem Header="Install" Visibility="Collapsed" Name="WPFTab1">
|
||||||
<Grid Background="Transparent" >
|
<Grid Background="Transparent" >
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user