Node JSPowerShellWindows PowerShell

System Information Web App Using Node JS, PUG and PowerShell

It all started with a simple question “How to deliver reports to clients?” simple ASK and solution is further more simple. Yes, using NODE JS and PowerShell we can play with data! Since I can’t share client data and to keep this blog simple let me show a easiest way to retrieve system information as fancy HTML sorry PUG. In my upcoming blogs we will cover retrieving remote machines and bootstrapping  for now it’s only for local host 🙂 ! All PowerShell lovers! Hold On I am not using ConvertTo-HTML or any other custom modules!

Our goal is to attain the below illustrated GIF 🙂


If you are PowerShell addict I bet you might have enjoyed Don Jones ConvertTo-EnhancedHTML – Find a TechNet Wiki Post shared by me! Yes, somewhat similar I tried! Now, let us host as web app using PowerShell, Node JS and PUG (NOTE: We play with PUG!). A sample system information PowerShell scripts is shown below! Yes, you can add functionality as required!

SystemInformation.ps1

$DiskInformation = Get-CimInstance -ClassName Win32_Volume | 
    Select-Object DriveLetter, Label, SerialNumber, @{n = 'FreeSpace'; E = {"{0:N2}" -f ($_.FreeSpace / 1GB)}},
@{n = 'Capacity'; E = {"{0:N2}" -f ($_.Capacity / 1GB)}}
$ServicesInformation = Get-CimInstance -ClassName Win32_Service | Select-Object Name , State , ExitCode -First 5 
$ProcessInformation = Get-CimInstance -ClassName Win32_Process | Select-Object Name , WorkingSetSize , Handle -First 5
[pscustomobject]@{
    Disk               = $DiskInformation
    Service            = $ServicesInformation
    ProcessInformation = $ProcessInformation
} | ConvertTo-Json -Compress

We get output as illustrated below

{
    "Disk": [
        {
            "DriveLetter": "C:",
            "Label": "XyZ_OS",
            "SerialNumber": 3390096209,
            "FreeSpace": "269.02",
            "Capacity": "471.55"
        },
        {
            "DriveLetter": null,
            "Label": "Windows",
            "SerialNumber": 1491697679,
            "FreeSpace": "4.46",
            "Capacity": "4.77"
        }
    ],
    "Service": [
        {
            "Name": "AdobeARMservice",
            "State": "Stopped",
            "ExitCode": 1077
        },
        {
            "Name": "AdobeFlashPlayerUpdateSvc",
            "State": "Stopped",
            "ExitCode": 1077
        },
        {
            "Name": "AgentService",
            "State": "Running",
            "ExitCode": 0
        },
        {
            "Name": "AJRouter",
            "State": "Stopped",
            "ExitCode": 1077
        },
        {
            "Name": "ALG",
            "State": "Stopped",
            "ExitCode": 1077
        }
    ],
    "ProcessInformation": [
        {
            "Name": "System Idle Process",
            "WorkingSetSize": 4096,
            "Handle": "0"
        },
        {
            "Name": "System",
            "WorkingSetSize": 32768,
            "Handle": "4"
        },
        {
            "Name": "smss.exe",
            "WorkingSetSize": 212992,
            "Handle": "444"
        },
        {
            "Name": "csrss.exe",
            "WorkingSetSize": 1761280,
            "Handle": "648"
        },
        {
            "Name": "wininit.exe",
            "WorkingSetSize": 32768,
            "Handle": "756"
        }
    ]
}

We all know this and no big deal here! What makes bit excitement is in PUG file! All, we need to loop through JSON and present the data! Here is the logic!

        tbody
            tr
                th DriveLetter  
                th Label 
                th SerialNumber
                th FreeSpace
                th Capacity 
            each result in results.Disk
                tr
                    td=result.DriveLetter 
                    td=result.Label 
                    td=result.SerialNumber
                    td=result.FreeSpace
                    td=result.Capacity

Using each statement in pug we are retrieving the Disk information and likewise Service and Process data. Note here the properties are case sensitive! With no wait! Here is the full code!

Server.JS

var express = require('express'),
    app = express(),
    path = require('path'),
    bodyparser = require('body-parser'),
    pug = require('pug'),
    shell = require('node-powershell'),
    ps = new shell({
        executionPolicy: 'bypass',
        noProfile: true
    });
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.get('/', function (request, response) {
    response.render('index')
});

app.get('/about', function (request, response) {
    response.render('about')
})
// Get-SystemInformation
app.get('/GetSystemInformation', function (request, response) {
    ps.addCommand("./scripts/SystemInformation.ps1")
    ps.invoke().then(output => {
        var SystemInformation = JSON.parse(output)
        response.render('SystemInformation', {
            results: SystemInformation
        })
    })
})
app.listen(3000)
console.log('Your application is hosted!')

SystemInformation.pug

doctype html
head
    meta(name='viewport', content='width=device-width, initial-scale=1')
    style.
        .accordion {
        background-color: #eee;
        color: #333;
        cursor: pointer;
        padding: 18px;
        width: 100%;
        border: none;
        text-align: center;
        outline: none;
        font-size: 15px;
        transition: 0.4s;
        font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
        }
        .active,
        .accordion:hover {
        background-color: #ccc;
        }
        .panel {
        padding: 0 18px;
        display: none;
        background-color: white;
        overflow: hidden;
        font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
        }
        #services {
        font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;
        border-collapse: collapse;
        width: 100%;
        }
        #services td,
        #services th {
        border: 1px solid #ddd;
        padding: 8px;
        }
        #services tr:nth-child(even) {
        background-color: #f2f2f2;
        }
        #services tr:hover {
        background-color: #ddd;
        }
        #services th {
        padding-top: 12px;
        padding-bottom: 12px;
        text-align: left;
        background-color: #4CAF50;
        color: white;
        }
        h1 {
        text-align: center
        }
h1 System Information
button.accordion Volume Information
.panel
    table#services
        hr  
        tbody
            tr
                th DriveLetter  
                th Label 
                th SerialNumber
                th FreeSpace
                th Capacity 
            each result in results.Disk
                tr
                    td=result.DriveLetter 
                    td=result.Label 
                    td=result.SerialNumber
                    td=result.FreeSpace
                    td=result.Capacity 
    hr 
button.accordion Service Information
.panel
    table#services
        hr 
        tbody
            tr
                th Name   
                th ExitCode 
                th State  
            each result in results.Service 
                tr
                    td=result.Name  
                    td=result.State 
                    td=result.ExitCode 
button.accordion Process Information
.panel
    table#services
        hr 
        tbody
            tr
                th Name   
                th WorkingSetSize 
                th Handle  
            each result in results.ProcessInformation 
                tr
                    td=result.Name  
                    td=result.WorkingSetSize 
                    td=result.Handle 
script.
    var acc = document.getElementsByClassName("accordion");
    var i;
    for (i = 0; i < acc.length; i++) {
    acc[ i ].addEventListener("click", function () {
    this.classList.toggle("active");
    var panel = this.nextElementSibling;
    if (panel.style.display === "block") {
    panel.style.display = "none";
    } else {
    panel.style.display = "block";
    }
    });
    }

Enjoy PowerShell!

Leave a Reply

Your email address will not be published. Required fields are marked *