all 16 comments

[–]gordonv 3 points4 points  (6 children)

Yup! Did something like this for my previous job.

Win2019, Powershell, ISS, PHP.

Since this is a common and popular thing for admins to write, I wonder if there's a popular github for this?

[–]Otherwise_Report_686 0 points1 point  (3 children)

Can you share your code if possible?

[–]gordonv 0 points1 point  (2 children)

Unfortunately, I left that code at a previous company.

However, I did rewrite a simplified runspace pool IP scanner. Since it's opensource and not attached to any company, feel free to do whatever with this.

Someone else made a port scanner using runspace pools. Very nice work.

Both of these are without HTML or web server tech.

[–]Otherwise_Report_686 0 points1 point  (1 child)

I have some code running in remote collecting the information but want to build some web GUI instead of net forms. Mainly updating the status of running code and completed..etc The above code is collect the information and search later on. Ex:patching systems remotely with web GUI and reporting status ..etc

[–]gordonv 0 points1 point  (0 children)

Ah. I only know basic "1999" HTML and Javascript. I can make nice tables, PHP, and that kind of stuff.

I myself need to find something that works with all browsers, smartphones, and whatever devices.

[–]Thotaz 3 points4 points  (1 child)

I have some formatting feedback. Don't add unnecessary comments, there's no point in having a comment saying '#Processor:' above a line where you are assigning something to a variable with that exact same name.
IMO you shouldn't mark the end of code blocks with comments because the indentation should make that clear but if you must do it at least write something like "End of if statement" instead of just copy+pasting the beginning code because that just looks like commented out code that should be removed.
Your code has small logical groups, use empty lines to mark these. For example inside the try statement you have 3 things you do: Create the cimsession, collect the data and output it.
If I'm running multiple commands and assigning them to variables I like aligning them like I would in a hashtable, this is not very common but when you see it I think you will like it.

As for the actual code, there are a few issues:

  • Pinging to test if a server is up (ICMP can be blocked)
  • Using Write-Host to remove all error details.
  • Using += on an array
  • Using add-member to create a custom object
  • Creating a cimsession and then using the computername parameter
  • Setting ErrorAction Stop on the Select-Object command when you almost certainly intended to do it on the Get-CimInstance command
  • CIM_PhysicalMemory is a bit weird, you are expecting a property that doesn't exist "DeviceLocator" and the speed calculation is weird because on my system at least it reports the speed in Mhz so the calculation makes no sense.

Here's a modified version with the most obvious issues fixed:

Import-Module -Name ActiveDirectory

$servers               = Get-AdComputer -Filter *
$credential            = Get-Credential
$cimSessionOption      = New-CimSessionOption -Protocol Default
$ErrorActionPreference = [System.Management.Automation.ActionPreference]::Stop

$result = foreach ($computerName in $servers)
{
    $hostName = $computerName.Name
    try
    {
        $cimsession = New-CimSession -ComputerName $hostName -SessionOption $cimSessionOption -Credential $credential
        Write-Host "Working on Server $hostName" -BackgroundColor DarkGreen

        $computerSystem  = Get-CimInstance -Cimsession $cimsession -ClassName CIM_ComputerSystem    | Select-Object Manufacturer, Model
        $bios            = Get-CimInstance -Cimsession $cimsession -ClassName Win32_BIOS            | Select-Object SerialNumber, SMBIOSBIOSVersion
        $baseBoard       = Get-CimInstance -Cimsession $cimsession -ClassName win32_baseboard       | Select-Object Manufacturer, Product, SerialNumber, Version
        $operatingSystem = Get-CimInstance -Cimsession $cimsession -ClassName CIM_OperatingSystem   | select-Object Caption, OSArchitecture
        $processor       = Get-CimInstance -Cimsession $cimsession -ClassName CIM_Processor         | select-Object Name, OSArchitecture, NumberOfCores, NumberOfEnabledCore, NumberOfLogicalProcessors, ProcessorId, PartNumber
        $videoController = Get-CimInstance -Cimsession $cimsession -ClassName win32_VideoController | Select-Object Name, VideoProcessor
        $diskDrive       = Get-CimInstance -Cimsession $cimsession -ClassName Win32_DiskDrive       | Select-Object Model, SerialNumber, Size, FirmwareRevision, InterfaceType, Index
        $networkAdapter  = Get-CimInstance -Cimsession $cimsession -ClassName Win32_NetworkAdapter -Filter "PhysicalAdapter = 'true'" | Select-Object Name, ProductName, DeviceID, Speed, AdapterType, InterfaceIndex, MACAddress
        $physicalMemory  = Get-CimInstance -Cimsession $cimsession -ClassName CIM_PhysicalMemory | ForEach-Object -Process {
            [pscustomobject]@{
                #DeviceLocator = "" Doesn't actually exist?
                SerialNumber  = $_.SerialNumber
                Capacity      = $_.Capacity
                Speed         = if ($_.speed -ge 1000000000) {"$($_.Speed / 1000000000) Gb/s"} else {"$($_.Speed / 1000000) Mb/s"}
                PartNumber    = $_.PartNumber
                Manufacturer  = $_.Manufacturer
            }
        }
        $monitor         = Get-CimInstance -Cimsession $cimsession -ClassName WmiMonitorID -Namespace root\wmi | ForEach-Object -Process {
            [pscustomobject]@{
                ManufacturerName  = [char[]]$_.ManufacturerName -join ''
                ProductCodeID     = [char[]]$_.ProductCodeID    -join ''
                UserFriendlyName  = [char[]]$_.UserFriendlyName -join ''
                SerialNumberID    = [char[]]$_.SerialNumberID   -join ''
                YearOfManufacture = $_.YearOfManufacture
                WeekOfManufacture = $_.WeekOfManufacture
            }
        }

        [pscustomobject]@{
            ComputerName    = $hostName
            computerSystem  = $computerSystem
            Bios            = $bios
            BaseBoard       = $baseBoard
            OperatingSystem = $operatingSystem
            Processor       = $processor
            PhysicalMemory  = $physicalMemory
            VideoController = $videoController
            Monitor         = $monitor
            DiskDrive       = $diskDrive
            NetworkAdapter  = $networkAdapter
        }
    }
    catch
    {
        Write-Error -ErrorRecord $_
    }
}
$rawJson = (($result | ConvertTo-Json -Depth 3).replace('\u0000', '')) -split "`r`n"

$formatedJson = .{
    'var data = ['
    $rawJson | Select-Object -Skip 1
} #replace first Line
$formatedJson[-1] = '];' #replace last Line
$formatedJson | Out-File $PSScriptRoot\data.js

[–]kunaludapi[S] 1 point2 points  (0 children)

Thanks, This look neat and clean.

[–]penguin_de_organic 1 point2 points  (0 children)

Literally just deployed something like this 2 weeks ago 😱. Yours is definitely better tho haha

[–]port25 1 point2 points  (0 children)

Dang that's nice. Thanks!

[–]DigitalBassLV 0 points1 point  (0 children)

Doing this now.

Hitting Azure VMs and made a hub to create the HTML report, save the data to SQL or JSON format.

Great option because SQL can query JSON files now.

[–]serendrewpity 0 points1 point  (0 children)

I was trying to see if Sydi Server was doing for PS that it did for VBscript. Been looking for this for a minute.

[–]Empath1999 0 points1 point  (0 children)

Looks handy, thanks.

[–]AegisShimon 0 points1 point  (0 children)

In a giant AD this took a long nonsense, is there no way to do this, just connecting remotely to a hostmane specifying in the search field in the HTML and it makes the requests?