refactor(windows scripts): remove BOM and improve UTF-8 handling

This commit is contained in:
2026-09-09 15:48:32 -04:00
parent d27bf49c40
commit bdeb9c767a
19 changed files with 148 additions and 89 deletions
+7 -1
View File
@@ -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 `
+5 -2
View File
@@ -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'
+8 -5
View File
@@ -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)) {
+7 -4
View File
@@ -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)"
}
+5 -2
View File
@@ -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'
+5 -2
View File
@@ -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 {
+5 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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.
# ═══════════════════════════════════════════════════════════════════════════
+11 -8
View File
@@ -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
View File
@@ -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"
}
}
}
+9 -6
View File
@@ -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.'
+6 -3
View File
@@ -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 }
}
}
+7 -3
View File
@@ -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
+9 -6
View File
@@ -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
}
+5 -2
View File
@@ -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'
+6 -3
View File
@@ -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.'
+8 -5
View File
@@ -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 `
+5 -2
View File
@@ -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'