|
|
|
@ -1,48 +1,45 @@
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
.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
|
|
|
|
|
#>
|
|
|
|
|
|
|
|
|
|
.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
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
.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?
|
|
|
|
|
|
|
|
|
|
.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
|
|
|
|
|
|
|
|
|
|
#>
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
.EXAMPLE
|
|
|
|
|
Remove-Features -keepDefender:$false
|
|
|
|
|
#>
|
|
|
|
|
try {
|
|
|
|
|
$featlist = (Get-WindowsOptionalFeature -Path $scratchDir).FeatureName
|
|
|
|
|
if ($dumpFeatures)
|
|
|
|
|
{
|
|
|
|
|
if ($dumpFeatures) {
|
|
|
|
|
$featlist > allfeaturesdump.txt
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -57,26 +54,22 @@ function Remove-Features([switch] $dumpFeatures = $false, [switch] $keepDefender
|
|
|
|
|
|
|
|
|
|
if ($keepDefender) { $featlist = $featlist | Where-Object { $_ -NotLike "*Defender*" }}
|
|
|
|
|
|
|
|
|
|
foreach($feature in $featlist)
|
|
|
|
|
{
|
|
|
|
|
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."
|
|
|
|
|
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
|
|
|
|
|
{
|
|
|
|
|
catch {
|
|
|
|
|
Write-Host "Unable to get information about the features. MicroWin processing will continue, but features will not be processed"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function Remove-Packages
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
function Remove-Packages {
|
|
|
|
|
try {
|
|
|
|
|
$pkglist = (Get-WindowsPackage -Path "$scratchDir").PackageName
|
|
|
|
|
|
|
|
|
|
$pkglist = $pkglist | Where-Object {
|
|
|
|
@ -117,8 +110,7 @@ function Remove-Packages
|
|
|
|
|
$_ -NotLike "*UI.XaML*"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
foreach ($pkg in $pkglist)
|
|
|
|
|
{
|
|
|
|
|
foreach ($pkg in $pkglist) {
|
|
|
|
|
try {
|
|
|
|
|
$status = "Removing $pkg"
|
|
|
|
|
Write-Progress -Activity "Removing Apps" -Status $status -PercentComplete ($counter++/$pkglist.Count*100)
|
|
|
|
@ -130,28 +122,24 @@ function Remove-Packages
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Write-Progress -Activity "Removing Apps" -Status "Ready" -Completed
|
|
|
|
|
Write-Progress -Activity "Removing Apps" -Status "Ready" -Completed
|
|
|
|
|
}
|
|
|
|
|
catch
|
|
|
|
|
{
|
|
|
|
|
Write-Host "Unable to get information about the packages. MicroWin processing will continue, but packages will not be processed"
|
|
|
|
|
catch {
|
|
|
|
|
Write-Host "Unable to get information about the packages. MicroWin processing will continue, but packages will not be processed"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function Remove-ProvisionedPackages([switch] $keepSecurity = $false)
|
|
|
|
|
{
|
|
|
|
|
<#
|
|
|
|
|
function Remove-ProvisionedPackages([switch] $keepSecurity = $false) {
|
|
|
|
|
<#
|
|
|
|
|
.SYNOPSIS
|
|
|
|
|
Removes AppX packages from a Windows image during MicroWin processing
|
|
|
|
|
|
|
|
|
|
.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
|
|
|
|
|
|
|
|
|
|
.PARAMETER Name
|
|
|
|
|
keepSecurity - Boolean that determines whether to keep "Microsoft.SecHealthUI" (Windows Security) in the Windows image
|
|
|
|
|
|
|
|
|
|
.EXAMPLE
|
|
|
|
|
Remove-ProvisionedPackages -keepSecurity:$false
|
|
|
|
|
|
|
|
|
|
#>
|
|
|
|
|
.EXAMPLE
|
|
|
|
|
Remove-ProvisionedPackages -keepSecurity:$false
|
|
|
|
|
#>
|
|
|
|
|
$appxProvisionedPackages = Get-AppxProvisionedPackage -Path "$($scratchDir)" | Where-Object {
|
|
|
|
|
$_.PackageName -NotLike "*AppInstaller*" -AND
|
|
|
|
|
$_.PackageName -NotLike "*Store*" -and
|
|
|
|
@ -165,14 +153,12 @@ function Remove-ProvisionedPackages([switch] $keepSecurity = $false)
|
|
|
|
|
$_.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)
|
|
|
|
|
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)
|
|
|
|
|
try {
|
|
|
|
|
Remove-AppxProvisionedPackage -Path $scratchDir -PackageName $appx.PackageName -ErrorAction SilentlyContinue
|
|
|
|
|
}
|
|
|
|
@ -180,17 +166,15 @@ function Remove-ProvisionedPackages([switch] $keepSecurity = $false)
|
|
|
|
|
Write-Host "Application $($appx.PackageName) could not be removed"
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Write-Progress -Activity "Removing Provisioned Apps" -Status "Ready" -Completed
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
Write-Host "Could not get Provisioned App information. Skipping process..."
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
function Copy-ToUSB([string] $fileToCopy) {
|
|
|
|
|
foreach ($volume in Get-Volume) {
|
|
|
|
|
if ($volume -and $volume.FileSystemLabel -ieq "ventoy") {
|
|
|
|
|
$destinationPath = "$($volume.DriveLetter):\"
|
|
|
|
@ -214,8 +198,7 @@ function Copy-ToUSB([string] $fileToCopy)
|
|
|
|
|
Write-Host "Ventoy USB Key is not inserted"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function Remove-FileOrDirectory([string] $pathToDelete, [string] $mask = "", [switch] $Directory = $false)
|
|
|
|
|
{
|
|
|
|
|
function Remove-FileOrDirectory([string] $pathToDelete, [string] $mask = "", [switch] $Directory = $false) {
|
|
|
|
|
if(([string]::IsNullOrEmpty($pathToDelete))) { return }
|
|
|
|
|
if (-not (Test-Path -Path "$($pathToDelete)")) { return }
|
|
|
|
|
|
|
|
|
@ -240,25 +223,21 @@ function Remove-FileOrDirectory([string] $pathToDelete, [string] $mask = "", [sw
|
|
|
|
|
|
|
|
|
|
$itemsToDelete = [System.Collections.ArrayList]::new()
|
|
|
|
|
|
|
|
|
|
if ($mask -eq "")
|
|
|
|
|
{
|
|
|
|
|
if ($mask -eq "") {
|
|
|
|
|
Write-Debug "Adding $($pathToDelete) to array."
|
|
|
|
|
[void]$itemsToDelete.Add($pathToDelete)
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
if (Test-Path -Path "$($itemToDelete)" -PathType Container) {
|
|
|
|
|
$status = "Deleting directory: $($itemToDelete)"
|
|
|
|
|
|
|
|
|
|
takeown /r /d $yesNo[0] /a /f "$($itemToDelete)"
|
|
|
|
@ -267,8 +246,7 @@ function Remove-FileOrDirectory([string] $pathToDelete, [string] $mask = "", [sw
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
elseif (Test-Path -Path "$($itemToDelete)" -PathType Leaf) {
|
|
|
|
|
$status = "Deleting file: $($itemToDelete)"
|
|
|
|
|
|
|
|
|
|
takeown /a /f "$($itemToDelete)"
|
|
|
|
@ -285,42 +263,42 @@ 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 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>
|
|
|
|
|
# <!-- 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 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 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 = @'
|
|
|
|
@ -328,7 +306,7 @@ function New-Unattend {
|
|
|
|
|
<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#>
|
|
|
|
|
<#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>
|
|
|
|
@ -343,9 +321,9 @@ function New-Unattend {
|
|
|
|
|
<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>
|
|
|
|
|
<HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
|
|
|
|
|
<SkipUserOOBE>false</SkipUserOOBE>
|
|
|
|
|
<SkipMachineOOBE>false</SkipMachineOOBE>
|
|
|
|
|
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
|
|
|
|
|
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
|
|
|
|
|
<HideEULAPage>true</HideEULAPage>
|
|
|
|
@ -369,26 +347,24 @@ function New-Unattend {
|
|
|
|
|
</settings>
|
|
|
|
|
</unattend>
|
|
|
|
|
'@
|
|
|
|
|
$specPass = @'
|
|
|
|
|
$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>
|
|
|
|
|
<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()
|
|
|
|
|
}
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -472,8 +448,7 @@ function New-FirstRun {
|
|
|
|
|
$firstRun = @'
|
|
|
|
|
# Set the global error action preference to continue
|
|
|
|
|
$ErrorActionPreference = "Continue"
|
|
|
|
|
function Remove-RegistryValue
|
|
|
|
|
{
|
|
|
|
|
function Remove-RegistryValue {
|
|
|
|
|
param (
|
|
|
|
|
[Parameter(Mandatory = $true)]
|
|
|
|
|
[string]$RegistryPath,
|
|
|
|
@ -483,30 +458,25 @@ function New-FirstRun {
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Check if the registry path exists
|
|
|
|
|
if (Test-Path -Path $RegistryPath)
|
|
|
|
|
{
|
|
|
|
|
if (Test-Path -Path $RegistryPath) {
|
|
|
|
|
$registryValue = Get-ItemProperty -Path $RegistryPath -Name $ValueName -ErrorAction SilentlyContinue
|
|
|
|
|
|
|
|
|
|
# Check if the registry value exists
|
|
|
|
|
if ($registryValue)
|
|
|
|
|
{
|
|
|
|
|
if ($registryValue) {
|
|
|
|
|
# Remove the registry value
|
|
|
|
|
Remove-ItemProperty -Path $RegistryPath -Name $ValueName -Force
|
|
|
|
|
Write-Host "Registry value '$ValueName' removed from '$RegistryPath'."
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
else {
|
|
|
|
|
Write-Host "Registry value '$ValueName' not found in '$RegistryPath'."
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
else {
|
|
|
|
|
Write-Host "Registry path '$RegistryPath' not found."
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function Stop-UnnecessaryServices
|
|
|
|
|
{
|
|
|
|
|
function Stop-UnnecessaryServices {
|
|
|
|
|
$servicesToExclude = @(
|
|
|
|
|
"AudioSrv",
|
|
|
|
|
"AudioEndpointBuilder",
|
|
|
|
@ -573,9 +543,8 @@ function New-FirstRun {
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
$runningServices = Get-Service | Where-Object { $servicesToExclude -notcontains $_.Name }
|
|
|
|
|
foreach($service in $runningServices)
|
|
|
|
|
{
|
|
|
|
|
Stop-Service -Name $service.Name -PassThru
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
@ -613,10 +582,8 @@ function New-FirstRun {
|
|
|
|
|
# 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)
|
|
|
|
|
{
|
|
|
|
|
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."
|
|
|
|
@ -639,8 +606,7 @@ function New-FirstRun {
|
|
|
|
|
# Create a shortcut object
|
|
|
|
|
$shortcut = $shell.CreateShortcut($shortcutPath)
|
|
|
|
|
|
|
|
|
|
if (Test-Path -Path "c:\Windows\cttlogo.png")
|
|
|
|
|
{
|
|
|
|
|
if (Test-Path -Path "c:\Windows\cttlogo.png") {
|
|
|
|
|
$shortcut.IconLocation = "c:\Windows\cttlogo.png"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -650,11 +616,11 @@ function New-FirstRun {
|
|
|
|
|
# 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)
|
|
|
|
|
# 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"
|
|
|
|
|
#
|
|
|
|
|