PowerShell Script - Time Report & Email results HTML?

Howdy -

I am trying to get the time from a list of servers. I have found a function I modified a bit and it works fine, then the script to use the function seems fine as well. The part I am hung on now is trying to capture the results and then email them out. I have tried many things and cant get anything to work. I am not sure whether I should be trying to store the results in a variable and then emailing them out or storing them in an array?
function Get-Time
{
[CmdletBinding()]
param(
[Parameter(Position=0, Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[System.String]
$ServerName,
$Credential
)
try {
If ($Credential) {
$DT = Get-WmiObject -Class Win32_LocalTime -ComputerName $servername -Credential $Credential
} Else {
$DT = Get-WmiObject -Class Win32_LocalTime -ComputerName $servername
}
}
catch {
throw
}
$Times = New-Object PSObject -Property @{
ServerName = $DT._Server
DateTime = (Get-Date -Day $DT.Day -Month $DT.Month -Year $DT.Year -Minute $DT.Minute -Hour $DT.Hour -Second $DT.Second)
}
$Times
}
#One way to use this function is importing a list of servers
$Servers = Get-Content C:\temp\timelist.txt
$Server| Foreach {
Get-Time $

}

There’s a lot of information on this site about creating HTML reports (including a free ebook you can download from https://powershell.org/newsletter/), so I don’t go into too much detail on all of the headers / footers / etc. Here’s a modification to your code that creates HTML (in pretty much its most basic form), and sends an email.

I’ve taken the liberty of modifying the function slightly so it accepts pipeline input. This makes the code that calls the function look very tidy, as you’ll see.

function Get-Time
{
    [CmdletBinding()]
    param(
        [Parameter(Position=0, ValueFromPipeline = $true)]
        [ValidateNotNull()]
        [System.String[]]
        $ServerName,

        $Credential
    )
    
    # I've changed the ServerName parameter to be an array of strings that can be passed via the pipeline,
    # and modified the code slightly to gracefully handle blank lines in the file, but have otherwise
    # left the code in this function alone.
    
    process
    {
        foreach ($server in $ServerName)
        {
            if ($server -match '^\s*$')
            {
                continue
            }

            try {
                If ($Credential) {
                    $DT = Get-WmiObject -Class Win32_LocalTime -ComputerName $server -Credential $Credential
                } Else {
                    $DT = Get-WmiObject -Class Win32_LocalTime -ComputerName $server
                }
            }
            catch {
                throw
            }

            $Times = New-Object PSObject -Property @{
                ServerName = $DT.__Server
                DateTime = (Get-Date -Day $DT.Day -Month $DT.Month -Year $DT.Year -Minute $DT.Minute -Hour $DT.Hour -Second $DT.Second)
            }

            $Times
        }
    }
}

# Because Get-Time now accepts pipeline input, you can pipe Get-Content straight to it,
# and then to ConvertTo-Html, without an ugly looking ForEach-Object loop in the middle.

# That's just my personal preference.

$body = Get-Content C:\temp\timelist.txt | Get-Time | ConvertTo-Html

# Sample of using the Send-MailMessage cmdlet.  Parameters are placed into a hashtable
# passed to the cmdlet using splatting to improve readability, since Send-MailMessage
# commands tend to be very long.

$mailParams = @{
    To = 'user@domain.com'
    From = 'me@domain.com'
    Body = $body
    BodyAsHtml = $true
    SmtpServer = 'smtp.domain.com'
    Subject = 'Date and Time Report'
}

Send-MailMessage @mailParams

I am going to test this right now! Thank you very very much! I really got stuck on the Function portion, couldn’t get the results out of it, but I thought that setting the get-time commands in a function would be helpful so that I could re-use it, but I’ve spent hours on trying to get the results from the 2nd part.

I just tested it and there was one error I got back and I think I fixed it as it now works, but if you have a better idea or way to make it “look nicer” let me know. Thanks again!

Send-MailMessage : Cannot convert ‘System.Object’ to the type ‘System.String’ required by parameter ‘Body’. Specified method is not supported.

Have a great weekend!
Jake

ConvertTo-Html must be outputting multiple objects, then. Try changing this line, to pipe the whole thing to Out-String:

$body = Get-Content C:\temp\timelist.txt | Get-Time | ConvertTo-Html | Out-String

Thanks again! It’s working fine, the only thing I’d like to do is add in something that will report on errors. I’m getting some where “RPC is unavailable”, some with “access denied”, and then where this has to be run on servers in a domain and then just stand alone, how can I handle authentication?

I meant to add in my prior post that I added the out-string when I edited the post, but I forgot :slight_smile:

Looks like the Get-Time function already has a Credential parameter. To run it against a standalone servers, you’d need to use that.

What did you have in mind for reporting errors? Did you want them in the same email, or something else?