Elevenbuilder.ps1 aktualisiert
Signed-off-by: hax <hax@lainlounge.xyz>
This commit is contained in:
parent
6a58f48ed0
commit
d0e336d0a2
1 changed files with 567 additions and 149 deletions
|
|
@ -1,163 +1,581 @@
|
||||||
# Enable debugging if needed
|
<#
|
||||||
# Set-PSDebug -Trace 1
|
.SYNOPSIS
|
||||||
|
Tiny11 Image Creator – Full Workflow (ISO Download, Mount, Customization, and ISO Creation)
|
||||||
|
|
||||||
|
.DESCRIPTION
|
||||||
|
This script uses DISM and other tools to create a customized Windows 11 image.
|
||||||
|
It now supports obtaining the Windows 11 ISO from a user-supplied path or by auto‑downloading
|
||||||
|
(using massgrave.dev as the source) if no ISO is provided. The ISO is then mounted and assigned
|
||||||
|
a free drive letter. The script then copies installation files, processes install.wim and boot.wim,
|
||||||
|
applies registry tweaks and removals, and finally creates an ISO using oscdimg.exe.
|
||||||
|
|
||||||
|
.PARAMETER ScratchDisk
|
||||||
|
A drive letter (e.g. "D") or path where the working files will be stored.
|
||||||
|
|
||||||
|
.PARAMETER ISOPath
|
||||||
|
(Optional) Full path to a Windows 11 ISO file. If not provided, the script will prompt for
|
||||||
|
the desired language and auto‑download the ISO.
|
||||||
|
|
||||||
|
.PARAMETER Language
|
||||||
|
(Optional) Desired language code for the ISO download (e.g. "en-US", "de-DE"). Only used if ISOPath is not provided.
|
||||||
|
|
||||||
|
.NOTES
|
||||||
|
- This script requires administrative privileges.
|
||||||
|
- It assumes that your original workflow (registry tweaks, application removals, etc.) must remain intact.
|
||||||
|
- Some API endpoints (for downloading the ISO) are hypothetical and may need adjustment.
|
||||||
|
#>
|
||||||
|
|
||||||
param (
|
param (
|
||||||
[ValidatePattern('^[c-zC-Z]$')]
|
[ValidatePattern('^[c-zC-Z]$')]
|
||||||
[string]$ScratchDisk
|
[string]$ScratchDisk,
|
||||||
|
[string]$ISOPath, # Full path to a Windows 11 ISO (optional)
|
||||||
|
[string]$Language # Desired language code (e.g., "en-US", "de-DE")
|
||||||
)
|
)
|
||||||
|
|
||||||
# Determine scratch disk location
|
#region Helper Functions (ISO download and mount)
|
||||||
if (-not $ScratchDisk) {
|
|
||||||
$ScratchDisk = $PSScriptRoot -replace '[\\]+$', ''
|
|
||||||
} else {
|
|
||||||
$ScratchDisk = "$ScratchDisk:"
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Output "Scratch disk set to $ScratchDisk"
|
function Get-Win11DownloadLink {
|
||||||
|
<#
|
||||||
# Ensure script is running with proper execution policy
|
.SYNOPSIS
|
||||||
if ((Get-ExecutionPolicy) -eq 'Restricted') {
|
Queries the API (via massgrave.dev) for the proper ISO download link.
|
||||||
Write-Host "Your current PowerShell Execution Policy is 'Restricted'. This prevents scripts from running."
|
.PARAMETER Language
|
||||||
$response = Read-Host "Do you want to change it to 'RemoteSigned'? (yes/no)"
|
The desired language code.
|
||||||
if ($response -eq 'yes') {
|
.OUTPUTS
|
||||||
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Confirm:$false
|
The download URL as a string.
|
||||||
} else {
|
#>
|
||||||
Write-Host "The script cannot proceed without changing the execution policy. Exiting..."
|
param(
|
||||||
exit
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$Language
|
||||||
|
)
|
||||||
|
# Adjust the endpoint and parameters as required.
|
||||||
|
$apiBase = "https://api.gravesoft.dev/msdl/"
|
||||||
|
$endpoint = "getDownloadLink" # Hypothetical endpoint.
|
||||||
|
$url = "$apiBase$endpoint?language=$Language"
|
||||||
|
|
||||||
|
Write-Host "Querying download link for Windows 11 ISO for language: $Language" -ForegroundColor Cyan
|
||||||
|
try {
|
||||||
|
$response = Invoke-RestMethod -Uri $url -Method Get
|
||||||
|
if ($response -and $response.downloadUrl) {
|
||||||
|
Write-Host "Download URL obtained: $($response.downloadUrl)" -ForegroundColor Green
|
||||||
|
return $response.downloadUrl
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Error "API did not return a valid download URL."
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Error "Error calling the download API: $_"
|
||||||
|
return $null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Ensure script is running as administrator
|
function Get-Windows11ISO {
|
||||||
$adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator
|
<#
|
||||||
$myWindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent())
|
.SYNOPSIS
|
||||||
|
Returns the path to a Windows 11 ISO. If a valid ISOPath is provided, that file is used.
|
||||||
|
Otherwise, prompts (or uses the provided language) and downloads the ISO.
|
||||||
|
.PARAMETER ISOPath
|
||||||
|
User-supplied ISO path.
|
||||||
|
.PARAMETER Language
|
||||||
|
Desired language code.
|
||||||
|
.OUTPUTS
|
||||||
|
The full path to the Windows 11 ISO.
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[string]$ISOPath,
|
||||||
|
[string]$Language
|
||||||
|
)
|
||||||
|
# Use provided ISO if valid
|
||||||
|
if ($ISOPath -and (Test-Path $ISOPath -PathType Leaf)) {
|
||||||
|
Write-Host "Using provided ISO: $ISOPath" -ForegroundColor Green
|
||||||
|
return $ISOPath
|
||||||
|
}
|
||||||
|
|
||||||
|
# If no ISO path, prompt for language (if not provided)
|
||||||
|
if (-not $Language) {
|
||||||
|
$Language = Read-Host "Enter your desired Windows 11 language (e.g., en-US, de-DE)"
|
||||||
|
}
|
||||||
|
|
||||||
|
$downloadLink = Get-Win11DownloadLink -Language $Language
|
||||||
|
if (-not $downloadLink) {
|
||||||
|
Write-Error "Could not retrieve a valid download link. Exiting."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$DownloadPath = "$env:TEMP\Windows11_$Language.iso"
|
||||||
|
Write-Host "Downloading Windows 11 ISO from $downloadLink ..." -ForegroundColor Cyan
|
||||||
|
try {
|
||||||
|
Invoke-WebRequest -Uri $downloadLink -OutFile $DownloadPath
|
||||||
|
Write-Host "Download complete: $DownloadPath" -ForegroundColor Green
|
||||||
|
return $DownloadPath
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Error "Failed to download the ISO: $_"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (-not $myWindowsPrincipal.IsInRole($adminRole)) {
|
function Mount-ISOAndAssignDriveLetter {
|
||||||
Write-Host "Restarting the script as administrator..."
|
<#
|
||||||
$newProcess = New-Object System.Diagnostics.ProcessStartInfo "PowerShell"
|
.SYNOPSIS
|
||||||
$newProcess.Arguments = "-File `"$($MyInvocation.MyCommand.Definition)`""
|
Mounts an ISO image and assigns a free drive letter if none is already assigned.
|
||||||
$newProcess.Verb = "runas"
|
.PARAMETER ISOPath
|
||||||
[System.Diagnostics.Process]::Start($newProcess)
|
The full path to the ISO file.
|
||||||
|
.OUTPUTS
|
||||||
|
The drive letter (e.g., "E:") where the ISO is mounted.
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$ISOPath
|
||||||
|
)
|
||||||
|
if (-not (Test-Path $ISOPath)) {
|
||||||
|
Write-Error "The ISO file '$ISOPath' does not exist."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Mounting ISO image: $ISOPath" -ForegroundColor Cyan
|
||||||
|
$mountedImage = Mount-DiskImage -ImagePath $ISOPath -PassThru
|
||||||
|
if (-not $mountedImage) {
|
||||||
|
Write-Error "Failed to mount ISO image."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Start-Sleep -Seconds 3 # Wait for the volume to become available
|
||||||
|
|
||||||
|
$diskImage = Get-DiskImage -ImagePath $ISOPath
|
||||||
|
if (-not $diskImage) {
|
||||||
|
Write-Error "Unable to retrieve disk image information."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
$disk = $diskImage | Get-Disk
|
||||||
|
if (-not $disk) {
|
||||||
|
Write-Error "Unable to retrieve disk information for the mounted image."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
$diskNumber = $disk.Number
|
||||||
|
|
||||||
|
# Retrieve the first partition (most ISOs contain a single partition)
|
||||||
|
$partition = Get-Partition -DiskNumber $diskNumber | Select-Object -First 1
|
||||||
|
if (-not $partition) {
|
||||||
|
Write-Error "No partition found on the mounted ISO."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
# If no drive letter is assigned, choose a free one (from C: to Z:)
|
||||||
|
if (-not $partition.DriveLetter) {
|
||||||
|
$freeLetters = [char[]](67..90) | ForEach-Object { [char]$_ }
|
||||||
|
$usedLetters = (Get-Volume | Where-Object { $_.DriveLetter } | Select-Object -ExpandProperty DriveLetter)
|
||||||
|
$availableLetters = $freeLetters | Where-Object { $usedLetters -notcontains $_ }
|
||||||
|
if ($availableLetters.Count -eq 0) {
|
||||||
|
Write-Error "No free drive letters available."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
$freeLetter = $availableLetters | Select-Object -First 1
|
||||||
|
Write-Host "Assigning drive letter '$freeLetter' to the mounted ISO." -ForegroundColor Yellow
|
||||||
|
Set-Partition -DiskNumber $diskNumber -PartitionNumber $partition.PartitionNumber -NewDriveLetter $freeLetter
|
||||||
|
$driveLetter = "$freeLetter`:"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$driveLetter = "$($partition.DriveLetter):"
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "ISO mounted at drive letter: $driveLetter" -ForegroundColor Green
|
||||||
|
return $driveLetter
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Helper Functions
|
||||||
|
|
||||||
|
#region Environment Setup
|
||||||
|
|
||||||
|
function Setup-Environment {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Performs pre-flight checks, sets the scratch disk, adjusts execution policy,
|
||||||
|
ensures admin rights, starts logging, and creates necessary directories.
|
||||||
|
#>
|
||||||
|
# Set ScratchDisk (if not provided, use the script folder)
|
||||||
|
if (-not $ScratchDisk) {
|
||||||
|
$global:ScratchDisk = $PSScriptRoot.TrimEnd('\')
|
||||||
|
} else {
|
||||||
|
$global:ScratchDisk = "$ScratchDisk`:" # Append colon if needed.
|
||||||
|
}
|
||||||
|
Write-Output "Scratch disk set to $global:ScratchDisk"
|
||||||
|
|
||||||
|
# Check and adjust execution policy
|
||||||
|
if ((Get-ExecutionPolicy) -eq 'Restricted') {
|
||||||
|
Write-Host "Your current PowerShell Execution Policy is 'Restricted'. Changing it to 'RemoteSigned'..."
|
||||||
|
Set-ExecutionPolicy RemoteSigned -Scope CurrentUser -Confirm:$false
|
||||||
|
}
|
||||||
|
|
||||||
|
# Ensure script is running as administrator
|
||||||
|
$adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator
|
||||||
|
$principal = New-Object System.Security.Principal.WindowsPrincipal([System.Security.Principal.WindowsIdentity]::GetCurrent())
|
||||||
|
if (-not $principal.IsInRole($adminRole)) {
|
||||||
|
Write-Host "Restarting the script with elevated privileges..."
|
||||||
|
$arguments = "-NoProfile -ExecutionPolicy Bypass -File `"$PSCommandPath`""
|
||||||
|
Start-Process powershell -Verb RunAs -ArgumentList $arguments
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
# Start logging and set window title
|
||||||
|
Start-Transcript -Path "$global:ScratchDisk\tiny11.log"
|
||||||
|
$Host.UI.RawUI.WindowTitle = "Tiny11 Image Creator"
|
||||||
|
Clear-Host
|
||||||
|
Write-Host "Welcome to the Tiny11 Image Creator! Release: 05-06-24" -ForegroundColor Cyan
|
||||||
|
|
||||||
|
# Create required directories
|
||||||
|
$global:tiny11Folder = Join-Path $global:ScratchDisk "tiny11"
|
||||||
|
$global:sourcesFolder = Join-Path $global:tiny11Folder "sources"
|
||||||
|
$global:mountPath = Join-Path $global:ScratchDisk "scratchdir"
|
||||||
|
New-Item -ItemType Directory -Force -Path $global:sourcesFolder | Out-Null
|
||||||
|
New-Item -ItemType Directory -Force -Path $global:mountPath | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Environment Setup
|
||||||
|
|
||||||
|
#region Obtain & Mount Installation Media
|
||||||
|
|
||||||
|
function Get-InstallationMedia {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Obtains the Windows 11 ISO (using a provided path or by downloading it) and mounts it.
|
||||||
|
.OUTPUTS
|
||||||
|
The drive letter where the installation media is mounted.
|
||||||
|
#>
|
||||||
|
# Get the ISO (download if necessary)
|
||||||
|
$global:win11ISO = Get-Windows11ISO -ISOPath $ISOPath -Language $Language
|
||||||
|
if (-not $global:win11ISO) {
|
||||||
|
Write-Error "Failed to obtain a Windows 11 ISO. Exiting."
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
|
||||||
|
# Mount the ISO and retrieve the drive letter
|
||||||
|
$mediaDrive = Mount-ISOAndAssignDriveLetter -ISOPath $global:win11ISO
|
||||||
|
if (-not $mediaDrive) {
|
||||||
|
Write-Error "Failed to mount the Windows 11 ISO. Exiting."
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
Write-Output "Installation media mounted at: $mediaDrive"
|
||||||
|
return $mediaDrive
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Obtain & Mount Installation Media
|
||||||
|
|
||||||
|
#region Process install.wim Image
|
||||||
|
|
||||||
|
function Process-InstallImage {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Processes the Windows installation image (install.wim). This includes:
|
||||||
|
- Validating that the necessary installation files exist (or converting install.esd)
|
||||||
|
- Copying installation files from the installation media to the working folder
|
||||||
|
- Mounting the install.wim, gathering image information, applying customizations,
|
||||||
|
removing apps, tweaking registries, and finally unmounting the image.
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[string]$DriveLetter # Installation media drive letter
|
||||||
|
)
|
||||||
|
|
||||||
|
# Validate Windows installation files
|
||||||
|
if ((Test-Path "$DriveLetter\sources\boot.wim") -eq $false -or (Test-Path "$DriveLetter\sources\install.wim") -eq $false) {
|
||||||
|
if (Test-Path "$DriveLetter\sources\install.esd") {
|
||||||
|
Write-Host "Found install.esd, converting to install.wim..."
|
||||||
|
Get-WindowsImage -ImagePath "$DriveLetter\sources\install.esd"
|
||||||
|
$index = Read-Host "Please enter the image index to convert from install.esd"
|
||||||
|
Write-Host "Converting install.esd to install.wim. This may take a while..."
|
||||||
|
Export-WindowsImage -SourceImagePath "$DriveLetter\sources\install.esd" `
|
||||||
|
-SourceIndex $index `
|
||||||
|
-DestinationImagePath "$global:ScratchDisk\tiny11\sources\install.wim" `
|
||||||
|
-CompressionType Maximum -CheckIntegrity
|
||||||
|
} else {
|
||||||
|
Write-Host "Cannot find Windows OS installation files on the installation media."
|
||||||
|
exit
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host "Copying Windows installation files from $DriveLetter..."
|
||||||
|
Copy-Item -Path "$DriveLetter\*" -Destination "$global:tiny11Folder" -Recurse -Force | Out-Null
|
||||||
|
# Remove install.esd if present
|
||||||
|
Set-ItemProperty -Path "$global:tiny11Folder\sources\install.esd" -Name IsReadOnly -Value $false -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item "$global:tiny11Folder\sources\install.esd" -ErrorAction SilentlyContinue
|
||||||
|
Write-Host "Copy complete!"
|
||||||
|
}
|
||||||
|
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
Clear-Host
|
||||||
|
Write-Host "Retrieving image information from install.wim..."
|
||||||
|
Get-WindowsImage -ImagePath (Join-Path $global:sourcesFolder "install.wim")
|
||||||
|
$index = Read-Host "Please enter the desired image index"
|
||||||
|
Write-Host "Mounting install.wim image. This may take a while..."
|
||||||
|
$global:wimFilePath = Join-Path $global:sourcesFolder "install.wim"
|
||||||
|
& takeown "/F" $global:wimFilePath
|
||||||
|
& icacls $global:wimFilePath "/grant" "$($adminGroup.Value):(F)"
|
||||||
|
try {
|
||||||
|
Set-ItemProperty -Path $global:wimFilePath -Name IsReadOnly -Value $false -ErrorAction Stop
|
||||||
|
} catch {
|
||||||
|
# Suppress errors
|
||||||
|
}
|
||||||
|
New-Item -ItemType Directory -Force -Path $global:mountPath > $null
|
||||||
|
Mount-WindowsImage -ImagePath $global:wimFilePath -Index $index -Path $global:mountPath
|
||||||
|
|
||||||
|
# Retrieve system UI language from the mounted image
|
||||||
|
$imageIntl = & dism /English /Get-Intl "/Image:$global:mountPath"
|
||||||
|
$languageLine = $imageIntl -split '\n' | Where-Object { $_ -match 'Default system UI language : ([a-zA-Z]{2}-[a-zA-Z]{2})' }
|
||||||
|
if ($languageLine) {
|
||||||
|
$languageCode = $Matches[1]
|
||||||
|
Write-Host "Default system UI language code: $languageCode"
|
||||||
|
} else {
|
||||||
|
Write-Host "Default system UI language code not found."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Retrieve architecture information from the image
|
||||||
|
$imageInfo = & dism /English /Get-WimInfo "/wimFile:$global:sourcesFolder\install.wim" "/index:$index"
|
||||||
|
$lines = $imageInfo -split '\r?\n'
|
||||||
|
foreach ($line in $lines) {
|
||||||
|
if ($line -like '*Architecture : *') {
|
||||||
|
$architecture = $line -replace 'Architecture : ',''
|
||||||
|
if ($architecture -eq 'x64') {
|
||||||
|
$architecture = 'amd64'
|
||||||
|
}
|
||||||
|
Write-Host "Architecture: $architecture"
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (-not $architecture) {
|
||||||
|
Write-Host "Architecture information not found."
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Install image mounted. Proceeding with application removals and customizations..."
|
||||||
|
|
||||||
|
# Remove unwanted applications (bloatware) via DISM
|
||||||
|
$packages = & dism /English "/image:$global:mountPath" '/Get-ProvisionedAppxPackages' |
|
||||||
|
ForEach-Object {
|
||||||
|
if ($_ -match 'PackageName : (.*)') {
|
||||||
|
$matches[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$packagePrefixes = 'Clipchamp.Clipchamp_', 'Microsoft.BingNews_', 'Microsoft.BingWeather_', 'Microsoft.GamingApp_', 'Microsoft.GetHelp_', 'Microsoft.Getstarted_', 'Microsoft.MicrosoftOfficeHub_', 'Microsoft.MicrosoftSolitaireCollection_', 'Microsoft.People_', 'Microsoft.PowerAutomateDesktop_', 'Microsoft.Todos_', 'Microsoft.WindowsAlarms_', 'microsoft.windowscommunicationsapps_', 'Microsoft.WindowsFeedbackHub_', 'Microsoft.WindowsMaps_', 'Microsoft.WindowsSoundRecorder_', 'Microsoft.Xbox.TCUI_', 'Microsoft.XboxGamingOverlay_', 'Microsoft.XboxGameOverlay_', 'Microsoft.XboxSpeechToTextOverlay_', 'Microsoft.YourPhone_', 'Microsoft.ZuneMusic_', 'Microsoft.ZuneVideo_', 'MicrosoftCorporationII.MicrosoftFamily_', 'MicrosoftCorporationII.QuickAssist_', 'MicrosoftTeams_', 'Microsoft.549981C3F5F10_'
|
||||||
|
$packagesToRemove = $packages | Where-Object {
|
||||||
|
$packageName = $_
|
||||||
|
$packagePrefixes -contains ($packagePrefixes | Where-Object { $packageName -like "$_*" })
|
||||||
|
}
|
||||||
|
foreach ($package in $packagesToRemove) {
|
||||||
|
& dism /English "/image:$global:mountPath" '/Remove-ProvisionedAppxPackage' "/PackageName:$package"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Remove Microsoft Edge and its components
|
||||||
|
Write-Host "Removing Microsoft Edge..."
|
||||||
|
Remove-Item -Path "$global:mountPath\Program Files (x86)\Microsoft\Edge" -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item -Path "$global:mountPath\Program Files (x86)\Microsoft\EdgeUpdate" -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item -Path "$global:mountPath\Program Files (x86)\Microsoft\EdgeCore" -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
if ($architecture -eq 'amd64') {
|
||||||
|
$folderPath = Get-ChildItem -Path "$global:mountPath\Windows\WinSxS" -Filter "amd64_microsoft-edge-webview_31bf3856ad364e35*" -Directory | Select-Object -ExpandProperty FullName
|
||||||
|
if ($folderPath) {
|
||||||
|
& takeown '/f' $folderPath '/r' | Out-Null
|
||||||
|
& icacls $folderPath "/grant" "$($adminGroup.Value):(F)" '/T' '/C' | Out-Null
|
||||||
|
Remove-Item -Path $folderPath -Recurse -Force | Out-Null
|
||||||
|
} else {
|
||||||
|
Write-Host "Edge WebView folder not found."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
elseif ($architecture -eq 'arm64') {
|
||||||
|
$folderPath = Get-ChildItem -Path "$global:mountPath\Windows\WinSxS" -Filter "arm64_microsoft-edge-webview_31bf3856ad364e35*" -Directory | Select-Object -ExpandProperty FullName
|
||||||
|
if ($folderPath) {
|
||||||
|
& takeown '/f' $folderPath '/r' | Out-Null
|
||||||
|
& icacls $folderPath "/grant" "$($adminGroup.Value):(F)" '/T' '/C' | Out-Null
|
||||||
|
Remove-Item -Path $folderPath -Recurse -Force | Out-Null
|
||||||
|
} else {
|
||||||
|
Write-Host "Edge WebView folder not found."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& takeown '/f' "$global:mountPath\Windows\System32\Microsoft-Edge-Webview" '/r' | Out-Null
|
||||||
|
& icacls "$global:mountPath\Windows\System32\Microsoft-Edge-Webview" '/grant' "$($adminGroup.Value):(F)" '/T' '/C' | Out-Null
|
||||||
|
Remove-Item -Path "$global:mountPath\Windows\System32\Microsoft-Edge-Webview" -Recurse -Force | Out-Null
|
||||||
|
|
||||||
|
# Remove OneDrive
|
||||||
|
Write-Host "Removing OneDrive..."
|
||||||
|
& takeown '/f' "$global:mountPath\Windows\System32\OneDriveSetup.exe" | Out-Null
|
||||||
|
& icacls "$global:mountPath\Windows\System32\OneDriveSetup.exe" '/grant' "$($adminGroup.Value):(F)" '/T' '/C' | Out-Null
|
||||||
|
Remove-Item -Path "$global:mountPath\Windows\System32\OneDriveSetup.exe" -Force | Out-Null
|
||||||
|
Write-Host "Application removal complete!"
|
||||||
|
|
||||||
|
Start-Sleep -Seconds 2
|
||||||
|
Clear-Host
|
||||||
|
|
||||||
|
# Load registry hives from the mounted image and apply tweaks
|
||||||
|
Write-Host "Loading registry hives from the mounted image..."
|
||||||
|
reg load HKLM\zCOMPONENTS "$global:mountPath\Windows\System32\config\COMPONENTS" | Out-Null
|
||||||
|
reg load HKLM\zDEFAULT "$global:mountPath\Windows\System32\config\default" | Out-Null
|
||||||
|
reg load HKLM\zNTUSER "$global:mountPath\Users\Default\ntuser.dat" | Out-Null
|
||||||
|
reg load HKLM\zSOFTWARE "$global:mountPath\Windows\System32\config\SOFTWARE" | Out-Null
|
||||||
|
reg load HKLM\zSYSTEM "$global:mountPath\Windows\System32\config\SYSTEM" | Out-Null
|
||||||
|
|
||||||
|
Write-Host "Applying registry tweaks to bypass system requirements..."
|
||||||
|
& reg add 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' '/v' 'SV1' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' '/v' 'SV2' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' '/v' 'SV1' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' '/v' 'SV2' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassCPUCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassRAMCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassSecureBootCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassStorageCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassTPMCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zSYSTEM\Setup\MoSetup' '/v' 'AllowUpgradesWithUnsupportedTPMOrCPU' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
|
||||||
|
|
||||||
|
Write-Host "Registry tweaks complete. Unloading registry hives..."
|
||||||
|
reg unload HKLM\zCOMPONENTS | Out-Null
|
||||||
|
reg unload HKLM\zDEFAULT | Out-Null
|
||||||
|
reg unload HKLM\zNTUSER | Out-Null
|
||||||
|
reg unload HKLM\zSOFTWARE | Out-Null
|
||||||
|
reg unload HKLM\zSYSTEM | Out-Null
|
||||||
|
|
||||||
|
Write-Host "Performing component cleanup on the image..."
|
||||||
|
Repair-WindowsImage -Path $global:mountPath -StartComponentCleanup -ResetBase
|
||||||
|
Write-Host "Unmounting install.wim image (saving changes)..."
|
||||||
|
Dismount-WindowsImage -Path $global:mountPath -Save
|
||||||
|
Clear-Host
|
||||||
|
|
||||||
|
Write-Host "Exporting updated install.wim..."
|
||||||
|
Export-WindowsImage -SourceImagePath (Join-Path $global:sourcesFolder "install.wim") -SourceIndex $index `
|
||||||
|
-DestinationImagePath (Join-Path $global:sourcesFolder "install2.wim") -CompressionType Fast
|
||||||
|
Remove-Item -Path (Join-Path $global:sourcesFolder "install.wim") -Force | Out-Null
|
||||||
|
Rename-Item -Path (Join-Path $global:sourcesFolder "install2.wim") -NewName "install.wim" -Force | Out-Null
|
||||||
|
Write-Host "Install image processing complete. Proceeding with boot.wim..."
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Process install.wim Image
|
||||||
|
|
||||||
|
#region Process boot.wim Image
|
||||||
|
|
||||||
|
function Process-BootImage {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Processes the boot image (boot.wim). This includes mounting the boot image,
|
||||||
|
applying necessary tweaks (if any), and then unmounting the image.
|
||||||
|
#>
|
||||||
|
Write-Host "Mounting boot.wim image..."
|
||||||
|
$global:wimFilePath = Join-Path $global:sourcesFolder "boot.wim"
|
||||||
|
& takeown "/F" $global:wimFilePath | Out-Null
|
||||||
|
& icacls $global:wimFilePath "/grant" "$($adminGroup.Value):(F)" | Out-Null
|
||||||
|
Set-ItemProperty -Path $global:wimFilePath -Name IsReadOnly -Value $false
|
||||||
|
Mount-WindowsImage -ImagePath $global:wimFilePath -Index 2 -Path $global:mountPath
|
||||||
|
Write-Host "Boot image mounted. Loading registry from boot image..."
|
||||||
|
reg load HKLM\zCOMPONENTS "$global:mountPath\Windows\System32\config\COMPONENTS" | Out-Null
|
||||||
|
reg load HKLM\zDEFAULT "$global:mountPath\Windows\System32\config\default" | Out-Null
|
||||||
|
reg load HKLM\zNTUSER "$global:mountPath\Users\Default\ntuser.dat" | Out-Null
|
||||||
|
reg load HKLM\zSOFTWARE "$global:mountPath\Windows\System32\config\SOFTWARE" | Out-Null
|
||||||
|
reg load HKLM\zSYSTEM "$global:mountPath\Windows\System32\config\SYSTEM" | Out-Null
|
||||||
|
|
||||||
|
Write-Host "Applying tweaks to boot image registry..."
|
||||||
|
& reg add 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' '/v' 'SV1' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zDEFAULT\Control Panel\UnsupportedHardwareNotificationCache' '/v' 'SV2' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' '/v' 'SV1' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zNTUSER\Control Panel\UnsupportedHardwareNotificationCache' '/v' 'SV2' '/t' 'REG_DWORD' '/d' '0' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassCPUCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassRAMCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassSecureBootCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassStorageCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zSYSTEM\Setup\LabConfig' '/v' 'BypassTPMCheck' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
|
||||||
|
& reg add 'HKLM\zSYSTEM\Setup\MoSetup' '/v' 'AllowUpgradesWithUnsupportedTPMOrCPU' '/t' 'REG_DWORD' '/d' '1' '/f' | Out-Null
|
||||||
|
|
||||||
|
Write-Host "Tweaks for boot image applied. Unloading registry hives..."
|
||||||
|
reg unload HKLM\zCOMPONENTS | Out-Null
|
||||||
|
reg unload HKLM\zDEFAULT | Out-Null
|
||||||
|
reg unload HKLM\zNTUSER | Out-Null
|
||||||
|
reg unload HKLM\zSOFTWARE | Out-Null
|
||||||
|
reg unload HKLM\zSYSTEM | Out-Null
|
||||||
|
|
||||||
|
Write-Host "Unmounting boot image (saving changes)..."
|
||||||
|
Dismount-WindowsImage -Path $global:mountPath -Save
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Process boot.wim Image
|
||||||
|
|
||||||
|
#region Finalize ISO Creation
|
||||||
|
|
||||||
|
function Finalize-ISO {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Uses oscdimg.exe to create the final Tiny11 ISO from the customized image.
|
||||||
|
#>
|
||||||
|
Write-Host "Copying unattended file for bypassing MS account on OOBE..."
|
||||||
|
Copy-Item -Path "$PSScriptRoot\autounattend.xml" -Destination "$global:tiny11Folder\autounattend.xml" -Force | Out-Null
|
||||||
|
|
||||||
|
Write-Host "Creating final ISO image..."
|
||||||
|
$ADKDepTools = "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\$hostarchitecture\Oscdimg"
|
||||||
|
$localOSCDIMGPath = "$PSScriptRoot\oscdimg.exe"
|
||||||
|
|
||||||
|
if ([System.IO.Directory]::Exists($ADKDepTools)) {
|
||||||
|
Write-Host "Using oscdimg.exe from the system ADK."
|
||||||
|
$OSCDIMG = Join-Path $ADKDepTools "oscdimg.exe"
|
||||||
|
} else {
|
||||||
|
Write-Host "ADK folder not found. Using bundled oscdimg.exe."
|
||||||
|
if (-not (Test-Path -Path $localOSCDIMGPath)) {
|
||||||
|
Write-Host "Downloading oscdimg.exe..."
|
||||||
|
$url = "https://msdl.microsoft.com/download/symbols/oscdimg.exe/3D44737265000/oscdimg.exe"
|
||||||
|
Invoke-WebRequest -Uri $url -OutFile $localOSCDIMGPath
|
||||||
|
if (-not (Test-Path $localOSCDIMGPath)) {
|
||||||
|
Write-Error "Failed to download oscdimg.exe."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Host "oscdimg.exe already exists locally."
|
||||||
|
}
|
||||||
|
$OSCDIMG = $localOSCDIMGPath
|
||||||
|
}
|
||||||
|
|
||||||
|
# Define boot data (adjust paths if necessary)
|
||||||
|
$bootData = "2#p0,e,b$global:tiny11Folder\boot\etfsboot.com#pEF,e,b$global:tiny11Folder\efi\microsoft\boot\efisys.bin"
|
||||||
|
$isoOutput = Join-Path $PSScriptRoot "tiny11.iso"
|
||||||
|
& "$OSCDIMG" '-m' '-o' '-u2' '-udfver102' "-bootdata:$bootData" "$global:tiny11Folder" "$isoOutput"
|
||||||
|
Write-Host "ISO creation complete: $isoOutput" -ForegroundColor Green
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Finalize ISO Creation
|
||||||
|
|
||||||
|
#region Cleanup
|
||||||
|
|
||||||
|
function Cleanup-Environment {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Cleans up temporary folders used during image processing.
|
||||||
|
#>
|
||||||
|
Write-Host "Performing cleanup..."
|
||||||
|
Remove-Item -Path "$global:tiny11Folder" -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
Remove-Item -Path "$global:mountPath" -Recurse -Force -ErrorAction SilentlyContinue
|
||||||
|
Stop-Transcript
|
||||||
|
Write-Host "Cleanup complete."
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion Cleanup
|
||||||
|
|
||||||
|
#region Main Flow
|
||||||
|
|
||||||
|
function Main {
|
||||||
|
# Step 1: Setup environment (parameters, admin check, logging, directories)
|
||||||
|
Setup-Environment
|
||||||
|
|
||||||
|
# Step 2: Obtain and mount installation media (ISO)
|
||||||
|
$mediaDrive = Get-InstallationMedia
|
||||||
|
|
||||||
|
# Step 3: Process the install.wim image (copy files, convert ESD if needed, apply tweaks)
|
||||||
|
Process-InstallImage -DriveLetter $mediaDrive
|
||||||
|
|
||||||
|
# Step 4: Process the boot.wim image
|
||||||
|
Process-BootImage
|
||||||
|
|
||||||
|
# Step 5: Finalize ISO creation using oscdimg.exe
|
||||||
|
Finalize-ISO
|
||||||
|
|
||||||
|
# Step 6: Cleanup temporary folders and stop logging
|
||||||
|
Cleanup-Environment
|
||||||
|
|
||||||
|
Write-Host "Tiny11 image creation completed. Press Enter to exit."
|
||||||
|
Read-Host
|
||||||
exit
|
exit
|
||||||
}
|
}
|
||||||
|
|
||||||
# Start logging
|
# Start the main flow
|
||||||
Start-Transcript -Path "$ScratchDisk\tiny11.log"
|
Main
|
||||||
|
|
||||||
# Set window title
|
#endregion Main Flow
|
||||||
$Host.UI.RawUI.WindowTitle = "Tiny11 Image Creator"
|
|
||||||
Clear-Host
|
|
||||||
Write-Host "Welcome to Tiny11 Image Creator! Release: 05-06-24"
|
|
||||||
|
|
||||||
# Ensure necessary directories exist
|
|
||||||
New-Item -ItemType Directory -Force -Path "$ScratchDisk\tiny11\sources" | Out-Null
|
|
||||||
|
|
||||||
# Prompt for Windows 11 installation media drive letter
|
|
||||||
do {
|
|
||||||
$DriveLetter = Read-Host "Enter the drive letter of the Windows 11 installation media"
|
|
||||||
if ($DriveLetter -match '^[c-zC-Z]$') {
|
|
||||||
$DriveLetter = "$DriveLetter:"
|
|
||||||
Write-Output "Drive letter set to $DriveLetter"
|
|
||||||
} else {
|
|
||||||
Write-Output "Invalid drive letter. Enter a letter between C and Z."
|
|
||||||
}
|
|
||||||
} while ($DriveLetter -notmatch '^[c-zC-Z]:$')
|
|
||||||
|
|
||||||
# Validate Windows installation files
|
|
||||||
if (-not (Test-Path "$DriveLetter\sources\boot.wim") -or -not (Test-Path "$DriveLetter\sources\install.wim")) {
|
|
||||||
if (Test-Path "$DriveLetter\sources\install.esd") {
|
|
||||||
Write-Host "install.esd found. Converting to install.wim..."
|
|
||||||
Get-WindowsImage -ImagePath "$DriveLetter\sources\install.esd"
|
|
||||||
$index = Read-Host "Enter the image index"
|
|
||||||
Write-Host "Converting install.esd to install.wim..."
|
|
||||||
Export-WindowsImage -SourceImagePath "$DriveLetter\sources\install.esd" `
|
|
||||||
-SourceIndex $index `
|
|
||||||
-DestinationImagePath "$ScratchDisk\tiny11\sources\install.wim" `
|
|
||||||
-CompressionType Maximum -CheckIntegrity
|
|
||||||
} else {
|
|
||||||
Write-Host "Windows installation files not found. Please provide the correct drive letter."
|
|
||||||
exit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Copy Windows installation files
|
|
||||||
Write-Host "Copying Windows installation files..."
|
|
||||||
Copy-Item -Path "$DriveLetter\*" -Destination "$ScratchDisk\tiny11" -Recurse -Force | Out-Null
|
|
||||||
Remove-Item "$ScratchDisk\tiny11\sources\install.esd" -ErrorAction SilentlyContinue
|
|
||||||
Write-Host "Copy complete!"
|
|
||||||
|
|
||||||
Start-Sleep -Seconds 2
|
|
||||||
Clear-Host
|
|
||||||
Write-Host "Retrieving image information..."
|
|
||||||
Get-WindowsImage -ImagePath "$ScratchDisk\tiny11\sources\install.wim"
|
|
||||||
|
|
||||||
# Prompt for image index
|
|
||||||
$index = Read-Host "Enter the image index"
|
|
||||||
|
|
||||||
# Mount Windows image
|
|
||||||
Write-Host "Mounting Windows image... This may take a while."
|
|
||||||
New-Item -ItemType Directory -Force -Path "$ScratchDisk\scratchdir" | Out-Null
|
|
||||||
Mount-WindowsImage -ImagePath "$ScratchDisk\tiny11\sources\install.wim" -Index $index -Path "$ScratchDisk\scratchdir"
|
|
||||||
|
|
||||||
# Retrieve system UI language
|
|
||||||
$imageIntl = & dism /English /Get-Intl "/Image:$($ScratchDisk)\scratchdir"
|
|
||||||
if ($imageIntl -match 'Default system UI language : ([a-zA-Z]{2}-[a-zA-Z]{2})') {
|
|
||||||
Write-Host "Default system UI language: $($matches[1])"
|
|
||||||
} else {
|
|
||||||
Write-Host "System UI language could not be determined."
|
|
||||||
}
|
|
||||||
|
|
||||||
# Retrieve architecture
|
|
||||||
$imageInfo = & dism /English /Get-WimInfo "/wimFile:$($ScratchDisk)\tiny11\sources\install.wim" "/index:$index"
|
|
||||||
if ($imageInfo -match "Architecture : (\S+)") {
|
|
||||||
$architecture = $matches[1] -replace "x64", "amd64"
|
|
||||||
Write-Host "Architecture: $architecture"
|
|
||||||
} else {
|
|
||||||
Write-Host "Architecture information not found."
|
|
||||||
}
|
|
||||||
|
|
||||||
# Remove bloatware applications
|
|
||||||
Write-Host "Removing preinstalled apps..."
|
|
||||||
$appsToRemove = @(
|
|
||||||
'Clipchamp.Clipchamp_', 'Microsoft.BingNews_', 'Microsoft.BingWeather_', 'Microsoft.GamingApp_',
|
|
||||||
'Microsoft.GetHelp_', 'Microsoft.Getstarted_', 'Microsoft.MicrosoftOfficeHub_', 'Microsoft.MicrosoftSolitaireCollection_',
|
|
||||||
'Microsoft.People_', 'Microsoft.PowerAutomateDesktop_', 'Microsoft.Todos_', 'Microsoft.WindowsAlarms_',
|
|
||||||
'microsoft.windowscommunicationsapps_', 'Microsoft.WindowsFeedbackHub_', 'Microsoft.WindowsMaps_', 'Microsoft.WindowsSoundRecorder_',
|
|
||||||
'Microsoft.Xbox.TCUI_', 'Microsoft.XboxGamingOverlay_', 'Microsoft.XboxGameOverlay_', 'Microsoft.XboxSpeechToTextOverlay_',
|
|
||||||
'Microsoft.YourPhone_', 'Microsoft.ZuneMusic_', 'Microsoft.ZuneVideo_', 'MicrosoftCorporationII.MicrosoftFamily_',
|
|
||||||
'MicrosoftCorporationII.QuickAssist_', 'MicrosoftTeams_', 'Microsoft.549981C3F5F10_'
|
|
||||||
)
|
|
||||||
|
|
||||||
$installedPackages = & dism /English "/image:$($ScratchDisk)\scratchdir" /Get-ProvisionedAppxPackages |
|
|
||||||
ForEach-Object { if ($_ -match 'PackageName : (.*)') { $matches[1] } }
|
|
||||||
|
|
||||||
foreach ($package in $appsToRemove) {
|
|
||||||
if ($installedPackages -match "$package*") {
|
|
||||||
& dism /English "/image:$($ScratchDisk)\scratchdir" /Remove-ProvisionedAppxPackage "/PackageName:$matches[0]"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# Remove Microsoft Edge
|
|
||||||
Write-Host "Removing Microsoft Edge..."
|
|
||||||
$edgeFolders = @(
|
|
||||||
"Program Files (x86)\Microsoft\Edge",
|
|
||||||
"Program Files (x86)\Microsoft\EdgeUpdate",
|
|
||||||
"Program Files (x86)\Microsoft\EdgeCore"
|
|
||||||
)
|
|
||||||
|
|
||||||
foreach ($folder in $edgeFolders) {
|
|
||||||
Remove-Item -Path "$ScratchDisk\scratchdir\$folder" -Recurse -Force -ErrorAction SilentlyContinue
|
|
||||||
}
|
|
||||||
|
|
||||||
# Remove OneDrive
|
|
||||||
Write-Host "Removing OneDrive..."
|
|
||||||
$oneDriveSetup = "$ScratchDisk\scratchdir\Windows\System32\OneDriveSetup.exe"
|
|
||||||
if (Test-Path $oneDriveSetup) {
|
|
||||||
& takeown /f $oneDriveSetup | Out-Null
|
|
||||||
& icacls $oneDriveSetup /grant "$($adminGroup.Value):(F)" /T /C | Out-Null
|
|
||||||
Remove-Item -Path $oneDriveSetup -Force | Out-Null
|
|
||||||
}
|
|
||||||
|
|
||||||
Write-Host "Optimizations complete!"
|
|
||||||
Start-Sleep -Seconds 2
|
|
||||||
Clear-Host
|
|
||||||
Write-Host "Tiny11 Image preparation finished!"
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue