Jump to content

Anyone feel up to helping me add a couple of options to a PowerShell script I use?


Recommended Posts

Posted

Howdy all,

 

On occasion I run a short PowerShell script one of my coworkers created for us to extract info from our workstations for inventory and maintenance help. I don't know much at all about PowerShell (trying to learn but just starting) but wondered if I pasted the contents of it here y'all could help me change the color of just two or three of the outputs. Would that be OK?

 

Thanks

Posted

Happy to take a look, but if all you want is the colour of the text that is written out to be changed then take a look at the documentation for Write-Host, especially Example 4.

 

Essentially you want to set -ForegroundColor to a colour if you want the text to change or -BackgroundColor if you want the area around the text to change.

Posted (edited)

Thanks for the help TM!

 

I've looked at the options but as I said I know nothing about PowerShell scripting and how the syntaxes are used. What I would like to do with this script is change the color of the serial number and Windows version number to green and yellow respectively. Here is the script:

 

Function Get-Compinfo {

[CmdletBinding()]

Param(

#Want to support multiple computers

[Parameter (ValueFromPipeline=$true,

ValueFromPipelineByPropertyName=$true)]

[Alias("HostName","CN")]

[string[]]$ComputerName= (Read-Host 'Enter Computername or Ip Address'),

 

#Switch to turn on Error logging

[switch]$ErrorLog,

[string]$LogFile = 'D:\Documents\Powershell\errorlog.txt'

)

Begin{}

Process {

#$Computers = Get-Content D:\Documents\Powershell\computers.txt

ForEach ($Client in $ComputerName) {

 

if (Test-Connection -Computername $client -BufferSize 16 -Count 1 -Quiet) {

$System =Get-WmiObject -Class Win32_ComputerSystem -ComputerName $Client

$Bios =Get-WmiObject -Class Win32_Bios -ComputerName $Client

$os =Get-Wmiobject -ComputerName $Client -Class Win32_OperatingSystem

$Disk =Get-WmiObject -ComputerName $Client -class Win32_LogicalDisk -filter "DeviceID='c:'"

$IP =Get-WmiObject win32_networkadapterconfiguration -filter "ipenabled = 'True'" -ComputerName $Client

$CPU =Get-WmiObject win32_processor -Computername $Client

$Chrome =Get-WmiObject -ComputerName $Client -Class CIM_DataFile -Filter "Name='C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'"

$SystemSKUNumber =Get-WmiObject Win32_BIOS | Select-Object SystemSKUNumber

$WinVer = Invoke-Command -ComputerName $Client -ScriptBlock { (Get-Item -Path 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion').GetValue("DisplayVersion") }

 

 

[PSCustomObject]@{

'ComputerName' = $System.Name

'Manufacturer' = $System.Manufacturer

'Model' = $System.Model

'Product ID' = $System.SystemSKUNumber

'Serial Number' = $Bios.SerialNumber

'Username' = $System.Username

'IP Address' = $IP.ipaddress[0] #'0' tells it to only get the IPV4 address#

'DNS' = $IP.DNSServerSearchOrder

'Gateway' = $IP.DefaultIPGateway

'MAC Address' = $IP.macaddress

'Network Card' = $IP.Description

'OS Name' = $os.caption

'OSBit' = $OS.OSArchitecture

'WinVersion' = $Winver

'Build Version' = $os.version

'Chrome Version' = $Chrome.Version

'LastBoot' = [Management.ManagementDateTimeConverter]::ToDateTime( (Get-WmiObject -Class Win32_OperatingSystem -Computer $client | Select -Exp LastBootUpTime) )

'Memory(GB)' = "{0:N2}" -f ($System.Totalphysicalmemory / 1gb)

'DiskSize(c:)' = "{0:N0}" -f ($Disk.Size / 1gb)

'FreeSpace(GB)' = "{0:N0}" -f ($Disk.Freespace / 1gb)

'UsedSpace(GB)' = "{0:N0}" -f ($Disk.size/1gb - $disk.FreeSpace/1gb)

'PercentFree' = "{0:P0}" -f ($Disk.Freespace / $Disk.Size)

'CPU' = $CPU.name

 

}#End pscustomobject block

 

#$Obj=New-Object -TypeName PSObject -Property $Prop

#Write-Output $Obj

 

}#End If block

Else {[PSCustomObject]@{

ComputerName = $Client

Manufacturer = "Not online"

} #End pscustomobject block

} #End Else

 

 

} #End Foreach loop

 

}#End Process

 

End {}

} #End Function}#End Process

 

Get-Compinfo

 

Thanks a bunch for your time!

 

Edit: Just realized it created a smiley in the Disk size line and disabled the smiley option under the options menu.

Edited by Hoyt
Posted

This should work

 

i.e.

 

## Output Version number

Write-Host "Version $version" -ForegroundColor Green

 

I got a habit of always putting comments in shell script too :-)

Posted
I'm not to clued up with PowerShell either but sometimes I paste scripts into ChatGPT and can usually work things out from that. It's been quite useful, not sure if that's of any help in the future.
Posted

I had co-pilot create an install ps script for me with a few options and it worked straight away! (is x already installed then quit, what version is it,? if so install, blah) also had it uninstall an older program first if it was detected.

 

just worked through the prompts as I went. Saved me trying to get the syntax right.

Posted (edited)
This should work

 

i.e.

 

## Output Version number

Write-Host "Version $version" -ForegroundColor Green

 

I got a habit of always putting comments in shell script too :-)

