148 lines
4.5 KiB
PowerShell
148 lines
4.5 KiB
PowerShell
# Sample functional PowerShell script using data-driven checkbox definitions
|
|
# Single-file, dynamic UI & routing based on a single $Global:Tasks table
|
|
|
|
#region Config
|
|
$Port = 8081
|
|
#endregion
|
|
|
|
#region Task Definitions
|
|
# Each task: Id → checkbox HTML id
|
|
# Name → route name & JS handler path
|
|
# Label → displayed text
|
|
# HandlerFn → PowerShell function to invoke
|
|
|
|
$Global:Tasks = @(
|
|
@{ Id = 'setSVSPowerplan'; Name = 'setSVSPowerplan'; Label = 'Set SVS Powerplan'; HandlerFn = 'Set-SVSPowerPlan' },
|
|
@{ Id = 'installSVSMSPModule'; Name = 'installSVSMSPModule'; Label = 'Install SVSMSP Module'; HandlerFn = 'Install-SVSMSPModule' },
|
|
@{ Id = 'installCyberQP'; Name = 'installCyberQP'; Label = 'Install CyberQP'; HandlerFn = 'Install-CyberQP' }
|
|
# ...add more tasks here
|
|
)
|
|
#endregion
|
|
|
|
#region Handler Function Stubs
|
|
function Set-SVSPowerPlan {
|
|
param($Context)
|
|
Write-LogHybrid -Message "[Handler] PowerPlan set" -Level Success
|
|
if ($Context) { Respond-Text $Context "Powerplan applied" }
|
|
}
|
|
|
|
function Install-SVSMSPModule {
|
|
param($Context)
|
|
Write-LogHybrid -Message "[Handler] SVSMSP Module installed" -Level Success
|
|
if ($Context) { Respond-Text $Context "SVSMSP Module installed" }
|
|
}
|
|
|
|
function Install-CyberQP {
|
|
param($Context)
|
|
Write-LogHybrid -Message "[Handler] CyberQP installed" -Level Success
|
|
if ($Context) { Respond-Text $Context "CyberQP installed" }
|
|
}
|
|
|
|
# Utility for sending plain-text HTTP responses
|
|
function Respond-Text {
|
|
param($Context, $Text)
|
|
$buffer = [Text.Encoding]::UTF8.GetBytes($Text)
|
|
$Context.Response.ContentType = 'text/plain'
|
|
$Context.Response.ContentLength64 = $buffer.Length
|
|
$Context.Response.OutputStream.Write($buffer, 0, $buffer.Length)
|
|
$Context.Response.OutputStream.Close()
|
|
}
|
|
#endregion
|
|
|
|
#region UI Generation
|
|
function Get-UIHtml {
|
|
# Build checkbox HTML (wrap pipeline in parentheses so -join applies to result array)
|
|
$checkboxes = (
|
|
$Global:Tasks | ForEach-Object {
|
|
"<label><input type=`"checkbox`" id=`"$($_.Id)`" name=`"$($_.Name)`"> $($_.Label)</label>"
|
|
}
|
|
) -join "`n"
|
|
|
|
# Build JS tasks array
|
|
$tasksJs = (
|
|
$Global:Tasks | ForEach-Object {
|
|
"{ id: '$($_.Id)', handler: '/$($_.Name)' }"
|
|
}
|
|
) -join ",`n "
|
|
|
|
$html = @"
|
|
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head><meta charset="UTF-8"><title>Dynamic UI</title></head>
|
|
<body>
|
|
<h1>Task Launcher</h1>
|
|
<div class="checkbox-group">
|
|
$checkboxes
|
|
</div>
|
|
<button onclick="triggerInstall()">Run Selected</button>
|
|
<pre id="logArea"></pre>
|
|
<script>
|
|
const tasks = [
|
|
$tasksJs
|
|
];
|
|
async function triggerInstall() {
|
|
const log = document.getElementById('logArea');
|
|
log.textContent = '';
|
|
for (const t of tasks) {
|
|
const cb = document.getElementById(t.id);
|
|
if (cb.checked) {
|
|
log.textContent += `Calling ${t.id}...\n`;
|
|
try {
|
|
const resp = await fetch(t.handler, { method: 'GET' });
|
|
const txt = await resp.text();
|
|
log.textContent += txt + "\n";
|
|
} catch (e) {
|
|
log.textContent += `Error ${t.id}: ${e.message}\n`;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|
|
"@
|
|
return $html
|
|
}
|
|
#endregion
|
|
|
|
#region HTTP Server & Routing
|
|
function Dispatch-Request {
|
|
param($Context)
|
|
$path = $Context.Request.Url.AbsolutePath.TrimStart('/')
|
|
# Match route to a task
|
|
$task = $Global:Tasks | Where-Object Name -EQ $path
|
|
if ($task) {
|
|
& $task.HandlerFn $Context
|
|
return
|
|
}
|
|
# Serve UI
|
|
if ($path -eq '' -or $path -eq '/') {
|
|
$html = Get-UIHtml
|
|
$buffer = [Text.Encoding]::UTF8.GetBytes($html)
|
|
$Context.Response.ContentType = 'text/html'
|
|
$Context.Response.ContentLength64 = $buffer.Length
|
|
$Context.Response.OutputStream.Write($buffer, 0, $buffer.Length)
|
|
$Context.Response.OutputStream.Close()
|
|
return
|
|
}
|
|
# Not found
|
|
$Context.Response.StatusCode = 404
|
|
Respond-Text $Context '404 - Not Found'
|
|
}
|
|
|
|
function Start-Server {
|
|
$listener = New-Object System.Net.HttpListener
|
|
$listener.Prefixes.Add("http://localhost:$Port/")
|
|
$listener.Start()
|
|
Write-Host "Listening on http://localhost:$Port/"
|
|
while ($listener.IsListening) {
|
|
$ctx = $listener.GetContext()
|
|
try { Dispatch-Request $ctx } catch { Write-Host "Error:" $_ }
|
|
}
|
|
$listener.Stop()
|
|
}
|
|
#endregion
|
|
|
|
# Bootstrap
|
|
Start-Server
|