Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save mcarneir0/7e533647af343f37789a034f29bab12e to your computer and use it in GitHub Desktop.

Select an option

Save mcarneir0/7e533647af343f37789a034f29bab12e to your computer and use it in GitHub Desktop.

How to reinstall Windows remotely with Tailscale VPN

Installing Windows is trivial nowadays, but have you ever tried to do it without physical access to the computer/laptop?

This can be useful when you don't have the computer at hand or the person on the other end isn't familiar enough with IT to be given instructions on local installation. Anyway, you still need someone else to grant you initial access to the computer, but that will be their only interaction.

Warning

This tutorial is provided for informational and educational purposes only. Following these instructions may involve risks, including but not limited to system malfunctions, data loss, security vulnerabilities or other unintended consequences. I make no guarantees about the accuracy, reliability, or safety of the information provided. By using this tutorial, you acknowledge that you do so at your own risk and assume full responsibility for any issues, damages, or losses that may occur. Additionally, I am not liable for the use, misuse, or interpretation of this content. Always back up your data and proceed with caution.

Table of Contents

Requirements

  • A free Tailscale account
  • A temporary remote access app
  • A Windows 10/11 Pro image
  • A Windows answer file (autounattend.xml)
  • WinNTSetup
  • Bootice (included in WinNTSetup)
  • MiniTool Partition Wizard

Getting Ready

Tailscale

Tailscale is a powerful service that provides secure access between multiple devices and servers in different scenarios, being useful for both personal and commercial use. In this tutorial, it will be used to establish a stable VPN connection between your computer and the remote computer, so that you can RDP connect to the remote computer after the Windows installation is complete. Create your account for free if you don't already have one.

With your account created and Tailscale installed in your computer, go to admin console, then enable device approval and generate an auth key with pre-approved option. Remember to copy and store the generated key in a safe place, as it will no longer be displayed in full.

These steps are required to create a Tailscale installation script that will be run right after Windows installation has finished.

Temporary remote access app

Before making any changes to the remote computer you need to access it first with someone's help, so let's make things easier here. I suggest using Anydesk, but feel free to use any other option you prefer. Ask the other person to install the program on remote computer and access it.

Important

All programs and files listed below should be downloaded on the remote computer.

Windows image

You'll need a Windows 10/11 Pro image, that could be an entire ISO or just the install.wim or install.esd file if you want to save some download time.

Tip

Just a quick comparison: 6.13 GB ISO vs 3.71 GB ESD, 40% smaller for Windows 11 Pro 24H2.

I suggest you three ways to obtain these files:

  1. Microsoft software download, only for Windows 11 ISO files.
    • You can obtain the install.wim file inside the sources folder from that ISO.
  2. file.rg-adguard.net for direct ESD files. Always check for the latest Windows 10/11 build available and download the CLIENTCONSUMER_RET_x64FRE_xx-xx.esd file.
  3. https://bit.ly/win-remoto, it's my personal OneDrive share, where you can download a Windows 10/11 ESD file and the other tools listed below.

Important

Make sure to download/install the Pro version, as the Home version doesn't support RDP, which will be used in this tutorial.

Windows answer file (autounattend.xml)

Answer files are used to modify Windows installation, allowing to automate steps (like account creation and wifi setup) and do some tweaks. Check this example file and create yours at https://schneegans.de/windows/unattend-generator/.

This site is full of options for modifying your Windows installation, feel free to select what you find interesting but remember to modify the options below:

  • User accounts
    • Make sure to create at least one Administrator account and set a password to it. Do not leave the password blank because it is required for RDP access.
  • System tweaks
    • Check "Enable Remote Desktop services (RDP)" option.
  • WLAN/Wi-Fi setup
    • If the remote computer is connected to the internet via Wi-Fi you'll need to configure this option to re-establish connection after installing Windows.
    • Otherwise, check "Skip Wi-Fi configuration" when the remote computer is connected by cable.
  • Run custom scripts
    • Scripts to run when the first user logs on after Windows has been installed
      • Paste the Tailscale install script here. (see a example)

WinNTSetup and Bootice

WinNTSetup is used to install Windows, you can download it at Mega, Mediafire or Majorgeeks. Always choose the x64 version.