Thanks for the reply Davit,

 

I'm afraid I don't know where to put that line in the script. Unfortunately I didn't write this script; I don't understand how PS scripts work. I had looked into the Write-Host functionality but don't know exactly which section to put it into or how to work the syntax. I haven't really used any AI tools yet, they keep me pretty busy just with hardware around here. Here is the output of the script I listed:

 

ComputerName : Computer

Manufacturer : HP

Model : HP Z2 Tower G5 Workstation

Product ID : 2X3M2UT#ABA

Serial Number : MXLXXXXXXX

Username : K12\user.name

IP Address : 10.10.80.12

DNS : {10.10.40.210, 10.10.72.210}

Gateway : {10.10.80.1}

MAC Address : C8:5B:CC:0C:12:3D

Network Card : Intel® Ethernet Connection (11) I219-LM

OS Name : Microsoft Windows 11 Pro

OSBit : 64-bit

WinVersion : 23H2

Build Version : 10.0.22631

Chrome Version : 131.0.6778.205

LastBoot : 12/22/2024 3:19:48 AM

Memory(GB) : 15.78

DiskSize(c:) : 476

FreeSpace(GB) : 154

UsedSpace(GB) : 322

PercentFree : 32%

CPU : Intel® Core™ i7-10700 CPU @ 2.90GHz

 

I would like the serial number to be green and the WinVersion to be yellow. Sorry I'm so clueless, I'm sort of taking this on as a side project. We've had a lot of turnover the past few years and there is only one person left that even remotely understands this stuff. The rest of us are trying to take on a little extra, but it's not easy to do so and keep up with our existing workloads.

 

So when I look at this script I see this line:

 

'Serial Number' = $Bios.SerialNumber

 

Is this generating the serial number output or is it just a variable? I tried working with Write-Host and -Foregroundcolor in this area but couldn't figure it out.

Edited by Hoyt
Posted

Ah, your issue is that all the information is pulled into an Object (the but after [PSCustomObject]) and then printed out as a big block of text. The Write-Host method won't work as that outputs to screen instantly.

Two seconds, & I'll see if there is any alternative to you, instead of rewriting the whole thing!

  • Thanks 1
Posted

So, I've made this work:

