separated church and state
parent
b9a8ded252
commit
c4d42aa54c
|
|
@ -0,0 +1 @@
|
||||||
|
build/
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# Builds the answer-file ISOs into build/:
|
||||||
|
# virtio-vms.iso latest virtio-win drivers + unattend/vms-WIPE-DISK.xml (as autounattend.xml) + oobe-vms.ps1
|
||||||
|
# desktop.iso unattend/desktop-PROMPT-DISK.xml (as autounattend.xml) + oobe-desktop.ps1
|
||||||
|
# The virtio-win ISO is only downloaded again when a new release is published.
|
||||||
|
# Requires: curl, xorriso
|
||||||
|
set -euo pipefail
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
VIRTIO_LATEST=https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/latest-virtio/virtio-win.iso
|
||||||
|
BUILD=build
|
||||||
|
STAGE=$BUILD/stage
|
||||||
|
# Joliet names so Windows sees oobe-*.ps1 and autounattend.xml unmangled (volume labels max 16 chars)
|
||||||
|
JOLIET=(-joliet on -compliance joliet_long_names)
|
||||||
|
|
||||||
|
# Root of the ISO as Windows reads it (Joliet, not Rock Ridge)
|
||||||
|
show_root() {
|
||||||
|
echo "== $1"
|
||||||
|
xorriso -report_about WARNING -read_fs norock -indev "$1" -lsl / 2>/dev/null | grep -E -i 'autounattend|oobe-|guest-tools' | awk '{print " ", $NF}'
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir -p "$BUILD"
|
||||||
|
|
||||||
|
# Resolve "latest" to the versioned file; Fedora's redirects drop to plain http, so force https
|
||||||
|
VIRTIO_URL=$(curl -fsSIL -o /dev/null -w '%{url_effective}' "$VIRTIO_LATEST" | sed 's#^http://#https://#')
|
||||||
|
VIRTIO_ISO=$BUILD/$(basename "$VIRTIO_URL")
|
||||||
|
if [[ -f $VIRTIO_ISO ]]; then
|
||||||
|
echo "Using cached $VIRTIO_ISO"
|
||||||
|
else
|
||||||
|
echo "Downloading $VIRTIO_URL"
|
||||||
|
curl -fL --retry 3 -o "$VIRTIO_ISO.part" "$VIRTIO_URL"
|
||||||
|
mv "$VIRTIO_ISO.part" "$VIRTIO_ISO"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# a. VMs: virtio-win + VM answer file + oobe-vms.ps1
|
||||||
|
# Files are added to a copy of the original image rather than extracting and repacking it:
|
||||||
|
# virtio-win stores identical drivers once, and repacking would nearly double its size.
|
||||||
|
rm -f "$BUILD/virtio-vms.iso"
|
||||||
|
xorriso -report_about WARNING -indev "$VIRTIO_ISO" -outdev "$BUILD/virtio-vms.iso" "${JOLIET[@]}" -volid VIRTIO_VMS \
|
||||||
|
-map unattend/vms-WIPE-DISK.xml /autounattend.xml \
|
||||||
|
-map oobe-vms.ps1 /oobe-vms.ps1 \
|
||||||
|
-commit
|
||||||
|
|
||||||
|
# b. Desktops: desktop answer file + oobe-desktop.ps1, no virtio
|
||||||
|
rm -rf "$STAGE" "$BUILD/desktop.iso"
|
||||||
|
mkdir -p "$STAGE"
|
||||||
|
cp unattend/desktop-PROMPT-DISK.xml "$STAGE/autounattend.xml"
|
||||||
|
cp oobe-desktop.ps1 "$STAGE/"
|
||||||
|
xorriso -report_about WARNING -outdev "$BUILD/desktop.iso" "${JOLIET[@]}" -volid OOBE_DESKTOP -map "$STAGE" / -commit
|
||||||
|
rm -rf "$STAGE"
|
||||||
|
show_root "$BUILD/virtio-vms.iso"
|
||||||
|
show_root "$BUILD/desktop.iso"
|
||||||
|
ls -lh "$BUILD"/*.iso
|
||||||
|
|
@ -0,0 +1,153 @@
|
||||||
|
# OOBE for Windows LTSC desktops and laptops. Runs fully unattended (no prompts).
|
||||||
|
# Pulled by autounattend.xml at first logon, or run by hand:
|
||||||
|
# irm https://url.isworking.fyi/oobe-desktop | iex
|
||||||
|
# Log: C:\ProgramData\OOBE\oobe-desktop.log
|
||||||
|
|
||||||
|
# Check if running with elevated privileges
|
||||||
|
if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
||||||
|
Write-Host "Please run this script as an administrator."
|
||||||
|
Exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
$MeshAgentUrl = "https://rmm.iamchrisama.com/meshagents?id=4&meshid=zxl@U2zM95zh9ZNqah@9mUEjCJ3ptGOE6s5cjsGniacVU1fjRXtVKCKlKJN4aJQW&installflags=0"
|
||||||
|
|
||||||
|
$ErrorActionPreference = 'Continue'
|
||||||
|
# The progress bar makes Invoke-WebRequest extremely slow on Windows PowerShell 5.1
|
||||||
|
$ProgressPreference = 'SilentlyContinue'
|
||||||
|
# Older LTSC builds don't enable TLS 1.2 by default, which breaks GitHub downloads
|
||||||
|
[Net.ServicePointManager]::SecurityProtocol = [Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls12
|
||||||
|
|
||||||
|
$WorkDir = Join-Path $env:ProgramData 'OOBE'
|
||||||
|
New-Item -ItemType Directory -Path $WorkDir -Force | Out-Null
|
||||||
|
Start-Transcript -Path (Join-Path $WorkDir 'oobe-desktop.log') -Append | Out-Null
|
||||||
|
|
||||||
|
function Save-Download($Uri, $OutFile) {
|
||||||
|
for ($Attempt = 1; $Attempt -le 3; $Attempt++) {
|
||||||
|
try {
|
||||||
|
Invoke-WebRequest -Uri $Uri -OutFile $OutFile -UseBasicParsing
|
||||||
|
return $true
|
||||||
|
} catch {
|
||||||
|
Write-Warning "Download attempt $Attempt of $Uri failed: $_"
|
||||||
|
Start-Sleep -Seconds 10
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
# Wait for internet access, the network may not be up yet during first logon
|
||||||
|
function Wait-Network {
|
||||||
|
$MeshHost = ([uri]$MeshAgentUrl).Host
|
||||||
|
$Deadline = (Get-Date).AddMinutes(5)
|
||||||
|
while ((Get-Date) -lt $Deadline) {
|
||||||
|
$Client = New-Object System.Net.Sockets.TcpClient
|
||||||
|
try { if ($Client.ConnectAsync($MeshHost, 443).Wait(5000)) { return } } catch {} finally { $Client.Close() }
|
||||||
|
Write-Output "Waiting for network..."
|
||||||
|
Start-Sleep -Seconds 5
|
||||||
|
}
|
||||||
|
Write-Warning "No network after 5 minutes, continuing anyway."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Balanced plan: dim the display after 5 minutes, sleep after 30 minutes.
|
||||||
|
# Turning the display off stays at the plan default (10 minutes plugged in).
|
||||||
|
$Balanced = '381b4222-f694-41f0-9685-ff5bb260df2e'
|
||||||
|
powercfg /setactive $Balanced
|
||||||
|
|
||||||
|
# "Dim display after" (seconds). Only has a visible effect on screens Windows can
|
||||||
|
# control the brightness of (laptops, all-in-ones); external monitors ignore it.
|
||||||
|
$DisplaySubgroup = '7516b95f-f776-4464-8c53-06167f40cc99'
|
||||||
|
$DimTimeout = '17aaa29b-8b43-4b94-aafe-35f64daaf1ee'
|
||||||
|
powercfg /setacvalueindex $Balanced $DisplaySubgroup $DimTimeout 300
|
||||||
|
powercfg /setdcvalueindex $Balanced $DisplaySubgroup $DimTimeout 300
|
||||||
|
|
||||||
|
powercfg /change standby-timeout-ac 30
|
||||||
|
powercfg /change standby-timeout-dc 30
|
||||||
|
powercfg /setactive $Balanced
|
||||||
|
|
||||||
|
# Treat the network as Private and suppress the "allow this PC to be discoverable" prompt
|
||||||
|
Wait-Network
|
||||||
|
New-Item -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Network\NewNetworkWindowOff' -Force | Out-Null
|
||||||
|
Get-NetConnectionProfile | Where-Object NetworkCategory -ne 'DomainAuthenticated' | Set-NetConnectionProfile -NetworkCategory Private
|
||||||
|
|
||||||
|
# Enable ping (ICMP Echo) requests
|
||||||
|
if (-not (Get-NetFirewallRule -Name 'OOBE-ICMPv4-In' -ErrorAction SilentlyContinue)) {
|
||||||
|
New-NetFirewallRule -Name 'OOBE-ICMPv4-In' -DisplayName "Allow ICMP Echo Request" -Protocol ICMPv4 -IcmpType 8 -Enabled True | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
# Allow Remote Desktop (firewall groups are referenced by resource ID so this works on non-English installs)
|
||||||
|
Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -Name "fDenyTSConnections" -Value 0
|
||||||
|
Enable-NetFirewallRule -Group '@FirewallAPI.dll,-28752'
|
||||||
|
|
||||||
|
# Enable c$ (AutoShareWks must be 1; 0 disables the admin shares)
|
||||||
|
reg add "HKLM\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters" /f /v AutoShareWks /t REG_DWORD /d 1
|
||||||
|
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v "LocalAccountTokenFilterPolicy" /t REG_DWORD /d 1 /f
|
||||||
|
Enable-NetFirewallRule -Group '@FirewallAPI.dll,-28502'
|
||||||
|
|
||||||
|
# Disable UAC prompt
|
||||||
|
Set-ItemProperty -Path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\policies\system' -Name "ConsentPromptBehaviorAdmin" -Value 0
|
||||||
|
|
||||||
|
# Dark Mode and no mouse acceleration, for the current user and the default profile (future users)
|
||||||
|
function Set-UserPreferences($Hive) {
|
||||||
|
reg add "$Hive\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize" /v AppsUseLightTheme /t REG_DWORD /d 0 /f | Out-Null
|
||||||
|
reg add "$Hive\Software\Microsoft\Windows\CurrentVersion\Themes\Personalize" /v SystemUsesLightTheme /t REG_DWORD /d 0 /f | Out-Null
|
||||||
|
# "Enhance pointer precision" off
|
||||||
|
reg add "$Hive\Control Panel\Mouse" /v MouseSpeed /t REG_SZ /d 0 /f | Out-Null
|
||||||
|
reg add "$Hive\Control Panel\Mouse" /v MouseThreshold1 /t REG_SZ /d 0 /f | Out-Null
|
||||||
|
reg add "$Hive\Control Panel\Mouse" /v MouseThreshold2 /t REG_SZ /d 0 /f | Out-Null
|
||||||
|
}
|
||||||
|
Set-UserPreferences 'HKCU'
|
||||||
|
$DefaultProfile = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList').Default
|
||||||
|
reg load 'HKU\OOBEDefault' "$DefaultProfile\NTUSER.DAT" | Out-Null
|
||||||
|
if ($LASTEXITCODE -eq 0) {
|
||||||
|
Set-UserPreferences 'HKU\OOBEDefault'
|
||||||
|
[gc]::Collect()
|
||||||
|
reg unload 'HKU\OOBEDefault' | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install MeshCentral agent silently as a service
|
||||||
|
if (Get-Service -Name 'Mesh Agent' -ErrorAction SilentlyContinue) {
|
||||||
|
Write-Output "Mesh Agent is already installed."
|
||||||
|
} else {
|
||||||
|
$MeshInstaller = Join-Path $WorkDir 'meshagent.exe'
|
||||||
|
if (Save-Download $MeshAgentUrl $MeshInstaller) {
|
||||||
|
# -fullinstall installs and starts the service without showing the install dialog
|
||||||
|
Start-Process -FilePath $MeshInstaller -ArgumentList '-fullinstall' -WindowStyle Hidden -Wait
|
||||||
|
}
|
||||||
|
if (-not (Get-Service -Name 'Mesh Agent' -ErrorAction SilentlyContinue)) {
|
||||||
|
Write-Warning "Mesh Agent service was not found after install."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install OpenSSH
|
||||||
|
foreach ($Capability in 'OpenSSH.Client~~~~0.0.1.0', 'OpenSSH.Server~~~~0.0.1.0') {
|
||||||
|
if ((Get-WindowsCapability -Online -Name $Capability).State -ne 'Installed') {
|
||||||
|
Add-WindowsCapability -Online -Name $Capability | Out-Null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Set-Service -Name sshd -StartupType 'Automatic'
|
||||||
|
Start-Service sshd
|
||||||
|
|
||||||
|
# Use PowerShell instead of cmd.exe for SSH sessions
|
||||||
|
if (Test-Path 'HKLM:\SOFTWARE\OpenSSH') {
|
||||||
|
New-ItemProperty -Path 'HKLM:\SOFTWARE\OpenSSH' -Name DefaultShell -Value "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" -PropertyType String -Force | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyContinue | Select-Object Name, Enabled)) {
|
||||||
|
Write-Output "Firewall Rule 'OpenSSH-Server-In-TCP' does not exist, creating it..."
|
||||||
|
New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
|
||||||
|
} else {
|
||||||
|
Write-Output "Firewall rule 'OpenSSH-Server-In-TCP' has been created and exists."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Install Winget (LTSC ships without the Store / App Installer)
|
||||||
|
# Run in a child process: the installer script calls exit, which would end this script too
|
||||||
|
$WingetInstaller = Join-Path $WorkDir 'winget-install.ps1'
|
||||||
|
if (Save-Download 'https://github.com/asheroto/winget-install/releases/latest/download/winget-install.ps1' $WingetInstaller) {
|
||||||
|
& powershell.exe -NoProfile -ExecutionPolicy Bypass -File $WingetInstaller -Force
|
||||||
|
}
|
||||||
|
|
||||||
|
# Restart to finish OpenSSH and driver installation.
|
||||||
|
# Delayed so the script can exit cleanly and the log is flushed before Windows goes down.
|
||||||
|
Write-Output "OOBE complete, restarting in 10 seconds."
|
||||||
|
Stop-Transcript | Out-Null
|
||||||
|
shutdown.exe /r /t 10 /d p:4:1 /c "OOBE complete, restarting to finish installation."
|
||||||
|
|
@ -1,63 +0,0 @@
|
||||||
# Check if running with elevated privileges
|
|
||||||
if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
|
||||||
Write-Host "Please run this script as an administrator."
|
|
||||||
Exit
|
|
||||||
}
|
|
||||||
|
|
||||||
# Enable ping (ICMP Echo) requests
|
|
||||||
New-NetFirewallRule -DisplayName "Allow ICMP Echo Request" -Protocol ICMPv4 -IcmpType 8 -Enabled True
|
|
||||||
|
|
||||||
# Turn on Dark Mode
|
|
||||||
New-ItemProperty -Path HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Themes\Personalize -Name AppsUseLightTheme -Value 0 -PropertyType DWORD -Force
|
|
||||||
|
|
||||||
# Disable Mouse Acceleration
|
|
||||||
Set-ItemProperty -Path "HKCU:\Control Panel\Mouse" -Name MouseSensitivity -Value 0
|
|
||||||
|
|
||||||
# Allow Remote Desktop
|
|
||||||
Set-ItemProperty -Path 'HKLM:\System\CurrentControlSet\Control\Terminal Server' -Name "fDenyTSConnections" -Value 0
|
|
||||||
Enable-NetFirewallRule -DisplayGroup "Remote Desktop"
|
|
||||||
|
|
||||||
# Enable c$
|
|
||||||
reg add "HKLM\SYSTEM\CurrentControlSet\Services\lanmanserver\parameters" /f /v AutoShareWks /t REG_DWORD /d 0
|
|
||||||
reg add "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" /v "LocalAccountTokenFilterPolicy" /t REG_DWORD /d 1 /f
|
|
||||||
|
|
||||||
# Disable UAC prompt
|
|
||||||
Set-ItemProperty -Path 'HKLM:\Software\Microsoft\Windows\CurrentVersion\policies\system' -Name "ConsentPromptBehaviorAdmin" -Value 0
|
|
||||||
|
|
||||||
# Download and run application
|
|
||||||
$DownloadPath = "$env:TEMP\app.exe"
|
|
||||||
Invoke-WebRequest -Uri "https://rmm.iamchrisama.com/meshagents?id=4&meshid=zxl@U2zM95zh9ZNqah@9mUEjCJ3ptGOE6s5cjsGniacVU1fjRXtVKCKlKJN4aJQW&installflags=0" -OutFile $DownloadPath
|
|
||||||
Start-Process -FilePath $DownloadPath -Wait
|
|
||||||
|
|
||||||
# Remove Winows AI
|
|
||||||
& ([scriptblock]::Create((irm "https://raw.githubusercontent.com/zoicware/RemoveWindowsAI/main/RemoveWindowsAi.ps1"))) -nonInteractive -AllOptions
|
|
||||||
|
|
||||||
# Run commands in new PowerShell instance
|
|
||||||
# Start-Process powershell.exe -ArgumentList "-NoProfile -Command {irm https://massgrave.dev/get | iex}"
|
|
||||||
# Start-Process powershell.exe -ArgumentList "-NoProfile -Command {irm https://christitus.com/win | iex}"
|
|
||||||
|
|
||||||
# Disable sleep and enable high performance mode, enable hibernation, and display black after 30 minutes
|
|
||||||
powercfg -change -standby-timeout-ac 0
|
|
||||||
powercfg -setactive 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c
|
|
||||||
powercfg /hibernate on
|
|
||||||
powercfg -change -monitor-timeout-ac 30
|
|
||||||
|
|
||||||
# Install Winget
|
|
||||||
#Add-AppxPackage -RegisterByFamilyName -MainPackage Microsoft.DesktopAppInstaller_8wekyb3d8bbwe
|
|
||||||
irm https://github.com/asheroto/winget-install/releases/latest/download/winget-install.ps1 | iex
|
|
||||||
|
|
||||||
# Install OpenSSH
|
|
||||||
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
|
|
||||||
Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0
|
|
||||||
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
|
|
||||||
|
|
||||||
Start-Service sshd
|
|
||||||
|
|
||||||
Set-Service -Name sshd -StartupType 'Automatic'
|
|
||||||
|
|
||||||
if (!(Get-NetFirewallRule -Name "OpenSSH-Server-In-TCP" -ErrorAction SilentlyContinue | Select-Object Name, Enabled)) {
|
|
||||||
Write-Output "Firewall Rule 'OpenSSH-Server-In-TCP' does not exist, creating it..."
|
|
||||||
New-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -DisplayName 'OpenSSH Server (sshd)' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22
|
|
||||||
} else {
|
|
||||||
Write-Output "Firewall rule 'OpenSSH-Server-In-TCP' has been created and exists."
|
|
||||||
}
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
# OOBE for Windows LTSC virtual machines. Runs fully unattended (no prompts), e.g. from autounattend.xml:
|
# OOBE for Windows LTSC virtual machines (Unraid / KVM with VirtIO). Runs fully unattended (no prompts).
|
||||||
# powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\Windows\Setup\Scripts\oobe-ltsc.ps1
|
# Pulled by autounattend.xml at first logon, or run by hand:
|
||||||
# Log: C:\ProgramData\OOBE\oobe-ltsc.log
|
# irm https://url.isworking.fyi/oobe-vms | iex
|
||||||
|
# Log: C:\ProgramData\OOBE\oobe-vms.log
|
||||||
|
|
||||||
# Check if running with elevated privileges
|
# Check if running with elevated privileges
|
||||||
if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
||||||
|
|
@ -18,7 +19,7 @@ $ProgressPreference = 'SilentlyContinue'
|
||||||
|
|
||||||
$WorkDir = Join-Path $env:ProgramData 'OOBE'
|
$WorkDir = Join-Path $env:ProgramData 'OOBE'
|
||||||
New-Item -ItemType Directory -Path $WorkDir -Force | Out-Null
|
New-Item -ItemType Directory -Path $WorkDir -Force | Out-Null
|
||||||
Start-Transcript -Path (Join-Path $WorkDir 'oobe-ltsc.log') -Append | Out-Null
|
Start-Transcript -Path (Join-Path $WorkDir 'oobe-vms.log') -Append | Out-Null
|
||||||
|
|
||||||
function Save-Download($Uri, $OutFile) {
|
function Save-Download($Uri, $OutFile) {
|
||||||
for ($Attempt = 1; $Attempt -le 3; $Attempt++) {
|
for ($Attempt = 1; $Attempt -le 3; $Attempt++) {
|
||||||
|
|
@ -0,0 +1,311 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
============================================================================
|
||||||
|
autounattend.xml - Windows 10 Enterprise LTSC 2021 (21H2), x64
|
||||||
|
Target: Physical desktops/laptops AND virtual machines, UEFI or BIOS
|
||||||
|
Storage: Any. VirtIO drivers load automatically if a virtio-win ISO is
|
||||||
|
attached; otherwise use "Load driver" on the disk screen.
|
||||||
|
Behavior: STOPS at "Where do you want to install Windows?" so you pick
|
||||||
|
(and delete/format) partitions yourself - nothing is wiped
|
||||||
|
without you. Then installs, autologons ONCE, installs VirtIO
|
||||||
|
guest tools if a virtio-win disc is present, and downloads and
|
||||||
|
runs oobe-desktop.ps1 from https://url.isworking.fyi/oobe-desktop.
|
||||||
|
|
||||||
|
BUILD: ./build-isos.sh produces build/desktop.iso with this file as
|
||||||
|
autounattend.xml plus oobe-desktop.ps1 (offline fallback).
|
||||||
|
VM: attach it as a second CD next to the LTSC ISO.
|
||||||
|
PC: copy autounattend.xml and oobe-desktop.ps1 to the root of
|
||||||
|
the LTSC install USB (or a second USB stick).
|
||||||
|
|
||||||
|
Credentials baked in below: labadmin / mdwelcome (stored in CLEAR TEXT)
|
||||||
|
Search for "EDIT" to find every value you probably want to change.
|
||||||
|
============================================================================
|
||||||
|
-->
|
||||||
|
<unattend xmlns="urn:schemas-microsoft-com:unattend">
|
||||||
|
|
||||||
|
<!-- =======================================================================
|
||||||
|
PASS 1: windowsPE
|
||||||
|
======================================================================= -->
|
||||||
|
<settings pass="windowsPE">
|
||||||
|
|
||||||
|
<component name="Microsoft-Windows-International-Core-WinPE"
|
||||||
|
processorArchitecture="amd64"
|
||||||
|
publicKeyToken="31bf3856ad364e35"
|
||||||
|
language="neutral"
|
||||||
|
versionScope="nonSxS"
|
||||||
|
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
|
||||||
|
<SetupUILanguage>
|
||||||
|
<UILanguage>en-US</UILanguage>
|
||||||
|
</SetupUILanguage>
|
||||||
|
<InputLocale>0409:00000409</InputLocale>
|
||||||
|
<SystemLocale>en-US</SystemLocale>
|
||||||
|
<UILanguage>en-US</UILanguage>
|
||||||
|
<UserLocale>en-US</UserLocale>
|
||||||
|
</component>
|
||||||
|
|
||||||
|
<!-- ===============================================================
|
||||||
|
VIRTIO DRIVER INJECTION - the load-bearing part.
|
||||||
|
WinPE has no viostor/vioscsi driver, so without this the vdisk is
|
||||||
|
invisible on the disk screen. On physical PCs these paths don't
|
||||||
|
exist and are skipped; the disk screen's Load Driver button is
|
||||||
|
still available for anything else (RAID/VMD/NVMe controllers).
|
||||||
|
|
||||||
|
Drive letters in WinPE are not deterministic: the LTSC disc and the
|
||||||
|
VirtIO disc land on D:/E: in either order, so both are listed, plus
|
||||||
|
F: as insurance. Setup logs a warning for paths that don't exist
|
||||||
|
and continues, so the extra entries cost nothing.
|
||||||
|
|
||||||
|
viostor = VirtIO block bus (Unraid vdisk bus: virtio)
|
||||||
|
vioscsi = VirtIO SCSI bus (Unraid vdisk bus: virtio-scsi)
|
||||||
|
NetKVM = network, so WinPE has connectivity if you ever need it
|
||||||
|
=============================================================== -->
|
||||||
|
<component name="Microsoft-Windows-PnpCustomizationsWinPE"
|
||||||
|
processorArchitecture="amd64"
|
||||||
|
publicKeyToken="31bf3856ad364e35"
|
||||||
|
language="neutral"
|
||||||
|
versionScope="nonSxS"
|
||||||
|
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
|
||||||
|
<DriverPaths>
|
||||||
|
<PathAndCredentials wcm:action="add" wcm:keyValue="1">
|
||||||
|
<Path>D:\viostor\w10\amd64</Path>
|
||||||
|
</PathAndCredentials>
|
||||||
|
<PathAndCredentials wcm:action="add" wcm:keyValue="2">
|
||||||
|
<Path>E:\viostor\w10\amd64</Path>
|
||||||
|
</PathAndCredentials>
|
||||||
|
<PathAndCredentials wcm:action="add" wcm:keyValue="3">
|
||||||
|
<Path>F:\viostor\w10\amd64</Path>
|
||||||
|
</PathAndCredentials>
|
||||||
|
|
||||||
|
<PathAndCredentials wcm:action="add" wcm:keyValue="4">
|
||||||
|
<Path>D:\vioscsi\w10\amd64</Path>
|
||||||
|
</PathAndCredentials>
|
||||||
|
<PathAndCredentials wcm:action="add" wcm:keyValue="5">
|
||||||
|
<Path>E:\vioscsi\w10\amd64</Path>
|
||||||
|
</PathAndCredentials>
|
||||||
|
<PathAndCredentials wcm:action="add" wcm:keyValue="6">
|
||||||
|
<Path>F:\vioscsi\w10\amd64</Path>
|
||||||
|
</PathAndCredentials>
|
||||||
|
|
||||||
|
<PathAndCredentials wcm:action="add" wcm:keyValue="7">
|
||||||
|
<Path>D:\NetKVM\w10\amd64</Path>
|
||||||
|
</PathAndCredentials>
|
||||||
|
<PathAndCredentials wcm:action="add" wcm:keyValue="8">
|
||||||
|
<Path>E:\NetKVM\w10\amd64</Path>
|
||||||
|
</PathAndCredentials>
|
||||||
|
<PathAndCredentials wcm:action="add" wcm:keyValue="9">
|
||||||
|
<Path>F:\NetKVM\w10\amd64</Path>
|
||||||
|
</PathAndCredentials>
|
||||||
|
</DriverPaths>
|
||||||
|
</component>
|
||||||
|
|
||||||
|
<component name="Microsoft-Windows-Setup"
|
||||||
|
processorArchitecture="amd64"
|
||||||
|
publicKeyToken="31bf3856ad364e35"
|
||||||
|
language="neutral"
|
||||||
|
versionScope="nonSxS"
|
||||||
|
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
|
||||||
|
|
||||||
|
<!-- No DiskConfiguration and no InstallTo on purpose: Setup prompts
|
||||||
|
for the target disk/partition, which is the only screen shown. -->
|
||||||
|
|
||||||
|
<ImageInstall>
|
||||||
|
<OSImage>
|
||||||
|
<InstallFrom>
|
||||||
|
<MetaData wcm:action="add">
|
||||||
|
<Key>/IMAGE/INDEX</Key>
|
||||||
|
<Value>1</Value>
|
||||||
|
</MetaData>
|
||||||
|
</InstallFrom>
|
||||||
|
<WillShowUI>OnError</WillShowUI>
|
||||||
|
</OSImage>
|
||||||
|
</ImageInstall>
|
||||||
|
|
||||||
|
<UserData>
|
||||||
|
<!-- EDIT: generic KMS client key for Enterprise LTSC 2021. Gets Setup
|
||||||
|
past the prompt; does NOT activate. N edition is
|
||||||
|
92NFX-8DJQP-P6BBQ-THF9C-7CG2H. -->
|
||||||
|
<ProductKey>
|
||||||
|
<Key>M7XTQ-FN8P6-TTKYV-9D4CC-J462D</Key>
|
||||||
|
<WillShowUI>OnError</WillShowUI>
|
||||||
|
</ProductKey>
|
||||||
|
<AcceptEula>true</AcceptEula>
|
||||||
|
<FullName>IT</FullName>
|
||||||
|
<Organization>Contoso</Organization>
|
||||||
|
</UserData>
|
||||||
|
|
||||||
|
</component>
|
||||||
|
</settings>
|
||||||
|
|
||||||
|
<!-- =======================================================================
|
||||||
|
PASS 2: specialize
|
||||||
|
======================================================================= -->
|
||||||
|
<settings pass="specialize">
|
||||||
|
|
||||||
|
<component name="Microsoft-Windows-Shell-Setup"
|
||||||
|
processorArchitecture="amd64"
|
||||||
|
publicKeyToken="31bf3856ad364e35"
|
||||||
|
language="neutral"
|
||||||
|
versionScope="nonSxS"
|
||||||
|
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
|
||||||
|
<!-- "*" = random name. A literal name must NOT match any local account. -->
|
||||||
|
<ComputerName>*</ComputerName>
|
||||||
|
<!-- EDIT: `tzutil /l` lists every valid value. -->
|
||||||
|
<TimeZone>Pacific Standard Time</TimeZone>
|
||||||
|
<RegisteredOwner>IT</RegisteredOwner>
|
||||||
|
<RegisteredOrganization>Contoso</RegisteredOrganization>
|
||||||
|
</component>
|
||||||
|
|
||||||
|
<component name="Microsoft-Windows-Security-SPP-UX"
|
||||||
|
processorArchitecture="amd64"
|
||||||
|
publicKeyToken="31bf3856ad364e35"
|
||||||
|
language="neutral"
|
||||||
|
versionScope="nonSxS"
|
||||||
|
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
|
||||||
|
<SkipAutoActivation>true</SkipAutoActivation>
|
||||||
|
</component>
|
||||||
|
|
||||||
|
<!-- RDP on (NLA required) so the machine is reachable remotely. -->
|
||||||
|
<component name="Microsoft-Windows-TerminalServices-LocalSessionManager"
|
||||||
|
processorArchitecture="amd64"
|
||||||
|
publicKeyToken="31bf3856ad364e35"
|
||||||
|
language="neutral"
|
||||||
|
versionScope="nonSxS"
|
||||||
|
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
|
||||||
|
<fDenyTSConnections>false</fDenyTSConnections>
|
||||||
|
</component>
|
||||||
|
|
||||||
|
<component name="Microsoft-Windows-TerminalServices-RDP-WinStationExtensions"
|
||||||
|
processorArchitecture="amd64"
|
||||||
|
publicKeyToken="31bf3856ad364e35"
|
||||||
|
language="neutral"
|
||||||
|
versionScope="nonSxS"
|
||||||
|
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
|
||||||
|
<UserAuthentication>1</UserAuthentication>
|
||||||
|
<SecurityLayer>2</SecurityLayer>
|
||||||
|
</component>
|
||||||
|
|
||||||
|
</settings>
|
||||||
|
|
||||||
|
<!-- =======================================================================
|
||||||
|
PASS 3: oobeSystem
|
||||||
|
======================================================================= -->
|
||||||
|
<settings pass="oobeSystem">
|
||||||
|
|
||||||
|
<component name="Microsoft-Windows-International-Core"
|
||||||
|
processorArchitecture="amd64"
|
||||||
|
publicKeyToken="31bf3856ad364e35"
|
||||||
|
language="neutral"
|
||||||
|
versionScope="nonSxS"
|
||||||
|
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
|
||||||
|
<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"
|
||||||
|
xmlns:wcm="http://schemas.microsoft.com/WMIConfig/2002/State">
|
||||||
|
|
||||||
|
<OOBE>
|
||||||
|
<HideEULAPage>true</HideEULAPage>
|
||||||
|
<HideOEMRegistrationScreen>true</HideOEMRegistrationScreen>
|
||||||
|
<HideOnlineAccountScreens>true</HideOnlineAccountScreens>
|
||||||
|
<HideLocalAccountScreen>true</HideLocalAccountScreen>
|
||||||
|
<HideWirelessSetupInOOBE>true</HideWirelessSetupInOOBE>
|
||||||
|
<NetworkLocation>Work</NetworkLocation>
|
||||||
|
<ProtectYourPC>3</ProtectYourPC>
|
||||||
|
</OOBE>
|
||||||
|
|
||||||
|
<!-- ===============================================================
|
||||||
|
ACCOUNTS - password is mdwelcome, in clear text, three times.
|
||||||
|
Treat this file and the merged ISO as secrets.
|
||||||
|
=============================================================== -->
|
||||||
|
<UserAccounts>
|
||||||
|
<AdministratorPassword>
|
||||||
|
<Value>mdwelcome</Value>
|
||||||
|
<PlainText>true</PlainText>
|
||||||
|
</AdministratorPassword>
|
||||||
|
|
||||||
|
<LocalAccounts>
|
||||||
|
<LocalAccount wcm:action="add">
|
||||||
|
<Name>labadmin</Name>
|
||||||
|
<DisplayName>Lab Admin</DisplayName>
|
||||||
|
<Description>Local administrator for automated builds</Description>
|
||||||
|
<Group>Administrators</Group>
|
||||||
|
<Password>
|
||||||
|
<Value>mdwelcome</Value>
|
||||||
|
<PlainText>true</PlainText>
|
||||||
|
</Password>
|
||||||
|
</LocalAccount>
|
||||||
|
</LocalAccounts>
|
||||||
|
</UserAccounts>
|
||||||
|
|
||||||
|
<!-- Autologon ONCE, just long enough for the FirstLogonCommands. After
|
||||||
|
oobe-desktop.ps1 restarts the PC it lands on the sign-in screen. -->
|
||||||
|
<AutoLogon>
|
||||||
|
<Enabled>true</Enabled>
|
||||||
|
<Username>labadmin</Username>
|
||||||
|
<LogonCount>1</LogonCount>
|
||||||
|
<Password>
|
||||||
|
<Value>mdwelcome</Value>
|
||||||
|
<PlainText>true</PlainText>
|
||||||
|
</Password>
|
||||||
|
</AutoLogon>
|
||||||
|
|
||||||
|
<DisableAutoDaylightTimeSet>false</DisableAutoDaylightTimeSet>
|
||||||
|
|
||||||
|
<!-- ===============================================================
|
||||||
|
FIRST LOGON COMMANDS - run once, elevated, as labadmin.
|
||||||
|
=============================================================== -->
|
||||||
|
<FirstLogonCommands>
|
||||||
|
|
||||||
|
<SynchronousCommand wcm:action="add">
|
||||||
|
<Order>1</Order>
|
||||||
|
<Description>Show file extensions</Description>
|
||||||
|
<CommandLine>reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /v HideFileExt /t REG_DWORD /d 0 /f</CommandLine>
|
||||||
|
<RequiresUserInput>false</RequiresUserInput>
|
||||||
|
</SynchronousCommand>
|
||||||
|
|
||||||
|
<SynchronousCommand wcm:action="add">
|
||||||
|
<Order>2</Order>
|
||||||
|
<Description>Allow signed PowerShell scripts</Description>
|
||||||
|
<CommandLine>powershell -NoProfile -Command "Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine -Force"</CommandLine>
|
||||||
|
<RequiresUserInput>false</RequiresUserInput>
|
||||||
|
</SynchronousCommand>
|
||||||
|
|
||||||
|
<!-- VMs only: if a virtio-win disc is attached, install the guest
|
||||||
|
tools (NetKVM is needed before anything can be downloaded). On
|
||||||
|
physical PCs no drive has the installer and this does nothing. Scans every drive for
|
||||||
|
the installer rather than assuming a letter, since the VirtIO
|
||||||
|
disc moves around post-install. -->
|
||||||
|
<SynchronousCommand wcm:action="add">
|
||||||
|
<Order>3</Order>
|
||||||
|
<Description>Install VirtIO guest tools</Description>
|
||||||
|
<CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command "Get-Volume | Where-Object DriveLetter | ForEach-Object { $exe = $_.DriveLetter + ':\virtio-win-guest-tools.exe'; if (Test-Path $exe) { Start-Process $exe -ArgumentList '/install','/quiet','/norestart' -Wait } }"</CommandLine>
|
||||||
|
<RequiresUserInput>false</RequiresUserInput>
|
||||||
|
</SynchronousCommand>
|
||||||
|
|
||||||
|
<!-- Provisioning: pulls oobe-desktop.ps1 from the repo so the PC always
|
||||||
|
gets the current version, retrying for ~2.5 minutes while the
|
||||||
|
network comes up. If that fails, falls back to the copy of
|
||||||
|
oobe-desktop.ps1 baked into the root of the ISO. The script installs
|
||||||
|
the MeshCentral agent, applies the power/RDP/SSH settings and
|
||||||
|
restarts the PC itself, so this must stay the LAST command.
|
||||||
|
Log: C:\ProgramData\OOBE\oobe-desktop.log -->
|
||||||
|
<SynchronousCommand wcm:action="add">
|
||||||
|
<Order>4</Order>
|
||||||
|
<Description>Run oobe-desktop.ps1 (url.isworking.fyi, else ISO copy)</Description>
|
||||||
|
<CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $s = $null; for ($i = 1; $i -le 10; $i++) { try { $s = Invoke-RestMethod 'https://url.isworking.fyi/oobe-desktop'; break } catch { Start-Sleep -Seconds 15 } }; if (-not $s) { $f = Get-PSDrive -PSProvider FileSystem | ForEach-Object { Join-Path $_.Root 'oobe-desktop.ps1' } | Where-Object { Test-Path $_ } | Select-Object -First 1; if ($f) { $s = Get-Content -Raw $f } }; if ($s) { Invoke-Expression $s } else { Write-Warning 'oobe-desktop.ps1 not found online or on any drive'; Start-Sleep -Seconds 60 }"</CommandLine>
|
||||||
|
<RequiresUserInput>false</RequiresUserInput>
|
||||||
|
</SynchronousCommand>
|
||||||
|
|
||||||
|
</FirstLogonCommands>
|
||||||
|
</component>
|
||||||
|
</settings>
|
||||||
|
|
||||||
|
</unattend>
|
||||||
|
|
||||||
|
|
@ -5,12 +5,12 @@
|
||||||
Target: Unraid / KVM virtual machine, UEFI firmware, GPT disk
|
Target: Unraid / KVM virtual machine, UEFI firmware, GPT disk
|
||||||
Storage: VirtIO (or VirtIO-SCSI) vdisk - drivers injected into WinPE
|
Storage: VirtIO (or VirtIO-SCSI) vdisk - drivers injected into WinPE
|
||||||
Behavior: Wipes Disk 0, creates ESP/MSR/Windows, installs, autologons,
|
Behavior: Wipes Disk 0, creates ESP/MSR/Windows, installs, autologons,
|
||||||
then runs oobe-ltsc.ps1 (VirtIO guest tools, MeshCentral, settings).
|
installs the VirtIO guest tools, then downloads and runs
|
||||||
|
oobe-vms.ps1 from https://url.isworking.fyi/oobe-vms.
|
||||||
|
|
||||||
PLACE AT: the ROOT of the merged VirtIO ISO, renamed to autounattend.xml,
|
BUILD: ./build-isos.sh produces build/virtio-vms.iso with this file as
|
||||||
alongside virtio-win-guest-tools.exe AND oobe-ltsc.ps1. The ISO
|
autounattend.xml plus oobe-vms.ps1 (offline fallback) at the
|
||||||
needs Joliet names so oobe-ltsc.ps1 isn't mangled to 8.3.
|
root of the latest virtio-win ISO. Attach that ISO in the Unraid VM's
|
||||||
Attach that ISO in the Unraid VM's
|
|
||||||
"VirtIO Drivers ISO" slot; leave "OS Install ISO" on the LTSC image.
|
"VirtIO Drivers ISO" slot; leave "OS Install ISO" on the LTSC image.
|
||||||
|
|
||||||
>>> DESTRUCTIVE: WillWipeDisk erases Disk 0 with no prompt. <<<
|
>>> DESTRUCTIVE: WillWipeDisk erases Disk 0 with no prompt. <<<
|
||||||
|
|
@ -325,16 +325,28 @@
|
||||||
<RequiresUserInput>false</RequiresUserInput>
|
<RequiresUserInput>false</RequiresUserInput>
|
||||||
</SynchronousCommand>
|
</SynchronousCommand>
|
||||||
|
|
||||||
<!-- Provisioning: oobe-ltsc.ps1 sits at the root of the merged ISO
|
<!-- NetKVM has to be in place before anything can be downloaded, so
|
||||||
next to this file. Scans every drive for it rather than assuming
|
the guest tools go on from the ISO first. Scans every drive for
|
||||||
a letter, since the VirtIO disc moves around post-install.
|
the installer rather than assuming a letter, since the VirtIO
|
||||||
The script installs the VirtIO guest tools, MeshCentral agent,
|
disc moves around post-install. -->
|
||||||
power/RDP/SSH settings, then restarts the VM itself, so this
|
|
||||||
must stay the LAST command. Log: C:\ProgramData\OOBE\oobe-ltsc.log -->
|
|
||||||
<SynchronousCommand wcm:action="add">
|
<SynchronousCommand wcm:action="add">
|
||||||
<Order>3</Order>
|
<Order>3</Order>
|
||||||
<Description>Run oobe-ltsc.ps1 provisioning script</Description>
|
<Description>Install VirtIO guest tools</Description>
|
||||||
<CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command "$s = Get-PSDrive -PSProvider FileSystem | ForEach-Object { Join-Path $_.Root 'oobe-ltsc.ps1' } | Where-Object { Test-Path $_ } | Select-Object -First 1; if ($s) { & $s } else { Write-Warning 'oobe-ltsc.ps1 not found on any drive'; Start-Sleep -Seconds 60 }"</CommandLine>
|
<CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command "Get-Volume | Where-Object DriveLetter | ForEach-Object { $exe = $_.DriveLetter + ':\virtio-win-guest-tools.exe'; if (Test-Path $exe) { Start-Process $exe -ArgumentList '/install','/quiet','/norestart' -Wait } }"</CommandLine>
|
||||||
|
<RequiresUserInput>false</RequiresUserInput>
|
||||||
|
</SynchronousCommand>
|
||||||
|
|
||||||
|
<!-- Provisioning: pulls oobe-vms.ps1 from the repo so the VM always
|
||||||
|
gets the current version, retrying for ~2.5 minutes while the
|
||||||
|
network comes up. If that fails, falls back to the copy of
|
||||||
|
oobe-vms.ps1 baked into the root of the ISO. The script installs
|
||||||
|
the MeshCentral agent, applies the power/RDP/SSH settings and
|
||||||
|
restarts the VM itself, so this must stay the LAST command.
|
||||||
|
Log: C:\ProgramData\OOBE\oobe-vms.log -->
|
||||||
|
<SynchronousCommand wcm:action="add">
|
||||||
|
<Order>4</Order>
|
||||||
|
<Description>Run oobe-vms.ps1 (url.isworking.fyi, else ISO copy)</Description>
|
||||||
|
<CommandLine>powershell -NoProfile -ExecutionPolicy Bypass -Command "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $s = $null; for ($i = 1; $i -le 10; $i++) { try { $s = Invoke-RestMethod 'https://url.isworking.fyi/oobe-vms'; break } catch { Start-Sleep -Seconds 15 } }; if (-not $s) { $f = Get-PSDrive -PSProvider FileSystem | ForEach-Object { Join-Path $_.Root 'oobe-vms.ps1' } | Where-Object { Test-Path $_ } | Select-Object -First 1; if ($f) { $s = Get-Content -Raw $f } }; if ($s) { Invoke-Expression $s } else { Write-Warning 'oobe-vms.ps1 not found online or on any drive'; Start-Sleep -Seconds 60 }"</CommandLine>
|
||||||
<RequiresUserInput>false</RequiresUserInput>
|
<RequiresUserInput>false</RequiresUserInput>
|
||||||
</SynchronousCommand>
|
</SynchronousCommand>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue