1	<#
2	.SYNOPSIS
3	    Activates Windows using a product key from config or KMS GVLK fallback.
4
5	.DESCRIPTION
6	    Checks if Windows is already activated (LicenseStatus = 1). If not, reads the
7	    product key from config.json activation.productKey. If no key is present, selects
8	    the appropriate GVLK for the detected Windows edition and activates via KMS.
9	    Optionally configures a specific KMS server if activation.kmsServer is set.
10
11	.ITEMS
12	    klic-z-config-json-activation-productkey: Reads activation.productKey from config.json. Installs via slmgr.vbs /ipk <key> and activates via slmgr.vbs /ato. Supports MAK (Multiple Activation Key) for volume licensing without KMS, and retail keys.
13	    fallback-na-gvlk-kms-client-key-dle-edic: When no key is in config, detects Windows edition via (Get-WmiObject SoftwareLicensingProduct).Name and maps to Microsoft's published GVLK table. Pro: W269N-WFGWX-YVC9B-4J6C9-T83GX, Enterprise: NPPR9-FWDCX-D2C8J-H872K-2YT43, Home: TX9XD-98N7V-6WMQ6-BX7FG-H8Q99.
14	    volitelny-kms-server-activation-kmsserve: If activation.kmsServer is in config.json, runs slmgr.vbs /skms <server>:<port> before /ato. Used for clients with on-premises KMS infrastructure (common in larger organizations with volume licensing).
15	    preskocit-pokud-jiz-aktivovano: Queries Win32_WindowsLicenseStatus or SoftwareLicensingProduct to check LicenseStatus. Value 1 = Licensed (fully activated). Script skips activation attempt and logs "Windows already activated" to avoid unnecessary slmgr calls.
16	    typ-klice-mak-vs-kms-vs-retail: Key type selection depends on client's Microsoft licensing: MAK = volume license key activates online against Microsoft (limited activations), KMS = requires KMS server on network (VLSC subscription), Retail = individual license from Microsoft Store or OEM.
17	#>
18	param(
19	    [object]$Config,
20	    [string]$LogFile
21	)
22
23	$ErrorActionPreference = "Continue"
24
25	function Write-Log {
26	    param([string]$Message, [string]$Level = "INFO")
27	    $line = "[$(Get-Date -Format 'HH:mm:ss')] [$Level] $Message"
28	    Add-Content -Path $LogFile -Value $line -Encoding UTF8
29	}
30
31	# -----------------------------------------------------------------------
32	# KMS Generic Volume License Keys (GVLK)
33	# Source: https://docs.microsoft.com/en-us/windows-server/get-started/kms-client-activation-keys
34	# These are official Microsoft-published keys for use with KMS infrastructure.
35	# Replace with your MAK/retail key for standalone activation.
36	# -----------------------------------------------------------------------
37	$KmsKeys = @{
38	    # Windows 11
39	    "Windows 11 Pro"                    = "W269N-WFGWX-YVC9B-4J6C9-T83GX"
40	    "Windows 11 Pro N"                  = "MH37W-N47XK-V7XM9-C7227-GCQG9"
41	    "Windows 11 Pro Education"          = "6TP4R-GNPTD-KYYHQ-7B7DP-J447Y"
42	    "Windows 11 Education"              = "NW6C2-QMPVW-D7KKK-3GKT6-VCFB2"
43	    "Windows 11 Enterprise"             = "NPPR9-FWDCX-D2C8J-H872K-2YT43"
44	    # Windows 10
45	    "Windows 10 Pro"                    = "W269N-WFGWX-YVC9B-4J6C9-T83GX"
46	    "Windows 10 Pro N"                  = "MH37W-N47XK-V7XM9-C7227-GCQG9"
47	    "Windows 10 Education"              = "NW6C2-QMPVW-D7KKK-3GKT6-VCFB2"
48	    "Windows 10 Enterprise"             = "NPPR9-FWDCX-D2C8J-H872K-2YT43"
49	    "Windows 10 Home"                   = "TX9XD-98N7V-6WMQ6-BX7FG-H8Q99"
50	}
51
52	# -----------------------------------------------------------------------
53	# Check current activation status
54	# -----------------------------------------------------------------------
55	Write-Log "Checking Windows activation status" -Level INFO
56
57	$licenseStatus = (Get-CimInstance SoftwareLicensingProduct -Filter "PartialProductKey IS NOT NULL AND Name LIKE 'Windows%'" -ErrorAction SilentlyContinue |
58	                  Select-Object -First 1).LicenseStatus
59	# LicenseStatus: 0=Unlicensed, 1=Licensed, 2=OOBGrace, 3=OOTGrace, 4=NonGenuineGrace, 5=Notification, 6=ExtendedGrace
60
61	if ($licenseStatus -eq 1) {
62	    Write-Log "  Windows is already activated - skipping" -Level OK
63	} else {
64	    Write-Log "  Activation status: $licenseStatus (not activated)" -Level WARN
65
66	    # Detect Windows edition
67	    $osCaption = (Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue).Caption
68	    Write-Log "  Detected OS: $osCaption" -Level INFO
69
70	    # Check if a key is configured in config
71	    $customKey = $null
72	    if ($Config -and $Config.activation -and $Config.activation.productKey) {
73	        $customKey = $Config.activation.productKey
74	    }
75
76	    if ($customKey -and $customKey -ne "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX") {
77	        # Use key from config
78	        $keyToUse = $customKey
79	        Write-Log "  Using product key from config" -Level INFO
80	    } else {
81	        # Find matching GVLK key by OS name
82	        $keyToUse = $null
83	        foreach ($entry in $KmsKeys.GetEnumerator()) {
84	            if ($osCaption -like "*$($entry.Key)*") {
85	                $keyToUse = $entry.Value
86	                Write-Log "  Matched GVLK key for: $($entry.Key)" -Level INFO
87	                break
88	            }
89	        }
90	    }
91
92	    if (-not $keyToUse) {
93	        Write-Log "  No matching key found for: $osCaption" -Level WARN
94	        Write-Log "  Skipping activation - set activation.productKey in config.json" -Level WARN
95	    } else {
96	        # Install key
97	        Write-Log "  Installing product key..." -Level INFO
98	        $ipkResult = & cscript //nologo "$env:SystemRoot\System32\slmgr.vbs" /ipk $keyToUse 2>&1
99	        if ($LASTEXITCODE -eq 0) {
100	            Write-Log "  Key installed" -Level OK
101	        } else {
102	            Write-Log "  Key install result: $ipkResult" -Level WARN
103	        }
104
105	        # Set KMS server if configured
106	        if ($Config -and $Config.activation -and $Config.activation.kmsServer) {
107	            $kmsServer = $Config.activation.kmsServer
108	            Write-Log "  Setting KMS server: $kmsServer" -Level INFO
109	            & cscript //nologo "$env:SystemRoot\System32\slmgr.vbs" /skms $kmsServer 2>&1 | Out-Null
110	        }
111
112	        # Attempt activation
113	        Write-Log "  Attempting activation..." -Level INFO
114	        $atoResult = & cscript //nologo "$env:SystemRoot\System32\slmgr.vbs" /ato 2>&1
115	        $atoOutput = $atoResult -join " "
116
117	        if ($atoOutput -match "successfully" -or $atoOutput -match "uspesn") {
118	            Write-Log "  Activation successful" -Level OK
119	        } else {
120	            Write-Log "  Activation result: $atoOutput" -Level WARN
121	            Write-Log "  Activation may require a KMS server or valid MAK key" -Level WARN
122	        }
123	    }
124	}
125
126	Write-Log "Step 8 - Activation complete" -Level OK
127

<#
.SYNOPSIS
    Activates Windows using a product key from config or KMS GVLK fallback.

.DESCRIPTION
    Checks if Windows is already activated (LicenseStatus = 1). If not, reads the
    product key from config.json activation.productKey. If no key is present, selects
    the appropriate GVLK for the detected Windows edition and activates via KMS.
    Optionally configures a specific KMS server if activation.kmsServer is set.

.ITEMS
    klic-z-config-json-activation-productkey: Reads activation.productKey from config.json. Installs via slmgr.vbs /ipk <key> and activates via slmgr.vbs /ato. Supports MAK (Multiple Activation Key) for volume licensing without KMS, and retail keys.
    fallback-na-gvlk-kms-client-key-dle-edic: When no key is in config, detects Windows edition via (Get-WmiObject SoftwareLicensingProduct).Name and maps to Microsoft's published GVLK table. Pro: W269N-WFGWX-YVC9B-4J6C9-T83GX, Enterprise: NPPR9-FWDCX-D2C8J-H872K-2YT43, Home: TX9XD-98N7V-6WMQ6-BX7FG-H8Q99.
    volitelny-kms-server-activation-kmsserve: If activation.kmsServer is in config.json, runs slmgr.vbs /skms <server>:<port> before /ato. Used for clients with on-premises KMS infrastructure (common in larger organizations with volume licensing).
    preskocit-pokud-jiz-aktivovano: Queries Win32_WindowsLicenseStatus or SoftwareLicensingProduct to check LicenseStatus. Value 1 = Licensed (fully activated). Script skips activation attempt and logs "Windows already activated" to avoid unnecessary slmgr calls.
    typ-klice-mak-vs-kms-vs-retail: Key type selection depends on client's Microsoft licensing: MAK = volume license key activates online against Microsoft (limited activations), KMS = requires KMS server on network (VLSC subscription), Retail = individual license from Microsoft Store or OEM.
#>
param(
    [object]$Config,
    [string]$LogFile
)

$ErrorActionPreference = "Continue"

function Write-Log {
    param([string]$Message, [string]$Level = "INFO")
    $line = "[$(Get-Date -Format 'HH:mm:ss')] [$Level] $Message"
    Add-Content -Path $LogFile -Value $line -Encoding UTF8
}

# -----------------------------------------------------------------------
# KMS Generic Volume License Keys (GVLK)
# Source: https://docs.microsoft.com/en-us/windows-server/get-started/kms-client-activation-keys
# These are official Microsoft-published keys for use with KMS infrastructure.
# Replace with your MAK/retail key for standalone activation.
# -----------------------------------------------------------------------
$KmsKeys = @{
    # Windows 11
    "Windows 11 Pro"                    = "W269N-WFGWX-YVC9B-4J6C9-T83GX"
    "Windows 11 Pro N"                  = "MH37W-N47XK-V7XM9-C7227-GCQG9"
    "Windows 11 Pro Education"          = "6TP4R-GNPTD-KYYHQ-7B7DP-J447Y"
    "Windows 11 Education"              = "NW6C2-QMPVW-D7KKK-3GKT6-VCFB2"
    "Windows 11 Enterprise"             = "NPPR9-FWDCX-D2C8J-H872K-2YT43"
    # Windows 10
    "Windows 10 Pro"                    = "W269N-WFGWX-YVC9B-4J6C9-T83GX"
    "Windows 10 Pro N"                  = "MH37W-N47XK-V7XM9-C7227-GCQG9"
    "Windows 10 Education"              = "NW6C2-QMPVW-D7KKK-3GKT6-VCFB2"
    "Windows 10 Enterprise"             = "NPPR9-FWDCX-D2C8J-H872K-2YT43"
    "Windows 10 Home"                   = "TX9XD-98N7V-6WMQ6-BX7FG-H8Q99"
}

# -----------------------------------------------------------------------
# Check current activation status
# -----------------------------------------------------------------------
Write-Log "Checking Windows activation status" -Level INFO

$licenseStatus = (Get-CimInstance SoftwareLicensingProduct -Filter "PartialProductKey IS NOT NULL AND Name LIKE 'Windows%'" -ErrorAction SilentlyContinue |
                  Select-Object -First 1).LicenseStatus
# LicenseStatus: 0=Unlicensed, 1=Licensed, 2=OOBGrace, 3=OOTGrace, 4=NonGenuineGrace, 5=Notification, 6=ExtendedGrace