Function Get-Compinfo {
   [CmdletBinding()]
   Param(
       #Want to support multiple computers
       [Parameter (ValueFromPipeline = $true,
           ValueFromPipelineByPropertyName = $true)]
       [Alias("HostName", "CN")]
       [string[]]$ComputerName = (Read-Host 'Enter Computername or Ip Address'),

       #Switch to turn on Error logging
       [switch]$ErrorLog,
       [string]$LogFile = 'D:\Documents\Powershell\errorlog.txt'

       
   )
   Begin {
       $apps = @()
       $systemapp = "This is systemapp"
   
       function to_yellow ($msg) {
           "$([char]0x1b)[93m$msg$([char]0x1b)[0m"
       }
   
       function to_green ($msg) {
           "$([char]0x1b)[32m$msg$([char]0x1b)[0m"
       }
   
       function to_red ($msg) {
           "$([char]0x1b)[91m$msg$([char]0x1b)[0m"
       }
   }
   Process {
       #$Computers = Get-Content D:\Documents\Powershell\computers.txt
       ForEach ($Client in $ComputerName) {

           if (Test-Connection -Computername $client -BufferSize 16 -Count 1 -Quiet) {
               $System = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $Client
               $Bios = Get-WmiObject -Class Win32_Bios -ComputerName $Client
               $os = Get-Wmiobject -ComputerName $Client -Class Win32_OperatingSystem
               $Disk = Get-WmiObject -ComputerName $Client -class Win32_LogicalDisk -filter "DeviceID='c:'"
               $IP = Get-WmiObject win32_networkadapterconfiguration -filter "ipenabled = 'True'" -ComputerName $Client
               $CPU = Get-WmiObject win32_processor -Computername $Client
               $Chrome = Get-WmiObject -ComputerName $Client -Class CIM_DataFile -Filter "Name='C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'"
               $SystemSKUNumber = Get-WmiObject Win32_BIOS | Select-Object SystemSKUNumber
               $WinVer = Invoke-Command -ComputerName $Client -ScriptBlock { (Get-Item -Path 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion').GetValue("DisplayVersion") }


               [PSCustomObject]@{
                   'ComputerName'   = $System.Name
                   'Manufacturer'   = $System.Manufacturer
                   'Model'          = $System.Model
                   'Product ID'     = $System.SystemSKUNumber
                   'Serial Number'  = $systemapp= (to_green $Bios.SerialNumber)
                   'Username'       = $System.Username
                   'IP Address'     = $IP.ipaddress[0] #'0' tells it to only get the IPV4 address#
                   'DNS'            = $IP.DNSServerSearchOrder
                   'Gateway'        = $IP.DefaultIPGateway
                   'MAC Address'    = $IP.macaddress
                   'Network Card'   = $IP.Description
                   'OS Name'        = $os.caption
                   'OSBit'          = $OS.OSArchitecture
                   'WinVersion'     = $systemapp= (to_yellow $Winver)
                   'Build Version'  = $os.version
                   'Chrome Version' = $Chrome.Version
                   'LastBoot'       = [Management.ManagementDateTimeConverter]::ToDateTime( (Get-WmiObject -Class Win32_OperatingSystem -Computer $client | Select -Exp LastBootUpTime) )
                   'Memory(GB)'     = "{0:N2}" -f ($System.Totalphysicalmemory / 1gb)
                   'DiskSize(c:)'   = "{0:N0}" -f ($Disk.Size / 1gb)
                   'FreeSpace(GB)'  = "{0:N0}" -f ($Disk.Freespace / 1gb)
                   'UsedSpace(GB)'  = "{0:N0}" -f ($Disk.size / 1gb - $disk.FreeSpace / 1gb)
                   'PercentFree'    = "{0:P0}" -f ($Disk.Freespace / $Disk.Size)
                   'CPU'            = $CPU.name

               }#End pscustomobject block

               #$Obj=New-Object -TypeName PSObject -Property $Prop
               #Write-Output $Obj

           }#End If block
           Else {
               [PSCustomObject]@{
                   ComputerName = $Client
                   Manufacturer = "Not online"
               } #End pscustomobject block
           } #End Else


       } #End Foreach loop

   }#End Process

   End {}
} #End Function}#End Process

Get-Compinfo

 

Chages are the adding

$apps = @()
       $systemapp = "This is systemapp"
   
       function to_yellow ($msg) {
           "$([char]0x1b)[93m$msg$([char]0x1b)[0m"
       }
   
       function to_green ($msg) {
           "$([char]0x1b)[32m$msg$([char]0x1b)[0m"
       }
   
       function to_red ($msg) {
           "$([char]0x1b)[91m$msg$([char]0x1b)[0m"
       }

Into the Begin{} bit and wrapping $systemapp= (to_green XXX) round the Serial Number variable and the yellow version around the WinVersion variable. It appears to work, though I don't get any output for WinVersion so can't test that.

 

I have no idea if this is the best way. I have to confess I don't fully understand the script as no output is called.

 

To answer your question 'Serial Number' = $Bios.SerialNumber is writing out that line to the screen but dynamically replacing $Bios.SerialNumber with the variable set higher up.

  • Thanks 1
Posted

Hey TechMonkey when I run that in the PowerShell ISE here is what happened:

 

It went from this:

 

Serial Number : MXLXXXXXXX

 

To this:

Serial Number : [32mMXLXXXXXXX[0m

 

And the Windows version went from this:

 

WinVersion : 23H2

 

to this:

WinVersion : [93m23H2[0m and was still white in color.

 

Now here's the weird part. When I actually created a .ps1 file and modified my batch file to match the new name it ran exactly as I wanted it to. Do you know why that is? At first I thought it didn't work until I actually saved it as a .ps1 file and ran it. I even had the PowerShell ISE running in Administrator mode.

 

Thanks again for all the help. I'm trying to learn this stuff while at the same time creating a new image and removing old projectors from classrooms....

Posted
I'm trying to learn this stuff while at the same time creating a new image and removing old projectors from classrooms....

 

This is the way :D

 

I don't know why that has happened. I was running it from a standard PowerShell command window, pasting all the code in. I edited it in VisualCode which interestingly showed a lot of errors in the terminal, so maybe it is an ISE issue, not fully interpreting output.

Trust me, I am in no way an expert, just muddling through on what I need and started out like you, grabbing code and making it work how I wanted. So, don't worry and don't hesitate to ask questions :)

  • Thanks 2
Posted

Thanks again for the help I've got it tweaked the way I want it now. This section here:

 

$apps = @()

$systemapp = "This is systemapp"

 

function to_yellow ($msg) {

"$([char]0x1b)[93m$msg$([char]0x1b)[0m"

}

 

function to_green ($msg) {

"$([char]0x1b)[32m$msg$([char]0x1b)[0m"

}

 

function to_red ($msg) {

"$([char]0x1b)[91m$msg$([char]0x1b)[0m"

}

 

Looks like some serious business. I have no idea what it means but I appreciate it. I wound up making both the serial number and Winver yellow due to my partial color blindness. We have a part timer helping us do some inventory and Windows version checking so this script is a big help.

Posted
Get into the habit of commenting what happens at each stage of the script. That is the one major bug bear I see with scripts found online. Then it is easy for people to one understand what that part of the script is doing and two backward engineer to modify/repair the script.
  • Thanks 1
Posted

Thought I'd posted this yesterday, evidently I didn't as it was staring at me this morning :doh:

 

I appreciate that you have found a working solution, however, I'll still post the full reply as it may help others in the same situation.

 

--

 

Depending on exactly what format you want the output to be, and how you are running the script, this can't be done, done with a hack or set up beautifully.

 

There is no way (as far as I'm aware) to colourise individual elements of a printed PSObject. That said you can either bludgeon it into doing what you want if your output is in a VT Escape supported console (standard PS console should be, ISE probably isn't) you should be able to use this:

$apps = @()
$systemapp = "This is systemapp"

function to_yellow ($msg) {
"$([char]0x1b)[93m$msg$([char]0x1b)[0m"
}

function to_green ($msg) {
"$([char]0x1b)[32m$msg$([char]0x1b)[0m"
}

function to_red ($msg) {
"$([char]0x1b)[91m$msg$([char]0x1b)[0m"
}

 

The example code injects terminal escapes and recolours the text within the string itself. However, if this is to be viewed in any other way, e.g. saved to file or emailed, you'll get a mess of text:

This is in [32mgreen[0m, this is in [93myellow[0m, and this is in [91mred[0m

 

A way around this is to have the script write each parameter separately with the "Write-Host" cmdlet. This will take the -ForegroundColor parameter as has been mentioned previously. See the example below:

 

Write-Host "ComputerName = $($System.Name)"
Write-Host "Manufacturer = $($System.Manufacturer)"
Write-Host "Model = $($System.Model)"
Write-Host "Product ID = $($System.SystemSKUNumber)"
Write-Host "Serial Number = $($Bios.SerialNumber)" -ForegroundColor Green
Write-Host "Username = $($System.Username)"
Write-Host "IP Address = $($IP.ipaddress[0])"
Write-Host "DNS = $($IP.DNSServerSearchOrder)"
Write-Host "Gateway = $($IP.DefaultIPGateway)"
Write-Host "MAC Address = $($IP.macaddress)"
Write-Host "Network Card = $($IP.Description)"
Write-Host "OS Name = $($os.caption)"
Write-Host "OSBit = $($OS.OSArchitecture)"
Write-Host "WinVersion = $Winver" -ForegroundColor Yellow

 

This will look messy if your fields are of different length (which yours are), but if you just care about functional data that's fine.

 

In my opinion, the best way to deal with this (again, depending on your use case), is to have it output in HTML which can either be emailed or viewed as a webpage/report:

#$Computers = Get-Content D:\Documents\Powershell\computers.txt
$Headings = 0
ForEach ($Client in $ComputerName) {
   If (Test-Connection -Computername $client -BufferSize 16 -Count 1 -Quiet) {
       $System =Get-WmiObject -Class Win32_ComputerSystem -ComputerName $Client
       $Bios =Get-WmiObject -Class Win32_Bios -ComputerName $Client
       $os =Get-Wmiobject -ComputerName $Client -Class Win32_OperatingSystem
       $Disk =Get-WmiObject -ComputerName $Client -class Win32_LogicalDisk -filter "DeviceID='c:'"
       $IP =Get-WmiObject win32_networkadapterconfiguration -filter "ipenabled = 'True'" -ComputerName $Client
       $CPU =Get-WmiObject win32_processor -Computername $Client
       $Chrome =Get-WmiObject -ComputerName $Client -Class CIM_DataFile -Filter "Name='C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe'"
       $SystemSKUNumber =Get-WmiObject Win32_BIOS | Select-Object SystemSKUNumber
       $WinVer = Invoke-Command -ComputerName $Client -ScriptBlock { (Get-Item -Path 'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows NT\CurrentVersion').GetValue("DisplayVersion")}

       $Obj = [PSCustomObject]@{
           'ComputerName' = $System.Name
           'Manufacturer' = $System.Manufacturer
           'Model' = $System.Model
           'Product ID' = $System.SystemSKUNumber
           'Serial Number' = $Bios.SerialNumber
           'Username' = $System.Username
           'IP Address' = $IP.ipaddress[0] #'0' tells it to only get the IPV4 address#
           'DNS' = $IP.DNSServerSearchOrder
           'Gateway' = $IP.DefaultIPGateway
           'MAC Address' = $IP.macaddress
           'Network Card' = $IP.Description
           'OS Name' = $os.caption
           'OSBit' = $OS.OSArchitecture
           'WinVersion' = $Winver
           'Build Version' = $os.version
           'Chrome Version' = $Chrome.Version
           'LastBoot' = [Management.ManagementDateTimeConverter]::ToDateTime( (Get-WmiObject -Class Win32_OperatingSystem -Computer $client | Select -Exp LastBootUpTime) )
           'Memory(GB)' = "{0:N2}" -f ($System.Totalphysicalmemory / 1gb)
           'DiskSize(c:)' = "{0:N0}" -f ($Disk.Size / 1gb)
           'FreeSpace(GB)' = "{0:N0}" -f ($Disk.Freespace / 1gb)
           'UsedSpace(GB)' = "{0:N0}" -f ($Disk.size/1gb - $disk.FreeSpace/1gb)
           'PercentFree' = "{0:P0}" -f ($Disk.Freespace / $Disk.Size)
           'CPU' = $CPU.name
       }#End pscustomobject block

       If ($Headings -eq 0) {
           $Body = "`n`n"
           $Body += "`n"
           $Body += "`t`n"<br />
            $Body += "`t`t.green {color: green;}`n"<br />
            $Body += "`t`t.yellow {color: yellow;}`n"<br />
            $Body += "`t`t.red {color: red;}`n"<br />
            $Body += "`t`n`n"
           $Body += "`t`n"
           $Body += "`t`t</pre><table>`n`t`t`t`n"

           Foreach ($Header in (Get-Member -InputObject $Obj -MemberType NoteProperty).Name) {
               $Body += "`t`t`t`t$Header`n"
           }
           $Body += "`t`t`t`n"

           $Headings = 1
       }

       $Body += "`t`t`t`n"

       Foreach ($Header in (Get-Member -InputObject $Obj -MemberType NoteProperty).Name) {
           If ($Header -eq "WinVersion") {
               $td = ""
           }
           ElseIf ($Header -eq "Serial Number") {
               $td = ""
           }
           Else {
               $td = ""
           }

           $Value = $Obj.$Header
           $Body += "`t`t`t`t$td$Value`n"
       }
       $Body += "`t`t`t`n"
   }
}
$Body += "`t`t</table>`n`t`n"<br><br>$Body | Out-File -FilePath C:\HTM

Obviously this is more in depth, but can be tailored to whatever viewpoints you need simply by changing the HTML/CSS within the code. This is my preferred method as I tend to get reports like this emailed to me periodically for various things, an I can easily tailor the output to suit what I need to know.

 

Hope this helps someone

  • Thanks 2
Posted

Thanks for the extra info Sephiroth. For better or worse I got into this sort of thing back in the Basic/DOS days and never seemed to graduate much above that. I never learned anything about HTML or stuff like that. I do want to learn more about PowerShell though because I still use a lot of batch files in my daily routine. I'll create a .bat file with the commands I want and push it out to our Windows clients using EMCO Remote Installer.

 

I would also like to know how to neaten things up like you mentioned. I don't know which spaces are necessary and which ones are just there because they got pasted in from somewhere else.

 

To give you a better idea of my skill level I created a script with what you just posted, which I'm sure works for you and nothing happens for me, it just blinks and goes away.

 

Thanks again to everyone that chimed in. I used to browse usenet back in the day and got so busy I sort of fell out of posting on forums for work and just did it for my personal hobbies. I have to remember that it's a lot cheaper and less frustrating to learn from other folks' mistakes as opposed to my own.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now



×
×
  • Create New...