lightman-agent 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent.config.template.json +30 -30
- package/package.json +52 -52
- package/public/assets/index-CcBNCz6h.css +1 -1
- package/public/assets/index-D9QHMG8k.js +1 -0
- package/public/assets/index-H-8HDl46.js +1 -1
- package/public/assets/index-YodeiCia.css +1 -0
- package/public/assets/index-legacy-DWtNM8y7.js +41 -0
- package/public/assets/museum-map-CwVDA2z1.svg +4182 -0
- package/public/assets/polyfills-legacy-DyVYWHbW.js +4 -0
- package/public/index.html +7 -2
- package/public/templates/custom08/elements/back-button.svg +20 -0
- package/public/templates/custom08/elements/base-map-background.svg +37 -0
- package/public/templates/custom08/elements/base-map.svg +1191 -0
- package/public/templates/custom08/elements/gallery-1-2-3-info-panel.svg +236 -0
- package/public/templates/custom08/elements/gallery-4-5-6-7-info-panel.svg +266 -0
- package/public/templates/custom08/elements/gallery-8-9-info-panel.svg +274 -0
- package/public/templates/custom08/elements/gallery-labels/_nav-map-styles.css +554 -0
- package/public/templates/custom08/elements/gallery-labels/_styles.css +556 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-1.svg +35 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-2.svg +34 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-3.svg +34 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-4.svg +37 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-5.svg +34 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-6.svg +34 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-7.svg +34 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-8.svg +37 -0
- package/public/templates/custom08/elements/gallery-labels/gallery-9.svg +34 -0
- package/public/templates/custom08/elements/hand-hint.png +0 -0
- package/public/templates/custom08/elements/idle-screen-bg.svg +5 -0
- package/public/templates/custom08/elements/idle-screen-map.svg +627 -0
- package/public/templates/custom08/elements/idle-screen-text.svg +350 -0
- package/public/templates/custom08/elements/key-map-1.svg +986 -0
- package/public/templates/custom08/elements/key-map-2.svg +1018 -0
- package/public/templates/custom08/elements/key-map-3.svg +1019 -0
- package/public/templates/custom08/elements/key-map-combined.svg +1001 -0
- package/public/templates/custom08/elements/map-highlight-marker.svg +11 -0
- package/public/templates/custom08/elements/map-pin-marker.svg +15 -0
- package/public/templates/custom08/elements/map-teardrop-star-marker.svg +13 -0
- package/public/templates/custom08/elements/nav-circle-galleries-1-3.svg +21 -0
- package/public/templates/custom08/elements/nav-circle-galleries-4-7.svg +24 -0
- package/public/templates/custom08/elements/nav-circle-galleries-8-9.svg +20 -0
- package/public/templates/custom08/elements/section1-map.svg +1435 -0
- package/public/templates/custom08/elements/section2-map.svg +1724 -0
- package/public/templates/custom08/elements/section3-map.svg +1295 -0
- package/public/templates/custom08/fonts/CabinetGrotesk-Variable.ttf +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-05_at_7.23.12_PM.png +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-05_at_7.23.56_PM.png +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-05_at_7.24.24_PM.png +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.31.58_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.32.11_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.32.36_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.32.48_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.32.59_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.15_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.27_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.34_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.42_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.50_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.33.58_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.34.04_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.34.11_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.34.20_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.34.57_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.35.03_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.35.16_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/Screenshot_2026-03-24_at_11.35.23_PM.jpg +0 -0
- package/public/templates/custom08/images/highlights/prologue-highlight.png +0 -0
- package/scripts/guardian.ps1 +75 -75
- package/scripts/install-linux.sh +134 -134
- package/scripts/install-rpi.sh +117 -117
- package/scripts/install-windows.ps1 +505 -505
- package/scripts/launch-kiosk.vbs +101 -101
- package/scripts/lightman-agent.logrotate +12 -12
- package/scripts/lightman-agent.service +38 -38
- package/scripts/lightman-shell.bat +107 -107
- package/scripts/reinstall-windows.ps1 +26 -26
- package/scripts/restore-desktop.ps1 +32 -32
- package/scripts/setup.ps1 +116 -116
- package/scripts/setup.sh +115 -115
- package/scripts/sync-display.mjs +20 -0
- package/scripts/uninstall-linux.sh +50 -50
- package/scripts/uninstall-windows.ps1 +54 -54
- package/src/commands/display.ts +177 -177
- package/src/commands/kiosk.ts +113 -113
- package/src/commands/maintenance.ts +106 -106
- package/src/commands/network.ts +129 -129
- package/src/commands/power.ts +163 -163
- package/src/commands/rpi.ts +45 -45
- package/src/commands/screenshot.ts +166 -166
- package/src/commands/serial.ts +17 -17
- package/src/commands/update.ts +124 -124
- package/src/index.ts +652 -652
- package/src/lib/config.ts +69 -69
- package/src/lib/identity.ts +40 -40
- package/src/lib/logger.ts +137 -137
- package/src/lib/platform.ts +10 -10
- package/src/lib/rpi.ts +180 -180
- package/src/lib/screens.ts +128 -128
- package/src/lib/types.ts +176 -176
- package/src/services/commands.ts +107 -107
- package/src/services/health.ts +161 -161
- package/src/services/kiosk.ts +384 -384
- package/src/services/localEvents.ts +60 -60
- package/src/services/logForwarder.ts +72 -72
- package/src/services/multiScreenKiosk.ts +324 -324
- package/src/services/oscBridge.ts +186 -186
- package/src/services/powerScheduler.ts +260 -260
- package/src/services/provisioning.ts +120 -120
- package/src/services/serialBridge.ts +230 -230
- package/src/services/serviceLauncher.ts +183 -183
- package/src/services/staticServer.ts +226 -226
- package/src/services/updater.ts +249 -249
- package/src/services/watchdog.ts +310 -310
- package/src/services/websocket.ts +152 -152
- package/tsconfig.json +28 -28
package/scripts/launch-kiosk.vbs
CHANGED
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
' LIGHTMAN Kiosk Launcher
|
|
2
|
-
' Runs at user logon AND at system startup to start the kiosk browser.
|
|
3
|
-
' Waits for the agent service to be ready before launching Chrome.
|
|
4
|
-
' If the agent is already managing Chrome, this script exits gracefully.
|
|
5
|
-
|
|
6
|
-
Set objShell = CreateObject("WScript.Shell")
|
|
7
|
-
Set objFSO = CreateObject("Scripting.FileSystemObject")
|
|
8
|
-
|
|
9
|
-
' --- Configuration ---
|
|
10
|
-
configPath = "C:\Program Files\Lightman\Agent\agent.config.json"
|
|
11
|
-
maxWaitSeconds = 120 ' Max time to wait for agent service
|
|
12
|
-
checkIntervalMs = 5000 ' Check every 5 seconds
|
|
13
|
-
|
|
14
|
-
' --- Wait for config file to exist (agent might still be installing) ---
|
|
15
|
-
If Not objFSO.FileExists(configPath) Then
|
|
16
|
-
WScript.Sleep 10000
|
|
17
|
-
If Not objFSO.FileExists(configPath) Then
|
|
18
|
-
WScript.Quit 1
|
|
19
|
-
End If
|
|
20
|
-
End If
|
|
21
|
-
|
|
22
|
-
' --- Read config ---
|
|
23
|
-
Set objFile = objFSO.OpenTextFile(configPath, 1)
|
|
24
|
-
jsonText = objFile.ReadAll
|
|
25
|
-
objFile.Close
|
|
26
|
-
|
|
27
|
-
browserPath = ExtractJsonValue(jsonText, "browserPath")
|
|
28
|
-
defaultUrl = ExtractJsonValue(jsonText, "defaultUrl")
|
|
29
|
-
|
|
30
|
-
If browserPath = "" Or defaultUrl = "" Then
|
|
31
|
-
WScript.Quit 1
|
|
32
|
-
End If
|
|
33
|
-
|
|
34
|
-
' --- Wait for network connectivity ---
|
|
35
|
-
' Try to ping the server (extract hostname from URL)
|
|
36
|
-
waitedMs = 0
|
|
37
|
-
Do While waitedMs < (maxWaitSeconds * 1000)
|
|
38
|
-
' Check if Chrome is already running (agent's KioskManager may have launched it)
|
|
39
|
-
Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
|
|
40
|
-
Set colProcesses = objWMI.ExecQuery("SELECT ProcessId FROM Win32_Process WHERE Name = 'chrome.exe'")
|
|
41
|
-
If colProcesses.Count > 0 Then
|
|
42
|
-
' Chrome already running - agent is handling it. Exit gracefully.
|
|
43
|
-
WScript.Quit 0
|
|
44
|
-
End If
|
|
45
|
-
|
|
46
|
-
' Check if LIGHTMAN service is running
|
|
47
|
-
Set colServices = objWMI.ExecQuery("SELECT State FROM Win32_Service WHERE DisplayName LIKE 'LIGHTMAN%'")
|
|
48
|
-
serviceRunning = False
|
|
49
|
-
For Each svc In colServices
|
|
50
|
-
If LCase(svc.State) = "running" Then
|
|
51
|
-
serviceRunning = True
|
|
52
|
-
End If
|
|
53
|
-
Next
|
|
54
|
-
|
|
55
|
-
If serviceRunning Then
|
|
56
|
-
' Service is running - give it a few more seconds to launch Chrome itself
|
|
57
|
-
WScript.Sleep 15000
|
|
58
|
-
|
|
59
|
-
' Re-check if Chrome appeared (agent launched it)
|
|
60
|
-
Set colProcesses2 = objWMI.ExecQuery("SELECT ProcessId FROM Win32_Process WHERE Name = 'chrome.exe'")
|
|
61
|
-
If colProcesses2.Count > 0 Then
|
|
62
|
-
' Agent launched Chrome successfully. Exit.
|
|
63
|
-
WScript.Quit 0
|
|
64
|
-
End If
|
|
65
|
-
|
|
66
|
-
' Agent is running but hasn't launched Chrome yet - we'll do it
|
|
67
|
-
Exit Do
|
|
68
|
-
End If
|
|
69
|
-
|
|
70
|
-
WScript.Sleep checkIntervalMs
|
|
71
|
-
waitedMs = waitedMs + checkIntervalMs
|
|
72
|
-
Loop
|
|
73
|
-
|
|
74
|
-
' --- Build Chrome kiosk args ---
|
|
75
|
-
chromeArgs = "--kiosk --noerrdialogs --disable-infobars --disable-session-crashed-bubble --no-first-run --no-default-browser-check --start-fullscreen --disable-translate --disable-extensions --autoplay-policy=no-user-gesture-required"
|
|
76
|
-
|
|
77
|
-
userDataDir = ExtractJsonValue(jsonText, "user-data-dir")
|
|
78
|
-
If userDataDir = "" Then
|
|
79
|
-
userDataDir = "C:\ProgramData\Lightman\chrome-kiosk"
|
|
80
|
-
End If
|
|
81
|
-
chromeArgs = chromeArgs & " --user-data-dir=""" & userDataDir & """"
|
|
82
|
-
|
|
83
|
-
' --- Launch Chrome ---
|
|
84
|
-
objShell.Run """" & browserPath & """ " & chromeArgs & " """ & defaultUrl & """", 1, False
|
|
85
|
-
|
|
86
|
-
' ========================================================
|
|
87
|
-
' Helper: extract a string value from JSON by key
|
|
88
|
-
' ========================================================
|
|
89
|
-
Function ExtractJsonValue(json, key)
|
|
90
|
-
ExtractJsonValue = ""
|
|
91
|
-
pos = InStr(json, """" & key & """")
|
|
92
|
-
If pos = 0 Then Exit Function
|
|
93
|
-
pos = InStr(pos, json, ":")
|
|
94
|
-
If pos = 0 Then Exit Function
|
|
95
|
-
pos = InStr(pos, json, """")
|
|
96
|
-
If pos = 0 Then Exit Function
|
|
97
|
-
pos = pos + 1
|
|
98
|
-
endPos = InStr(pos, json, """")
|
|
99
|
-
If endPos = 0 Then Exit Function
|
|
100
|
-
ExtractJsonValue = Mid(json, pos, endPos - pos)
|
|
101
|
-
End Function
|
|
1
|
+
' LIGHTMAN Kiosk Launcher
|
|
2
|
+
' Runs at user logon AND at system startup to start the kiosk browser.
|
|
3
|
+
' Waits for the agent service to be ready before launching Chrome.
|
|
4
|
+
' If the agent is already managing Chrome, this script exits gracefully.
|
|
5
|
+
|
|
6
|
+
Set objShell = CreateObject("WScript.Shell")
|
|
7
|
+
Set objFSO = CreateObject("Scripting.FileSystemObject")
|
|
8
|
+
|
|
9
|
+
' --- Configuration ---
|
|
10
|
+
configPath = "C:\Program Files\Lightman\Agent\agent.config.json"
|
|
11
|
+
maxWaitSeconds = 120 ' Max time to wait for agent service
|
|
12
|
+
checkIntervalMs = 5000 ' Check every 5 seconds
|
|
13
|
+
|
|
14
|
+
' --- Wait for config file to exist (agent might still be installing) ---
|
|
15
|
+
If Not objFSO.FileExists(configPath) Then
|
|
16
|
+
WScript.Sleep 10000
|
|
17
|
+
If Not objFSO.FileExists(configPath) Then
|
|
18
|
+
WScript.Quit 1
|
|
19
|
+
End If
|
|
20
|
+
End If
|
|
21
|
+
|
|
22
|
+
' --- Read config ---
|
|
23
|
+
Set objFile = objFSO.OpenTextFile(configPath, 1)
|
|
24
|
+
jsonText = objFile.ReadAll
|
|
25
|
+
objFile.Close
|
|
26
|
+
|
|
27
|
+
browserPath = ExtractJsonValue(jsonText, "browserPath")
|
|
28
|
+
defaultUrl = ExtractJsonValue(jsonText, "defaultUrl")
|
|
29
|
+
|
|
30
|
+
If browserPath = "" Or defaultUrl = "" Then
|
|
31
|
+
WScript.Quit 1
|
|
32
|
+
End If
|
|
33
|
+
|
|
34
|
+
' --- Wait for network connectivity ---
|
|
35
|
+
' Try to ping the server (extract hostname from URL)
|
|
36
|
+
waitedMs = 0
|
|
37
|
+
Do While waitedMs < (maxWaitSeconds * 1000)
|
|
38
|
+
' Check if Chrome is already running (agent's KioskManager may have launched it)
|
|
39
|
+
Set objWMI = GetObject("winmgmts:\\.\root\cimv2")
|
|
40
|
+
Set colProcesses = objWMI.ExecQuery("SELECT ProcessId FROM Win32_Process WHERE Name = 'chrome.exe'")
|
|
41
|
+
If colProcesses.Count > 0 Then
|
|
42
|
+
' Chrome already running - agent is handling it. Exit gracefully.
|
|
43
|
+
WScript.Quit 0
|
|
44
|
+
End If
|
|
45
|
+
|
|
46
|
+
' Check if LIGHTMAN service is running
|
|
47
|
+
Set colServices = objWMI.ExecQuery("SELECT State FROM Win32_Service WHERE DisplayName LIKE 'LIGHTMAN%'")
|
|
48
|
+
serviceRunning = False
|
|
49
|
+
For Each svc In colServices
|
|
50
|
+
If LCase(svc.State) = "running" Then
|
|
51
|
+
serviceRunning = True
|
|
52
|
+
End If
|
|
53
|
+
Next
|
|
54
|
+
|
|
55
|
+
If serviceRunning Then
|
|
56
|
+
' Service is running - give it a few more seconds to launch Chrome itself
|
|
57
|
+
WScript.Sleep 15000
|
|
58
|
+
|
|
59
|
+
' Re-check if Chrome appeared (agent launched it)
|
|
60
|
+
Set colProcesses2 = objWMI.ExecQuery("SELECT ProcessId FROM Win32_Process WHERE Name = 'chrome.exe'")
|
|
61
|
+
If colProcesses2.Count > 0 Then
|
|
62
|
+
' Agent launched Chrome successfully. Exit.
|
|
63
|
+
WScript.Quit 0
|
|
64
|
+
End If
|
|
65
|
+
|
|
66
|
+
' Agent is running but hasn't launched Chrome yet - we'll do it
|
|
67
|
+
Exit Do
|
|
68
|
+
End If
|
|
69
|
+
|
|
70
|
+
WScript.Sleep checkIntervalMs
|
|
71
|
+
waitedMs = waitedMs + checkIntervalMs
|
|
72
|
+
Loop
|
|
73
|
+
|
|
74
|
+
' --- Build Chrome kiosk args ---
|
|
75
|
+
chromeArgs = "--kiosk --noerrdialogs --disable-infobars --disable-session-crashed-bubble --no-first-run --no-default-browser-check --start-fullscreen --disable-translate --disable-extensions --autoplay-policy=no-user-gesture-required"
|
|
76
|
+
|
|
77
|
+
userDataDir = ExtractJsonValue(jsonText, "user-data-dir")
|
|
78
|
+
If userDataDir = "" Then
|
|
79
|
+
userDataDir = "C:\ProgramData\Lightman\chrome-kiosk"
|
|
80
|
+
End If
|
|
81
|
+
chromeArgs = chromeArgs & " --user-data-dir=""" & userDataDir & """"
|
|
82
|
+
|
|
83
|
+
' --- Launch Chrome ---
|
|
84
|
+
objShell.Run """" & browserPath & """ " & chromeArgs & " """ & defaultUrl & """", 1, False
|
|
85
|
+
|
|
86
|
+
' ========================================================
|
|
87
|
+
' Helper: extract a string value from JSON by key
|
|
88
|
+
' ========================================================
|
|
89
|
+
Function ExtractJsonValue(json, key)
|
|
90
|
+
ExtractJsonValue = ""
|
|
91
|
+
pos = InStr(json, """" & key & """")
|
|
92
|
+
If pos = 0 Then Exit Function
|
|
93
|
+
pos = InStr(pos, json, ":")
|
|
94
|
+
If pos = 0 Then Exit Function
|
|
95
|
+
pos = InStr(pos, json, """")
|
|
96
|
+
If pos = 0 Then Exit Function
|
|
97
|
+
pos = pos + 1
|
|
98
|
+
endPos = InStr(pos, json, """")
|
|
99
|
+
If endPos = 0 Then Exit Function
|
|
100
|
+
ExtractJsonValue = Mid(json, pos, endPos - pos)
|
|
101
|
+
End Function
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
/var/log/lightman/*.log {
|
|
2
|
-
daily
|
|
3
|
-
rotate 7
|
|
4
|
-
compress
|
|
5
|
-
delaycompress
|
|
6
|
-
missingok
|
|
7
|
-
notifempty
|
|
8
|
-
create 0640 lightman lightman
|
|
9
|
-
postrotate
|
|
10
|
-
systemctl reload lightman-agent > /dev/null 2>&1 || true
|
|
11
|
-
endscript
|
|
12
|
-
}
|
|
1
|
+
/var/log/lightman/*.log {
|
|
2
|
+
daily
|
|
3
|
+
rotate 7
|
|
4
|
+
compress
|
|
5
|
+
delaycompress
|
|
6
|
+
missingok
|
|
7
|
+
notifempty
|
|
8
|
+
create 0640 lightman lightman
|
|
9
|
+
postrotate
|
|
10
|
+
systemctl reload lightman-agent > /dev/null 2>&1 || true
|
|
11
|
+
endscript
|
|
12
|
+
}
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
-
[Unit]
|
|
2
|
-
Description=LIGHTMAN Agent - Museum Display Management
|
|
3
|
-
Documentation=https://github.com/sagrkv/lightman-app01
|
|
4
|
-
After=network-online.target
|
|
5
|
-
Wants=network-online.target
|
|
6
|
-
|
|
7
|
-
[Service]
|
|
8
|
-
Type=simple
|
|
9
|
-
User=lightman
|
|
10
|
-
Group=lightman
|
|
11
|
-
WorkingDirectory=/opt/lightman/agent
|
|
12
|
-
ExecStart=/usr/bin/node dist/index.js
|
|
13
|
-
Restart=always
|
|
14
|
-
RestartSec=10
|
|
15
|
-
StartLimitIntervalSec=300
|
|
16
|
-
StartLimitBurst=5
|
|
17
|
-
|
|
18
|
-
# Environment
|
|
19
|
-
Environment=NODE_ENV=production
|
|
20
|
-
EnvironmentFile=-/opt/lightman/agent/.env
|
|
21
|
-
|
|
22
|
-
# Security hardening
|
|
23
|
-
ProtectSystem=strict
|
|
24
|
-
ReadWritePaths=/opt/lightman/agent /var/log/lightman /tmp
|
|
25
|
-
PrivateTmp=true
|
|
26
|
-
NoNewPrivileges=true
|
|
27
|
-
ProtectHome=true
|
|
28
|
-
ProtectKernelTunables=true
|
|
29
|
-
ProtectControlGroups=true
|
|
30
|
-
RestrictSUIDSGID=true
|
|
31
|
-
|
|
32
|
-
# Logging
|
|
33
|
-
StandardOutput=journal
|
|
34
|
-
StandardError=journal
|
|
35
|
-
SyslogIdentifier=lightman-agent
|
|
36
|
-
|
|
37
|
-
[Install]
|
|
38
|
-
WantedBy=multi-user.target
|
|
1
|
+
[Unit]
|
|
2
|
+
Description=LIGHTMAN Agent - Museum Display Management
|
|
3
|
+
Documentation=https://github.com/sagrkv/lightman-app01
|
|
4
|
+
After=network-online.target
|
|
5
|
+
Wants=network-online.target
|
|
6
|
+
|
|
7
|
+
[Service]
|
|
8
|
+
Type=simple
|
|
9
|
+
User=lightman
|
|
10
|
+
Group=lightman
|
|
11
|
+
WorkingDirectory=/opt/lightman/agent
|
|
12
|
+
ExecStart=/usr/bin/node dist/index.js
|
|
13
|
+
Restart=always
|
|
14
|
+
RestartSec=10
|
|
15
|
+
StartLimitIntervalSec=300
|
|
16
|
+
StartLimitBurst=5
|
|
17
|
+
|
|
18
|
+
# Environment
|
|
19
|
+
Environment=NODE_ENV=production
|
|
20
|
+
EnvironmentFile=-/opt/lightman/agent/.env
|
|
21
|
+
|
|
22
|
+
# Security hardening
|
|
23
|
+
ProtectSystem=strict
|
|
24
|
+
ReadWritePaths=/opt/lightman/agent /var/log/lightman /tmp
|
|
25
|
+
PrivateTmp=true
|
|
26
|
+
NoNewPrivileges=true
|
|
27
|
+
ProtectHome=true
|
|
28
|
+
ProtectKernelTunables=true
|
|
29
|
+
ProtectControlGroups=true
|
|
30
|
+
RestrictSUIDSGID=true
|
|
31
|
+
|
|
32
|
+
# Logging
|
|
33
|
+
StandardOutput=journal
|
|
34
|
+
StandardError=journal
|
|
35
|
+
SyslogIdentifier=lightman-agent
|
|
36
|
+
|
|
37
|
+
[Install]
|
|
38
|
+
WantedBy=multi-user.target
|
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
@echo off
|
|
2
|
-
REM ================================================================
|
|
3
|
-
REM LIGHTMAN Shell - Replaces explorer.exe as the Windows shell
|
|
4
|
-
REM ================================================================
|
|
5
|
-
REM SINGLE SOURCE OF TRUTH: agent.config.json
|
|
6
|
-
REM
|
|
7
|
-
REM Boot flow:
|
|
8
|
-
REM 1. Auto-login (no password)
|
|
9
|
-
REM 2. This script runs INSTEAD of explorer.exe
|
|
10
|
-
REM 3. Reads slug + browser from agent.config.json (THE ONLY SOURCE)
|
|
11
|
-
REM 4. Waits for agent service (port 3403)
|
|
12
|
-
REM 5. Launches Chrome fullscreen
|
|
13
|
-
REM 6. If Chrome crashes, relaunches in 3 seconds (infinite loop)
|
|
14
|
-
REM ================================================================
|
|
15
|
-
|
|
1
|
+
@echo off
|
|
2
|
+
REM ================================================================
|
|
3
|
+
REM LIGHTMAN Shell - Replaces explorer.exe as the Windows shell
|
|
4
|
+
REM ================================================================
|
|
5
|
+
REM SINGLE SOURCE OF TRUTH: agent.config.json
|
|
6
|
+
REM
|
|
7
|
+
REM Boot flow:
|
|
8
|
+
REM 1. Auto-login (no password)
|
|
9
|
+
REM 2. This script runs INSTEAD of explorer.exe
|
|
10
|
+
REM 3. Reads slug + browser from agent.config.json (THE ONLY SOURCE)
|
|
11
|
+
REM 4. Waits for agent service (port 3403)
|
|
12
|
+
REM 5. Launches Chrome fullscreen
|
|
13
|
+
REM 6. If Chrome crashes, relaunches in 3 seconds (infinite loop)
|
|
14
|
+
REM ================================================================
|
|
15
|
+
|
|
16
16
|
set INSTALL_DIR=C:\Program Files\Lightman\Agent
|
|
17
17
|
set CONFIG_FILE=%INSTALL_DIR%\agent.config.json
|
|
18
18
|
set URL_SIDECAR=C:\ProgramData\Lightman\kiosk-url.txt
|
|
19
19
|
set CHROME_DATA=C:\ProgramData\Lightman\chrome-kiosk
|
|
20
20
|
set LOG_FILE=C:\ProgramData\Lightman\logs\shell.log
|
|
21
|
-
|
|
22
|
-
REM Ensure directories exist
|
|
23
|
-
if not exist "C:\ProgramData\Lightman\logs" mkdir "C:\ProgramData\Lightman\logs"
|
|
24
|
-
if not exist "%CHROME_DATA%" mkdir "%CHROME_DATA%"
|
|
25
|
-
|
|
26
|
-
echo [%date% %time%] ===== LIGHTMAN Shell starting ===== >> "%LOG_FILE%"
|
|
27
|
-
|
|
28
|
-
REM ----------------------------------------------------------------
|
|
29
|
-
REM Read slug and browser from agent.config.json ONLY
|
|
30
|
-
REM No sidecar files, no hardcoded URLs, no confusion.
|
|
31
|
-
REM ----------------------------------------------------------------
|
|
32
|
-
set DEVICE_SLUG=
|
|
33
|
-
set BROWSER=
|
|
34
|
-
set URL=
|
|
35
|
-
|
|
36
|
-
REM Wait for node.exe to be available
|
|
37
|
-
set NODE_WAIT=0
|
|
38
|
-
:wait_for_node
|
|
39
|
-
where node >nul 2>&1
|
|
40
|
-
if %errorlevel%==0 goto node_ready
|
|
41
|
-
set /a NODE_WAIT+=1
|
|
42
|
-
if %NODE_WAIT% geq 30 (
|
|
43
|
-
echo [%date% %time%] ERROR: node.exe not found after 30s >> "%LOG_FILE%"
|
|
44
|
-
goto use_fallbacks
|
|
45
|
-
)
|
|
46
|
-
timeout /t 1 /nobreak >nul
|
|
47
|
-
goto wait_for_node
|
|
48
|
-
|
|
49
|
-
:node_ready
|
|
50
|
-
|
|
51
|
-
REM Read slug from config
|
|
52
|
-
if exist "%CONFIG_FILE%" (
|
|
53
|
-
for /f "delims=" %%a in ('node -e "try{console.log(JSON.parse(require('fs').readFileSync(String.raw`%CONFIG_FILE%`,'utf8')).deviceSlug)}catch(e){console.log('')}" 2^>nul') do set DEVICE_SLUG=%%a
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
REM Read browser from config
|
|
57
|
-
if exist "%CONFIG_FILE%" (
|
|
58
|
-
for /f "delims=" %%a in ('node -e "try{const c=JSON.parse(require('fs').readFileSync(String.raw`%CONFIG_FILE%`,'utf8'));console.log(c.kiosk&&c.kiosk.browserPath||'')}catch(e){console.log('')}" 2^>nul') do set BROWSER=%%a
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
:use_fallbacks
|
|
62
|
-
|
|
21
|
+
|
|
22
|
+
REM Ensure directories exist
|
|
23
|
+
if not exist "C:\ProgramData\Lightman\logs" mkdir "C:\ProgramData\Lightman\logs"
|
|
24
|
+
if not exist "%CHROME_DATA%" mkdir "%CHROME_DATA%"
|
|
25
|
+
|
|
26
|
+
echo [%date% %time%] ===== LIGHTMAN Shell starting ===== >> "%LOG_FILE%"
|
|
27
|
+
|
|
28
|
+
REM ----------------------------------------------------------------
|
|
29
|
+
REM Read slug and browser from agent.config.json ONLY
|
|
30
|
+
REM No sidecar files, no hardcoded URLs, no confusion.
|
|
31
|
+
REM ----------------------------------------------------------------
|
|
32
|
+
set DEVICE_SLUG=
|
|
33
|
+
set BROWSER=
|
|
34
|
+
set URL=
|
|
35
|
+
|
|
36
|
+
REM Wait for node.exe to be available
|
|
37
|
+
set NODE_WAIT=0
|
|
38
|
+
:wait_for_node
|
|
39
|
+
where node >nul 2>&1
|
|
40
|
+
if %errorlevel%==0 goto node_ready
|
|
41
|
+
set /a NODE_WAIT+=1
|
|
42
|
+
if %NODE_WAIT% geq 30 (
|
|
43
|
+
echo [%date% %time%] ERROR: node.exe not found after 30s >> "%LOG_FILE%"
|
|
44
|
+
goto use_fallbacks
|
|
45
|
+
)
|
|
46
|
+
timeout /t 1 /nobreak >nul
|
|
47
|
+
goto wait_for_node
|
|
48
|
+
|
|
49
|
+
:node_ready
|
|
50
|
+
|
|
51
|
+
REM Read slug from config
|
|
52
|
+
if exist "%CONFIG_FILE%" (
|
|
53
|
+
for /f "delims=" %%a in ('node -e "try{console.log(JSON.parse(require('fs').readFileSync(String.raw`%CONFIG_FILE%`,'utf8')).deviceSlug)}catch(e){console.log('')}" 2^>nul') do set DEVICE_SLUG=%%a
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
REM Read browser from config
|
|
57
|
+
if exist "%CONFIG_FILE%" (
|
|
58
|
+
for /f "delims=" %%a in ('node -e "try{const c=JSON.parse(require('fs').readFileSync(String.raw`%CONFIG_FILE%`,'utf8'));console.log(c.kiosk&&c.kiosk.browserPath||'')}catch(e){console.log('')}" 2^>nul') do set BROWSER=%%a
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
:use_fallbacks
|
|
62
|
+
|
|
63
63
|
REM Build URL from slug (ALWAYS from config, never from sidecar)
|
|
64
64
|
if not "%DEVICE_SLUG%"=="" (
|
|
65
65
|
set URL=http://localhost:3403/display/%DEVICE_SLUG%
|
|
@@ -77,47 +77,47 @@ if exist "%URL_SIDECAR%" (
|
|
|
77
77
|
echo [%date% %time%] Using sidecar URL >> "%LOG_FILE%"
|
|
78
78
|
)
|
|
79
79
|
)
|
|
80
|
-
|
|
81
|
-
REM Fallback browser
|
|
82
|
-
if "%BROWSER%"=="" (
|
|
83
|
-
if exist "C:\Program Files\Google\Chrome\Application\chrome.exe" (
|
|
84
|
-
set "BROWSER=C:\Program Files\Google\Chrome\Application\chrome.exe"
|
|
85
|
-
) else if exist "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" (
|
|
86
|
-
set "BROWSER=C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
|
|
87
|
-
) else (
|
|
88
|
-
echo [%date% %time%] ERROR: Chrome not found! >> "%LOG_FILE%"
|
|
89
|
-
start explorer.exe
|
|
90
|
-
exit /b 1
|
|
91
|
-
)
|
|
92
|
-
)
|
|
93
|
-
|
|
94
|
-
echo [%date% %time%] Browser: %BROWSER% >> "%LOG_FILE%"
|
|
95
|
-
echo [%date% %time%] URL: %URL% >> "%LOG_FILE%"
|
|
96
|
-
|
|
97
|
-
REM ----------------------------------------------------------------
|
|
98
|
-
REM Wait for agent service (port 3403)
|
|
99
|
-
REM ----------------------------------------------------------------
|
|
100
|
-
echo [%date% %time%] Waiting for port 3403... >> "%LOG_FILE%"
|
|
101
|
-
set WAIT_COUNT=0
|
|
102
|
-
set MAX_WAIT=60
|
|
103
|
-
|
|
104
|
-
:wait_for_agent
|
|
105
|
-
netstat -an | findstr ":3403.*LISTENING" >nul 2>&1
|
|
106
|
-
if %errorlevel%==0 goto agent_ready
|
|
107
|
-
set /a WAIT_COUNT+=1
|
|
108
|
-
if %WAIT_COUNT% geq %MAX_WAIT% (
|
|
109
|
-
echo [%date% %time%] Port 3403 not ready after %MAX_WAIT%s, launching anyway >> "%LOG_FILE%"
|
|
110
|
-
goto agent_ready
|
|
111
|
-
)
|
|
112
|
-
timeout /t 1 /nobreak >nul
|
|
113
|
-
goto wait_for_agent
|
|
114
|
-
|
|
115
|
-
:agent_ready
|
|
116
|
-
echo [%date% %time%] Agent ready >> "%LOG_FILE%"
|
|
117
|
-
|
|
118
|
-
REM ----------------------------------------------------------------
|
|
119
|
-
REM Infinite Chrome loop
|
|
120
|
-
REM ----------------------------------------------------------------
|
|
80
|
+
|
|
81
|
+
REM Fallback browser
|
|
82
|
+
if "%BROWSER%"=="" (
|
|
83
|
+
if exist "C:\Program Files\Google\Chrome\Application\chrome.exe" (
|
|
84
|
+
set "BROWSER=C:\Program Files\Google\Chrome\Application\chrome.exe"
|
|
85
|
+
) else if exist "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" (
|
|
86
|
+
set "BROWSER=C:\Program Files (x86)\Google\Chrome\Application\chrome.exe"
|
|
87
|
+
) else (
|
|
88
|
+
echo [%date% %time%] ERROR: Chrome not found! >> "%LOG_FILE%"
|
|
89
|
+
start explorer.exe
|
|
90
|
+
exit /b 1
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
echo [%date% %time%] Browser: %BROWSER% >> "%LOG_FILE%"
|
|
95
|
+
echo [%date% %time%] URL: %URL% >> "%LOG_FILE%"
|
|
96
|
+
|
|
97
|
+
REM ----------------------------------------------------------------
|
|
98
|
+
REM Wait for agent service (port 3403)
|
|
99
|
+
REM ----------------------------------------------------------------
|
|
100
|
+
echo [%date% %time%] Waiting for port 3403... >> "%LOG_FILE%"
|
|
101
|
+
set WAIT_COUNT=0
|
|
102
|
+
set MAX_WAIT=60
|
|
103
|
+
|
|
104
|
+
:wait_for_agent
|
|
105
|
+
netstat -an | findstr ":3403.*LISTENING" >nul 2>&1
|
|
106
|
+
if %errorlevel%==0 goto agent_ready
|
|
107
|
+
set /a WAIT_COUNT+=1
|
|
108
|
+
if %WAIT_COUNT% geq %MAX_WAIT% (
|
|
109
|
+
echo [%date% %time%] Port 3403 not ready after %MAX_WAIT%s, launching anyway >> "%LOG_FILE%"
|
|
110
|
+
goto agent_ready
|
|
111
|
+
)
|
|
112
|
+
timeout /t 1 /nobreak >nul
|
|
113
|
+
goto wait_for_agent
|
|
114
|
+
|
|
115
|
+
:agent_ready
|
|
116
|
+
echo [%date% %time%] Agent ready >> "%LOG_FILE%"
|
|
117
|
+
|
|
118
|
+
REM ----------------------------------------------------------------
|
|
119
|
+
REM Infinite Chrome loop
|
|
120
|
+
REM ----------------------------------------------------------------
|
|
121
121
|
:loop
|
|
122
122
|
REM Prefer sidecar URL for auth params/device routing; fallback to slug URL.
|
|
123
123
|
set SIDE_URL=
|
|
@@ -134,12 +134,12 @@ REM ----------------------------------------------------------------
|
|
|
134
134
|
)
|
|
135
135
|
)
|
|
136
136
|
)
|
|
137
|
-
|
|
138
|
-
echo [%date% %time%] Launching Chrome: %URL% >> "%LOG_FILE%"
|
|
139
|
-
|
|
140
|
-
start /wait "" "%BROWSER%" --kiosk --noerrdialogs --disable-infobars --disable-session-crashed-bubble --no-first-run --no-default-browser-check --start-fullscreen --disable-translate --disable-extensions --autoplay-policy=no-user-gesture-required --disable-features=TranslateUI --user-data-dir="%CHROME_DATA%" "%URL%"
|
|
141
|
-
|
|
142
|
-
echo [%date% %time%] Chrome exited (code: %errorlevel%). Restarting in 3s... >> "%LOG_FILE%"
|
|
143
|
-
timeout /t 3 /nobreak >nul
|
|
144
|
-
|
|
145
|
-
goto loop
|
|
137
|
+
|
|
138
|
+
echo [%date% %time%] Launching Chrome: %URL% >> "%LOG_FILE%"
|
|
139
|
+
|
|
140
|
+
start /wait "" "%BROWSER%" --kiosk --noerrdialogs --disable-infobars --disable-session-crashed-bubble --no-first-run --no-default-browser-check --start-fullscreen --disable-translate --disable-extensions --autoplay-policy=no-user-gesture-required --disable-features=TranslateUI --user-data-dir="%CHROME_DATA%" "%URL%"
|
|
141
|
+
|
|
142
|
+
echo [%date% %time%] Chrome exited (code: %errorlevel%). Restarting in 3s... >> "%LOG_FILE%"
|
|
143
|
+
timeout /t 3 /nobreak >nul
|
|
144
|
+
|
|
145
|
+
goto loop
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
#Requires -RunAsAdministrator
|
|
2
|
-
<#
|
|
3
|
-
.SYNOPSIS
|
|
4
|
-
LIGHTMAN Agent - Reinstall (install-windows.ps1 handles cleanup automatically)
|
|
5
|
-
.EXAMPLE
|
|
6
|
-
powershell -ExecutionPolicy Bypass -File scripts\reinstall-windows.ps1 -Slug "F-AV04" -Server "http://192.168.1.180:3401" -ShellReplace
|
|
7
|
-
#>
|
|
8
|
-
param(
|
|
9
|
-
[Parameter(Mandatory=$true)] [string]$Slug,
|
|
10
|
-
[Parameter(Mandatory=$true)] [string]$Server,
|
|
11
|
-
[switch]$ShellReplace = $false,
|
|
12
|
-
[string]$Timezone = "Asia/Kolkata",
|
|
13
|
-
[switch]$NoReboot = $false
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
17
|
-
|
|
18
|
-
$args = @("-ExecutionPolicy", "Bypass", "-File", "$ScriptDir\install-windows.ps1", "-Slug", $Slug, "-Server", $Server, "-Timezone", $Timezone)
|
|
19
|
-
if ($ShellReplace) { $args += "-ShellReplace" }
|
|
20
|
-
& powershell @args
|
|
21
|
-
|
|
22
|
-
if (-not $NoReboot) {
|
|
23
|
-
Write-Host " Rebooting in 10 seconds... (Ctrl+C to cancel)" -ForegroundColor Yellow
|
|
24
|
-
Start-Sleep -Seconds 10
|
|
25
|
-
Restart-Computer -Force
|
|
26
|
-
}
|
|
1
|
+
#Requires -RunAsAdministrator
|
|
2
|
+
<#
|
|
3
|
+
.SYNOPSIS
|
|
4
|
+
LIGHTMAN Agent - Reinstall (install-windows.ps1 handles cleanup automatically)
|
|
5
|
+
.EXAMPLE
|
|
6
|
+
powershell -ExecutionPolicy Bypass -File scripts\reinstall-windows.ps1 -Slug "F-AV04" -Server "http://192.168.1.180:3401" -ShellReplace
|
|
7
|
+
#>
|
|
8
|
+
param(
|
|
9
|
+
[Parameter(Mandatory=$true)] [string]$Slug,
|
|
10
|
+
[Parameter(Mandatory=$true)] [string]$Server,
|
|
11
|
+
[switch]$ShellReplace = $false,
|
|
12
|
+
[string]$Timezone = "Asia/Kolkata",
|
|
13
|
+
[switch]$NoReboot = $false
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
17
|
+
|
|
18
|
+
$args = @("-ExecutionPolicy", "Bypass", "-File", "$ScriptDir\install-windows.ps1", "-Slug", $Slug, "-Server", $Server, "-Timezone", $Timezone)
|
|
19
|
+
if ($ShellReplace) { $args += "-ShellReplace" }
|
|
20
|
+
& powershell @args
|
|
21
|
+
|
|
22
|
+
if (-not $NoReboot) {
|
|
23
|
+
Write-Host " Rebooting in 10 seconds... (Ctrl+C to cancel)" -ForegroundColor Yellow
|
|
24
|
+
Start-Sleep -Seconds 10
|
|
25
|
+
Restart-Computer -Force
|
|
26
|
+
}
|
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
# LIGHTMAN - Restore Windows Desktop
|
|
2
|
-
# Reverses shell replacement: sets explorer.exe back as the Windows shell.
|
|
3
|
-
# Run via RDP with admin account, or from Safe Mode:
|
|
4
|
-
# powershell -ExecutionPolicy Bypass -File restore-desktop.ps1
|
|
5
|
-
#Requires -RunAsAdministrator
|
|
6
|
-
|
|
7
|
-
$ErrorActionPreference = "Stop"
|
|
8
|
-
|
|
9
|
-
Write-Host ""
|
|
10
|
-
Write-Host "=== LIGHTMAN - Restore Windows Desktop ===" -ForegroundColor Cyan
|
|
11
|
-
Write-Host ""
|
|
12
|
-
|
|
13
|
-
# Restore HKLM shell
|
|
14
|
-
$HKLMPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
|
|
15
|
-
$original = (Get-ItemProperty -Path $HKLMPath -Name "Shell_Original" -ErrorAction SilentlyContinue).Shell_Original
|
|
16
|
-
if ($original) {
|
|
17
|
-
Set-ItemProperty -Path $HKLMPath -Name "Shell" -Value $original
|
|
18
|
-
Write-Host " HKLM shell restored to: $original" -ForegroundColor Green
|
|
19
|
-
} else {
|
|
20
|
-
Set-ItemProperty -Path $HKLMPath -Name "Shell" -Value "explorer.exe"
|
|
21
|
-
Write-Host " HKLM shell restored to: explorer.exe" -ForegroundColor Green
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
# Remove HKCU shell override
|
|
25
|
-
$HKCUPath = "HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon"
|
|
26
|
-
Remove-ItemProperty -Path $HKCUPath -Name "Shell" -ErrorAction SilentlyContinue
|
|
27
|
-
Write-Host " HKCU shell override removed" -ForegroundColor Green
|
|
28
|
-
|
|
29
|
-
Write-Host ""
|
|
30
|
-
Write-Host " Desktop will be restored on next reboot." -ForegroundColor Yellow
|
|
31
|
-
Write-Host " Run: Restart-Computer" -ForegroundColor Yellow
|
|
32
|
-
Write-Host ""
|
|
1
|
+
# LIGHTMAN - Restore Windows Desktop
|
|
2
|
+
# Reverses shell replacement: sets explorer.exe back as the Windows shell.
|
|
3
|
+
# Run via RDP with admin account, or from Safe Mode:
|
|
4
|
+
# powershell -ExecutionPolicy Bypass -File restore-desktop.ps1
|
|
5
|
+
#Requires -RunAsAdministrator
|
|
6
|
+
|
|
7
|
+
$ErrorActionPreference = "Stop"
|
|
8
|
+
|
|
9
|
+
Write-Host ""
|
|
10
|
+
Write-Host "=== LIGHTMAN - Restore Windows Desktop ===" -ForegroundColor Cyan
|
|
11
|
+
Write-Host ""
|
|
12
|
+
|
|
13
|
+
# Restore HKLM shell
|
|
14
|
+
$HKLMPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon"
|
|
15
|
+
$original = (Get-ItemProperty -Path $HKLMPath -Name "Shell_Original" -ErrorAction SilentlyContinue).Shell_Original
|
|
16
|
+
if ($original) {
|
|
17
|
+
Set-ItemProperty -Path $HKLMPath -Name "Shell" -Value $original
|
|
18
|
+
Write-Host " HKLM shell restored to: $original" -ForegroundColor Green
|
|
19
|
+
} else {
|
|
20
|
+
Set-ItemProperty -Path $HKLMPath -Name "Shell" -Value "explorer.exe"
|
|
21
|
+
Write-Host " HKLM shell restored to: explorer.exe" -ForegroundColor Green
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
# Remove HKCU shell override
|
|
25
|
+
$HKCUPath = "HKCU:\Software\Microsoft\Windows NT\CurrentVersion\Winlogon"
|
|
26
|
+
Remove-ItemProperty -Path $HKCUPath -Name "Shell" -ErrorAction SilentlyContinue
|
|
27
|
+
Write-Host " HKCU shell override removed" -ForegroundColor Green
|
|
28
|
+
|
|
29
|
+
Write-Host ""
|
|
30
|
+
Write-Host " Desktop will be restored on next reboot." -ForegroundColor Yellow
|
|
31
|
+
Write-Host " Run: Restart-Computer" -ForegroundColor Yellow
|
|
32
|
+
Write-Host ""
|