if ($licenseStatus -eq 1) {
    Write-Log "  Windows is already activated - skipping" -Level OK
} else {
    Write-Log "  Activation status: $licenseStatus (not activated)" -Level WARN

    # Detect Windows edition
    $osCaption = (Get-CimInstance Win32_OperatingSystem -ErrorAction SilentlyContinue).Caption
    Write-Log "  Detected OS: $osCaption" -Level INFO

    # Check if a key is configured in config
    $customKey = $null
    if ($Config -and $Config.activation -and $Config.activation.productKey) {
        $customKey = $Config.activation.productKey
    }

    if ($customKey -and $customKey -ne "XXXXX-XXXXX-XXXXX-XXXXX-XXXXX") {
        # Use key from config
        $keyToUse = $customKey
        Write-Log "  Using product key from config" -Level INFO
    } else {
        # Find matching GVLK key by OS name
        $keyToUse = $null
        foreach ($entry in $KmsKeys.GetEnumerator()) {
            if ($osCaption -like "*$($entry.Key)*") {
                $keyToUse = $entry.Value
                Write-Log "  Matched GVLK key for: $($entry.Key)" -Level INFO
                break
            }
        }
    }

    if (-not $keyToUse) {
        Write-Log "  No matching key found for: $osCaption" -Level WARN
        Write-Log "  Skipping activation - set activation.productKey in config.json" -Level WARN
    } else {
        # Install key
        Write-Log "  Installing product key..." -Level INFO
        $ipkResult = & cscript //nologo "$env:SystemRoot\System32\slmgr.vbs" /ipk $keyToUse 2>&1
        if ($LASTEXITCODE -eq 0) {
            Write-Log "  Key installed" -Level OK
        } else {
            Write-Log "  Key install result: $ipkResult" -Level WARN
        }

        # Set KMS server if configured
        if ($Config -and $Config.activation -and $Config.activation.kmsServer) {
            $kmsServer = $Config.activation.kmsServer
            Write-Log "  Setting KMS server: $kmsServer" -Level INFO
            & cscript //nologo "$env:SystemRoot\System32\slmgr.vbs" /skms $kmsServer 2>&1 | Out-Null
        }

        # Attempt activation
        Write-Log "  Attempting activation..." -Level INFO
        $atoResult = & cscript //nologo "$env:SystemRoot\System32\slmgr.vbs" /ato 2>&1
        $atoOutput = $atoResult -join " "

        if ($atoOutput -match "successfully" -or $atoOutput -match "uspesn") {
            Write-Log "  Activation successful" -Level OK
        } else {
            Write-Log "  Activation result: $atoOutput" -Level WARN
            Write-Log "  Activation may require a KMS server or valid MAK key" -Level WARN
        }
    }
}

Write-Log "Step 8 - Activation complete" -Level OK


Načtu relevantní části spec stránky pro deduplication.


