Hi All,
Sorry, though completely new to powershell and trying to learn for the first time this week but really lost and have very short deadline to obtain,so hoping someone can help so i dont have to manually walk and scan each monitor.
I want to scan a list of machines (text file I) that I got from a DSquery and display their Make/Model/Serial number along side of the Hostname of the machine, and the 2 last logged in users of the machine.
Any help or advice would be greatly appreciated. I need in similar format as the most i would have is 4 monitors connected and will then use this data to input into other systems. Thanks
PC Name / PC Model / PC Serial Number / L.Logged In User 1 / L.Logged in User 2 /Monitor Make Model/ Monitor SN /
PC1SYD1234 DEL 7500 XXXXX mrX, Mrs Y HP HP LA2405x CN12345678 SSL7-F108F-9D4Z
PC1SYD1234 DEL 7500 XXXXX mrX, Mrs Y HP HP LA2405x CN12345679 SSL7-F108F-9D4Z
PC1SYD1234 DEL 7500 XXXXX mrX, Mrs Y HP HP LA2405x CN123456710 SSL7-F108F-9D4Z
PC2SYD1235 DEL 7500 XXXXX mrX, Mrs Y HP HP LA2405x CN123456710 SSL7-F108F-9D4Z
PC2SYD1235 DEL 7500 XXXXX mrX, Mrs Y HP HP LA2405x CN123456710 SSL7-F108F-9D4Z
I need to make sure it caters for Dell Monitors that apparently have issues with scripts from what I’ve read, so may need to some how incorporate:
function Decode {
If ($args[0] -is [System.Array]) {
[System.Text.Encoding]::ASCII.GetString($args[0])
}
Else {
“Not Found”
}
}
Not sure how much you already have written, but since you mention using a “get-monitor” command I’m assuming that’s a function you’ve started writing. If not, here is what you might use to start.
function Get-Monitor {
Param(
[String[]]$Computername
)
Foreach ($Computer in $Computername){
}
}
You can pass your list of computers to that function, which will then loop through each one of them and do stuff. In this case it sounds like you just need to do a few WMI (or CIM) queries. So maybe something like this:
That gets all the info into memory, probably more than you are actually looking for. The last thing to do then is to just create an output object to cherry pick the specific items you want in your output.
I left out the monitor stuff since that’s not a strict one to one mapping. You could have one or more monitors, so I’d probably use add-member to append those.
Not to dampen the project but keep in mind when getting serial numbers from the monitors, the values ‘burned’ in the monitor itself can be different than what the outside or packaging shows; a lot of times it’s a shortened version of the full serial number.
The internal value depends on how the manufacturer has entered it, and unfortunately with many of them, they don’t always match (based on my experience). However, the script can still be useful as some will work.
Thanks guys,
Much appreciated for the prompt response.
Unfortunately I hadn’t written much so far as powershell is virtually brand new to me,
I had played around with vbscript many years ago and read several forums warning of especially Dell using different Serial numbers than what is on the sticker and apparently the need to search for “Friendly Names/Numbers”.
I’ll have a go at the above when i get to work.
Enjoy your Day/Weekend and Thanks again.
Sorry if this sounds silly, but when looking at this in Powershell ISE, I am getting errors,
One of them being "Missing Expression after =… Not too sure why as I’m pretty sure I have used other scripts with similar format.
SideQuestion, anyone in Epping Area Sydney that would be interested in some Tutoring lessons on PowerShell, paid of course?
Just so I can get the basics downpacked and not have to disturb others so often.
Sorry for the floods, but I think I have almost figured it out, though I get an error about PARAM not being correct,
however when I ctrl f and search for param, nothing found,
function Get-Monitor {}
Param(
[String]$Computernames = get-content “c:\scripts\machinelist.txt”
)
Foreach ($Computer in $Computernames){
$ComputerSystemInfo = Get-WmiObject -Class win32_computersystem -Computer $Computer
$MonitorInfo = Get-WmiObject -Namespace root\wmi -Class WmiMonitorID -Computer $Computer
$BIOSInfo = Get-WmiObject -Class win32_bios -Computer $Computer
Thanks mate,
I modified, now getting the below:
In the meantime, ill look up the examples.
PS C:\Scripts> C:\Scripts\MonitorScan.ps1
Param : The term ‘Param’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again.
At C:\Scripts\MonitorScan.ps1:2 char:5
function Get-Monitor {} should be function Get-Monitor {, the matching block ending } goes at the bottom of file.
I recommend that you watch the Microsoft Virtual Academy (mva.microsoft.com) Powershell videos on getting started and then advanced tools & scripts - that will self enable you to a great extent. Probably the best way to train yourself.
Updated Script: just in case anyone else is after a similar script, I think its now working as I am getting results and no error so you can modify the below to your needs. thanks all:
function Get-Monitor {
Param
[String]$Computernames = get-content “c:\scripts\machinelist.txt” }
Hi All,
I have come across a great script that seems to work,
However just need to figure out where/how i can get it to include the PC’s Serial Number:
If anyone interested, here is the Script:
And if anyone is able to spare me some time to help me figure out how to get the PC Serial Number that would be greatly appreciated.
Thanks,
Param(
[switch]$CSVReport,
[string]$CSVOutputFile = "C:\Test\AttachedMonitors.csv",
[switch]$HTMLReport = $true,
[string]$HTMLOutputFile = "C:\Test\AttachedMonitors.htm",
[switch]$EmailReportAsHTML,
[switch]$FromAD,
[switch]$FromFile,
[string]$FromFileLocation = "C:\Test\Servers.txt",
[switch]$Test
)
### SMTP Mail Settings
$SMTPProperties = @{
To = "ToUser@domain.com"
From = "FromUser@Domain.com"
Subject = "Monitor Inventory"
SMTPServer = "mail.domain.com"
}
$Results = @()
$Count = 0
if ($FromAD)
{ ### Attempts to Import ActiveDirectory Module. Produces error if fails.
Try { Import-Module ActiveDirectory -ErrorAction Stop }
Catch { Write-Host "Unable to load Active Directory module, is RSAT installed?"; Break }
}
### HTML Header
$Header = @"
TABLE {border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;margin-left: auto;margin-right: auto;}
TH {border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color: #808080;}
TD {border-width: 1px;padding: 3px;border-style: solid;border-color: black;}
.odd { background-color:#ffffff; }
.even { background-color:#dddddd; }
Attached Monitor Inventory Report
"@
Function ConvertTo-Char ($Array)
{
$Output = ""
ForEach($char in $Array)
{ $Output += [char]$char -join ""
}
return $Output
}
Function Detect-VirtualMachine
{
Param (
[string]$ComputerName
)
$VMModels = @("Virtual Machine","VMware Virtual Platform","Xen","VirtualBox")
$CheckPhysicalOrVMQuery = Get-WmiObject -ComputerName $ComputerName -Query "Select * FROM Win32_ComputerSystem" -Namespace "root\CIMV2" -ErrorAction Stop
if ($VMModels -contains $CheckPhysicalOrVMQuery.Model)
{ $IsVM = $True
}
Else
{ $IsVM = $False
}
Return $IsVM
}
Function Set-AlternatingRows
{
<#
.SYNOPSIS
Simple function to alternate the row colors in an HTML table
.DESCRIPTION
This function accepts pipeline input from ConvertTo-HTML or any
string with HTML in it. It will then search for and replace
it with . With the combination of CSS it
can set alternating colors on table rows.
CSS requirements:
.odd { background-color:#ffffff; }
.even { background-color:#dddddd; }
Classnames can be anything and are configurable when executing the
function. Colors can, of course, be set to your preference.
This function does not add CSS to your report, so you must provide
the style sheet, typically part of the ConvertTo-HTML cmdlet using
the -Head parameter.
.PARAMETER Line
String containing the HTML line, typically piped in through the
pipeline.
.PARAMETER CSSEvenClass
Define which CSS class is your "even" row and color.
.PARAMETER CSSOddClass
Define which CSS class is your "odd" row and color.
.EXAMPLE $Report | ConvertTo-HTML -Head $Header | Set-AlternateRows -CSSEvenClass even -CSSOddClass odd | Out-File HTMLReport.html
$Header can be defined with a here-string as:
$Header = @"
TABLE {border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}
TH {border-width: 1px;padding: 3px;border-style: solid;border-color: black;background-color: #6495ED;}
TD {border-width: 1px;padding: 3px;border-style: solid;border-color: black;}
.odd { background-color:#ffffff; }
.even { background-color:#dddddd; }
"@
This will produce a table with alternating white and grey rows. Custom CSS
is defined in the $Header string and included with the table thanks to the -Head
parameter in ConvertTo-HTML.
.NOTES
Author: Martin Pugh
Twitter: @thesurlyadm1n
Spiceworks: Martin9700
Blog: www.thesurlyadmin.com
Changelog:
1.0 Initial function release
.LINK
http://community.spiceworks.com/scripts/show/1745-set-alternatingrows-function-modify-your-html-table-to-have-alternating-row-colors
#>
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True,ValueFromPipeline=$True)]
[string]$Line,
[Parameter(Mandatory=$True)]
[string]$CSSEvenClass,
[Parameter(Mandatory=$True)]
[string]$CSSOddClass
)
Begin {
$ClassName = $CSSEvenClass
}
Process {
If ($Line.Contains(""))
{ $Line = $Line.Replace("","")
If ($ClassName -eq $CSSEvenClass)
{ $ClassName = $CSSOddClass
}
Else
{ $ClassName = $CSSEvenClass
}
}
Return $Line
}
}# End Set-AlternatingRows Function
if ($FromAD){ $Computers = Get-ADComputer -Filter * -Properties Name }
if ($FromFile){ $Computers = Get-Content $FromFileLocation }
ForEach ($Computer in $Computers)
{
$progress = @{
Activity = "Querying Connected Monitors on $ComputerName"
Status = "$Count of $($Computers.Count) completed"
PercentComplete = $Count / $($Computers.Count) * 100
Id = 0
}
Write-Progress @progress
$Count++
if ($FromAD)
{ $ComputerName = $Computer.DNSHostName
}
ElseIf ($FromFile)
{ $ComputerName = $Computer
}
ElseIf ($Test)
{ Write-Host "Test Mode Enabled" -ForegroundColor Yellow
$ComputerName = $Env:ComputerName
}
Try
{
if (-not ($Test))
{ $IsPhysicalMachine = Detect-VirtualMachine -ComputerName $ComputerName
}
Else
{ $IsPhysicalMachine = Detect-VirtualMachine -ComputerName "localhost"
}
}
Catch
{
if (-not ($Test))
{ Write-Host "ComputerName: $($ComputerName), caught an error checking if the computer was physical or virtual: $($Error[0])" -ForegroundColor Red -BackgroundColor Black
}
Else
{ Write-Host "ComputerName: $($ComputerName), caught an error checking if the computer was physical or virtual: $($Error[0])" -ForegroundColor Red -BackgroundColor Black
}
$Results += New-Object PSObject -Property @{
ComputerName = $ComputerName
Active = "N/A"
Manufacturer = "N/A"
UserFriendlyName = "N/A"
SerialNumber = "N/A"
WeekOfManufacture = "N/A"
YearOfManufacture = "N/A"
Status = "2 - Warning"
Message = "There was a problem checking if the computer was physical or virtual: $($Error[0])"
}
Continue
}
If ($IsPhysicalMachine -eq $false)
{
Try
{
if (-not ($Test))
{ $Query = Get-WmiObject -ComputerName $ComputerName -Query "Select * FROM WMIMonitorID" -Namespace root\wmi -ErrorAction Stop
}
Else
{ $Query = Get-WmiObject -Query "Select * FROM WMIMonitorID" -Namespace root\wmi -ErrorAction Stop
}
ForEach ($Monitor in $Query)
{
$Results += New-Object PSObject -Property @{
ComputerName = $ComputerName
Active = $Monitor.Active
Manufacturer = ConvertTo-Char($Monitor.ManufacturerName)
UserFriendlyName = ConvertTo-Char($Monitor.userfriendlyname)
SerialNumber = ConvertTo-Char($Monitor.serialnumberid)
WeekOfManufacture = $Monitor.WeekOfManufacture
YearOfManufacture = $Monitor.YearOfManufacture
Status = "0 - OK"
Message = "N/A"
}
}
Continue
}
Catch
{
$Results += New-Object PSObject -Property @{
ComputerName = $ComputerName
Active = "N/A"
Manufacturer = "N/A"
UserFriendlyName = "N/A"
SerialNumber = "N/A"
WeekOfManufacture = "N/A"
YearOfManufacture = "N/A"
Status = "1 - Error"
Message = "Error: $($Error[0])"
}
}
}
Else
{ Write-Host "ComputerName: $($ComputerName) was a virtual machine. Skipping monitor inventory." -ForegroundColor Yellow
$Results += New-Object PSObject -Property @{
ComputerName = $ComputerName
Active = $false
Manufacturer = "N/A"
UserFriendlyName = "N/A"
SerialNumber = "N/A"
WeekOfManufacture = "N/A"
YearOfManufacture = "N/A"
Status = "N/A - Informational"
Message = "Virtual Machine, skipped monitor inventory."
}
}
}
### Debugging to make sure there are results.
#Write-Host "Results Count: $($Results.count)"
If ($Results.count -gt 0)
{ $Results = $Results | Select ComputerName,Active,Manufacturer,UserFriendlyName,SerialNumber,WeekOfManufacture,YearOfManufacture,Status,Message
if ($CSVReport)
{ $Results | Sort Status,ComputerName | Export-CSV -Path $CSVOutputFile -NoTypeInformation
}
if ($HTMLReport)
{ $Results | Sort Status,ComputerName | ConvertTo-HTML -Head $Header | Out-File $HTMLOutputFile
}
if ($EmailReportAsHTML)
{ $Body = $Results | Sort Status,ComputerName | ConvertTo-HTML -Head $Header | Out-String
Send-MailMessage @SMTPProperties -Body $Body -BodyAsHTML
}
}
Else
{ Write-Output "There were 0 results in the `$Results array."
}
I can’t seem to locate this bit on your script. Well, this is how you get the serial number of a computer. Maybe assign it to a variable and stick to your report, also change the localhost to a computer name variable.