Bootice will be used to edit the BCD where Windows boot entries are stored.

Note

Now that everything is ready, you can continue. Remember to always have a backup of your data.

Reinstalling Windows

Disk

First of all you have to allocate some disk space for the new OS. It's not possible to install it on top of the existing OS but you can shrink the actual partition for it.

Open disk management and create a new NTFS partition with at least 20 GB.

Windows Disk Management

WinNTSetup

Here is where you configure the Windows install.

  • 1st drop-down: Select the installation image (ISO, WIM or ESD file).
  • 2nd drop-down: Select boot partition, usually the first partition of the disk.
    • In most cases, it is selected automatically and has a green background in the drop-down list.
  • 3rd drop-down: Select the newly created partition.
  • Options: Select the Windows version to be installed.
    • Unattend: Select the autounattend.xml you made.
    • (Optional) Drivers: If you have a directory with device drivers (.inf files) you can select it here.
  • Mode: Select "Winboot:WINCOPY" or any "Compact" option if you want a Compact OS install. Make sure that it is marked with a green ball.
WinNTSetup

Click install then click accept in the new window that appears, there's no need to change the default options. Wait till the install ends.

After that, click on the Windows logo below close button and click Bootice.

WinNTSetup - Bootice

Bootice

Time to tell the system to boot on the new Windows next time.

  1. Open BCD tab and click "Easy mode" button.
  2. Delete the current Windows entry and leave the new one only.
  3. Click "Save current system" and reboot.
Bootice

Now you'll be left "waiting in the dark" while Windows completes the installation.

What's Next?

If everything goes fine Windows will boot up, logon the user created on autounattend.xml and Tailscale install script will start.

You'll see a new entry in Tailscale admin console. Copy that IP and RDP connect using the same account created and you're good to go.

Expand Windows partition

Windows Disk Management

To reclaim the disk space left by the old operating system, you should use third-party disk managers such as MiniTool Partition Wizard Portable.

Download, extract and open partitionwizard.exe. You'll see all partitions on the disk. All you have to do is:

  1. Delete the old OS partition.
  2. Extend the actual OS partition with all the unallocated space, click OK.
  3. Click Aplly, then Yes and Restart Now.
MiniTool Partition Wizard

MiniTool will resize Windows partition during reboot and you'll have all disk space for the new OS.

Windows Disk Management

That's It

Install all missing drivers, programs and once you have finished, if you're not planning to use it, unnistall Tailscale on remote computer and remove its entry on admin console.

References