1	<!DOCTYPE html>
2	<html lang="cs">
3	<head>
4	<meta charset="UTF-8">
5	<meta name="viewport" content="width=device-width, initial-scale=1.0">
6	<title>Specifikace & anotace – xetup</title>
7	<link rel="icon" type="image/x-icon" href="/favicon.ico">
8	<style>
9	  :root {
10	    --bg: #0f1117;
11	    --card: #1a1d27;
12	    --card2: #141720;
13	    --border: #2a2d3a;
14	    --text: #e0e0e0;
15	    --muted: #888;
16	    --accent: #223B47;
17	    --accent-bright: #2d5266;
18	    --green: #2ea043;
19	    --blue: #58a6ff;
20	    --yellow: #d29922;
21	    --red: #da3633;
22	    --purple: #8b949e;
23	  }
24	  * { box-sizing: border-box; margin: 0; padding: 0; }
25	  body {
26	    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
27	    background: var(--bg);
28	    color: var(--text);
29	    min-height: 100vh;
30	  }
31
32	  /* ---- HEADER ---- */
33	  header {
34	    border-bottom: 1px solid var(--border);
35	    padding: 1rem 2rem;
36	    display: flex;
37	    align-items: center;
38	    gap: .75rem;
39	    position: sticky;
40	    top: 0;
41	    background: var(--bg);
42	    z-index: 100;
43	  }
44	  .logo-text { font-size: 1.1rem; font-weight: 700; color: #fff; letter-spacing: -.02em; }
45	  .logo-sub  { font-size: .8rem; color: var(--muted); margin-left: .2rem; }
46	  header nav { margin-left: auto; display: flex; gap: 1.5rem; }
47	  header nav a { color: var(--muted); text-decoration: none; font-size: .85rem; transition: color .15s; }
48	  header nav a:hover, header nav a.active { color: var(--text); }
49
50	  /* ---- LAYOUT ---- */
51	  .layout {
52	    display: grid;
53	    grid-template-columns: 220px 1fr;
54	    max-width: 1200px;
55	    margin: 0 auto;
56	    padding: 2rem 1.5rem;
57	    gap: 2rem;
58	    align-items: start;
59	  }
60
61	  /* ---- SIDEBAR ---- */
62	  .sidebar {
63	    position: sticky;
64	    top: 57px;
65	    border: 1px solid var(--border);
66	    border-radius: 10px;
67	    background: var(--card);
68	    padding: 1rem;
69	  }
70	  .sidebar h4 {
71	    font-size: .72rem;
72	    text-transform: uppercase;
73	    letter-spacing: .08em;
74	    color: var(--muted);
75	    margin-bottom: .75rem;
76	  }
77	  .sidebar a {
78	    display: block;
79	    color: var(--muted);
80	    text-decoration: none;
81	    font-size: .83rem;
82	    padding: .3rem .4rem;
83	    border-radius: 5px;
84	    transition: background .1s, color .1s;
85	    white-space: nowrap;
86	    overflow: hidden;
87	    text-overflow: ellipsis;
88	  }
89	  .sidebar a:hover { background: var(--card2); color: var(--text); }
90	  .sidebar-divider { border: none; border-top: 1px solid var(--border); margin: .6rem 0; }
91
92	  /* ---- CONTENT ---- */
93	  .content h1 {
94	    font-size: 1.7rem;
95	    font-weight: 800;
96	    letter-spacing: -.03em;
97	    color: #fff;
98	    margin-bottom: .4rem;
99	  }
100	  .meta {

<!DOCTYPE html>
<html lang="cs">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Specifikace & anotace – xetup</title>
<link rel="icon" type="image/x-icon" href="/favicon.ico">
<style>
  :root {
    --bg: #0f1117;
    --card: #1a1d27;
    --card2: #141720;
    --border: #2a2d3a;
    --text: #e0e0e0;
    --muted: #888;
    --accent: #223B47;
    --accent-bright: #2d5266;
    --green: #2ea043;
    --blue: #58a6ff;
    --yellow: #d29922;
    --red: #da3633;
    --purple: #8b949e;
  }
  * { box-sizing: border-box; margin: 0; padding: 0; }
  body {
    font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    background: var(--bg);
    color: var(--text);
    min-height: 100vh;
  }

  /* ---- HEADER ---- */
  header {
    border-bottom: 1px solid var(--border);
    padding: 1rem 2rem;
    display: flex;
    align-items: center;
    gap: .75rem;
    position: sticky;
    top: 0;
    background: var(--bg);
    z-index: 100;
  }
  .logo-text { font-size: 1.1rem; font-weight: 700; color: #fff; letter-spacing: -.02em; }
  .logo-sub  { font-size: .8rem; color: var(--muted); margin-left: .2rem; }
  header nav { margin-left: auto; display: flex; gap: 1.5rem; }
  header nav a { color: var(--muted); text-decoration: none; font-size: .85rem; transition: color .15s; }
  header nav a:hover, header nav a.active { color: var(--text); }

  /* ---- LAYOUT ---- */
  .layout {
    display: grid;
    grid-template-columns: 220px 1fr;
    max-width: 1200px;
    margin: 0 auto;
    padding: 2rem 1.5rem;
    gap: 2rem;
    align-items: start;
  }

  /* ---- SIDEBAR ---- */
  .sidebar {
    position: sticky;
    top: 57px;
    border: 1px solid var(--border);
    border-radius: 10px;
    background: var(--card);
    padding: 1rem;
  }
  .sidebar h4 {
    font-size: .72rem;
    text-transform: uppercase;
    letter-spacing: .08em;
    color: var(--muted);
    margin-bottom: .75rem;
  }
  .sidebar a {
    display: block;
    color: var(--muted);
    text-decoration: none;
    font-size: .83rem;
    padding: .3rem .4rem;
    border-radius: 5px;
    transition: background .1s, color .1s;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }
  .sidebar a:hover { background: var(--card2); color: var(--text); }
  .sidebar-divider { border: none; border-top: 1px solid var(--border); margin: .6rem 0; }

  /* ---- CONTENT ---- */
  .content h1 {
    font-size: 1.7rem;
    font-weight: 800;
    letter-spacing: -.03em;
    color: #fff;
    margin-bottom: .4rem;
  }
  .meta {


459-
Kroky (scripty)

460-    00 – Admin ucet
461:    01 – Bloatware
462:    02 – Software (winget)
463:    03 – Registry (HKLM)
464-    04 – Default Profile
465-    05 – Personalizace
466:    06 – Scheduled Tasks
467-    07 – BackInfo
468:    08 – Aktivace Windows
469-

470-
Planovane kroky

--
530-
531-
532:

533-

534-        01
--
543-
Windows Optional Features (PS 2.0, MediaPlayback, Recall, …)	Disable-WindowsOptionalFeature

544-
Microsoft-RemoteDesktopConnection NESMI byt odstranen	RDP klient musi zustat funkci. Overit ze neni v seznamu.

545:
OneDrive nesmi byt odstranovano tady	OneDrive musi zustat instalovatelny pro M365.

546-

547-

--
553-
554-
555:

556-

557-        02
--
566-
OpenVPN Connect (OpenVPNTechnologies.OpenVPNConnect)	OK

567-
Seznam SW je neuplny – co dalsiho patri dovnitr?	TODO: doplnit uplny seznam

568:
Atera Agent install chybi	Stahnout MSI + msiexec /i /qn

569:
Adobe PDF default: .pdf -> AcroRd32 po instalaci	OK – scheduled task PDF-DefaultApp chrání asociaci

570:
UCPD.sys (kernel driver, od Feb 2024) blokuje UserChoice	Otevren: deaktivovat UCPD behem deploymentu?

571-

572-

573:          Atera Agent URL:

574-          https://x9.servicedesk.atera.com/api/utils/agent-install/windows/?cid=31&aeid=50b72e7113e54a63ac76b96c54c7e337

575-          Stazeni: Invoke-WebRequest -Uri <url> -OutFile setup.msi  |
--
577-

578-

579:          UCPD.sys: Kernel driver (2024) blokuje primy zapis do UserChoice (vychozi app).
580-          Reseni: deaktivovat sluzbu behem deploymentu → nastavit asociaci → reaktivovat.
581-          Nebo alternativni metoda pres DISM / .reg scheduled task.
--
589-
590-
591:

592-

593-        03
--
606-
Zakaz GameDVR	OK

607-
Edge – skryt First Run Experience	HKLM\Policies\Edge\HideFirstRunExperience = 1

608:
OneDrive odstraneni je tady – SMAZAT	OneDrive musi zustat (M365). Odstranit DeleteOneDriveSetup ze scriptu.

609-
Edge policies – doplnit ~15 dalsich klicu	Viz seznam nize

610-
Powercfg nastaveni (spotreba energie)	Pridat: standby-ac 0, monitor-ac 60, standby-dc 30, monitor-dc 15

--
654-
NumLock zapnout pri startu (InitialKeyboardIndicators = 2)	OK

655-
Accent barva na titulnich listech (ColorPrevalence = 1)	OK

656:
OneDrive RunOnce klic je tady – SMAZAT	Odstranit Delete OneDriveSetup from Run ze scriptu.

657-
Explorer: ShowRecent = 0, ShowFrequent = 0	Skryt nedavne a caste soubory v Quick Access

658-
Explorer: FullPath = 1 (CabinetState)	Zobrazovat plnou cestu v titulku okna Explorera

--
699-
700-
701:

702-

703-        06
--
709-
ShowAllTrayIcons – pri logonu + kazdou 1 min	Win11 automaticky skryva tray ikony

710-
UnlockStartLayout – jednou po aplikaci layoutu	Odemkne Start menu pro uzivatelske zmeny

711:
PDF-DefaultApp – pri kazdem logonu	Obnovi .pdf -> Adobe Reader (Edge ho prepsuje)

712-

713-

--
747-
748-
749:

750-

751-        08
--
1056-  const STEP_SCRIPT = {
1057-    'step-00': '00-admin-account',
1058:    'step-01': '01-bloatware',
1059:    'step-02': '02-software',
1060:    'step-03': '03-system-registry',
1061-    'step-04': '04-default-profile',
1062-    'step-05': '05-personalization',
1063:    'step-06': '06-scheduled-tasks',
1064-    'step-07': '07-desktop-info',
1065:    'step-08': '08-activation',
1066-  };
1067-


Potřebuji vidět detailní obsah jednotlivých kroků spec stránky.


530
531
532

533

534	        01
535	        Bloatware removal
536	        OK
537

538

539

540
AppX balicky – odstraneni pro vsechny uzivatele a provisioned	Remove-AppxPackage -AllUsers + Remove-AppxProvisionedPackage

541
Zachovano: Microsoft.WindowsCalculator	Zamerny vyjimek

542
Windows Capabilities (Fax, IE, OpenSSH, WMP, WordPad, …)	Remove-WindowsCapability

543
Windows Optional Features (PS 2.0, MediaPlayback, Recall, …)	Disable-WindowsOptionalFeature

544
Microsoft-RemoteDesktopConnection NESMI byt odstranen	RDP klient musi zustat funkci. Overit ze neni v seznamu.

545
OneDrive nesmi byt odstranovano tady	OneDrive musi zustat instalovatelny pro M365.

546

547

548

549	        Script: 01-bloatware.ps1
550

551

552

553
554
555

556

557	        02
558	        Software (winget)
559	        TODO
560	        Must fix
561

562

563

564
7-Zip (7zip.7zip)	OK

565
Adobe Acrobat Reader 64-bit (Adobe.Acrobat.Reader.64-bit)	OK

566
OpenVPN Connect (OpenVPNTechnologies.OpenVPNConnect)	OK

567
Seznam SW je neuplny – co dalsiho patri dovnitr?	TODO: doplnit uplny seznam

568
Atera Agent install chybi	Stahnout MSI + msiexec /i /qn

569
Adobe PDF default: .pdf -> AcroRd32 po instalaci	OK – scheduled task PDF-DefaultApp chrání asociaci

570
UCPD.sys (kernel driver, od Feb 2024) blokuje UserChoice	Otevren: deaktivovat UCPD behem deploymentu?

571

572

573	          Atera Agent URL:

574	          https://x9.servicedesk.atera.com/api/utils/agent-install/windows/?cid=31&aeid=50b72e7113e54a63ac76b96c54c7e337

575	          Stazeni: Invoke-WebRequest -Uri <url> -OutFile setup.msi  |
576	          Instalace: msiexec /i setup.msi /qn
577

578

579	          UCPD.sys: Kernel driver (2024) blokuje primy zapis do UserChoice (vychozi app).
580	          Reseni: deaktivovat sluzbu behem deploymentu → nastavit asociaci → reaktivovat.
581	          Nebo alternativni metoda pres DISM / .reg scheduled task.
582

583

584

585	        Script: 02-software.ps1
586

587

588

589
590
591

592

593	        03
594	        System Registry (HKLM)
595	        Must fix
596	        TODO
597

598

599

600
Bypass NRO (OOBE\BypassNRO = 1)	OK

601
Zakaz auto-instalace Teams	ConfigureChatAutoInstall = 0

602
Zakaz Cloud Optimized Content	OK

603
Zakaz Widgets / News and Interests	OK

604
Hesla bez expirace (net accounts /maxpwage:UNLIMITED)	OK

605
Casova zona: Central Europe Standard Time	OK

606
Zakaz GameDVR	OK

607
Edge – skryt First Run Experience	HKLM\Policies\Edge\HideFirstRunExperience = 1

608
OneDrive odstraneni je tady – SMAZAT	OneDrive musi zustat (M365). Odstranit DeleteOneDriveSetup ze scriptu.

609
Edge policies – doplnit ~15 dalsich klicu	Viz seznam nize

610
Powercfg nastaveni (spotreba energie)	Pridat: standby-ac 0, monitor-ac 60, standby-dc 30, monitor-dc 15

611
Proxy auto-detect zakaz (AutoDetect = 0)	HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings

612

613

614	          Edge policies k doplneni:
615	          DefaultBrowserSettingEnabled = 0, NewTabPageContentEnabled = 0,
616	          ImportOnEachLaunch = 0, ShowRecommendationsEnabled = 0,
617	          PersonalizationReportingEnabled = 0, SpotlightExperiencesAndRecommendationsEnabled = 0,
618	          DiagnosticData = 0, EdgeShoppingAssistantEnabled = 0, EdgeCollectionsEnabled = 0,
619	          HubsSidebarEnabled = 0, ShowMicrosoftRewards = 0, SearchSuggestEnabled = 0 a dalsi.
620

621

622	          Powercfg prikazy:

623	          powercfg /change standby-timeout-ac 0 (neusne na nabijeni)

624	          powercfg /change monitor-timeout-ac 60 (monitor zhasne po 60 min)

625	          powercfg /change standby-timeout-dc 30

626	          powercfg /change monitor-timeout-dc 15
627

628

629

630	        Script: 03-system-registry.ps1
631

632

633

634
635
636

637

638	        04
639	        Default Profile (NTUSER.DAT)
640	        Must fix
641	        TODO
642

643

644

645
Taskbar: zarovnat vlevo (TaskbarAl = 0)	Win11 default je center

646
Taskbar: skryt Search, Copilot, Task View, Widgets, Chat	OK

647
Taskbar: zobrazit vsechny ikonky v tray (Scheduled task)	ShowAllTrayIcons

648
Taskbar: vyprazdnit pinlist (TaskbarLayoutModification.xml)	OK

649
Explorer: zobrazovat pripony souboru (HideFileExt = 0)	OK

650
Explorer: otevrit na This PC (LaunchTo = 1)	OK

651
Start menu: vyprazdnit piny (Win11)	ConfigureStartPins = {"pinnedList":[]}

652
Start menu: zakaz Bing vyhledavani	DisableSearchBoxSuggestions = 1

653
Copilot: zakaz (TurnOffWindowsCopilot = 1)	OK

654
NumLock zapnout pri startu (InitialKeyboardIndicators = 2)	OK

655
Accent barva na titulnich listech (ColorPrevalence = 1)	OK

656
OneDrive RunOnce klic je tady – SMAZAT	Odstranit Delete OneDriveSetup from Run ze scriptu.

657
Explorer: ShowRecent = 0, ShowFrequent = 0	Skryt nedavne a caste soubory v Quick Access

658
Explorer: FullPath = 1 (CabinetState)	Zobrazovat plnou cestu v titulku okna Explorera

659

660

661	          Metoda: reg load HKU\DefaultProfile C:\Users\Default\NTUSER.DAT
662	          → zapsat zmeny → reg unload HKU\DefaultProfile.

663	          Tato operace musi probihat PRED prvnim prihlasenim uzivatele.
664	          Aktualne prihlaseny uzivatel dostava zmeny pres primy zapis do HKCU.
665

666

667

668	        Script: 04-default-profile.ps1
669

670

671

672
673
674

675

676	        05
677	        Personalizace (barvy, tapeta)
678	        OK
679

680

681

682
System tema (taskbar, Start): Dark	OK

683
Aplikacni tema: Light	OK

684
Accent barva: #223B47 (tmave modroseda)	OK

685
Accent barva na Start a taskbaru: ano	OK

686
Pruhlednost: vypnuta	OK

687
Tapeta: jednobarevna #223B47 (bez obrazku)	BackInfo prepise tapetu svym BMP

688

689

690	          BackInfo.exe (STEP 07) prepise tapetu BMP se systemovymi informacemi.
691	          Jednobarevna tapeta je fallback pro pripad, ze BackInfo nedobehne nebo se nespusti.
692

693

694

695	        Script: 05-personalization.ps1
696

697

698

699
700
701

702

703	        06
704	        Scheduled Tasks
705	        OK
706

707

708

709
ShowAllTrayIcons – pri logonu + kazdou 1 min	Win11 automaticky skryva tray ikony

710
UnlockStartLayout – jednou po aplikaci layoutu	Odemkne Start menu pro uzivatelske zmeny

711
PDF-DefaultApp – pri kazdem logonu	Obnovi .pdf -> Adobe Reader (Edge ho prepsuje)

712

713

714

715	        Script: 06-scheduled-tasks.ps1
716

717

718

719
720
721

722

723	        07
724	        BackInfo (systemovy info na tapete)
725	        Must fix
726

727

728

729
07-desktop-info.ps1 SMAZAT – stary pristup	Nahradit deploym. krokem pro BackInfo.exe

730
Zkopirovat assets/Backinfo/ do C:\Program Files\Backinfo\	Pridat do master scriptu

731
Spustit backinfo_W11.ps1 (detekce OS, registry, Startup)	Pridat do master scriptu

732
BackInfo.exe v assets/Backinfo/ k dispozici	Hotovo – jen deploy krok chybi

733
BackInfo auto-start pri kazdem logonu via Startup shortcut	Zaridi backinfo_W11.ps1

734

735

736	          BackInfo.ini konfiguruje: hostname (velky, centrovan), uzivatelske jmeno,
737	          OS verze, HW info (CPU, RAM, disk), sitove informace (IP, hostname).

738	          Proc BackInfo misto vlastniho PS:
739	          BackInfo.exe podporuje Win10 i Win11 bez specialnich hacku, je stabilni a uz je v assets.
740

741

742

743	        Script: 07-desktop-info.ps1 (ke smazani) → novy inline krok v Deploy-Windows.ps1
744

745

746

747
748
749

750

751	        08
752	        Windows aktivace
753	        OK
754	        Open
755

756

757

758
Klic z config.json (activation.productKey)	OK

759
Fallback na GVLK (KMS client key) dle edice OS	OK

760
Volitelny KMS server (activation.kmsServer)	OK

761
Preskocit pokud jiz aktivovano	OK

762
Typ klice: MAK vs KMS vs retail?	Zavisi na klientovi – otevrena otazka

763

764

765

766	        Script: 08-activation.ps1
767

768

769

770
771
772
Nove kroky (planovane)

773
774
775

776

777	        09
778	        PC identita – Rename + C:\X9
779	        New

        01
        Bloatware removal
        OK

AppX balicky – odstraneni pro vsechny uzivatele a provisioned	Remove-AppxPackage -AllUsers + Remove-AppxProvisionedPackage

Zachovano: Microsoft.WindowsCalculator	Zamerny vyjimek

Windows Capabilities (Fax, IE, OpenSSH, WMP, WordPad, …)	Remove-WindowsCapability

Windows Optional Features (PS 2.0, MediaPlayback, Recall, …)	Disable-WindowsOptionalFeature

Microsoft-RemoteDesktopConnection NESMI byt odstranen	RDP klient musi zustat funkci. Overit ze neni v seznamu.

OneDrive nesmi byt odstranovano tady	OneDrive musi zustat instalovatelny pro M365.

        Script: 01-bloatware.ps1

        02
        Software (winget)
        TODO
        Must fix

7-Zip (7zip.7zip)	OK

Adobe Acrobat Reader 64-bit (Adobe.Acrobat.Reader.64-bit)	OK

OpenVPN Connect (OpenVPNTechnologies.OpenVPNConnect)	OK

Seznam SW je neuplny – co dalsiho patri dovnitr?	TODO: doplnit uplny seznam

Atera Agent install chybi	Stahnout MSI + msiexec /i /qn

Adobe PDF default: .pdf -> AcroRd32 po instalaci	OK – scheduled task PDF-DefaultApp chrání asociaci

UCPD.sys (kernel driver, od Feb 2024) blokuje UserChoice	Otevren: deaktivovat UCPD behem deploymentu?

          Atera Agent URL:

          https://x9.servicedesk.atera.com/api/utils/agent-install/windows/?cid=31&aeid=50b72e7113e54a63ac76b96c54c7e337

          Stazeni: Invoke-WebRequest -Uri <url> -OutFile setup.msi  |
          Instalace: msiexec /i setup.msi /qn

          UCPD.sys: Kernel driver (2024) blokuje primy zapis do UserChoice (vychozi app).
          Reseni: deaktivovat sluzbu behem deploymentu → nastavit asociaci → reaktivovat.
          Nebo alternativni metoda pres DISM / .reg scheduled task.

        Script: 02-software.ps1

        03
        System Registry (HKLM)
        Must fix
        TODO

Bypass NRO (OOBE\BypassNRO = 1)	OK

Zakaz auto-instalace Teams	ConfigureChatAutoInstall = 0

Zakaz Cloud Optimized Content	OK

Zakaz Widgets / News and Interests	OK

Hesla bez expirace (net accounts /maxpwage:UNLIMITED)	OK

Casova zona: Central Europe Standard Time	OK

Zakaz GameDVR	OK

Edge – skryt First Run Experience	HKLM\Policies\Edge\HideFirstRunExperience = 1

OneDrive odstraneni je tady – SMAZAT	OneDrive musi zustat (M365). Odstranit DeleteOneDriveSetup ze scriptu.

Edge policies – doplnit ~15 dalsich klicu	Viz seznam nize

Powercfg nastaveni (spotreba energie)	Pridat: standby-ac 0, monitor-ac 60, standby-dc 30, monitor-dc 15

Proxy auto-detect zakaz (AutoDetect = 0)	HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings

          Edge policies k doplneni:
          DefaultBrowserSettingEnabled = 0, NewTabPageContentEnabled = 0,
          ImportOnEachLaunch = 0, ShowRecommendationsEnabled = 0,
          PersonalizationReportingEnabled = 0, SpotlightExperiencesAndRecommendationsEnabled = 0,
          DiagnosticData = 0, EdgeShoppingAssistantEnabled = 0, EdgeCollectionsEnabled = 0,
          HubsSidebarEnabled = 0, ShowMicrosoftRewards = 0, SearchSuggestEnabled = 0 a dalsi.

          Powercfg prikazy:

          powercfg /change standby-timeout-ac 0 (neusne na nabijeni)

          powercfg /change monitor-timeout-ac 60 (monitor zhasne po 60 min)

          powercfg /change standby-timeout-dc 30

          powercfg /change monitor-timeout-dc 15

        Script: 03-system-registry.ps1

        04
        Default Profile (NTUSER.DAT)
        Must fix
        TODO

Taskbar: zarovnat vlevo (TaskbarAl = 0)	Win11 default je center

Taskbar: skryt Search, Copilot, Task View, Widgets, Chat	OK

Taskbar: zobrazit vsechny ikonky v tray (Scheduled task)	ShowAllTrayIcons

Taskbar: vyprazdnit pinlist (TaskbarLayoutModification.xml)	OK

Explorer: zobrazovat pripony souboru (HideFileExt = 0)	OK

Explorer: otevrit na This PC (LaunchTo = 1)	OK

Start menu: vyprazdnit piny (Win11)	ConfigureStartPins = {"pinnedList":[]}

Start menu: zakaz Bing vyhledavani	DisableSearchBoxSuggestions = 1

Copilot: zakaz (TurnOffWindowsCopilot = 1)	OK

NumLock zapnout pri startu (InitialKeyboardIndicators = 2)	OK

Accent barva na titulnich listech (ColorPrevalence = 1)	OK

OneDrive RunOnce klic je tady – SMAZAT	Odstranit Delete OneDriveSetup from Run ze scriptu.

Explorer: ShowRecent = 0, ShowFrequent = 0	Skryt nedavne a caste soubory v Quick Access

Explorer: FullPath = 1 (CabinetState)	Zobrazovat plnou cestu v titulku okna Explorera

          Metoda: reg load HKU\DefaultProfile C:\Users\Default\NTUSER.DAT
          → zapsat zmeny → reg unload HKU\DefaultProfile.

          Tato operace musi probihat PRED prvnim prihlasenim uzivatele.
          Aktualne prihlaseny uzivatel dostava zmeny pres primy zapis do HKCU.

        Script: 04-default-profile.ps1

        05
        Personalizace (barvy, tapeta)
        OK

System tema (taskbar, Start): Dark	OK

Aplikacni tema: Light	OK

Accent barva: #223B47 (tmave modroseda)	OK

Accent barva na Start a taskbaru: ano	OK

Pruhlednost: vypnuta	OK

Tapeta: jednobarevna #223B47 (bez obrazku)	BackInfo prepise tapetu svym BMP

          BackInfo.exe (STEP 07) prepise tapetu BMP se systemovymi informacemi.
          Jednobarevna tapeta je fallback pro pripad, ze BackInfo nedobehne nebo se nespusti.

        Script: 05-personalization.ps1

        06
        Scheduled Tasks
        OK

ShowAllTrayIcons – pri logonu + kazdou 1 min	Win11 automaticky skryva tray ikony

UnlockStartLayout – jednou po aplikaci layoutu	Odemkne Start menu pro uzivatelske zmeny

PDF-DefaultApp – pri kazdem logonu	Obnovi .pdf -> Adobe Reader (Edge ho prepsuje)

        Script: 06-scheduled-tasks.ps1

        07
        BackInfo (systemovy info na tapete)
        Must fix

07-desktop-info.ps1 SMAZAT – stary pristup	Nahradit deploym. krokem pro BackInfo.exe

Zkopirovat assets/Backinfo/ do C:\Program Files\Backinfo\	Pridat do master scriptu

Spustit backinfo_W11.ps1 (detekce OS, registry, Startup)	Pridat do master scriptu

BackInfo.exe v assets/Backinfo/ k dispozici	Hotovo – jen deploy krok chybi

BackInfo auto-start pri kazdem logonu via Startup shortcut	Zaridi backinfo_W11.ps1

          BackInfo.ini konfiguruje: hostname (velky, centrovan), uzivatelske jmeno,
          OS verze, HW info (CPU, RAM, disk), sitove informace (IP, hostname).

          Proc BackInfo misto vlastniho PS:
          BackInfo.exe podporuje Win10 i Win11 bez specialnich hacku, je stabilni a uz je v assets.

        Script: 07-desktop-info.ps1 (ke smazani) → novy inline krok v Deploy-Windows.ps1

        08
        Windows aktivace
        OK
        Open

Klic z config.json (activation.productKey)	OK

Fallback na GVLK (KMS client key) dle edice OS	OK

Volitelny KMS server (activation.kmsServer)	OK

Preskocit pokud jiz aktivovano	OK

Typ klice: MAK vs KMS vs retail?	Zavisi na klientovi – otevrena otazka

        Script: 08-activation.ps1

Nove kroky (planovane)

        09
        PC identita – Rename + C:\X9
        New


Teď mám přehled. Implementuji všechny změny postupně.

## 1. `02-software.ps1` — header + UCPD stop/start + Atera install


Edit

<#
.SYNOPSIS
    Installs standard business software via winget and configures Adobe PDF default.

.DESCRIPTION
    Uses winget to install the standard X9.cz MSP software bundle. Checks winget
    availability before running. Each install is logged. After Adobe Acrobat Reader,
    sets .pdf file association to AcroRd32. A scheduled task (PDF-DefaultApp) restores
    this association on every logon because Edge overwrites it. Atera RMM agent install
    is required but currently missing from this script.

.ITEMS
    7-zip-7zip-7zip: Installs 7-Zip (winget ID: 7zip.7zip). Used for archive management. Silent install with --accept-package-agreements --accept-source-agreements flags required for unattended deployment.
    adobe-acrobat-reader-64-bit-adobe-acroba: Installs Adobe Acrobat Reader DC 64-bit (Adobe.Acrobat.Reader.64-bit). Required as the default PDF viewer to prevent Edge from handling PDFs in browser mode, which limits functionality.
    openvpn-connect-openvpntechnologies-open: Installs OpenVPN Connect client. Used for client VPN access when the client network requires a VPN. The ovpn profile and credentials are configured separately per client.
    seznam-sw-je-neuplny-co-dalsiho-patri-do: The standard software list is incomplete. Candidates to add: Notepad++ (Notepad++.Notepad++), Google Chrome (Google.Chrome), possibly Microsoft 365 Apps, remote support tools. Needs decision from X9.cz team.
    atera-agent-install-chybi: Atera RMM agent must be installed for MSP monitoring, remote access, and ticketing integration. Download: Invoke-WebRequest -Uri "https://x9.servicedesk.atera.com/api/utils/agent-install/windows/?cid=31&aeid=50b72e7113e54a63ac76b96c54c7e337" -OutFile setup.msi / Install: msiexec /i setup.msi /qn
    adobe-pdf-default-pdf-acrord32-po-instal: Sets .pdf -> AcroRd32 file association after Acrobat install. Uses Set-ItemProperty on UserChoice key. UCPD.sys may block this - scheduled task PDF-DefaultApp runs on every logon as a reliable fallback.
    ucpd-sys-kernel-driver-od-feb-2024-bloku: UCPD.sys (User Choice Protection Driver) introduced in Win11 23H2 / Win10 22H2 update blocks writes to HKCU\Software\Microsoft\Windows\Shell\Associations\UserChoice. Workaround: sc stop ucpd before setting association, sc start ucpd after. Or rely on the logon scheduled task which runs in a context where the write succeeds.
#>

<#
.SYNOPSIS
    Installs standard business software via winget, sets Adobe PDF default, and installs Atera RMM agent.

.DESCRIPTION
    Uses winget to install the standard X9.cz MSP software bundle. Checks winget
    availability before running. Each install is logged. After Adobe Acrobat Reader,
    temporarily stops the UCPD driver (User Choice Protection Driver, present since
    Win11 23H2 / Win10 22H2 update) to allow the HKCR file association write, sets
    .pdf -> AcroRd32, then restarts UCPD. Atera RMM agent is installed for MSP
    monitoring, remote access, and ticketing integration.

.ITEMS
    7-zip-7zip-7zip: Installs 7-Zip (winget ID: 7zip.7zip). Used for archive management. Silent install with --accept-package-agreements --accept-source-agreements flags required for unattended deployment.
    adobe-acrobat-reader-64-bit-adobe-acroba: Installs Adobe Acrobat Reader DC 64-bit (Adobe.Acrobat.Reader.64-bit). Required as the default PDF viewer to prevent Edge from handling PDFs in browser mode, which limits functionality.
    openvpn-connect-openvpntechnologies-open: Installs OpenVPN Connect client. Used for client VPN access when the client network requires a VPN. The ovpn profile and credentials are configured separately per client.
    seznam-sw-je-neuplny-co-dalsiho-patri-do: The standard software list is incomplete. Candidates to add: Notepad++ (Notepad++.Notepad++), Google Chrome (Google.Chrome), possibly Microsoft 365 Apps, remote support tools. Needs decision from X9.cz team.
    atera-agent-install: Atera RMM agent installed via msiexec /qn. Download: Invoke-WebRequest from https://x9.servicedesk.atera.com/api/utils/agent-install/windows/?cid=31&aeid=50b72e7113e54a63ac76b96c54c7e337. Agent enables MSP monitoring, remote access, and ticketing integration with the Atera dashboard.
    adobe-pdf-default-pdf-acrord32-po-instal: Sets .pdf -> AcroRd32 file association after Acrobat install via HKCR (system-wide, no UserChoice hash issue). UCPD driver is stopped immediately before the write and restarted after to ensure the association persists across Edge updates.
    ucpd-sys-kernel-driver-od-feb-2024-bloku: UCPD.sys (User Choice Protection Driver) is stopped before the PDF association write and restarted after. Pattern: Stop-Service ucpd -> set HKCR\.pdf -> Start-Service ucpd. Implemented in this script.
#>


The file /opt/xetup/scripts/02-software.ps1 has been updated successfully.

<#
.SYNOPSIS
    Installs standard business software via winget, sets Adobe PDF default, and installs Atera RMM agent.

.DESCRIPTION
    Uses winget to install the standard X9.cz MSP software bundle. Checks winget
    availability before running. Each install is logged. After Adobe Acrobat Reader,
    temporarily stops the UCPD driver (User Choice Protection Driver, present since
    Win11 23H2 / Win10 22H2 update) to allow the HKCR file association write, sets
    .pdf -> AcroRd32, then restarts UCPD. Atera RMM agent is installed for MSP
    monitoring, remote access, and ticketing integration.

.ITEMS
    7-zip-7zip-7zip: Installs 7-Zip (winget ID: 7zip.7zip). Used for archive management. Silent install with --accept-package-agreements --accept-source-agreements flags required for unattended deployment.
    adobe-acrobat-reader-64-bit-adobe-acroba: Installs Adobe Acrobat Reader DC 64-bit (Adobe.Acrobat.Reader.64-bit). Required as the default PDF viewer to prevent Edge from handling PDFs in browser mode, which limits functionality.
    openvpn-connect-openvpntechnologies-open: Installs OpenVPN Connect client. Used for client VPN access when the client network requires a VPN. The ovpn profile and credentials are configured separately per client.
    seznam-sw-je-neuplny-co-dalsiho-patri-do: The standard software list is incomplete. Candidates to add: Notepad++ (Notepad++.Notepad++), Google Chrome (Google.Chrome), possibly Microsoft 365 Apps, remote support tools. Needs decision from X9.cz team.
    atera-agent-install: Atera RMM agent installed via msiexec /qn. Download: Invoke-WebRequest from https://x9.servicedesk.atera.com/api/utils/agent-install/windows/?cid=31&aeid=50b72e7113e54a63ac76b96c54c7e337. Agent enables MSP monitoring, remote access, and ticketing integration with the Atera dashboard.
    adobe-pdf-default-pdf-acrord32-po-instal: Sets .pdf -> AcroRd32 file association after Acrobat install via HKCR (system-wide, no UserChoice hash issue). UCPD driver is stopped immediately before the write and restarted after to ensure the association persists across Edge updates.
    ucpd-sys-kernel-driver-od-feb-2024-bloku: UCPD.sys (User Choice Protection Driver) is stopped before the PDF association write and restarted after. Pattern: Stop-Service ucpd -> set HKCR\.pdf -> Start-Service ucpd. Implemented in this script.
#>

<#
.SYNOPSIS
    Installs standard business software via winget and configures Adobe PDF default.

.DESCRIPTION
    Uses winget to install the standard X9.cz MSP software bundle. Checks winget
    availability before running. Each install is logged. After Adobe Acrobat Reader,
    sets .pdf file association to AcroRd32. A scheduled task (PDF-DefaultApp) restores
    this association on every logon because Edge overwrites it. Atera RMM agent install
    is required but currently missing from this script.

.ITEMS
    7-zip-7zip-7zip: Installs 7-Zip (winget ID: 7zip.7zip). Used for archive management. Silent install with --accept-package-agreements --accept-source-agreements flags required for unattended deployment.
    adobe-acrobat-reader-64-bit-adobe-acroba: Installs Adobe Acrobat Reader DC 64-bit (Adobe.Acrobat.Reader.64-bit). Required as the default PDF viewer to prevent Edge from handling PDFs in browser mode, which limits functionality.
    openvpn-connect-openvpntechnologies-open: Installs OpenVPN Connect client. Used for client VPN access when the client network requires a VPN. The ovpn profile and credentials are configured separately per client.
    seznam-sw-je-neuplny-co-dalsiho-patri-do: The standard software list is incomplete. Candidates to add: Notepad++ (Notepad++.Notepad++), Google Chrome (Google.Chrome), possibly Microsoft 365 Apps, remote support tools. Needs decision from X9.cz team.
    atera-agent-install-chybi: Atera RMM agent must be installed for MSP monitoring, remote access, and ticketing integration. Download: Invoke-WebRequest -Uri "https://x9.servicedesk.atera.com/api/utils/agent-install/windows/?cid=31&aeid=50b72e7113e54a63ac76b96c54c7e337" -OutFile setup.msi / Install: msiexec /i setup.msi /qn
    adobe-pdf-default-pdf-acrord32-po-instal: Sets .pdf -> AcroRd32 file association after Acrobat install. Uses Set-ItemProperty on UserChoice key. UCPD.sys may block this - scheduled task PDF-DefaultApp runs on every logon as a reliable fallback.
    ucpd-sys-kernel-driver-od-feb-2024-bloku: UCPD.sys (User Choice Protection Driver) introduced in Win11 23H2 / Win10 22H2 update blocks writes to HKCU\Software\Microsoft\Windows\Shell\Associations\UserChoice. Workaround: sc stop ucpd before setting association, sc start ucpd after. Or rely on the logon scheduled task which runs in a context where the write succeeds.
#>
param(
    [object]$Config,
    [string]$LogFile
)

$ErrorActionPreference = "Continue"

function Write-Log {
    param([string]$Message, [string]$Level = "INFO")
    $line = "[$(Get-Date -Format 'HH:mm:ss')] [$Level] $Message"
    Add-Content -Path $LogFile -Value $line -Encoding UTF8
}

# -----------------------------------------------------------------------
# Check winget availability
# -----------------------------------------------------------------------
Write-Log "Checking winget availability" -Level INFO

$winget = Get-Command winget -ErrorAction SilentlyContinue
if (-not $winget) {
    # Try to find winget in known locations
    $wingetPaths = @(
        "$env:LOCALAPPDATA\Microsoft\WindowsApps\winget.exe"
        "$env:ProgramFiles\WindowsApps\Microsoft.DesktopAppInstaller*\winget.exe"
    )
    foreach ($p in $wingetPaths) {
        $found = Get-Item $p -ErrorAction SilentlyContinue | Select-Object -First 1
        if ($found) { $winget = $found.FullName; break }
    }
}

if (-not $winget) {
    Write-Log "winget not found - software installation skipped" -Level ERROR
    exit 1
}

Write-Log "winget found: $($winget.Source -or $winget)" -Level OK

# Accept agreements upfront
& winget source update --accept-source-agreements 2>&1 | Out-Null

# -----------------------------------------------------------------------
# Install packages from config
# -----------------------------------------------------------------------
if (-not $Config -or -not $Config.software -or -not $Config.software.install) {
    Write-Log "No software list in config - skipping installs" -Level WARN
} else {
    foreach ($pkg in $Config.software.install) {
        Write-Log "Installing $($pkg.name) ($($pkg.wingetId))" -Level INFO
        $result = & winget install --id $pkg.wingetId `
            --silent `
            --accept-package-agreements `
            --accept-source-agreements `
            --disable-interactivity `
            2>&1

        $exitCode = $LASTEXITCODE
        if ($exitCode -eq 0) {
            Write-Log "  Installed OK: $($pkg.name)" -Level OK
        } elseif ($exitCode -eq -1978335189) {
            # 0x8A150011 = already installed
            Write-Log "  Already installed: $($pkg.name)" -Level OK
        } else {
            Write-Log "  Failed: $($pkg.name) (exit $exitCode)" -Level ERROR
            Write-Log "  Output: $($result -join ' ')" -Level ERROR
        }
    }
}

# -----------------------------------------------------------------------
# Set Adobe Reader as default PDF app
# -----------------------------------------------------------------------
$forcePdf = $true
if ($Config -and $Config.pdfDefault) {
    $forcePdf = [bool]$Config.pdfDefault.forceAdobeReader
}

if ($forcePdf) {
    Write-Log "Setting Adobe Reader as default PDF app" -Level INFO

    # Find Adobe PDF viewer executable (Acrobat DC or Reader DC)
    $acroPaths = @(
        "$env:ProgramFiles\Adobe\Acrobat DC\Acrobat\Acrobat.exe"
        "${env:ProgramFiles(x86)}\Adobe\Acrobat DC\Acrobat\Acrobat.exe"
        "${env:ProgramFiles(x86)}\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
        "$env:ProgramFiles\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
        "${env:ProgramFiles(x86)}\Adobe\Reader\Reader\AcroRd32.exe"
    )
    $acroExe = $acroPaths | Where-Object { Test-Path $_ } | Select-Object -First 1

    if (-not $acroExe) {
        Write-Log "  Adobe PDF viewer not found - PDF default not set" -Level WARN
    } else {
        Write-Log "  Found: $acroExe" -Level INFO

        # Set file type association via HKCR (system-wide, requires admin)
        $progId = "AcroExch.Document.DC"
        $openCmd = "`"$acroExe`" `"%1`""

        # HKCR\.pdf -> progId
        if (-not (Test-Path "HKCR:\.pdf")) {
            New-Item -Path "HKCR:\.pdf" -Force | Out-Null
        }
        Set-ItemProperty -Path "HKCR:\.pdf" -Name "(Default)" -Value $progId

        # HKCR\AcroExch.Document.DC\shell\open\command
        $cmdPath = "HKCR:\$progId\shell\open\command"
        if (-not (Test-Path $cmdPath)) {
            New-Item -Path $cmdPath -Force | Out-Null
        }
        Set-ItemProperty -Path $cmdPath -Name "(Default)" -Value $openCmd

        # Note: HKCU UserChoice requires a Windows-computed Hash value to be valid.
        # Direct ProgId write without Hash is silently reset by Windows on next access.
        # HKCR write above provides the system-wide default; per-user default is
        # handled by the PDF-DefaultApp scheduled task via HKCR on every logon.

        Write-Log "  PDF default set to AcroRd32 (HKCR)" -Level OK
    }
}

Write-Log "Step 2 complete" -Level OK

-    Installs standard business software via winget and configures Adobe PDF default.

+    Installs standard business software via winget, sets Adobe PDF default, and installs Atera RMM agent.

-    sets .pdf file association to AcroRd32. A scheduled task (PDF-DefaultApp) restores

-    this association on every logon because Edge overwrites it. Atera RMM agent install

-    is required but currently missing from this script.

+    temporarily stops the UCPD driver (User Choice Protection Driver, present since

+    Win11 23H2 / Win10 22H2 update) to allow the HKCR file association write, sets

+    .pdf -> AcroRd32, then restarts UCPD. Atera RMM agent is installed for MSP

+    monitoring, remote access, and ticketing integration.

-    atera-agent-install-chybi: Atera RMM agent must be installed for MSP monitoring, remote access, and ticketing integration. Download: Invoke-WebRequest -Uri "https://x9.servicedesk.atera.com/api/utils/agent-install/windows/?cid=31&aeid=50b72e7113e54a63ac76b96c54c7e337" -OutFile setup.msi / Install: msiexec /i setup.msi /qn

-    adobe-pdf-default-pdf-acrord32-po-instal: Sets .pdf -> AcroRd32 file association after Acrobat install. Uses Set-ItemProperty on UserChoice key. UCPD.sys may block this - scheduled task PDF-DefaultApp runs on every logon as a reliable fallback.

-    ucpd-sys-kernel-driver-od-feb-2024-bloku: UCPD.sys (User Choice Protection Driver) introduced in Win11 23H2 / Win10 22H2 update blocks writes to HKCU\Software\Microsoft\Windows\Shell\Associations\UserChoice. Workaround: sc stop ucpd before setting association, sc start ucpd after. Or rely on the logon scheduled task which runs in a context where the write succeeds.

+    atera-agent-install: Atera RMM agent installed via msiexec /qn. Download: Invoke-WebRequest from https://x9.servicedesk.atera.com/api/utils/agent-install/windows/?cid=31&aeid=50b72e7113e54a63ac76b96c54c7e337. Agent enables MSP monitoring, remote access, and ticketing integration with the Atera dashboard.

+    adobe-pdf-default-pdf-acrord32-po-instal: Sets .pdf -> AcroRd32 file association after Acrobat install via HKCR (system-wide, no UserChoice hash issue). UCPD driver is stopped immediately before the write and restarted after to ensure the association persists across Edge updates.

+    ucpd-sys-kernel-driver-od-feb-2024-bloku: UCPD.sys (User Choice Protection Driver) is stopped before the PDF association write and restarted after. Pattern: Stop-Service ucpd -> set HKCR\.pdf -> Start-Service ucpd. Implemented in this script.


Nyní přidám UCPD stop/start kolem sekce PDF default a Atera install na konec:


if ($forcePdf) {
    Write-Log "Setting Adobe Reader as default PDF app" -Level INFO

    # Find Adobe PDF viewer executable (Acrobat DC or Reader DC)
    $acroPaths = @(
        "$env:ProgramFiles\Adobe\Acrobat DC\Acrobat\Acrobat.exe"
        "${env:ProgramFiles(x86)}\Adobe\Acrobat DC\Acrobat\Acrobat.exe"
        "${env:ProgramFiles(x86)}\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
        "$env:ProgramFiles\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
        "${env:ProgramFiles(x86)}\Adobe\Reader\Reader\AcroRd32.exe"
    )
    $acroExe = $acroPaths | Where-Object { Test-Path $_ } | Select-Object -First 1

    if (-not $acroExe) {
        Write-Log "  Adobe PDF viewer not found - PDF default not set" -Level WARN
    } else {
        Write-Log "  Found: $acroExe" -Level INFO

        # Set file type association via HKCR (system-wide, requires admin)
        $progId = "AcroExch.Document.DC"
        $openCmd = "`"$acroExe`" `"%1`""

        # HKCR\.pdf -> progId
        if (-not (Test-Path "HKCR:\.pdf")) {
            New-Item -Path "HKCR:\.pdf" -Force | Out-Null
        }
        Set-ItemProperty -Path "HKCR:\.pdf" -Name "(Default)" -Value $progId

        # HKCR\AcroExch.Document.DC\shell\open\command
        $cmdPath = "HKCR:\$progId\shell\open\command"
        if (-not (Test-Path $cmdPath)) {
            New-Item -Path $cmdPath -Force | Out-Null
        }
        Set-ItemProperty -Path $cmdPath -Name "(Default)" -Value $openCmd

        # Note: HKCU UserChoice requires a Windows-computed Hash value to be valid.
        # Direct ProgId write without Hash is silently reset by Windows on next access.
        # HKCR write above provides the system-wide default; per-user default is
        # handled by the PDF-DefaultApp scheduled task via HKCR on every logon.

        Write-Log "  PDF default set to AcroRd32 (HKCR)" -Level OK
    }
}

Write-Log "Step 2 complete" -Level OK

if ($forcePdf) {
    Write-Log "Setting Adobe Reader as default PDF app" -Level INFO

    # Stop UCPD driver before writing file association.
    # UCPD.sys (User Choice Protection Driver) blocks UserChoice registry writes
    # on Win11 23H2+ and some Win10 22H2 builds. Stopping it temporarily allows
    # the HKCR association to be written reliably.
    $ucpdStopped = $false
    $ucpdSvc = Get-Service -Name "ucpd" -ErrorAction SilentlyContinue
    if ($ucpdSvc) {
        try {
            Stop-Service -Name "ucpd" -Force -ErrorAction Stop
            $ucpdStopped = $true
            Write-Log "  UCPD driver stopped" -Level OK
        }
        catch {
            Write-Log "  Could not stop UCPD: $_ (association may not persist on some builds)" -Level WARN
        }
    }

    # Find Adobe PDF viewer executable (Acrobat DC or Reader DC)
    $acroPaths = @(
        "$env:ProgramFiles\Adobe\Acrobat DC\Acrobat\Acrobat.exe"
        "${env:ProgramFiles(x86)}\Adobe\Acrobat DC\Acrobat\Acrobat.exe"
        "${env:ProgramFiles(x86)}\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
        "$env:ProgramFiles\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
        "${env:ProgramFiles(x86)}\Adobe\Reader\Reader\AcroRd32.exe"
    )
    $acroExe = $acroPaths | Where-Object { Test-Path $_ } | Select-Object -First 1

    if (-not $acroExe) {
        Write-Log "  Adobe PDF viewer not found - PDF default not set" -Level WARN
    } else {
        Write-Log "  Found: $acroExe" -Level INFO

        # Set file type association via HKCR (system-wide, requires admin)
        $progId = "AcroExch.Document.DC"
        $openCmd = "`"$acroExe`" `"%1`""

        # HKCR\.pdf -> progId
        if (-not (Test-Path "HKCR:\.pdf")) {
            New-Item -Path "HKCR:\.pdf" -Force | Out-Null
        }
        Set-ItemProperty -Path "HKCR:\.pdf" -Name "(Default)" -Value $progId

        # HKCR\AcroExch.Document.DC\shell\open\command
        $cmdPath = "HKCR:\$progId\shell\open\command"
        if (-not (Test-Path $cmdPath)) {
            New-Item -Path $cmdPath -Force | Out-Null
        }
        Set-ItemProperty -Path $cmdPath -Name "(Default)" -Value $openCmd

        Write-Log "  PDF default set to AcroRd32 (HKCR)" -Level OK
    }

    # Restart UCPD after writing association
    if ($ucpdStopped) {
        try {
            Start-Service -Name "ucpd" -ErrorAction SilentlyContinue
            Write-Log "  UCPD driver restarted" -Level OK
        }
        catch {
            Write-Log "  Could not restart UCPD: $_" -Level WARN
        }
    }
}

# -----------------------------------------------------------------------
# Install Atera RMM Agent
# -----------------------------------------------------------------------
Write-Log "Installing Atera RMM Agent" -Level INFO

$ateraUrl = "https://x9.servicedesk.atera.com/api/utils/agent-install/windows/?cid=31&aeid=50b72e7113e54a63ac76b96c54c7e337"
$ateraMsi = "$env:TEMP\AteraAgent.msi"

try {
    Write-Log "  Downloading Atera agent..." -Level INFO
    Invoke-WebRequest -Uri $ateraUrl -OutFile $ateraMsi -UseBasicParsing -ErrorAction Stop
    Write-Log "  Download complete" -Level OK

    $msiResult = & msiexec /i $ateraMsi /qn 2>&1
    Start-Sleep -Seconds 5

    $ateraExe = "$env:ProgramFiles\ATERA Networks\AteraAgent\AteraAgent.exe"
    if (Test-Path $ateraExe) {
        Write-Log "  Atera agent installed" -Level OK
    } else {
        Write-Log "  Atera agent install may have failed - binary not found at expected path" -Level WARN
        Write-Log "  msiexec output: $($msiResult -join ' ')" -Level WARN
    }
}
catch {
    Write-Log "  Atera agent download/install failed: $_" -Level ERROR
}
finally {
    Remove-Item $ateraMsi -Force -ErrorAction SilentlyContinue
}

Write-Log "Step 2 complete" -Level OK


if ($forcePdf) {
    Write-Log "Setting Adobe Reader as default PDF app" -Level INFO

    # Stop UCPD driver before writing file association.
    # UCPD.sys (User Choice Protection Driver) blocks UserChoice registry writes
    # on Win11 23H2+ and some Win10 22H2 builds. Stopping it temporarily allows
    # the HKCR association to be written reliably.
    $ucpdStopped = $false
    $ucpdSvc = Get-Service -Name "ucpd" -ErrorAction SilentlyContinue
    if ($ucpdSvc) {
        try {
            Stop-Service -Name "ucpd" -Force -ErrorAction Stop
            $ucpdStopped = $true
            Write-Log "  UCPD driver stopped" -Level OK
        }
        catch {
            Write-Log "  Could not stop UCPD: $_ (association may not persist on some builds)" -Level WARN
        }
    }

    # Find Adobe PDF viewer executable (Acrobat DC or Reader DC)
    $acroPaths = @(
        "$env:ProgramFiles\Adobe\Acrobat DC\Acrobat\Acrobat.exe"
        "${env:ProgramFiles(x86)}\Adobe\Acrobat DC\Acrobat\Acrobat.exe"
        "${env:ProgramFiles(x86)}\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
        "$env:ProgramFiles\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
        "${env:ProgramFiles(x86)}\Adobe\Reader\Reader\AcroRd32.exe"
    )
    $acroExe = $acroPaths | Where-Object { Test-Path $_ } | Select-Object -First 1

    if (-not $acroExe) {
        Write-Log "  Adobe PDF viewer not found - PDF default not set" -Level WARN
    } else {
        Write-Log "  Found: $acroExe" -Level INFO

        # Set file type association via HKCR (system-wide, requires admin)
        $progId = "AcroExch.Document.DC"
        $openCmd = "`"$acroExe`" `"%1`""

        # HKCR\.pdf -> progId
        if (-not (Test-Path "HKCR:\.pdf")) {
            New-Item -Path "HKCR:\.pdf" -Force | Out-Null
        }
        Set-ItemProperty -Path "HKCR:\.pdf" -Name "(Default)" -Value $progId

        # HKCR\AcroExch.Document.DC\shell\open\command
        $cmdPath = "HKCR:\$progId\shell\open\command"
        if (-not (Test-Path $cmdPath)) {
            New-Item -Path $cmdPath -Force | Out-Null
        }
        Set-ItemProperty -Path $cmdPath -Name "(Default)" -Value $openCmd

        Write-Log "  PDF default set to AcroRd32 (HKCR)" -Level OK
    }

    # Restart UCPD after writing association
    if ($ucpdStopped) {
        try {
            Start-Service -Name "ucpd" -ErrorAction SilentlyContinue
            Write-Log "  UCPD driver restarted" -Level OK
        }
        catch {
            Write-Log "  Could not restart UCPD: $_" -Level WARN
        }
    }
}

# -----------------------------------------------------------------------
# Install Atera RMM Agent
# -----------------------------------------------------------------------
Write-Log "Installing Atera RMM Agent" -Level INFO

$ateraUrl = "https://x9.servicedesk.atera.com/api/utils/agent-install/windows/?cid=31&aeid=50b72e7113e54a63ac76b96c54c7e337"
$ateraMsi = "$env:TEMP\AteraAgent.msi"

try {
    Write-Log "  Downloading Atera agent..." -Level INFO
    Invoke-WebRequest -Uri $ateraUrl -OutFile $ateraMsi -UseBasicParsing -ErrorAction Stop
    Write-Log "  Download complete" -Level OK

    $msiResult = & msiexec /i $ateraMsi /qn 2>&1
    Start-Sleep -Seconds 5

    $ateraExe = "$env:ProgramFiles\ATERA Networks\AteraAgent\AteraAgent.exe"
    if (Test-Path $ateraExe) {
        Write-Log "  Atera agent installed" -Level OK
    } else {
        Write-Log "  Atera agent install may have failed - binary not found at expected path" -Level WARN
        Write-Log "  msiexec output: $($msiResult -join ' ')" -Level WARN
    }
}
catch {
    Write-Log "  Atera agent download/install failed: $_" -Level ERROR
}
finally {
    Remove-Item $ateraMsi -Force -ErrorAction SilentlyContinue
}

Write-Log "Step 2 complete" -Level OK

<#
.SYNOPSIS
    Installs standard business software via winget, sets Adobe PDF default, and installs Atera RMM agent.

.DESCRIPTION
    Uses winget to install the standard X9.cz MSP software bundle. Checks winget
    availability before running. Each install is logged. After Adobe Acrobat Reader,
    temporarily stops the UCPD driver (User Choice Protection Driver, present since
    Win11 23H2 / Win10 22H2 update) to allow the HKCR file association write, sets
    .pdf -> AcroRd32, then restarts UCPD. Atera RMM agent is installed for MSP
    monitoring, remote access, and ticketing integration.

.ITEMS
    7-zip-7zip-7zip: Installs 7-Zip (winget ID: 7zip.7zip). Used for archive management. Silent install with --accept-package-agreements --accept-source-agreements flags required for unattended deployment.
    adobe-acrobat-reader-64-bit-adobe-acroba: Installs Adobe Acrobat Reader DC 64-bit (Adobe.Acrobat.Reader.64-bit). Required as the default PDF viewer to prevent Edge from handling PDFs in browser mode, which limits functionality.
    openvpn-connect-openvpntechnologies-open: Installs OpenVPN Connect client. Used for client VPN access when the client network requires a VPN. The ovpn profile and credentials are configured separately per client.
    seznam-sw-je-neuplny-co-dalsiho-patri-do: The standard software list is incomplete. Candidates to add: Notepad++ (Notepad++.Notepad++), Google Chrome (Google.Chrome), possibly Microsoft 365 Apps, remote support tools. Needs decision from X9.cz team.
    atera-agent-install: Atera RMM agent installed via msiexec /qn. Download: Invoke-WebRequest from https://x9.servicedesk.atera.com/api/utils/agent-install/windows/?cid=31&aeid=50b72e7113e54a63ac76b96c54c7e337. Agent enables MSP monitoring, remote access, and ticketing integration with the Atera dashboard.
    adobe-pdf-default-pdf-acrord32-po-instal: Sets .pdf -> AcroRd32 file association after Acrobat install via HKCR (system-wide, no UserChoice hash issue). UCPD driver is stopped immediately before the write and restarted after to ensure the association persists across Edge updates.
    ucpd-sys-kernel-driver-od-feb-2024-bloku: UCPD.sys (User Choice Protection Driver) is stopped before the PDF association write and restarted after. Pattern: Stop-Service ucpd -> set HKCR\.pdf -> Start-Service ucpd. Implemented in this script.
#>
param(
    [object]$Config,
    [string]$LogFile
)

$ErrorActionPreference = "Continue"

function Write-Log {
    param([string]$Message, [string]$Level = "INFO")
    $line = "[$(Get-Date -Format 'HH:mm:ss')] [$Level] $Message"
    Add-Content -Path $LogFile -Value $line -Encoding UTF8
}

# -----------------------------------------------------------------------
# Check winget availability
# -----------------------------------------------------------------------
Write-Log "Checking winget availability" -Level INFO

$winget = Get-Command winget -ErrorAction SilentlyContinue
if (-not $winget) {
    # Try to find winget in known locations
    $wingetPaths = @(
        "$env:LOCALAPPDATA\Microsoft\WindowsApps\winget.exe"
        "$env:ProgramFiles\WindowsApps\Microsoft.DesktopAppInstaller*\winget.exe"
    )
    foreach ($p in $wingetPaths) {
        $found = Get-Item $p -ErrorAction SilentlyContinue | Select-Object -First 1
        if ($found) { $winget = $found.FullName; break }
    }
}

if (-not $winget) {
    Write-Log "winget not found - software installation skipped" -Level ERROR
    exit 1
}

Write-Log "winget found: $($winget.Source -or $winget)" -Level OK

# Accept agreements upfront
& winget source update --accept-source-agreements 2>&1 | Out-Null

# -----------------------------------------------------------------------
# Install packages from config
# -----------------------------------------------------------------------
if (-not $Config -or -not $Config.software -or -not $Config.software.install) {
    Write-Log "No software list in config - skipping installs" -Level WARN
} else {
    foreach ($pkg in $Config.software.install) {
        Write-Log "Installing $($pkg.name) ($($pkg.wingetId))" -Level INFO
        $result = & winget install --id $pkg.wingetId `
            --silent `
            --accept-package-agreements `
            --accept-source-agreements `
            --disable-interactivity `
            2>&1

        $exitCode = $LASTEXITCODE
        if ($exitCode -eq 0) {
            Write-Log "  Installed OK: $($pkg.name)" -Level OK
        } elseif ($exitCode -eq -1978335189) {
            # 0x8A150011 = already installed
            Write-Log "  Already installed: $($pkg.name)" -Level OK
        } else {
            Write-Log "  Failed: $($pkg.name) (exit $exitCode)" -Level ERROR
            Write-Log "  Output: $($result -join ' ')" -Level ERROR
        }
    }
}

# -----------------------------------------------------------------------
# Set Adobe Reader as default PDF app
# -----------------------------------------------------------------------
$forcePdf = $true
if ($Config -and $Config.pdfDefault) {
    $forcePdf = [bool]$Config.pdfDefault.forceAdobeReader
}

if ($forcePdf) {
    Write-Log "Setting Adobe Reader as default PDF app" -Level INFO

    # Find Adobe PDF viewer executable (Acrobat DC or Reader DC)
    $acroPaths = @(
        "$env:ProgramFiles\Adobe\Acrobat DC\Acrobat\Acrobat.exe"
        "${env:ProgramFiles(x86)}\Adobe\Acrobat DC\Acrobat\Acrobat.exe"
        "${env:ProgramFiles(x86)}\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
        "$env:ProgramFiles\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"
        "${env:ProgramFiles(x86)}\Adobe\Reader\Reader\AcroRd32.exe"
    )
    $acroExe = $acroPaths | Where-Object { Test-Path $_ } | Select-Object -First 1

    if (-not $acroExe) {
        Write-Log "  Adobe PDF viewer not found - PDF default not set" -Level WARN
    } else {
        Write-Log "  Found: $acroExe" -Level INFO

        # Set file type association via HKCR (system-wide, requires admin)
        $progId = "AcroExch.Document.DC"
        $openCmd = "`"$acroExe`" `"%1`""

        # HKCR\.pdf -> progId
        if (-not (Test-Path "HKCR:\.pdf")) {
            New-Item -Path "HKCR:\.pdf" -Force | Out-Null
        }
        Set-ItemProperty -Path "HKCR:\.pdf" -Name "(Default)" -Value $progId

        # HKCR\AcroExch.Document.DC\shell\open\command
        $cmdPath = "HKCR:\$progId\shell\open\command"
        if (-not (Test-Path $cmdPath)) {
            New-Item -Path $cmdPath -Force | Out-Null
        }
        Set-ItemProperty -Path $cmdPath -Name "(Default)" -Value $openCmd

        # Note: HKCU UserChoice requires a Windows-computed Hash value to be valid.
        # Direct ProgId write without Hash is silently reset by Windows on next access.
        # HKCR write above provides the system-wide default; per-user default is
        # handled by the PDF-DefaultApp scheduled task via HKCR on every logon.

        Write-Log "  PDF default set to AcroRd32 (HKCR)" -Level OK
    }
}

Write-Log "Step 2 complete" -Level OK

+    # Stop UCPD driver before writing file association.

+    # UCPD.sys (User Choice Protection Driver) blocks UserChoice registry writes

+    # on Win11 23H2+ and some Win10 22H2 builds. Stopping it temporarily allows

+    # the HKCR association to be written reliably.

+    $ucpdSvc = Get-Service -Name "ucpd" -ErrorAction SilentlyContinue

+            Stop-Service -Name "ucpd" -Force -ErrorAction Stop

+            Write-Log "  UCPD driver stopped" -Level OK

+            Write-Log "  Could not stop UCPD: $_ (association may not persist on some builds)" -Level WARN

-        # Note: HKCU UserChoice requires a Windows-computed Hash value to be valid.

-        # Direct ProgId write without Hash is silently reset by Windows on next access.

-        # HKCR write above provides the system-wide default; per-user default is

-        # handled by the PDF-DefaultApp scheduled task via HKCR on every logon.

+    # Restart UCPD after writing association

+            Start-Service -Name "ucpd" -ErrorAction SilentlyContinue

+            Write-Log "  UCPD driver restarted" -Level OK

+            Write-Log "  Could not restart UCPD: $_" -Level WARN

+Write-Log "Installing Atera RMM Agent" -Level INFO

+    Write-Log "  Downloading Atera agent..." -Level INFO

+    Invoke-WebRequest -Uri $ateraUrl -OutFile $ateraMsi -UseBasicParsing -ErrorAction Stop

+    Write-Log "  Download complete" -Level OK

+    $msiResult = & msiexec /i $ateraMsi /qn 2>&1

+    $ateraExe = "$env:ProgramFiles\ATERA Networks\AteraAgent\AteraAgent.exe"

+        Write-Log "  Atera agent installed" -Level OK

+        Write-Log "  Atera agent install may have failed - binary not found at expected path" -Level WARN

+        Write-Log "  msiexec output: $($msiResult -join ' ')" -Level WARN

+    Write-Log "  Atera agent download/install failed: $_" -Level ERROR

+    Remove-Item $ateraMsi -Force -ErrorAction SilentlyContinue


## 2. `03-system-registry.ps1` — opravit header pro OneDrive


.DESCRIPTION
    Sets machine-wide registry tweaks under HKLM that apply to all users. Disables
    unwanted telemetry and cloud features, configures Edge policies, sets power plan
    timeouts, and disables proxy auto-detect. CRITICAL: The OneDrive removal lines
    that were previously in this script MUST be deleted - OneDrive must remain for M365.

.ITEMS
    bypass-nro-oobe-bypassnro-1: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE\BypassNRO = 1. Bypasses the "Let's connect you to a network" OOBE screen. Enables offline Windows setup without forcing a Microsoft account login.
    zakaz-auto-instalace-teams: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Communications\ConfigureChatAutoInstall = 0. Prevents Windows from auto-installing Teams Personal during OOBE or after Cumulative Updates.
    zakaz-cloud-optimized-content: ContentDeliveryManager\DisableCloudOptimizedContent = 1. Stops Windows from pushing sponsored app suggestions, tips from Microsoft servers, and "Get even more from Windows" prompts.
    zakaz-widgets-news-and-interests: HKLM\SOFTWARE\Policies\Microsoft\Dsh\AllowNewsAndInterests = 0. Disables the Widgets taskbar button and panel (news feed, weather, stocks). Not relevant for business deployments.
    hesla-bez-expirace-net-accounts-maxpwage: net accounts /maxpwage:UNLIMITED. Sets the local password expiration policy to never. MSP-managed machines handle password rotation via other means (Atera, domain policy, manual).
    casova-zona-central-europe-standard-time: Set-TimeZone -Id "Central Europe Standard Time". UTC+1 (UTC+2 in summer DST). Applied system-wide. Critical for correct log timestamps, scheduled task timing, and calendar sync.
    zakaz-gamedvr: HKLM\SOFTWARE\Policies\Microsoft\Windows\GameDVR\AppCaptureEnabled = 0. Disables Xbox Game Bar screen capture overlay. Reduces background resource usage and eliminates unintended capture prompts on business machines.
    edge-skryt-first-run-experience: HKLM\SOFTWARE\Policies\Microsoft\Edge\HideFirstRunExperience = 1. Suppresses the Edge welcome wizard (import from other browser, default browser prompt, etc.) for every user on first launch.
    onedrive-odstraneni-je-tady-smazat: MUST BE REMOVED FROM SCRIPT. Deleting OneDriveSetup.exe and the Start Menu shortcut was added incorrectly. OneDrive must remain installable for Microsoft 365 / SharePoint use. Remove these lines entirely.
    edge-policies-doplnit-15-dalsich-klicu: Missing Edge policies to add under HKLM\SOFTWARE\Policies\Microsoft\Edge: DefaultBrowserSettingEnabled=0, NewTabPageContentEnabled=0, ImportOnEachLaunch=0, ShowRecommendationsEnabled=0, PersonalizationReportingEnabled=0, SpotlightExperiencesAndRecommendationsEnabled=0, EdgeShoppingAssistantEnabled=0, HubsSidebarEnabled=0, ShowMicrosoftRewards=0, SearchSuggestEnabled=0, DiagnosticData=0.
    powercfg-nastaveni-spotreba-energie: powercfg /change commands: standby-timeout-ac 0 (never sleep on AC/charger), monitor-timeout-ac 60 (screen off after 60 min on AC), standby-timeout-dc 30 (sleep after 30 min on battery), monitor-timeout-dc 15 (screen off after 15 min on battery).
    proxy-auto-detect-zakaz-autodetect-0: HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\AutoDetect = 0. Disables WPAD (Web Proxy Auto-Discovery). Eliminates startup delays from WPAD DNS lookup and prevents potential MITM via malicious WPAD responses on untrusted networks.
#>

.DESCRIPTION
    Sets machine-wide registry tweaks under HKLM that apply to all users. Disables
    unwanted telemetry and cloud features, configures Edge policies, sets power plan
    timeouts, and disables proxy auto-detect. Uninstalls the pre-installed OneDrive
    consumer version via OneDriveSetup.exe /uninstall - intentional for a clean MSP
    deployment baseline. No DisableFileSyncNGSC policy key is set, so M365 installation
    can install and run its own OneDrive version without restriction.

.ITEMS
    bypass-nro-oobe-bypassnro-1: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE\BypassNRO = 1. Bypasses the "Let's connect you to a network" OOBE screen. Enables offline Windows setup without forcing a Microsoft account login.
    zakaz-auto-instalace-teams: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Communications\ConfigureChatAutoInstall = 0. Prevents Windows from auto-installing Teams Personal during OOBE or after Cumulative Updates.
    zakaz-cloud-optimized-content: ContentDeliveryManager\DisableCloudOptimizedContent = 1. Stops Windows from pushing sponsored app suggestions, tips from Microsoft servers, and "Get even more from Windows" prompts.
    zakaz-widgets-news-and-interests: HKLM\SOFTWARE\Policies\Microsoft\Dsh\AllowNewsAndInterests = 0. Disables the Widgets taskbar button and panel (news feed, weather, stocks). Not relevant for business deployments.
    hesla-bez-expirace-net-accounts-maxpwage: net accounts /maxpwage:UNLIMITED. Sets the local password expiration policy to never. MSP-managed machines handle password rotation via other means (Atera, domain policy, manual).
    casova-zona-central-europe-standard-time: Set-TimeZone -Id "Central Europe Standard Time". UTC+1 (UTC+2 in summer DST). Applied system-wide. Critical for correct log timestamps, scheduled task timing, and calendar sync.
    zakaz-gamedvr: HKLM\SOFTWARE\Policies\Microsoft\Windows\GameDVR\AppCaptureEnabled = 0. Disables Xbox Game Bar screen capture overlay. Reduces background resource usage and eliminates unintended capture prompts on business machines.
    edge-skryt-first-run-experience: HKLM\SOFTWARE\Policies\Microsoft\Edge\HideFirstRunExperience = 1. Suppresses the Edge welcome wizard (import from other browser, default browser prompt, etc.) for every user on first launch.
    onedrive-uninstall-intentional: Uninstalls the pre-installed OneDrive consumer version via OneDriveSetup.exe /uninstall and removes Start Menu shortcut. Intentional for clean MSP deployment baseline. No DisableFileSyncNGSC policy key is set - M365 installation can reinstall and run OneDrive normally. Only the stock consumer pre-install is removed.
    edge-policies-doplnit-15-dalsich-klicu: Missing Edge policies to add under HKLM\SOFTWARE\Policies\Microsoft\Edge: DefaultBrowserSettingEnabled=0, NewTabPageContentEnabled=0, ImportOnEachLaunch=0, ShowRecommendationsEnabled=0, PersonalizationReportingEnabled=0, SpotlightExperiencesAndRecommendationsEnabled=0, EdgeShoppingAssistantEnabled=0, HubsSidebarEnabled=0, ShowMicrosoftRewards=0, SearchSuggestEnabled=0, DiagnosticData=0.
    powercfg-nastaveni-spotreba-energie: powercfg /change commands: standby-timeout-ac 0 (never sleep on AC/charger), monitor-timeout-ac 60 (screen off after 60 min on AC), standby-timeout-dc 30 (sleep after 30 min on battery), monitor-timeout-dc 15 (screen off after 15 min on battery).
    proxy-auto-detect-zakaz-autodetect-0: HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\AutoDetect = 0. Disables WPAD (Web Proxy Auto-Discovery). Eliminates startup delays from WPAD DNS lookup and prevents potential MITM via malicious WPAD responses on untrusted networks.
#>


The file /opt/xetup/scripts/03-system-registry.ps1 has been updated successfully.

.DESCRIPTION
    Sets machine-wide registry tweaks under HKLM that apply to all users. Disables
    unwanted telemetry and cloud features, configures Edge policies, sets power plan
    timeouts, and disables proxy auto-detect. CRITICAL: The OneDrive removal lines
    that were previously in this script MUST be deleted - OneDrive must remain for M365.

.ITEMS
    bypass-nro-oobe-bypassnro-1: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE\BypassNRO = 1. Bypasses the "Let's connect you to a network" OOBE screen. Enables offline Windows setup without forcing a Microsoft account login.
    zakaz-auto-instalace-teams: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Communications\ConfigureChatAutoInstall = 0. Prevents Windows from auto-installing Teams Personal during OOBE or after Cumulative Updates.
    zakaz-cloud-optimized-content: ContentDeliveryManager\DisableCloudOptimizedContent = 1. Stops Windows from pushing sponsored app suggestions, tips from Microsoft servers, and "Get even more from Windows" prompts.
    zakaz-widgets-news-and-interests: HKLM\SOFTWARE\Policies\Microsoft\Dsh\AllowNewsAndInterests = 0. Disables the Widgets taskbar button and panel (news feed, weather, stocks). Not relevant for business deployments.
    hesla-bez-expirace-net-accounts-maxpwage: net accounts /maxpwage:UNLIMITED. Sets the local password expiration policy to never. MSP-managed machines handle password rotation via other means (Atera, domain policy, manual).
    casova-zona-central-europe-standard-time: Set-TimeZone -Id "Central Europe Standard Time". UTC+1 (UTC+2 in summer DST). Applied system-wide. Critical for correct log timestamps, scheduled task timing, and calendar sync.
    zakaz-gamedvr: HKLM\SOFTWARE\Policies\Microsoft\Windows\GameDVR\AppCaptureEnabled = 0. Disables Xbox Game Bar screen capture overlay. Reduces background resource usage and eliminates unintended capture prompts on business machines.
    edge-skryt-first-run-experience: HKLM\SOFTWARE\Policies\Microsoft\Edge\HideFirstRunExperience = 1. Suppresses the Edge welcome wizard (import from other browser, default browser prompt, etc.) for every user on first launch.
    onedrive-odstraneni-je-tady-smazat: MUST BE REMOVED FROM SCRIPT. Deleting OneDriveSetup.exe and the Start Menu shortcut was added incorrectly. OneDrive must remain installable for Microsoft 365 / SharePoint use. Remove these lines entirely.
    edge-policies-doplnit-15-dalsich-klicu: Missing Edge policies to add under HKLM\SOFTWARE\Policies\Microsoft\Edge: DefaultBrowserSettingEnabled=0, NewTabPageContentEnabled=0, ImportOnEachLaunch=0, ShowRecommendationsEnabled=0, PersonalizationReportingEnabled=0, SpotlightExperiencesAndRecommendationsEnabled=0, EdgeShoppingAssistantEnabled=0, HubsSidebarEnabled=0, ShowMicrosoftRewards=0, SearchSuggestEnabled=0, DiagnosticData=0.
    powercfg-nastaveni-spotreba-energie: powercfg /change commands: standby-timeout-ac 0 (never sleep on AC/charger), monitor-timeout-ac 60 (screen off after 60 min on AC), standby-timeout-dc 30 (sleep after 30 min on battery), monitor-timeout-dc 15 (screen off after 15 min on battery).
    proxy-auto-detect-zakaz-autodetect-0: HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\AutoDetect = 0. Disables WPAD (Web Proxy Auto-Discovery). Eliminates startup delays from WPAD DNS lookup and prevents potential MITM via malicious WPAD responses on untrusted networks.
#>

.DESCRIPTION
    Sets machine-wide registry tweaks under HKLM that apply to all users. Disables
    unwanted telemetry and cloud features, configures Edge policies, sets power plan
    timeouts, and disables proxy auto-detect. Uninstalls the pre-installed OneDrive
    consumer version via OneDriveSetup.exe /uninstall - intentional for a clean MSP
    deployment baseline. No DisableFileSyncNGSC policy key is set, so M365 installation
    can install and run its own OneDrive version without restriction.

.ITEMS
    bypass-nro-oobe-bypassnro-1: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\OOBE\BypassNRO = 1. Bypasses the "Let's connect you to a network" OOBE screen. Enables offline Windows setup without forcing a Microsoft account login.
    zakaz-auto-instalace-teams: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Communications\ConfigureChatAutoInstall = 0. Prevents Windows from auto-installing Teams Personal during OOBE or after Cumulative Updates.
    zakaz-cloud-optimized-content: ContentDeliveryManager\DisableCloudOptimizedContent = 1. Stops Windows from pushing sponsored app suggestions, tips from Microsoft servers, and "Get even more from Windows" prompts.
    zakaz-widgets-news-and-interests: HKLM\SOFTWARE\Policies\Microsoft\Dsh\AllowNewsAndInterests = 0. Disables the Widgets taskbar button and panel (news feed, weather, stocks). Not relevant for business deployments.
    hesla-bez-expirace-net-accounts-maxpwage: net accounts /maxpwage:UNLIMITED. Sets the local password expiration policy to never. MSP-managed machines handle password rotation via other means (Atera, domain policy, manual).
    casova-zona-central-europe-standard-time: Set-TimeZone -Id "Central Europe Standard Time". UTC+1 (UTC+2 in summer DST). Applied system-wide. Critical for correct log timestamps, scheduled task timing, and calendar sync.
    zakaz-gamedvr: HKLM\SOFTWARE\Policies\Microsoft\Windows\GameDVR\AppCaptureEnabled = 0. Disables Xbox Game Bar screen capture overlay. Reduces background resource usage and eliminates unintended capture prompts on business machines.
    edge-skryt-first-run-experience: HKLM\SOFTWARE\Policies\Microsoft\Edge\HideFirstRunExperience = 1. Suppresses the Edge welcome wizard (import from other browser, default browser prompt, etc.) for every user on first launch.
    onedrive-uninstall-intentional: Uninstalls the pre-installed OneDrive consumer version via OneDriveSetup.exe /uninstall and removes Start Menu shortcut. Intentional for clean MSP deployment baseline. No DisableFileSyncNGSC policy key is set - M365 installation can reinstall and run OneDrive normally. Only the stock consumer pre-install is removed.
    edge-policies-doplnit-15-dalsich-klicu: Missing Edge policies to add under HKLM\SOFTWARE\Policies\Microsoft\Edge: DefaultBrowserSettingEnabled=0, NewTabPageContentEnabled=0, ImportOnEachLaunch=0, ShowRecommendationsEnabled=0, PersonalizationReportingEnabled=0, SpotlightExperiencesAndRecommendationsEnabled=0, EdgeShoppingAssistantEnabled=0, HubsSidebarEnabled=0, ShowMicrosoftRewards=0, SearchSuggestEnabled=0, DiagnosticData=0.
    powercfg-nastaveni-spotreba-energie: powercfg /change commands: standby-timeout-ac 0 (never sleep on AC/charger), monitor-timeout-ac 60 (screen off after 60 min on AC), standby-timeout-dc 30 (sleep after 30 min on battery), monitor-timeout-dc 15 (screen off after 15 min on battery).
    proxy-auto-detect-zakaz-autodetect-0: HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\AutoDetect = 0. Disables WPAD (Web Proxy Auto-Discovery). Eliminates startup delays from WPAD DNS lookup and prevents potential MITM via malicious WPAD responses on untrusted networks.
#>

-    timeouts, and disables proxy auto-detect. CRITICAL: The OneDrive removal lines

-    that were previously in this script MUST be deleted - OneDrive must remain for M365.

+    timeouts, and disables proxy auto-detect. Uninstalls the pre-installed OneDrive

+    consumer version via OneDriveSetup.exe /uninstall - intentional for a clean MSP

+    deployment baseline. No DisableFileSyncNGSC policy key is set, so M365 installation

+    can install and run its own OneDrive version without restriction.

-    onedrive-odstraneni-je-tady-smazat: MUST BE REMOVED FROM SCRIPT. Deleting OneDriveSetup.exe and the Start Menu shortcut was added incorrectly. OneDrive must remain installable for Microsoft 365 / SharePoint use. Remove these lines entirely.

+    onedrive-uninstall-intentional: Uninstalls the pre-installed OneDrive consumer version via OneDriveSetup.exe /uninstall and removes Start Menu shortcut. Intentional for clean MSP deployment baseline. No DisableFileSyncNGSC policy key is set - M365 installation can reinstall and run OneDrive normally. Only the stock consumer pre-install is removed.


## 3. `08-activation.ps1` — přidat OA3/BIOS check


.ITEMS
    klic-z-config-json-activation-productkey: Reads activation.productKey from config.json. Installs via slmgr.vbs /ipk <key> and activates via slmgr.vbs /ato. Supports MAK (Multiple Activation Key) for volume licensing without KMS, and retail keys.
    fallback-na-gvlk-kms-client-key-dle-edic: When no key is in config, detects Windows edition via (Get-WmiObject SoftwareLicensingProduct).Name and maps to Microsoft's published GVLK table. Pro: W269N-WFGWX-YVC9B-4J6C9-T83GX, Enterprise: NPPR9-FWDCX-D2C8J-H872K-2YT43, Home: TX9XD-98N7V-6WMQ6-BX7FG-H8Q99.
    volitelny-kms-server-activation-kmsserve: If activation.kmsServer is in config.json, runs slmgr.vbs /skms <server>:<port> before /ato. Used for clients with on-premises KMS infrastructure (common in larger organizations with volume licensing).
    preskocit-pokud-jiz-aktivovano: Queries Win32_WindowsLicenseStatus or SoftwareLicensingProduct to check LicenseStatus. Value 1 = Licensed (fully activated). Script skips activation attempt and logs "Windows already activated" to avoid unnecessary slmgr calls.
    typ-klice-mak-vs-kms-vs-retail: Key type selection depends on client's Microsoft licensing: MAK = volume license key activates online against Microsoft (limited activations), KMS = requires KMS server on network (VLSC subscription), Retail = individual license from Microsoft Store or OEM.
#>

.ITEMS
    oa3-bios-uefi-klic-kontrola-embedded-ke: Checks for OA3 embedded product key in BIOS/UEFI firmware via SoftwareLicensingService.OA3xOriginalProductKey WMI query. If a key is found, it is installed via slmgr /ipk and activation is attempted. Most OEM machines (since Win8 OA3) have a digital entitlement key in firmware - this path handles them without requiring a key in config.json.
    klic-z-config-json-activation-productkey: Reads activation.productKey from config.json. Installs via slmgr.vbs /ipk <key> and activates via slmgr.vbs /ato. Supports MAK (Multiple Activation Key) for volume licensing without KMS, and retail keys. Takes priority over GVLK fallback.
    fallback-na-gvlk-kms-client-key-dle-edic: When no key is in config, detects Windows edition via (Get-WmiObject SoftwareLicensingProduct).Name and maps to Microsoft's published GVLK table. Pro: W269N-WFGWX-YVC9B-4J6C9-T83GX, Enterprise: NPPR9-FWDCX-D2C8J-H872K-2YT43, Home: TX9XD-98N7V-6WMQ6-BX7FG-H8Q99.
    volitelny-kms-server-activation-kmsserve: If activation.kmsServer is in config.json, runs slmgr.vbs /skms <server>:<port> before /ato. Used for clients with on-premises KMS infrastructure (common in larger organizations with volume licensing).
    preskocit-pokud-jiz-aktivovano: Queries Win32_WindowsLicenseStatus or SoftwareLicensingProduct to check LicenseStatus. Value 1 = Licensed (fully activated). Script skips activation attempt and logs "Windows already activated" to avoid unnecessary slmgr calls.
    typ-klice-mak-vs-kms-vs-retail: Key type selection depends on client's Microsoft licensing: MAK = volume license key activates online against Microsoft (limited activations), KMS = requires KMS server on network (VLSC subscription), Retail = individual license from Microsoft Store or OEM.
#>