PowerShell Morning Report with Credentials

I had an email about trying to use my Morning Report script to connect to machines that required alternate credentials. For example, you might have non-domain systems in a DMZ. Fair enough. Since most of the report script uses WMI, it wasn’t too hard to add a Credential parameter and modify the WMI code to use it. I tweaked the code a bit to use hashtables to splat parameters.


#region define a parameter hashtable
$paramhash=@{
Classname="Win32_OperatingSystem"
Computername=$Computername
ErrorAction="Stop"
}

if ($credential) {
$paramhash.Add("Credential",$Credential)
}
If ($OK) {

Try {
#get Operating system information from WMI
$os = Get-WmiObject @paramhash
...

I’m a little mixed on using splatting in the script. On one hand it makes it easier to wrap up parameters but the actual command might be a little confusing. Hopefully the comments make it clear.

So that handled all the WMI parts. The event log section is using Get-Eventlog which doesn’t have a -Credential parameter. I could have tried to rewrite the section using WMI, but that seemed like a lot of work. So I made the assumption that the computers you are querying are running PowerShell 2 or later with remoting enabled. That means I can use Invoke-Command to run Get-Eventlog ON the remote computer. As an additional benefit this seems to run a little faster, at least in my testing.

The tricky part was passing all the parameter values to Get-EventLog and Invoke-Command. I ended up with some complicated nesting but it works.


#Event log errors and warnings in the last $Hours hours
$last=(Get-Date).AddHours(-$Hours)
#define a hash table of parameters to splat to Get-Eventlog
$GetEventLogParam = @{
LogName="System"
EntryType="Error","Warning"
After=$last}

#System Log
Write-Host "...System Event Log Error/Warning since $last" -ForegroundColor Cyan
#hashtable of optional parameters for Invoke-Command
$InvokeCommandParam = @{
Computername=$Computername
ArgumentList=$GetEventLogParam
ScriptBlock = {Param ($params) Get-EventLog @params }
}

if ($Credential) { $InvokeCommandParam.Add("Credential",$Credential) }

$syslog = Invoke-Command @InvokeCommandParam

$syslogdata = $syslog | Select TimeGenerated,EventID,Source,Message

#Application Log
Write-Host "...Application Event Log Error/Warning since $last" -ForegroundColor Cyan
#update the hashtable
$GetEventLogParam.LogName="Application"

#update invoke-command parameters
$InvokeCommandParam.ArgumentList = $GetEventLogParam

$applog = Invoke-Command @InvokeCommandParam
$applogdata = $applog | Select TimeGenerated,EventID,Source,Message

Now you can run the script using -Credential, specifying either a saved credential object or the user name which will give you the Get-Credential prompt. I also made some slight tweaks to the embedded style and layout.

morning report

If you missed the original and related posts, you might want to read:
http://jdhitsolutions.com/blog/2012/01/the-powershell-morning-report/
http://jdhitsolutions.com/blog/2012/02/morning-report-revised/
http://jdhitsolutions.com/blog/2012/08/event-log-morning-report/

Download the latest version of the MorningReport.

Morning Report Revised

Last month I posted a PowerShell script I called The Morning Report. I received some very nice feedback. One comment was about making it easier to use the script in a pipelined expression. For example, get a list of computers from a text file and create a single HTML report. That sounds reasonable to me so I decided to revisit the script and add a few tweaks.

The latest version can still be used as I originally described. But now the computername parameter can be piped in to the script.


PS C:\> $report=get-content computers.txt | c:\scripts\morningreport.ps1

The report will still write a collection of custom report objects to the pipeline. But now I can do this:


PS C:\> get-content computers.txt | c:\scripts\morningreport.ps1 -text | out-file c:\work\morning-report.txt

This will create a single text file for all computers in the list. If you prefer a separate file per computer, use a ForEach loop.


PS C:\> get-content computers.txt | foreach {
>> $comp=$_
>> c:\scripts\morningreport.ps1 -Comp $comp -text |
>> out-file "c:\work\$comp-morning-report.txt"
>> }
>>

Similarly, I can now create a single HTML file.


PS C:\> get-content computers.txt | c:\scripts\morningreport.ps1 -html -hours 36 | out-file c:\work\morning-report.htm

I had to revise the HTML related code a bit to accommodate multiple computers in the same file. I modified the navigation links to the computername and inserted a list of computers at the beginning of the file. Clicking on a computername will take you to the corresponding summary. I probably wouldn’t try this with hundreds of computers, but for most small to mid-size groups I think this will work just fine.

The last change I made, which was as much for me as anyone, was to add a -Quick parameter. Querying event logs is time consuming so if you are in a hurry you can skip the event log query by using -Quick. You’ll still get an event log section in the output, but it will be empty.

Download the revised version of MorningReport.ps1 and let me know what you think.

The PowerShell Balloon Festival

I trust by now you are realizing how valuable Windows PowerShell  is as a management tool. With a one line command you can accomplish an extraordinary amount of work. Sometimes this work may be long running, which is where background jobs come in handy. Or you may simply kick off a long running script and go about your other administrative tasks. Unfortunately, you have to keep stopping what you’re doing to check and see if your script or job has finished. But there is a better way, assuming you are running Windows Vista or later.

Continue reading