@echo off
TITLE Tailscale installer
set tailscale_key=<insert_your_key_here>
echo Downloading Tailscale...
echo .
curl -L "https://pkgs.tailscale.com/stable/tailscale-setup-1.88.4-amd64.msi" -o tailscale.msi
echo Installing Tailscale...
start /wait msiexec /i tailscale.msi /qb TS_ADMINCONSOLE="hide" TS_ALLOWINCOMINGCONNECTIONS="always" TS_INSTALLUPDATES="never" TS_NETWORKDEVICES="hide" TS_PREFERENCESMENU="hide" TS_UNATTENDEDMODE="always" TS_UPDATEMENU="hide"
timeout /t 10
cd "C:\Program Files\Tailscale\"
tailscale.exe up --auth-key=%tailscale_key%
<?xml version="1.0" encoding="utf-8"?>
<unattend xmlns="urn:schemas-microsoft-com:unattend" xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
<!--https://schneegans.de/windows/unattend-generator/?LanguageMode=Unattended&UILanguage=en-US&Locale=en-US&Keyboard=00000409&GeoLocation=244&ProcessorArchitecture=amd64&BypassRequirementsCheck=true&HidePowerShellWindows=true&ComputerNameMode=Random&CompactOsMode=Default&TimeZoneMode=Implicit&PartitionMode=Interactive&DiskAssertionMode=Skip&WindowsEditionMode=Generic&WindowsEdition=pro&InstallFromMode=Automatic&PEMode=Default&UserAccountMode=Unattended&AccountName0=Admin&AccountDisplayName0=&AccountPassword0=123456&AccountGroup0=Administrators&AutoLogonMode=Own&PasswordExpirationMode=Unlimited&LockoutMode=Default&HideFiles=Hidden&ShowFileExtensions=true&TaskbarSearch=Box&TaskbarIconsMode=Default&StartTilesMode=Default&StartPinsMode=Empty&EnableLongPaths=true&EnableRemoteDesktop=true&PreventDeviceEncryption=true&EffectsMode=Default&DesktopIconsMode=Default&StartFoldersMode=Default&WifiMode=Skip&ExpressSettings=DisableAll&LockKeysMode=Skip&StickyKeysMode=Disabled&ColorMode=Default&WallpaperMode=Default&LockScreenMode=Default&Remove3DViewer=true&RemoveMixedReality=true&RemoveRecall=true&RemoveSkype=true&FirstLogonScript0=%40echo+off%0D%0A%0D%0ATITLE+Tailscale+installer%0D%0A%0D%0Aset+tailscale_key%3D%3Cinsert_your_key_here%3E%0D%0A%0D%0Aecho+Downloading+Tailscale...%0D%0Aecho+.%0D%0Acurl+-L+%22https%3A%2F%2Fpkgs.tailscale.com%2Fstable%2Ftailscale-setup-1.88.4-amd64.msi%22+-o+tailscale.msi%0D%0A%0D%0Aecho+Installing+Tailscale...%0D%0Astart+%2Fwait+msiexec+%2Fi+tailscale.msi+%2Fqb+TS_ADMINCONSOLE%3D%22hide%22+TS_ALLOWINCOMINGCONNECTIONS%3D%22always%22+TS_INSTALLUPDATES%3D%22never%22+TS_NETWORKDEVICES%3D%22hide%22+TS_PREFERENCESMENU%3D%22hide%22+TS_UNATTENDEDMODE%3D%22always%22+TS_UPDATEMENU%3D%22hide%22%0D%0Atimeout+%2Ft+10%0D%0A%0D%0Acd+%22C%3A%5CProgram+Files%5CTailscale%5C%22%0D%0Atailscale.exe+up+%2D%2Dauth-key%3D%25tailscale_key%25%0D%0A&FirstLogonScriptType0=Cmd&WdacMode=Skip-->
<settings pass="offlineServicing"></settings>
<settings pass="windowsPE">
<component name="Microsoft-Windows-International-Core-WinPE" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<UILanguage>en-US</UILanguage>
</component>
<component name="Microsoft-Windows-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<UserData>
<ProductKey>
<Key>VK7JG-NPHTM-C97JM-9MPGT-3V66T</Key>
<WillShowUI>OnError</WillShowUI>
</ProductKey>
<AcceptEula>true</AcceptEula>
</UserData>
<UseConfigurationSet>false</UseConfigurationSet>
<RunSynchronous>
<RunSynchronousCommand wcm:action="add">
<Order>1</Order>
<Path>reg.exe add "HKLM\SYSTEM\Setup\LabConfig" /v BypassTPMCheck /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>2</Order>
<Path>reg.exe add "HKLM\SYSTEM\Setup\LabConfig" /v BypassSecureBootCheck /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>3</Order>
<Path>reg.exe add "HKLM\SYSTEM\Setup\LabConfig" /v BypassRAMCheck /t REG_DWORD /d 1 /f</Path>
</RunSynchronousCommand>
</RunSynchronous>
</component>
</settings>
<settings pass="generalize"></settings>
<settings pass="specialize">
<component name="Microsoft-Windows-Deployment" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<RunSynchronous>
<RunSynchronousCommand wcm:action="add">
<Order>1</Order>
<Path>powershell.exe -WindowStyle Hidden -NoProfile -Command "$xml = [xml]::new(); $xml.Load('C:\Windows\Panther\unattend.xml'); $sb = [scriptblock]::Create( $xml.unattend.Extensions.ExtractScript ); Invoke-Command -ScriptBlock $sb -ArgumentList $xml;"</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>2</Order>
<Path>powershell.exe -WindowStyle Hidden -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\Specialize.ps1' -Raw | Invoke-Expression;"</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>3</Order>
<Path>reg.exe load "HKU\DefaultUser" "C:\Users\Default\NTUSER.DAT"</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>4</Order>
<Path>powershell.exe -WindowStyle Hidden -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\DefaultUser.ps1' -Raw | Invoke-Expression;"</Path>
</RunSynchronousCommand>
<RunSynchronousCommand wcm:action="add">
<Order>5</Order>
<Path>reg.exe unload "HKU\DefaultUser"</Path>
</RunSynchronousCommand>
</RunSynchronous>
</component>
</settings>
<settings pass="auditSystem"></settings>
<settings pass="auditUser"></settings>
<settings pass="oobeSystem">
<component name="Microsoft-Windows-International-Core" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<InputLocale>0409:00000409</InputLocale>
<SystemLocale>en-US</SystemLocale>
<UILanguage>en-US</UILanguage>
<UserLocale>en-US</UserLocale>
</component>
<component name="Microsoft-Windows-Shell-Setup" processorArchitecture="amd64" publicKeyToken="31bf3856ad364e35" language="neutral" versionScope="nonSxS">
<UserAccounts>
<LocalAccounts>
<LocalAccount wcm:action="add">
<Name>Admin</Name>
<DisplayName></DisplayName>
<Group>Administrators</Group>
<Password>
<Value>123456</Value>
<PlainText>true</PlainText>
</Password>
</LocalAccount>
</LocalAccounts>
</UserAccounts>
<AutoLogon>
<Username>Admin</Username>
<Enabled>true</Enabled>
<LogonCount>1</LogonCount>
<Password>
<Value>123456</Value>
<PlainText>true</PlainText>
</Password>
</AutoLogon>
<OOBE>
<ProtectYourPC>3</ProtectYourPC>
<HideEULAPage>true</HideEULAPage>
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
<HideOnlineAccountScreens>false</HideOnlineAccountScreens>
</OOBE>
<FirstLogonCommands>
<SynchronousCommand wcm:action="add">
<Order>1</Order>
<CommandLine>powershell.exe -WindowStyle Hidden -NoProfile -Command "Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\FirstLogon.ps1' -Raw | Invoke-Expression;"</CommandLine>
</SynchronousCommand>
</FirstLogonCommands>
</component>
</settings>
<Extensions xmlns="https://schneegans.de/windows/unattend-generator/">
<ExtractScript>
param(
[xml] $Document
);
foreach( $file in $Document.unattend.Extensions.File ) {
$path = [System.Environment]::ExpandEnvironmentVariables( $file.GetAttribute( 'path' ) );
mkdir -Path( $path | Split-Path -Parent ) -ErrorAction 'SilentlyContinue';
$encoding = switch( [System.IO.Path]::GetExtension( $path ) ) {
{ $_ -in '.ps1', '.xml' } { [System.Text.Encoding]::UTF8; }
{ $_ -in '.reg', '.vbs', '.js' } { [System.Text.UnicodeEncoding]::new( $false, $true ); }
default { [System.Text.Encoding]::Default; }
};
$bytes = $encoding.GetPreamble() + $encoding.GetBytes( $file.InnerText.Trim() );
[System.IO.File]::WriteAllBytes( $path, $bytes );
}
</ExtractScript>
<File path="C:\Windows\Setup\Scripts\RemovePackages.ps1">
$selectors = @(
'Microsoft.Microsoft3DViewer';
'Microsoft.MixedReality.Portal';
'Microsoft.SkypeApp';
);
$getCommand = {
Get-AppxProvisionedPackage -Online;
};
$filterCommand = {
$_.DisplayName -eq $selector;
};
$removeCommand = {
[CmdletBinding()]
param(
[Parameter( Mandatory, ValueFromPipeline )]
$InputObject
);
process {
$InputObject | Remove-AppxProvisionedPackage -AllUsers -Online -ErrorAction 'Continue';
}
};
$type = 'Package';
$logfile = 'C:\Windows\Setup\Scripts\RemovePackages.log';
&amp; {
$installed = &amp; $getCommand;
foreach( $selector in $selectors ) {
$result = [ordered] @{
Selector = $selector;
};
$found = $installed | Where-Object -FilterScript $filterCommand;
if( $found ) {
$result.Output = $found | &amp; $removeCommand;
if( $? ) {
$result.Message = "$type removed.";
} else {
$result.Message = "$type not removed.";
$result.Error = $Error[0];
}
} else {
$result.Message = "$type not installed.";
}
$result | ConvertTo-Json -Depth 3 -Compress;
}
} *&gt;&amp;1 &gt;&gt; $logfile;
</File>
<File path="C:\Windows\Setup\Scripts\RemoveFeatures.ps1">
$selectors = @(
'Recall';
);
$getCommand = {
Get-WindowsOptionalFeature -Online | Where-Object -Property 'State' -NotIn -Value @(
'Disabled';
'DisabledWithPayloadRemoved';
);
};
$filterCommand = {
$_.FeatureName -eq $selector;
};
$removeCommand = {
[CmdletBinding()]
param(
[Parameter( Mandatory, ValueFromPipeline )]
$InputObject
);
process {
$InputObject | Disable-WindowsOptionalFeature -Online -Remove -NoRestart -ErrorAction 'Continue';
}
};
$type = 'Feature';
$logfile = 'C:\Windows\Setup\Scripts\RemoveFeatures.log';
&amp; {
$installed = &amp; $getCommand;
foreach( $selector in $selectors ) {
$result = [ordered] @{
Selector = $selector;
};
$found = $installed | Where-Object -FilterScript $filterCommand;
if( $found ) {
$result.Output = $found | &amp; $removeCommand;
if( $? ) {
$result.Message = "$type removed.";
} else {
$result.Message = "$type not removed.";
$result.Error = $Error[0];
}
} else {
$result.Message = "$type not installed.";
}
$result | ConvertTo-Json -Depth 3 -Compress;
}
} *&gt;&amp;1 &gt;&gt; $logfile;
</File>
<File path="C:\Windows\Setup\Scripts\SetStartPins.ps1">
$json = '{"pinnedList":[]}';
if( [System.Environment]::OSVersion.Version.Build -lt 20000 ) {
return;
}
$key = 'Registry::HKLM\SOFTWARE\Microsoft\PolicyManager\current\device\Start';
New-Item -Path $key -ItemType 'Directory' -ErrorAction 'SilentlyContinue';
Set-ItemProperty -LiteralPath $key -Name 'ConfigureStartPins' -Value $json -Type 'String';
</File>
<File path="C:\Windows\Setup\Scripts\unattend-01.cmd">
@echo off
TITLE Tailscale installer
set tailscale_key=&lt;insert_your_key_here&gt;
echo Downloading Tailscale...
echo .
curl -L "https://pkgs.tailscale.com/stable/tailscale-setup-1.88.4-amd64.msi" -o tailscale.msi
echo Installing Tailscale...
start /wait msiexec /i tailscale.msi /qb TS_ADMINCONSOLE="hide" TS_ALLOWINCOMINGCONNECTIONS="always" TS_INSTALLUPDATES="never" TS_NETWORKDEVICES="hide" TS_PREFERENCESMENU="hide" TS_UNATTENDEDMODE="always" TS_UPDATEMENU="hide"
timeout /t 10
cd "C:\Program Files\Tailscale\"
tailscale.exe up --auth-key=%tailscale_key%
</File>
<File path="C:\Windows\Setup\Scripts\Specialize.ps1">
$scripts = @(
{
reg.exe add "HKLM\SYSTEM\Setup\MoSetup" /v AllowUpgradesWithUnsupportedTPMOrCPU /t REG_DWORD /d 1 /f;
};
{
Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\RemovePackages.ps1' -Raw | Invoke-Expression;
};
{
Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\RemoveFeatures.ps1' -Raw | Invoke-Expression;
};
{
net.exe accounts /maxpwage:UNLIMITED;
};
{
reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\FileSystem" /v LongPathsEnabled /t REG_DWORD /d 1 /f
};
{
netsh.exe advfirewall firewall set rule group="@FirewallAPI.dll,-28752" new enable=Yes;
reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f;
};
{
reg.exe add "HKLM\SYSTEM\CurrentControlSet\Control\BitLocker" /v "PreventDeviceEncryption" /t REG_DWORD /d 1 /f;
};
{
Get-Content -LiteralPath 'C:\Windows\Setup\Scripts\SetStartPins.ps1' -Raw | Invoke-Expression;
};
{
reg.exe add "HKU\.DEFAULT\Control Panel\Accessibility\StickyKeys" /v Flags /t REG_SZ /d 10 /f;
};
);
&amp; {
[float] $complete = 0;
[float] $increment = 100 / $scripts.Count;
foreach( $script in $scripts ) {
Write-Progress -Activity 'Running scripts to customize your Windows installation. Do not close this window.' -PercentComplete $complete;
'*** Will now execute command &#xAB;{0}&#xBB;.' -f $(
$str = $script.ToString().Trim() -replace '\s+', ' ';
$max = 100;
if( $str.Length -le $max ) {
$str;
} else {
$str.Substring( 0, $max - 1 ) + '&#x2026;';
}
);
$start = [datetime]::Now;
&amp; $script;
'*** Finished executing command after {0:0} ms.' -f [datetime]::Now.Subtract( $start ).TotalMilliseconds;
"`r`n" * 3;
$complete += $increment;
}
} *&gt;&amp;1 &gt;&gt; "C:\Windows\Setup\Scripts\Specialize.log";
</File>
<File path="C:\Windows\Setup\Scripts\DefaultUser.ps1">
$scripts = @(
{
reg.exe add "HKU\DefaultUser\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v "HideFileExt" /t REG_DWORD /d 0 /f;
};
{
reg.exe add "HKU\DefaultUser\Control Panel\Accessibility\StickyKeys" /v Flags /t REG_SZ /d 10 /f;
};
);
&amp; {
[float] $complete = 0;
[float] $increment = 100 / $scripts.Count;
foreach( $script in $scripts ) {
Write-Progress -Activity 'Running scripts to modify the default user&#x2019;&#x2019;s registry hive. Do not close this window.' -PercentComplete $complete;
'*** Will now execute command &#xAB;{0}&#xBB;.' -f $(
$str = $script.ToString().Trim() -replace '\s+', ' ';
$max = 100;
if( $str.Length -le $max ) {
$str;
} else {
$str.Substring( 0, $max - 1 ) + '&#x2026;';
}
);
$start = [datetime]::Now;
&amp; $script;
'*** Finished executing command after {0:0} ms.' -f [datetime]::Now.Subtract( $start ).TotalMilliseconds;
"`r`n" * 3;
$complete += $increment;
}
} *&gt;&amp;1 &gt;&gt; "C:\Windows\Setup\Scripts\DefaultUser.log";
</File>
<File path="C:\Windows\Setup\Scripts\FirstLogon.ps1">
$scripts = @(
{
Set-ItemProperty -LiteralPath 'Registry::HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' -Name 'AutoLogonCount' -Type 'DWord' -Force -Value 0;
};
{
C:\Windows\Setup\Scripts\unattend-01.cmd;
};
{
Remove-Item -LiteralPath @(
'C:\Windows\Panther\unattend.xml';
'C:\Windows\Panther\unattend-original.xml';
'C:\Windows\Setup\Scripts\Wifi.xml';
) -Force -ErrorAction 'SilentlyContinue' -Verbose;
};
);
&amp; {
[float] $complete = 0;
[float] $increment = 100 / $scripts.Count;
foreach( $script in $scripts ) {
Write-Progress -Activity 'Running scripts to finalize your Windows installation. Do not close this window.' -PercentComplete $complete;
'*** Will now execute command &#xAB;{0}&#xBB;.' -f $(
$str = $script.ToString().Trim() -replace '\s+', ' ';
$max = 100;
if( $str.Length -le $max ) {
$str;
} else {
$str.Substring( 0, $max - 1 ) + '&#x2026;';
}
);
$start = [datetime]::Now;
&amp; $script;
'*** Finished executing command after {0:0} ms.' -f [datetime]::Now.Subtract( $start ).TotalMilliseconds;
"`r`n" * 3;
$complete += $increment;
}
} *&gt;&amp;1 &gt;&gt; "C:\Windows\Setup\Scripts\FirstLogon.log";
</File>
</Extensions>
</unattend>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment