refactor(windows scripts): remove BOM and improve UTF-8 handling
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
<#
|
||||
LXS - platform dispatcher (Windows side)
|
||||
|
||||
NOTE: this file must stay BOM-less and pure ASCII. It is the one script
|
||||
fetched with `irm ... | iex`, and Invoke-Expression fails on a leading
|
||||
U+FEFF. Being ASCII keeps it parseable when Windows PowerShell 5.1 falls
|
||||
back to the ANSI codepage for a BOM-less file. Everything under windows\
|
||||
carries a UTF-8 BOM instead, because 5.1 reads those from disk.
|
||||
|
||||
Thin shim kept at the repo root so the documented one-liner stays short and
|
||||
stable while the real implementation lives in windows\lxs.ps1:
|
||||
|
||||
@@ -40,7 +46,7 @@ if ($LxsSelfDir) {
|
||||
}
|
||||
}
|
||||
|
||||
# No files on disk — we were piped from irm. Fetch the platform entrypoint.
|
||||
# No files on disk - we were piped from irm. Fetch the platform entrypoint.
|
||||
$temp = Join-Path $env:TEMP ("lxs.entrypoint.{0}.ps1" -f [guid]::NewGuid().ToString('N').Substring(0, 8))
|
||||
try {
|
||||
Invoke-WebRequest -Uri "$LxsRawBase/$LxsPlatformDir/lxs.ps1" -OutFile $temp `
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
LXS - Browsers and media (Windows)
|
||||
Description: Browsers and media players installed through winget.
|
||||
Repo: https://git.hyko.cx/hykocx/lxs
|
||||
@@ -19,7 +19,10 @@ if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($LxsLibSource))
|
||||
# The library ships with a UTF-8 BOM (Windows PowerShell 5.1 needs it to
|
||||
# read the file as UTF-8); over HTTP that BOM arrives as a leading U+FEFF
|
||||
# character, which the parser will not accept.
|
||||
. ([scriptblock]::Create(($LxsLibSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
$env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_browsers.log'
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<#
|
||||
<#
|
||||
LXS - Claude Code (Windows)
|
||||
Description: Install and check the Claude Code CLI.
|
||||
|
||||
Two supported install methods, both official:
|
||||
- winget (Anthropic.ClaudeCode) — does not auto-update
|
||||
- the native installer from claude.ai — updates itself in the background
|
||||
- winget (Anthropic.ClaudeCode) - does not auto-update
|
||||
- the native installer from claude.ai - updates itself in the background
|
||||
|
||||
Repo: https://git.hyko.cx/hykocx/lxs
|
||||
#>
|
||||
@@ -24,7 +24,10 @@ if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($LxsLibSource))
|
||||
# The library ships with a UTF-8 BOM (Windows PowerShell 5.1 needs it to
|
||||
# read the file as UTF-8); over HTTP that BOM arrives as a leading U+FEFF
|
||||
# character, which the parser will not accept.
|
||||
. ([scriptblock]::Create(($LxsLibSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
$env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_claude_code.log'
|
||||
@@ -67,7 +70,7 @@ function Install-LxsClaudeWinget {
|
||||
Write-Host ''
|
||||
Write-Host 'Installs the Anthropic.ClaudeCode package.'
|
||||
Write-Host ''
|
||||
Write-Host "$($script:Gray)winget installs do not update themselves — run option 5, or$($script:NC)"
|
||||
Write-Host "$($script:Gray)winget installs do not update themselves - run option 5, or$($script:NC)"
|
||||
Write-Host "$($script:Gray)$('winget upgrade Anthropic.ClaudeCode'), to get new versions.$($script:NC)"
|
||||
Write-Host ''
|
||||
if (-not (Confirm-LxsAction -Question 'Install Claude Code with winget?' -DefaultYes)) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
LXS - Containers and virtualization (Windows)
|
||||
Description: WSL 2, Hyper-V, Docker Desktop and VirtualBox.
|
||||
Repo: https://git.hyko.cx/hykocx/lxs
|
||||
@@ -19,7 +19,10 @@ if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($LxsLibSource))
|
||||
# The library ships with a UTF-8 BOM (Windows PowerShell 5.1 needs it to
|
||||
# read the file as UTF-8); over HTTP that BOM arrives as a leading U+FEFF
|
||||
# character, which the parser will not accept.
|
||||
. ([scriptblock]::Create(($LxsLibSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
$env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_containers.log'
|
||||
@@ -86,7 +89,7 @@ function Install-LxsWsl {
|
||||
Write-Host ''
|
||||
& wsl.exe --install
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-LxsOk 'WSL install started — reboot to finish'
|
||||
Write-LxsOk 'WSL install started - reboot to finish'
|
||||
} else {
|
||||
Write-LxsWarn "wsl --install exited with code $LASTEXITCODE"
|
||||
}
|
||||
@@ -110,7 +113,7 @@ function Enable-LxsHyperV {
|
||||
Write-Host ''
|
||||
try {
|
||||
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-All -All -NoRestart -ErrorAction Stop | Out-Null
|
||||
Write-LxsOk 'Hyper-V enabled — reboot to finish'
|
||||
Write-LxsOk 'Hyper-V enabled - reboot to finish'
|
||||
} catch {
|
||||
Write-LxsErr "Could not enable Hyper-V: $($_.Exception.Message)"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
LXS - Dev Pack (Windows)
|
||||
Description: The usual development toolchain, installed through winget.
|
||||
Repo: https://git.hyko.cx/hykocx/lxs
|
||||
@@ -19,7 +19,10 @@ if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($LxsLibSource))
|
||||
# The library ships with a UTF-8 BOM (Windows PowerShell 5.1 needs it to
|
||||
# read the file as UTF-8); over HTTP that BOM arrives as a leading U+FEFF
|
||||
# character, which the parser will not accept.
|
||||
. ([scriptblock]::Create(($LxsLibSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
$env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_dev_pack.log'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
LXS - Apps index (Windows)
|
||||
Description: Interactive menu listing the installers in windows\apps
|
||||
Repo: https://git.hyko.cx/hykocx/lxs
|
||||
@@ -19,7 +19,10 @@ if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($LxsLibSource))
|
||||
# The library ships with a UTF-8 BOM (Windows PowerShell 5.1 needs it to
|
||||
# read the file as UTF-8); over HTTP that BOM arrives as a leading U+FEFF
|
||||
# character, which the parser will not accept.
|
||||
. ([scriptblock]::Create(($LxsLibSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
function Show-LxsAppsMenu {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
LXS - Utilities (Windows)
|
||||
Description: Everyday utilities installed through winget.
|
||||
Repo: https://git.hyko.cx/hykocx/lxs
|
||||
@@ -19,7 +19,10 @@ if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($LxsLibSource))
|
||||
# The library ships with a UTF-8 BOM (Windows PowerShell 5.1 needs it to
|
||||
# read the file as UTF-8); over HTTP that BOM arrives as a leading U+FEFF
|
||||
# character, which the parser will not accept.
|
||||
. ([scriptblock]::Create(($LxsLibSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
$env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_utilities.log'
|
||||
|
||||
+19
-18
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
LXS - Common library (Windows)
|
||||
|
||||
Sourced by windows\lxs.ps1 and every sub-script. Mirrors linux/lib/common.sh:
|
||||
@@ -11,7 +11,7 @@
|
||||
#>
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# Console setup — UTF-8 output (box drawing chars) and VT sequences (colors).
|
||||
# Console setup - UTF-8 output (box drawing chars) and VT sequences (colors).
|
||||
# Both are best-effort: a console that refuses either falls back to plain text.
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
@@ -26,7 +26,7 @@ function Initialize-LxsConsole {
|
||||
[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding $false
|
||||
$script:LxsUnicodeEnabled = $true
|
||||
} catch {
|
||||
# Redirected output or a locked-down host — fall back to ASCII rules.
|
||||
# Redirected output or a locked-down host - fall back to ASCII rules.
|
||||
$script:LxsUnicodeEnabled = $false
|
||||
}
|
||||
|
||||
@@ -77,14 +77,14 @@ public static extern bool SetConsoleMode(IntPtr hConsoleHandle, uint dwMode);
|
||||
Initialize-LxsConsole
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# UI helpers — title + horizontal rule, no closed box. Mirrors common.sh.
|
||||
# UI helpers - title + horizontal rule, no closed box. Mirrors common.sh.
|
||||
#
|
||||
# Show-LxsBoxTop "TITLE" "RIGHT" → TITLE [ RIGHT ]
|
||||
# ──────────────────────────────────
|
||||
# Show-LxsBoxMid "SECTION" → ─ SECTION ────────────────────────
|
||||
# Show-LxsBoxBottom → ──────────────────────────────────
|
||||
# Show-LxsMenuItem "01" "LABEL" "desc" → [01] LABEL // desc
|
||||
# Show-LxsPrompt → >
|
||||
# Show-LxsBoxTop "TITLE" "RIGHT" -> TITLE [ RIGHT ]
|
||||
# ----------------------------------
|
||||
# Show-LxsBoxMid "SECTION" -> - SECTION ------------------------
|
||||
# Show-LxsBoxBottom -> ----------------------------------
|
||||
# Show-LxsMenuItem "01" "LABEL" "desc" -> [01] LABEL // desc
|
||||
# Show-LxsPrompt -> >
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
function Get-LxsTermWidth {
|
||||
@@ -193,7 +193,7 @@ function Write-LxsErr { param([string]$Message) Write-Host "$($script:Red)[KO]$
|
||||
# Sub-scripts read $args by hand, exactly like the bash `for arg in "$@"` loop.
|
||||
# A param([switch]) block cannot be used: LXS invokes sub-scripts with a
|
||||
# splatted string[] (& $script @Arguments), and PowerShell binds every element
|
||||
# of a splatted array positionally — '-Yes' would land in $args as a value and
|
||||
# of a splatted array positionally - '-Yes' would land in $args as a value and
|
||||
# the switch would silently stay $false.
|
||||
#
|
||||
# $opts = Read-LxsFlags -Arguments $args -Known @('-Yes', '-y', '-Help')
|
||||
@@ -255,9 +255,9 @@ function Confirm-LxsAction {
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# Progress helpers
|
||||
#
|
||||
# Invoke-LxsSpinner — external command, output captured to a log file,
|
||||
# Invoke-LxsSpinner - external command, output captured to a log file,
|
||||
# animated spinner (mirrors run_spinner in common.sh).
|
||||
# Invoke-LxsStep — inline PowerShell work; prints [..] then [OK]/[KO].
|
||||
# Invoke-LxsStep - inline PowerShell work; prints [..] then [OK]/[KO].
|
||||
#
|
||||
# Both return $true on success. Log file: $env:LXS_LOG_FILE or %TEMP%\lxs.log
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
@@ -419,7 +419,7 @@ function Assert-LxsWindows {
|
||||
Write-LxsWarn "Windows build $build is older than the supported floor ($MinimumBuild). Some tools may fail."
|
||||
}
|
||||
} catch {
|
||||
# Not fatal — CIM can be unavailable in stripped-down images.
|
||||
# Not fatal - CIM can be unavailable in stripped-down images.
|
||||
}
|
||||
return $true
|
||||
}
|
||||
@@ -435,7 +435,8 @@ function Test-LxsDiskSpace {
|
||||
$seen = @{}
|
||||
foreach ($path in $Paths) {
|
||||
if ([string]::IsNullOrWhiteSpace($path)) { continue }
|
||||
$root = try { [System.IO.Path]::GetPathRoot((Resolve-Path $path -ErrorAction Stop).Path) } catch { $null }
|
||||
$root = $null
|
||||
try { $root = [System.IO.Path]::GetPathRoot((Resolve-Path $path -ErrorAction Stop).Path) } catch { $root = $null }
|
||||
if (-not $root) { $root = [System.IO.Path]::GetPathRoot($path) }
|
||||
if (-not $root) {
|
||||
Write-LxsErr "Cannot read disk usage for $path"
|
||||
@@ -478,7 +479,7 @@ function Assert-LxsWinget {
|
||||
}
|
||||
|
||||
# `winget list` is slow (a second or more per call), and a package menu asks
|
||||
# about a dozen ids at once — so the full listing is fetched once and reused.
|
||||
# about a dozen ids at once - so the full listing is fetched once and reused.
|
||||
$script:LxsWingetListCache = $null
|
||||
|
||||
function Get-LxsWingetListText {
|
||||
@@ -535,7 +536,7 @@ function Install-LxsWingetPackage {
|
||||
Clear-LxsWingetListCache
|
||||
|
||||
if (-not $installed) {
|
||||
Write-Host "$($script:Gray) Package id: $Id — check it with: winget search --id $Id$($script:NC)"
|
||||
Write-Host "$($script:Gray) Package id: $Id - check it with: winget search --id $Id$($script:NC)"
|
||||
}
|
||||
return $installed
|
||||
}
|
||||
@@ -717,7 +718,7 @@ function Add-LxsUserPath {
|
||||
$current = [Environment]::GetEnvironmentVariable('Path', 'User')
|
||||
if ($null -eq $current) { $current = '' }
|
||||
# Windows paths are case-insensitive and a trailing backslash is
|
||||
# meaningless, so compare normalized — otherwise every run appends a
|
||||
# meaningless, so compare normalized - otherwise every run appends a
|
||||
# near-duplicate entry.
|
||||
$normalized = $Directory.TrimEnd('\')
|
||||
foreach ($entry in ($current -split ';')) {
|
||||
|
||||
+8
-5
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
LXS - Windows multi-tool
|
||||
Description: Centralized workstation management and deployment toolkit
|
||||
Repo: https://git.hyko.cx/hykocx/lxs
|
||||
@@ -73,7 +73,10 @@ if ($libPath -and (Test-Path $libPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($libSource))
|
||||
# Strip the UTF-8 BOM: it is required in the file (Windows PowerShell 5.1
|
||||
# reads a BOM-less .ps1 with the ANSI codepage) but arrives as a leading
|
||||
# U+FEFF character when fetched over HTTP, which the parser rejects.
|
||||
. ([scriptblock]::Create(($libSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
@@ -113,7 +116,7 @@ function Test-LxsRemoteVersion {
|
||||
}
|
||||
|
||||
if ($age -ge $LxsVersionTtl) {
|
||||
# Refresh inline but on a short leash — a slow repo must not stall the menu.
|
||||
# Refresh inline but on a short leash - a slow repo must not stall the menu.
|
||||
try {
|
||||
$remote = Invoke-RestMethod -Uri "$LxsRawBase/VERSION" -TimeoutSec 3 `
|
||||
-Headers @{ 'Cache-Control' = 'no-cache' } -UseBasicParsing -ErrorAction Stop
|
||||
@@ -162,7 +165,7 @@ function Show-LxsHeader {
|
||||
$totalMem = [math]::Round($os.TotalVisibleMemorySize / 1MB, 1)
|
||||
$usedMem = [math]::Round(($os.TotalVisibleMemorySize - $os.FreePhysicalMemory) / 1MB, 1)
|
||||
} catch {
|
||||
# CIM unavailable — the header degrades but the menu still works.
|
||||
# CIM unavailable - the header degrades but the menu still works.
|
||||
}
|
||||
|
||||
$cores = $env:NUMBER_OF_PROCESSORS
|
||||
@@ -318,7 +321,7 @@ function Invoke-LxsCmdTool {
|
||||
}
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# setup / update — download the repo zip and mirror it into $LxsInstallDir.
|
||||
# setup / update - download the repo zip and mirror it into $LxsInstallDir.
|
||||
# Everything lands under %LOCALAPPDATA%, so no elevation is needed here;
|
||||
# individual tools elevate themselves when they touch the machine.
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
LXS - Disk Cleanup (Windows)
|
||||
Description: Reclaim disk space (temp files, Windows Update cache, recycle
|
||||
bin, Prefetch, error reports, WinSxS component store).
|
||||
@@ -23,7 +23,10 @@ if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($LxsLibSource))
|
||||
# The library ships with a UTF-8 BOM (Windows PowerShell 5.1 needs it to
|
||||
# read the file as UTF-8); over HTTP that BOM arrives as a leading U+FEFF
|
||||
# character, which the parser will not accept.
|
||||
. ([scriptblock]::Create(($LxsLibSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
$env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_cleanup.log'
|
||||
@@ -80,14 +83,14 @@ function Get-LxsFolderSize {
|
||||
}
|
||||
|
||||
# Delete the *contents* of a folder, never the folder itself. Files locked by a
|
||||
# running process are skipped silently — that is expected on a live system.
|
||||
# running process are skipped silently - that is expected on a live system.
|
||||
function Clear-LxsFolderContents {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][string]$Path,
|
||||
[Parameter(Mandatory = $true)][string]$Label
|
||||
)
|
||||
if (-not (Test-Path $Path)) {
|
||||
Write-Host "$($script:Gray) $Label — not present, skipped$($script:NC)"
|
||||
Write-Host "$($script:Gray) $Label - not present, skipped$($script:NC)"
|
||||
return 0
|
||||
}
|
||||
$before = Get-LxsFolderSize -Path $Path
|
||||
@@ -102,7 +105,7 @@ function Clear-LxsFolderContents {
|
||||
$after = Get-LxsFolderSize -Path $Path
|
||||
$freed = [math]::Max(0, $before - $after)
|
||||
$suffix = if ($skipped -gt 0) { " ($skipped item(s) in use, skipped)" } else { '' }
|
||||
Write-LxsOk "$Label — $(Format-LxsSize $freed) reclaimed$suffix"
|
||||
Write-LxsOk "$Label - $(Format-LxsSize $freed) reclaimed$suffix"
|
||||
return $freed
|
||||
}
|
||||
|
||||
@@ -170,7 +173,7 @@ if (-not $NoRecycleBin) {
|
||||
Write-LxsOk 'Recycle bin emptied'
|
||||
} catch {
|
||||
# Clear-RecycleBin throws when the bin is already empty.
|
||||
Write-Host "$($script:Gray) Recycle bin — already empty or not accessible$($script:NC)"
|
||||
Write-Host "$($script:Gray) Recycle bin - already empty or not accessible$($script:NC)"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,14 +190,14 @@ if ($doUpdateCache) {
|
||||
$stopped += $svc
|
||||
}
|
||||
} catch {
|
||||
Write-LxsWarn "Could not stop $svc — the update cache may be partially locked."
|
||||
Write-LxsWarn "Could not stop $svc - the update cache may be partially locked."
|
||||
}
|
||||
}
|
||||
try {
|
||||
Clear-LxsFolderContents -Path (Join-Path $env:SystemRoot 'SoftwareDistribution\Download') -Label 'Windows Update cache' | Out-Null
|
||||
} finally {
|
||||
foreach ($svc in $stopped) {
|
||||
try { Start-Service -Name $svc -ErrorAction Stop } catch { Write-LxsWarn "Failed to restart $svc — start it manually." }
|
||||
try { Start-Service -Name $svc -ErrorAction Stop } catch { Write-LxsWarn "Failed to restart $svc - start it manually." }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+13
-10
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
LXS - Debloat and privacy (Windows)
|
||||
Description: Remove preinstalled apps you pick, and turn off telemetry,
|
||||
Cortana, ads, tracking tasks, Copilot and Recall.
|
||||
@@ -27,7 +27,10 @@ if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($LxsLibSource))
|
||||
# The library ships with a UTF-8 BOM (Windows PowerShell 5.1 needs it to
|
||||
# read the file as UTF-8); over HTTP that BOM arrives as a leading U+FEFF
|
||||
# character, which the parser will not accept.
|
||||
. ([scriptblock]::Create(($LxsLibSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
$env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_debloat.log'
|
||||
@@ -57,9 +60,9 @@ function Assert-LxsCheckpoint {
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# Preinstalled apps
|
||||
#
|
||||
# Only packages on this list are ever offered. Anything not listed here —
|
||||
# Only packages on this list are ever offered. Anything not listed here -
|
||||
# including the Store, App Installer (winget), Terminal, Defender UI, the
|
||||
# VCLibs/.NET runtime frameworks and every driver package — is left alone,
|
||||
# VCLibs/.NET runtime frameworks and every driver package - is left alone,
|
||||
# because removing those breaks Windows or LXS itself.
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
@@ -152,13 +155,13 @@ function Remove-LxsSelectedApps {
|
||||
|
||||
Write-Host ''
|
||||
Write-Host "$($script:Gray)Enter the numbers to remove, separated by commas (e.g. 1,4,7),$($script:NC)"
|
||||
Write-Host "$($script:Gray)or 'all' for every entry above. Empty cancels — nothing is removed$($script:NC)"
|
||||
Write-Host "$($script:Gray)or 'all' for every entry above. Empty cancels - nothing is removed$($script:NC)"
|
||||
Write-Host "$($script:Gray)unless you name it here.$($script:NC)"
|
||||
Write-Host ''
|
||||
$selection = Read-Host -Prompt 'Selection'
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($selection)) {
|
||||
Write-LxsInfo 'Cancelled — nothing removed.'
|
||||
Write-LxsInfo 'Cancelled - nothing removed.'
|
||||
return
|
||||
}
|
||||
|
||||
@@ -347,7 +350,7 @@ function Invoke-LxsTweakGroup {
|
||||
Disable-ScheduledTask -TaskName $leaf -TaskPath $parent -ErrorAction Stop | Out-Null
|
||||
$disabled++
|
||||
} catch {
|
||||
# Absent on this edition/build — nothing to disable.
|
||||
# Absent on this edition/build - nothing to disable.
|
||||
}
|
||||
}
|
||||
Write-LxsOk "$disabled tracking scheduled task(s) disabled"
|
||||
@@ -360,7 +363,7 @@ function Restore-LxsTweaks {
|
||||
Write-Host 'This restores every registry value, service and scheduled task that'
|
||||
Write-Host 'this script changes, back to the Windows default.'
|
||||
Write-Host ''
|
||||
Write-Host "$($script:Gray)Apps you removed are NOT restored — reinstall them from the Store.$($script:NC)"
|
||||
Write-Host "$($script:Gray)Apps you removed are NOT restored - reinstall them from the Store.$($script:NC)"
|
||||
Write-Host ''
|
||||
if (-not (Confirm-LxsAction -Question 'Revert the privacy tweaks?')) {
|
||||
Write-LxsInfo 'Cancelled.'
|
||||
@@ -374,13 +377,13 @@ function Restore-LxsTweaks {
|
||||
if (Test-Path $e.Path) {
|
||||
Remove-ItemProperty -Path $e.Path -Name $e.Name -ErrorAction Stop
|
||||
}
|
||||
Write-LxsOk "$($e.Label) — policy removed"
|
||||
Write-LxsOk "$($e.Label) - policy removed"
|
||||
} catch {
|
||||
# Already absent: that is the default state we wanted.
|
||||
}
|
||||
} else {
|
||||
if (Set-LxsRegistryValue -Path $e.Path -Name $e.Name -Value $e.Default) {
|
||||
Write-LxsOk "$($e.Label) — restored to default"
|
||||
Write-LxsOk "$($e.Label) - restored to default"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
LXS - Harden Windows
|
||||
Description: Apply a baseline security posture (firewall, SMBv1, UAC,
|
||||
Defender, LLMNR/NetBIOS) and audit local accounts.
|
||||
@@ -24,7 +24,10 @@ if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($LxsLibSource))
|
||||
# The library ships with a UTF-8 BOM (Windows PowerShell 5.1 needs it to
|
||||
# read the file as UTF-8); over HTTP that BOM arrives as a leading U+FEFF
|
||||
# character, which the parser will not accept.
|
||||
. ([scriptblock]::Create(($LxsLibSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
$env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_harden.log'
|
||||
@@ -266,7 +269,7 @@ if ($DoNameResolution) {
|
||||
}
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
# Account audit — reports only, changes nothing.
|
||||
# Account audit - reports only, changes nothing.
|
||||
# ═══════════════════════════════════════════════════════════════════════════
|
||||
|
||||
Write-Host ''
|
||||
@@ -279,7 +282,7 @@ try {
|
||||
foreach ($a in $admins) { Write-Host " - $($a.Name) $($script:Gray)($($a.ObjectClass), $($a.PrincipalSource))$($script:NC)" }
|
||||
if ($admins.Count -gt 2) {
|
||||
Write-Host ''
|
||||
Write-LxsWarn "$($admins.Count) accounts have administrator rights — review whether they all need it."
|
||||
Write-LxsWarn "$($admins.Count) accounts have administrator rights - review whether they all need it."
|
||||
}
|
||||
} catch {
|
||||
Write-LxsWarn "Could not enumerate the Administrators group: $($_.Exception.Message)"
|
||||
@@ -301,7 +304,7 @@ try {
|
||||
Write-Host "$($script:Gray) Password never expires: $($enabledNoExpiry.Name -join ', ')$($script:NC)"
|
||||
}
|
||||
if ($guest -and $guest.Enabled) {
|
||||
Write-LxsWarn 'The Guest account is ENABLED — disable it unless you rely on it.'
|
||||
Write-LxsWarn 'The Guest account is ENABLED - disable it unless you rely on it.'
|
||||
} else {
|
||||
Write-LxsOk 'Guest account is disabled'
|
||||
}
|
||||
@@ -318,7 +321,7 @@ Show-LxsSeparator
|
||||
Write-Host ''
|
||||
Write-LxsOk "$changes hardening change(s) applied"
|
||||
if ($problems -gt 0) {
|
||||
Write-LxsWarn "$problems change(s) failed — see the messages above."
|
||||
Write-LxsWarn "$problems change(s) failed - see the messages above."
|
||||
}
|
||||
if ($DoSmb) {
|
||||
Write-LxsWarn 'Reboot to finish removing the SMBv1 client feature.'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
LXS - Tools index (Windows)
|
||||
Description: Interactive menu listing the scripts in windows\tools
|
||||
Repo: https://git.hyko.cx/hykocx/lxs
|
||||
@@ -19,7 +19,10 @@ if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($LxsLibSource))
|
||||
# The library ships with a UTF-8 BOM (Windows PowerShell 5.1 needs it to
|
||||
# read the file as UTF-8); over HTTP that BOM arrives as a leading U+FEFF
|
||||
# character, which the parser will not accept.
|
||||
. ([scriptblock]::Create(($LxsLibSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
function Show-LxsToolsMenu {
|
||||
@@ -66,7 +69,7 @@ function Show-LxsToolsMenu {
|
||||
$code = Invoke-LxsSibling -RelativePath $script -SelfDirectory $PSScriptRoot
|
||||
|
||||
# Exit code 75 from a child means it already paused on its own
|
||||
# (its own "Back" or end-of-run prompt) — skip the redundant prompt.
|
||||
# (its own "Back" or end-of-run prompt) - skip the redundant prompt.
|
||||
if ($code -ne 75) { Read-LxsEnter }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
LXS - Network Diagnostics (Windows)
|
||||
Description: Inspect and repair the network stack.
|
||||
Everything is read-only except option 8 (stack reset).
|
||||
@@ -20,7 +20,10 @@ if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($LxsLibSource))
|
||||
# The library ships with a UTF-8 BOM (Windows PowerShell 5.1 needs it to
|
||||
# read the file as UTF-8); over HTTP that BOM arrives as a leading U+FEFF
|
||||
# character, which the parser will not accept.
|
||||
. ([scriptblock]::Create(($LxsLibSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
$env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_net_diag.log'
|
||||
@@ -51,7 +54,8 @@ function Show-LxsListeningPorts {
|
||||
Write-Host ''
|
||||
try {
|
||||
$rows = Get-NetTCPConnection -State Listen -ErrorAction Stop | ForEach-Object {
|
||||
$procName = try { (Get-Process -Id $_.OwningProcess -ErrorAction Stop).ProcessName } catch { 'unknown' }
|
||||
$procName = 'unknown'
|
||||
try { $procName = (Get-Process -Id $_.OwningProcess -ErrorAction Stop).ProcessName } catch { $procName = 'unknown' }
|
||||
[pscustomobject]@{
|
||||
Local = "$($_.LocalAddress):$($_.LocalPort)"
|
||||
Port = $_.LocalPort
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<#
|
||||
<#
|
||||
LXS - Remote Access (Windows)
|
||||
Description: Remote Desktop and the OpenSSH server — status, enable,
|
||||
Description: Remote Desktop and the OpenSSH server - status, enable,
|
||||
disable. The Windows counterpart of root-ssh-login.sh.
|
||||
Repo: https://git.hyko.cx/hykocx/lxs
|
||||
#>
|
||||
@@ -20,7 +20,10 @@ if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($LxsLibSource))
|
||||
# The library ships with a UTF-8 BOM (Windows PowerShell 5.1 needs it to
|
||||
# read the file as UTF-8); over HTTP that BOM arrives as a leading U+FEFF
|
||||
# character, which the parser will not accept.
|
||||
. ([scriptblock]::Create(($LxsLibSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
$env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_remote_access.log'
|
||||
@@ -60,7 +63,7 @@ function Show-LxsRemoteStatus {
|
||||
if (Get-LxsNlaState) {
|
||||
Write-LxsOk 'Network Level Authentication is on'
|
||||
} else {
|
||||
Write-LxsWarn 'Network Level Authentication is OFF — turn it on (option 2).'
|
||||
Write-LxsWarn 'Network Level Authentication is OFF - turn it on (option 2).'
|
||||
}
|
||||
try {
|
||||
$port = (Get-ItemProperty -Path $LxsRdpTcpKey -Name 'PortNumber' -ErrorAction Stop).PortNumber
|
||||
@@ -123,7 +126,7 @@ function Enable-LxsRdp {
|
||||
Write-LxsWarn "Could not enable the firewall rules: $($_.Exception.Message)"
|
||||
}
|
||||
Write-Host ''
|
||||
Write-LxsWarn 'Only expose RDP to the internet behind a VPN — it is a constant brute-force target.'
|
||||
Write-LxsWarn 'Only expose RDP to the internet behind a VPN - it is a constant brute-force target.'
|
||||
}
|
||||
|
||||
function Disable-LxsRdp {
|
||||
@@ -255,7 +258,7 @@ function Set-LxsSshDefaultShell {
|
||||
default { $null }
|
||||
}
|
||||
if (-not $shell) {
|
||||
if ($choice -eq '2') { Write-LxsErr 'pwsh.exe was not found — install PowerShell 7 first.' }
|
||||
if ($choice -eq '2') { Write-LxsErr 'pwsh.exe was not found - install PowerShell 7 first.' }
|
||||
else { Write-LxsInfo 'Cancelled.' }
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
LXS - System Repair (Windows)
|
||||
Description: Integrity repair for the component store and system files
|
||||
(SFC, DISM, chkdsk). Requires administrator rights.
|
||||
@@ -20,7 +20,10 @@ if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($LxsLibSource))
|
||||
# The library ships with a UTF-8 BOM (Windows PowerShell 5.1 needs it to
|
||||
# read the file as UTF-8); over HTTP that BOM arrives as a leading U+FEFF
|
||||
# character, which the parser will not accept.
|
||||
. ([scriptblock]::Create(($LxsLibSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
$env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_repair.log'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
LXS - System Restore Point (Windows)
|
||||
Description: Enable System Protection, create checkpoints, list them and
|
||||
roll back. The safety net for harden.ps1 and debloat.ps1.
|
||||
@@ -20,7 +20,10 @@ if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($LxsLibSource))
|
||||
# The library ships with a UTF-8 BOM (Windows PowerShell 5.1 needs it to
|
||||
# read the file as UTF-8); over HTTP that BOM arrives as a leading U+FEFF
|
||||
# character, which the parser will not accept.
|
||||
. ([scriptblock]::Create(($LxsLibSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
$env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_restore_point.log'
|
||||
@@ -70,7 +73,7 @@ function Show-LxsProtectionStatus {
|
||||
Write-Host " Shadow storage: $usedGB GB used of $maxGB GB allocated"
|
||||
}
|
||||
} else {
|
||||
Write-LxsWarn "System Protection looks OFF for $drive — no restore points can be created."
|
||||
Write-LxsWarn "System Protection looks OFF for $drive - no restore points can be created."
|
||||
}
|
||||
} catch {
|
||||
Write-LxsWarn 'Could not read the shadow storage configuration.'
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
LXS - System Infos (Windows)
|
||||
Description: Essential system monitoring and diagnostic views.
|
||||
Read-only: nothing here changes the machine.
|
||||
@@ -20,7 +20,10 @@ if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($LxsLibSource))
|
||||
# The library ships with a UTF-8 BOM (Windows PowerShell 5.1 needs it to
|
||||
# read the file as UTF-8); over HTTP that BOM arrives as a leading U+FEFF
|
||||
# character, which the parser will not accept.
|
||||
. ([scriptblock]::Create(($LxsLibSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
$env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_system_infos.log'
|
||||
@@ -63,7 +66,7 @@ function Show-LxsSystemInformation {
|
||||
ForEach-Object { "$($_.Name) (driver $($_.DriverVersion))" })
|
||||
if ($gpu.Count -gt 0) { Write-LxsField 'GPU' $gpu }
|
||||
} catch {
|
||||
# Headless or restricted WMI — not worth failing the whole view.
|
||||
# Headless or restricted WMI - not worth failing the whole view.
|
||||
}
|
||||
|
||||
# Activation status. LicenseStatus 1 = licensed.
|
||||
@@ -81,7 +84,7 @@ function Show-LxsSystemInformation {
|
||||
6 { 'Extended grace' }
|
||||
default { 'Unknown' }
|
||||
}
|
||||
Write-LxsField 'Activation' "$state — $($lic[0].Name)"
|
||||
Write-LxsField 'Activation' "$state - $($lic[0].Name)"
|
||||
}
|
||||
} catch {
|
||||
# SoftwareLicensingProduct is unavailable on some SKUs.
|
||||
@@ -172,7 +175,7 @@ function Show-LxsEventLogs {
|
||||
Show-LxsBoxTop -Title 'SYSTEM LOGS' -Right 'LAST 50'
|
||||
Write-Host ''
|
||||
foreach ($logName in @('System', 'Application')) {
|
||||
Write-Host "$($script:Cyan)$($script:Bold)$logName — errors and warnings$($script:NC)"
|
||||
Write-Host "$($script:Cyan)$($script:Bold)$logName - errors and warnings$($script:NC)"
|
||||
try {
|
||||
$events = Get-WinEvent -FilterHashtable @{ LogName = $logName; Level = 1, 2, 3 } -MaxEvents 25 -ErrorAction Stop
|
||||
$events | Format-Table -AutoSize -Wrap `
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<#
|
||||
<#
|
||||
LXS - Update Windows
|
||||
Description: Install pending Windows updates and upgrade every winget
|
||||
package. Mirror of linux/tools/update-server.sh.
|
||||
@@ -22,7 +22,10 @@ if ($LxsLibPath -and (Test-Path $LxsLibPath)) {
|
||||
Write-Error 'Failed to fetch lib/common.ps1'
|
||||
exit 1
|
||||
}
|
||||
. ([scriptblock]::Create($LxsLibSource))
|
||||
# The library ships with a UTF-8 BOM (Windows PowerShell 5.1 needs it to
|
||||
# read the file as UTF-8); over HTTP that BOM arrives as a leading U+FEFF
|
||||
# character, which the parser will not accept.
|
||||
. ([scriptblock]::Create(($LxsLibSource -replace '^\uFEFF', '')))
|
||||
}
|
||||
|
||||
$env:LXS_LOG_FILE = Join-Path (Get-LxsTempDir) 'lxs_update_windows.log'
|
||||
|
||||
Reference in New Issue
Block a user