PowerShell Script - Time Report & Email results HTML?

This topic contains 7 replies, has 2 voices, and was last updated by  Dave Wyatt 3 years, 10 months ago.

  • Author
    Posts
  • #11151

    Jake Sully
    Participant

    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 $_
    }

  • #11153

    Dave Wyatt
    Moderator

    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
    
  • #11154

    Jake Sully
    Participant

    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.

  • #11155

    Jake Sully
    Participant

    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

  • #11157

    Dave Wyatt
    Moderator

    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
    
  • #11158

    Jake Sully
    Participant

    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?

  • #11160

    Jake Sully
    Participant

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

  • #11166

    Dave Wyatt
    Moderator

    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?

You must be logged in to reply to this topic.