1
1
# Enable debugging
2
- # Set-PSDebug -Trace 1
2
+ # Set-PSDebug -Trace 1
3
3
4
4
param (
5
- [ValidatePattern (' ^[c-zC-Z]$' )]
5
+ [ValidatePattern (' ^[c-zC-Z]: $' )]
6
6
[string ]$ScratchDisk
7
7
)
8
8
9
9
if (-not $ScratchDisk ) {
10
- $ScratchDisk = $PSScriptRoot -replace ' [\\]+$ ' , ' '
10
+ $ScratchDisk = (( Get-Location ).Drive.Name) + " : "
11
11
} else {
12
12
$ScratchDisk = $ScratchDisk + " :"
13
13
}
14
14
15
15
Write-Output " Scratch disk set to $ScratchDisk "
16
16
17
- # Check if PowerShell execution is restricted
18
- if ((Get-ExecutionPolicy ) -eq ' Restricted' ) {
19
- Write-Host " Your current PowerShell Execution Policy is set to Restricted, which prevents scripts from running. Do you want to change it to RemoteSigned? (yes/no)"
17
+ # Check if PowerShell execution is Restricted or AllSigned or Undefined
18
+ $needchange = @ (" AllSigned" , " Restricted" , " Undefined" )
19
+ $curpolicy = Get-ExecutionPolicy
20
+ if ($curpolicy -in $needchange ) {
21
+ Write-Host " Your current PowerShell Execution Policy is set to $curpolicy , which prevents scripts from running. Do you want to change it to RemoteSigned? (yes/no)"
20
22
$response = Read-Host
21
23
if ($response -eq ' yes' ) {
22
24
Set-ExecutionPolicy RemoteSigned - Scope CurrentUser - Confirm:$false
25
+ Set-ExecutionPolicy RemoteSigned - Scope Process - Confirm:$false
23
26
} else {
24
27
Write-Host " The script cannot be run without changing the execution policy. Exiting..."
25
28
exit
@@ -32,8 +35,7 @@ $adminGroup = $adminSID.Translate([System.Security.Principal.NTAccount])
32
35
$myWindowsID = [System.Security.Principal.WindowsIdentity ]::GetCurrent()
33
36
$myWindowsPrincipal = new-object System.Security.Principal.WindowsPrincipal($myWindowsID )
34
37
$adminRole = [System.Security.Principal.WindowsBuiltInRole ]::Administrator
35
- if (! $myWindowsPrincipal.IsInRole ($adminRole ))
36
- {
38
+ if (! $myWindowsPrincipal.IsInRole ($adminRole )) {
37
39
Write-Host " Restarting Tiny11 image creator as admin in a new window, you can close this one."
38
40
$newProcess = new-object System.Diagnostics.ProcessStartInfo " PowerShell" ;
39
41
$newProcess.Arguments = $myInvocation.MyCommand.Definition ;
@@ -42,10 +44,8 @@ if (! $myWindowsPrincipal.IsInRole($adminRole))
42
44
exit
43
45
}
44
46
45
-
46
-
47
47
# Start the transcript and prepare the window
48
- Start-Transcript - Path " $ScratchDisk \tiny11.log"
48
+ Start-Transcript - Path " $ScratchDisk \tiny11.log"
49
49
50
50
$Host.UI.RawUI.WindowTitle = " Tiny11 image creator"
51
51
Clear-Host
@@ -87,19 +87,26 @@ Start-Sleep -Seconds 2
87
87
Clear-Host
88
88
Write-Host " Getting image information:"
89
89
Get-WindowsImage - ImagePath $ScratchDisk \tiny11\sources\install.wim
90
- $index = Read-Host " Please enter the image index"
90
+
91
+ $index = Read-Host " Please enter the image index : "
92
+ $ImagesIndex = (Get-WindowsImage - ImagePath $ScratchDisk \tiny11\sources\install.wim).ImageIndex
93
+ while ($ImagesIndex -notcontains $index ) {
94
+ $index = Read-Host " Please enter a valide image index : "
95
+ }
96
+
91
97
Write-Host " Mounting Windows image. This may take a while."
92
98
$wimFilePath = " $ScratchDisk \tiny11\sources\install.wim"
93
- & takeown " /F" $wimFilePath
99
+ & takeown " /F" $wimFilePath
94
100
& icacls $wimFilePath " /grant" " $ ( $adminGroup.Value ) :(F)"
95
101
try {
96
102
Set-ItemProperty - Path $wimFilePath - Name IsReadOnly - Value $false - ErrorAction Stop
97
103
} catch {
98
104
# This block will catch the error and suppress it.
99
105
}
100
106
New-Item - ItemType Directory - Force - Path " $ScratchDisk \scratchdir" > $null
101
- Mount-WindowsImage - ImagePath $ScratchDisk \tiny11\sources\install.wim - Index $index - Path $ScratchDisk \scratchdir
107
+ Mount-WindowsImage - ImagePath $wimFilePath - Index $index - Path $ScratchDisk \scratchdir
102
108
109
+ # Powershell dism module does not have direct equivalent for /Get-Intl
103
110
$imageIntl = & dism / English / Get-Intl " /Image:$ ( $ScratchDisk ) \scratchdir"
104
111
$languageLine = $imageIntl -split ' \n' | Where-Object { $_ -match ' Default system UI language : ([a-zA-Z]{2}-[a-zA-Z]{2})' }
105
112
@@ -110,45 +117,71 @@ if ($languageLine) {
110
117
Write-Host " Default system UI language code not found."
111
118
}
112
119
113
- $imageInfo = & ' dism' ' /English' ' /Get-WimInfo' " /wimFile:$ ( $ScratchDisk ) \tiny11\sources\install.wim" " /index:$index "
114
- $lines = $imageInfo -split ' \r?\n'
115
-
116
- foreach ($line in $lines ) {
117
- if ($line -like ' *Architecture : *' ) {
118
- $architecture = $line -replace ' Architecture : ' , ' '
119
- # If the architecture is x64, replace it with amd64
120
- if ($architecture -eq ' x64' ) {
121
- $architecture = ' amd64'
122
- }
123
- Write-Host " Architecture: $architecture "
124
- break
125
- }
120
+ # Defined in (Microsoft.Dism.Commands.ImageInfoObject).Architecture formatting script
121
+ # 0 -> x86, 5 -> arm(currently unused), 6 -> ia64(currently unused), 9 -> x64, 12 -> arm64
122
+ switch ((Get-WindowsImage - ImagePath $wimFilePath - Index $index ).Architecture)
123
+ {
124
+ 0 { $architecture = " x86" }
125
+ 9 { $architecture = " amd64" }
126
+ 12 { $architecture = " arm64" }
126
127
}
127
128
128
129
if (-not $architecture ) {
130
+ if ($architecture ) {
131
+ Write-Host " Architecture: $architecture "
132
+ } else {
129
133
Write-Host " Architecture information not found."
130
134
}
131
135
132
- Write-Host " Mounting complete! Performing removal of applications..."
136
+ Write-Host " Mounting complete! Performing removal of applications...`n "
133
137
134
- $packages = & ' dism ' ' /English ' " /image: $ ( $ ScratchDisk) \scratchdir" ' /Get-ProvisionedAppxPackages ' |
138
+ $packages = Get-ProvisionedAppxPackage - Path " $ ScratchDisk \scratchdir" |
135
139
ForEach-Object {
136
- if ($_ -match ' PackageName : (.*)' ) {
137
- $matches [1 ]
138
- }
140
+ $_.PackageName
139
141
}
140
- $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_'
142
+
143
+ $packagePrefixes =
144
+ ' Clipchamp.Clipchamp_' ,
145
+ ' Microsoft.BingNews_' ,
146
+ ' Microsoft.BingSearch_' ,
147
+ ' Microsoft.BingWeather_' ,
148
+ ' Microsoft.GamingApp_' ,
149
+ ' Microsoft.GetHelp_' ,
150
+ ' Microsoft.Getstarted_' ,
151
+ ' Microsoft.MicrosoftOfficeHub_' ,
152
+ ' Microsoft.MicrosoftSolitaireCollection_' ,
153
+ ' Microsoft.OutlookForWindows_' ,
154
+ ' Microsoft.People_' ,
155
+ ' Microsoft.MicrosoftStickyNotes_' ,
156
+ ' Microsoft.Todos_' ,
157
+ ' Microsoft.WindowsAlarms_' ,
158
+ ' microsoft.windowscommunicationsapps_' ,
159
+ ' Microsoft.WindowsFeedbackHub_' ,
160
+ ' Microsoft.WindowsMaps_' ,
161
+ ' Microsoft.WindowsSoundRecorder_' ,
162
+ ' Microsoft.Xbox.TCUI_' ,
163
+ ' Microsoft.XboxGameOverlay_' ,
164
+ ' Microsoft.XboxGamingOverlay_' ,
165
+ ' Microsoft.XboxSpeechToTextOverlay_' ,
166
+ ' Microsoft.YourPhone_' ,
167
+ ' Microsoft.ZuneMusic_' ,
168
+ ' Microsoft.ZuneVideo_' ,
169
+ ' MicrosoftCorporationII.MicrosoftFamily_' ,
170
+ ' MicrosoftCorporationII.QuickAssist_' ,
171
+ ' MicrosoftTeams_' ,
172
+ ' Microsoft.549981C3F5F10_' ,
173
+ ' MSTeams_'
141
174
142
175
$packagesToRemove = $packages | Where-Object {
143
176
$packageName = $_
144
177
$packagePrefixes -contains ($packagePrefixes | Where-Object { $packageName -like " $_ *" })
145
178
}
146
179
foreach ($package in $packagesToRemove ) {
147
- & ' dism' ' /English' " /image:$ ( $ScratchDisk ) \scratchdir" ' /Remove-ProvisionedAppxPackage' " /PackageName:$package "
180
+ Write-Host " Removing $package ..."
181
+ Remove-AppxProvisionedPackage - Path " $ScratchDisk \scratchdir" - PackageName " $package " | Out-Null
148
182
}
149
183
150
-
151
- Write-Host " Removing Edge:"
184
+ Write-Host " `n Removing Edge:"
152
185
Remove-Item - Path " $ScratchDisk \scratchdir\Program Files (x86)\Microsoft\Edge" - Recurse - Force | Out-Null
153
186
Remove-Item - Path " $ScratchDisk \scratchdir\Program Files (x86)\Microsoft\EdgeUpdate" - Recurse - Force | Out-Null
154
187
Remove-Item - Path " $ScratchDisk \scratchdir\Program Files (x86)\Microsoft\EdgeCore" - Recurse - Force | Out-Null
@@ -258,8 +291,8 @@ Write-Host "Disabling Telemetry:"
258
291
& ' reg' ' add' ' HKLM\zNTUSER\Software\Microsoft\Personalization\Settings' ' /v' ' AcceptedPrivacyPolicy' ' /t' ' REG_DWORD' ' /d' ' 0' ' /f' | Out-Null
259
292
& ' reg' ' add' ' HKLM\zSOFTWARE\Policies\Microsoft\Windows\DataCollection' ' /v' ' AllowTelemetry' ' /t' ' REG_DWORD' ' /d' ' 0' ' /f' | Out-Null
260
293
& ' reg' ' add' ' HKLM\zSYSTEM\ControlSet001\Services\dmwappushservice' ' /v' ' Start' ' /t' ' REG_DWORD' ' /d' ' 4' ' /f' | Out-Null
261
- # # Prevents installation or DevHome and Outlook
262
- Write-Host " Prevents installation or DevHome and Outlook:"
294
+ # # Prevents installation of DevHome and Outlook
295
+ Write-Host " Prevents installation of DevHome and Outlook:"
263
296
& ' reg' ' add' ' HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler\OutlookUpdate' ' /v' ' workCompleted' ' /t' ' REG_DWORD' ' /d' ' 1' ' /f' | Out-Null
264
297
& ' reg' ' add' ' HKLM\zSOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Orchestrator\UScheduler\DevHomeUpdate' ' /v' ' workCompleted' ' /t' ' REG_DWORD' ' /d' ' 1' ' /f' | Out-Null
265
298
& ' reg' ' delete' ' HKLM\zSOFTWARE\Microsoft\WindowsUpdate\Orchestrator\UScheduler_Oobe\OutlookUpdate' ' /f' | Out-Null
@@ -289,13 +322,13 @@ function Enable-Privilege {
289
322
$definition = @'
290
323
using System;
291
324
using System.Runtime.InteropServices;
292
-
325
+
293
326
public class AdjPriv
294
327
{
295
328
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
296
329
internal static extern bool AdjustTokenPrivileges(IntPtr htok, bool disall,
297
330
ref TokPriv1Luid newst, int len, IntPtr prev, IntPtr relen);
298
-
331
+
299
332
[DllImport("advapi32.dll", ExactSpelling = true, SetLastError = true)]
300
333
internal static extern bool OpenProcessToken(IntPtr h, int acc, ref IntPtr phtok);
301
334
[DllImport("advapi32.dll", SetLastError = true)]
@@ -307,7 +340,7 @@ function Enable-Privilege {
307
340
public long Luid;
308
341
public int Attr;
309
342
}
310
-
343
+
311
344
internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
312
345
internal const int SE_PRIVILEGE_DISABLED = 0x00000000;
313
346
internal const int TOKEN_QUERY = 0x00000008;
@@ -364,7 +397,7 @@ Write-Host 'Deleting Customer Experience Improvement Program'
364
397
reg delete " HKEY_LOCAL_MACHINE\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{4738DE7A-BCC1-4E2D-B1B0-CADB044BFA81}" / f | Out-Null
365
398
reg delete " HKEY_LOCAL_MACHINE\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{6FAC31FA-4A85-4E64-BFD5-2154FF4594B3}" / f | Out-Null
366
399
reg delete " HKEY_LOCAL_MACHINE\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{FC931F16-B50A-472E-B061-B6F79A71EF59}" / f | Out-Null
367
- Write-Host ' Deleting Program Data Updater'
400
+ Write-Host ' Deleting Program Data Updater'
368
401
reg delete " HKEY_LOCAL_MACHINE\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{0671EB05-7D95-4153-A32B-1426B9FE61DB}" / f | Out-Null
369
402
Write-Host ' Deleting autochk proxy'
370
403
reg delete " HKEY_LOCAL_MACHINE\zSOFTWARE\Microsoft\Windows NT\CurrentVersion\Schedule\TaskCache\Tasks\{87BF85F4-2CE1-4160-96EA-52F554AA28A2}" / f | Out-Null
@@ -396,7 +429,7 @@ Write-Host "Windows image completed. Continuing with boot.wim."
396
429
Start-Sleep - Seconds 2
397
430
Clear-Host
398
431
Write-Host " Mounting boot image:"
399
- $wimFilePath = " $ScratchDisk \tiny11\sources\boot.wim"
432
+ $wimFilePath = " $ScratchDisk \tiny11\sources\boot.wim"
400
433
& takeown " /F" $wimFilePath | Out-Null
401
434
& icacls $wimFilePath " /grant" " $ ( $adminGroup.Value ) :(F)"
402
435
Set-ItemProperty - Path $wimFilePath - Name IsReadOnly - Value $false
@@ -436,22 +469,31 @@ Write-Host "The tiny11 image is now completed. Proceeding with the making of the
436
469
Write-Host " Copying unattended file for bypassing MS account on OOBE..."
437
470
Copy-Item - Path " $PSScriptRoot \autounattend.xml" - Destination " $ScratchDisk \tiny11\autounattend.xml" - Force | Out-Null
438
471
Write-Host " Creating ISO image..."
439
- $ADKDepTools = " C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\$hostarchitecture \Oscdimg"
472
+ # Get Windows ADK path from registry(following Visual Studio's winsdk.bat approach).
473
+ $WinSDKPath = [Microsoft.Win32.Registry ]::GetValue(" HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows Kits\Installed Roots" , " KitsRoot10" , $null )
474
+ if (! $WinSDKPath ) {
475
+ $WinSDKPath = [Microsoft.Win32.Registry ]::GetValue(" HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots" , " KitsRoot10" , $null )
476
+ }
477
+ if ($WinSDKPath ) {
478
+ # Trim the following backslash for path concatenation.
479
+ $WinSDKPath = $WinSDKPath.TrimEnd (' \' )
480
+ $ADKDepTools = " $WinSDKPath \Assessment and Deployment Kit\Deployment Tools\$hostarchitecture \Oscdimg"
481
+ }
440
482
$localOSCDIMGPath = " $PSScriptRoot \oscdimg.exe"
441
483
442
- if ([System.IO.Directory ]::Exists($ADKDepTools )) {
484
+ if ($ADKDepTools -and [System.IO.File ]::Exists(" $ADKDepTools \oscdimg.exe " )) {
443
485
Write-Host " Will be using oscdimg.exe from system ADK."
444
486
$OSCDIMG = " $ADKDepTools \oscdimg.exe"
445
487
} else {
446
- Write-Host " ADK folder not found. Will be using bundled oscdimg.exe."
447
-
488
+ Write-Host " oscdimg.exe from system ADK not found. Will be using bundled oscdimg.exe."
489
+
448
490
$url = " https://msdl.microsoft.com/download/symbols/oscdimg.exe/3D44737265000/oscdimg.exe"
449
491
450
- if (-not ( Test-Path - Path $localOSCDIMGPath )) {
492
+ if (! [ System.IO.File ]::Exists( $localOSCDIMGPath )) {
451
493
Write-Host " Downloading oscdimg.exe..."
452
494
Invoke-WebRequest - Uri $url - OutFile $localOSCDIMGPath
453
495
454
- if (Test-Path $localOSCDIMGPath ) {
496
+ if ([ System.IO.File ]::Exists( $localOSCDIMGPath ) ) {
455
497
Write-Host " oscdimg.exe downloaded successfully."
456
498
} else {
457
499
Write-Error " Failed to download oscdimg.exe."
0 commit comments