{"id":1977,"date":"2012-01-10T13:18:31","date_gmt":"2012-01-10T18:18:31","guid":{"rendered":"http:\/\/jdhitsolutions.com\/blog\/?p=1977"},"modified":"2012-02-13T11:02:11","modified_gmt":"2012-02-13T16:02:11","slug":"the-powershell-morning-report","status":"publish","type":"post","link":"https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/","title":{"rendered":"The PowerShell Morning Report"},"content":{"rendered":"<p><img decoding=\"async\" src=\"http:\/\/www.lionking.org\/imgarchive\/Clip_Art\/zazu03.gif\" alt=\"Zazu\" style='float:left' width='240' height='200' hspace=15 vspace=15\/>I love how easy it is to manage computers with Windows PowerShell. It is a great reporting tool, but often I find people getting locked into one approach. I'm a big believer in flexibility and re-use and using objects in the pipeline wherever I can. So I put together a PowerShell script that I can run every morning on my computer and get a quick summary about what is happening, or perhaps not happening. My script, MorningReport.ps1, relies on WMI to gather a variety of system information. By default it connects to the local host, but I've provided a computername parameter. I'm assuming current credentials are good enough for any remote system, but you can always add support for alternate credentials, assuming I don't in some future version.<\/p>\n<p>By default the script writes a custom object to the pipeline that contains all of the other WMI information like disk utilization, service status, and event logs. But I wanted flexibility and ease of use, so the script also supports parameters of -Text and -HTML. The former creates nicely formatted text suitable for printing or saving to a file. The latter creates HTML code from the original objects. I rely heavily on creating HTML fragments with ConvertTo-HTML and then assembling everything at the end. The script writes the HTML code to the pipeline so if you want to save results to a file, simply pipe to Out-File. I did this because there may be times when you want the \"raw\" HTML code. You might want to save the HTML and create an HTML mail message with Send-MailMessage. Or maybe further tweak the HTML before saving it to a file. Again, I didn't want to lock myself in. Here's the main part of the script.<\/p>\n<p><code lang='PowerShell'><br \/>\n[cmdletbinding(DefaultParameterSetName=\"object\")]<\/p>\n<p>Param(<br \/>\n[Parameter(Position=0,ValueFromPipeline=$True)]<br \/>\n[ValidateNotNullOrEmpty()]<br \/>\n[string]$Computername=$env:computername,<br \/>\n[ValidateNotNullOrEmpty()]<br \/>\n[alias(\"title\")]<br \/>\n[string]$ReportTitle=\"System Report\",<br \/>\n[ValidateScript({$_ -ge 1})]<br \/>\n[int]$Hours=24,<br \/>\n[Parameter(ParameterSetName=\"HTML\")]<br \/>\n[switch]$HTML,<br \/>\n[Parameter(ParameterSetName=\"TEXT\")]<br \/>\n[switch]$Text<br \/>\n)<\/p>\n<p>#script internal version number used in output<br \/>\n[string]$reportVersion=\"1.0.8\"<\/p>\n<p><#\ndefine some HTML style\nhere's a source for HTML color codes\nhttp:\/\/www.immigration-usa.com\/html_colors.html\n\nthe code must be left justified  \n#><br \/>\n$head = @\"<\/p>\n<style>\nbody { background-color:#CCFFFF;\n       font-family:Tahoma;\n       font-size:12pt; }\ntd, th { border:1px solid #000033; \n         border-collapse:collapse; }\nth { color:white;\n     background-color:#000033; }\ntable, tr, td, th { padding: 2px; margin: 0px }\ntable { margin-left:50px; }\n<\/style>\n<p><Title>$ReportTitle<\/Title><br \/>\n\"@<\/p>\n<p>If ($computername -eq $env:computername) {<br \/>\n #local computer so no ping test is necessary<br \/>\n $OK=$True<br \/>\n}<br \/>\nelseIf (($computername -ne $env:computername) -AND (Test-Connection -ComputerName $computername -quiet -Count 2)) {<br \/>\n #not local computer and it can be pinged so proceed<br \/>\n $OK=$True<br \/>\n}<\/p>\n<p>If ($OK) {<\/p>\n<p>    Try {<br \/>\n        $os=Get-WmiObject Win32_operatingSystem -ComputerName $computername -ErrorAction Stop<br \/>\n        #set a variable to indicate WMI can be reached<br \/>\n        $wmi=$True<br \/>\n    }<br \/>\n    Catch {<br \/>\n        Write-Warning \"WMI failed to connect to $($computername.ToUpper())\"<br \/>\n    }<\/p>\n<p>    if ($wmi) {<br \/>\n        Write-Host \"Preparing morning report for $($os.CSname)\" -ForegroundColor Cyan<\/p>\n<p>        #OS Summary<br \/>\n        Write-Host \"...Operating System\" -ForegroundColor Cyan<br \/>\n        $osdata=$os | Select @{Name=\"Computername\";Expression={$_.CSName}},<br \/>\n        @{Name=\"OS\";Expression={$_.Caption}},<br \/>\n        @{Name=\"ServicePack\";Expression={$_.CSDVersion}},<br \/>\n        free*memory,totalv*,NumberOfProcesses,<br \/>\n        @{Name=\"LastBoot\";Expression={$_.ConvertToDateTime($_.LastBootupTime)}},<br \/>\n        @{Name=\"Uptime\";Expression={(Get-Date) - ($_.ConvertToDateTime($_.LastBootupTime))}}<\/p>\n<p>        #Computer system<br \/>\n        Write-Host \"...Computer System\" -ForegroundColor Cyan<br \/>\n        $cs=Get-WmiObject -Class Win32_Computersystem -ComputerName $computername<br \/>\n        $csdata=$cs | Select Status,Manufacturer,Model,SystemType,Number*<\/p>\n<p>        #services<br \/>\n        Write-Host \"...Services\" -ForegroundColor Cyan<br \/>\n        #get services via WMI and group into a hash table<br \/>\n        $wmiservices=Get-WmiObject -class Win32_Service -ComputerName $computername<br \/>\n        $services=$wmiservices | Group State -AsHashTable <\/p>\n<p>        #get services set to auto start that are not running<br \/>\n        $failedAutoStart=$wmiservices | Where { ($_.startmode -eq \"Auto\") -AND ($_.state -ne \"Running\")} <\/p>\n<p>        #Disk Utilization<br \/>\n        Write-Host \"...Logical Disks\" -ForegroundColor Cyan<br \/>\n        $disks=Get-WmiObject -Class Win32_logicaldisk -Filter \"Drivetype=3\" -ComputerName $computername<br \/>\n        $diskData=$disks | Select DeviceID,<br \/>\n        @{Name=\"SizeGB\";Expression={$_.size\/1GB -as [int]}},<br \/>\n        @{Name=\"FreeGB\";Expression={\"{0:N2}\" -f ($_.Freespace\/1GB)}},<br \/>\n        @{Name=\"PercentFree\";Expression={\"{0:P2}\"  -f ($_.Freespace\/$_.Size)}}<\/p>\n<p>        #NetworkAdapters<br \/>\n        Write-Host \"...Network Adapters\" -ForegroundColor Cyan<br \/>\n        #get NICS that have a MAC address only<br \/>\n        $nics=Get-WmiObject -Class Win32_NetworkAdapter -filter \"MACAddress Like '%'\" -ComputerName $Computername<br \/>\n        $nicdata=$nics | Foreach {<br \/>\n         $tempHash=@{Name=$_.Name;DeviceID=$_.DeviceID;AdapterType=$_.AdapterType;MACAddress=$_.MACAddress}<br \/>\n         #get related configuation information<br \/>\n         $config=$_.GetRelated() | where {$_.__CLASS -eq \"Win32_NetworkadapterConfiguration\"}<br \/>\n         #add to temporary hash<br \/>\n         $tempHash.Add(\"IPAddress\",$config.IPAddress)<br \/>\n         $tempHash.Add(\"IPSubnet\",$config.IPSubnet)<br \/>\n         $tempHash.Add(\"DefaultGateway\",$config.DefaultIPGateway)<br \/>\n         $tempHash.Add(\"DHCP\",$config.DHCPEnabled)<br \/>\n         #convert lease information if found<br \/>\n         if ($config.DHCPEnabled -AND $config.DHCPLeaseObtained) {<br \/>\n            $tempHash.Add(\"DHCPLeaseExpires\",($config.ConvertToDateTime($config.DHCPLeaseExpires)))<br \/>\n            $tempHash.Add(\"DHCPLeaseObtained\",($config.ConvertToDateTime($config.DHCPLeaseObtained)))<br \/>\n            $tempHash.Add(\"DHCPServer\",$config.DHCPServer)<br \/>\n         }<\/p>\n<p>         New-Object -TypeName PSObject -Property $tempHash<\/p>\n<p>         }<\/p>\n<p>        #Event log errors and warnings in the last $Hours hours<br \/>\n        $last=(Get-Date).AddHours(-$Hours)<br \/>\n        #System Log<br \/>\n        Write-Host \"...System Event Log Error\/Warning since $last\" -ForegroundColor Cyan<br \/>\n        $syslog=Get-EventLog -LogName System -ComputerName $computername -EntryType Error,Warning -After $last<br \/>\n        $syslogdata=$syslog | Select TimeGenerated,EventID,Source,Message<\/p>\n<p>        #Application Log<br \/>\n        Write-Host \"...Application Event Log Error\/Warning since $last\" -ForegroundColor Cyan<br \/>\n        $applog=Get-EventLog -LogName Application -ComputerName $computername -EntryType Error,Warning -After $last<br \/>\n        $applogdata=$applog | Select TimeGenerated,EventID,Source,Message<\/p>\n<p>    } #if wmi is ok<\/p>\n<p>    #write results depending on parameter set<br \/>\n    $footer=\"Report v{3} run {0} by {1}\\{2}\" -f (Get-Date),$env:USERDOMAIN,$env:USERNAME,$reportVersion<\/p>\n<p>    if ($HTML) {<br \/>\n        #prepare HTML code<br \/>\n        $fragments=@()<br \/>\n        #insert a graphic header with one of the two following lines<br \/>\n        #$fragments+=\"<center><img src='http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2011\/03\/jdhit-blog-header-2.png' \/><\/Center>\"<br \/>\n        $fragments+=\"<Img src='http:\/\/www.lionking.org\/imgarchive\/Clip_Art\/zazu03.gif' Alt='Zazu' style='float:left' width='120' height='100' hspace=10><H1> The Morning Report<\/H1>\"<\/p>\n<p>        #insert navigation bookmarks<br \/>\n$nav=@\"<br \/>\n<a href='#Services'>Services<\/a><br \/>\n<a href='#NoAutoStart'>Failed Auto Start<\/a><br \/>\n<a href='#Disks'>Disks<\/a><br \/>\n<a href='#Network'>Network<\/a><br \/>\n<a href='#SysLog'>System Log<\/a><br \/>\n<a href='#AppLog'>Application Log<\/a><br \/>\n\"@<br \/>\n        $fragments+=$nav<br \/>\n        $fragments+=\"<br clear='All'>\"<\/p>\n<p>        #add a link to the document top<br \/>\n        $nav+=\"`n<a href='#' target='_top'>Top<\/a>\"<\/p>\n<p>        $fragments+=\"<H2>System Summary<\/H2>\"<br \/>\n        $fragments+=$osdata | ConvertTo-Html -as List -Fragment<br \/>\n        $fragments+=$csdata | ConvertTo-Html -as List -Fragment<br \/>\n        $fragments+=ConvertTo-Html -Fragment -PreContent \"<H2><a name='Services'>Services<\/a><\/H2>\"<br \/>\n        $services.keys | foreach {<br \/>\n         $fragments+= ConvertTo-Html -Fragment -PreContent \"<H3>$_<\/H3>\"<br \/>\n         $fragments+=$services.$_ | Select Name,Displayname,StartMode| ConvertTo-HTML -Fragment<br \/>\n         #insert navigation link after each section<br \/>\n         $fragments+=$nav<br \/>\n        } <\/p>\n<p>        $fragments+=$failedAutoStart | Select Name,Displayname,StartMode,State |<br \/>\n         ConvertTo-Html -Fragment -PreContent \"<\/p>\n<h3><a name='NoAutoStart'>Failed Auto Start<\/a><\/h3>\n<p>\"<br \/>\n         $fragments+=$nav<\/p>\n<p>        $fragments+=$diskdata | ConvertTo-HTML -Fragment -PreContent \"<H2><a name='Disks'>Disk Utilization<\/a><\/H2>\"<br \/>\n        $fragments+=$nav<\/p>\n<p>        #convert nested object array properties to strings<br \/>\n        $fragments+=$nicdata | Select Name,DeviceID,DHCP*,AdapterType,MACAddress,<br \/>\n         @{Name=\"IPAddress\";Expression={$_.IPAddress | Out-String}},<br \/>\n         @{Name=\"IPSubnet\";Expression={$_.IPSubnet | Out-String}},<br \/>\n         @{Name=\"IPGateway\";Expression={$_.DefaultGateway | Out-String}}  |<br \/>\n          ConvertTo-HTML -Fragment -PreContent \"<H2><a name='Network'>Network Adapters<\/a><\/H2>\"<br \/>\n        $fragments+=$nav<\/p>\n<p>        $fragments+=$syslogData | ConvertTo-HTML -Fragment -PreContent \"<H2><a name='SysLog'>System Event Log Summary<\/a><\/H2>\"<br \/>\n        $fragments+=$nav<\/p>\n<p>        $fragments+=$applogData | ConvertTo-HTML -Fragment -PreContent \"<H2><a name='AppLog'>Application Event Log Summary<\/a><\/H2>\"<br \/>\n        $fragments+=$nav<\/p>\n<p>        Write $fragments | clip<br \/>\n        ConvertTo-Html -Head $head -Title $ReportTitle -PreContent ($fragments | out-String) -PostContent \"<br \/><I>$footer<\/I>\"<br \/>\n    }<br \/>\n    elseif ($TEXT) {<br \/>\n        #prepare formatted text<br \/>\n        $ReportTitle<br \/>\n        \"-\"*($ReportTitle.Length)<br \/>\n        \"System Summary\"<br \/>\n        $osdata | Out-String<br \/>\n        $csdata | format-List | Out-String<br \/>\n        Write \"Services\"<br \/>\n        $services.keys | foreach {<br \/>\n         $services.$_ | Select Name,Displayname,StartMode,State<br \/>\n        } | Format-List | Out-String<br \/>\n        Write \"Failed Autostart Services\"<br \/>\n        $failedAutoStart | Select Name,Displayname,StartMode,State<br \/>\n        Write \"Disk Utilization\"<br \/>\n        $diskdata | Format-table -AutoSize | Out-String<br \/>\n        Write \"Network Adapters\"<br \/>\n        $nicdata | Format-List | Out-String<br \/>\n        Write \"System Event Log Summary\"<br \/>\n        $syslogdata | Format-List | Out-String<br \/>\n        Write \"Application Event Log Summary\"<br \/>\n        $applogdata | Format-List | Out-String<br \/>\n        Write $Footer<br \/>\n    }<br \/>\n    else {<br \/>\n        #Write data to the pipeline as part of a custom object<\/p>\n<p>        New-Object -TypeName PSObject -Property @{<br \/>\n         OperatingSystem=$osdata<br \/>\n         ComputerSystem=$csdata<br \/>\n         Services=$services.keys | foreach {$services.$_ | Select Name,Displayname,StartMode,State}<br \/>\n         FailedAutoStart=$failedAutoStart | Select Name,Displayname,StartMode,State<br \/>\n         Disks=$diskData<br \/>\n         Network=$nicData<br \/>\n         SystemLog=$syslogdata<br \/>\n         ApplicationLog=$applogdata<br \/>\n         ReportVersion=$reportVersion<br \/>\n         RunDate=Get-Date<br \/>\n         RunBy=\"$env:USERDOMAIN\\$env:USERNAME\"<br \/>\n        }<br \/>\n    }<\/p>\n<p>} #if OK<\/p>\n<p>else {<br \/>\n    #can't ping computer so fail<br \/>\n    Write-Warning \"Failed to ping $computername\"<br \/>\n}<br \/>\n<\/code><\/p>\n<p>As you can see, it is a lengthy script, but I've tried to include a fair amount of internal comments and documentation, so I won't repeat it here, but I will touch on a few key points.<\/p>\n<p>First, I'm embedding a style sheet directly in any HTML output so any files I create can stand alone. You could certainly modify the relevant sections and use the -CSSUri parameter with ConvertTo-HTML.  Next, I use a combination of Test-Connection and Try\/Catch to handle computers that are offline or I can't access. This speeds up the script and makes it nicer for the script user.  Assuming all is good, I create a number of variables that hold the WMI information I am interested in.<\/p>\n<p><code lang='PowerShell'><br \/>\n...<br \/>\n#OS Summary<br \/>\n        Write-Host \"...Operating System\" -ForegroundColor Cyan<br \/>\n        $osdata=$os | Select @{Name=\"Computername\";Expression={$_.CSName}},<br \/>\n        @{Name=\"OS\";Expression={$_.Caption}},<br \/>\n        @{Name=\"ServicePack\";Expression={$_.CSDVersion}},<br \/>\n        free*memory,totalv*,NumberOfProcesses,<br \/>\n        @{Name=\"LastBoot\";Expression={$_.ConvertToDateTime($_.LastBootupTime)}},<br \/>\n        @{Name=\"Uptime\";Expression={(Get-Date) - ($_.ConvertToDateTime($_.LastBootupTime))}}<\/p>\n<p>        #Computer system<br \/>\n        Write-Host \"...Computer System\" -ForegroundColor Cyan<br \/>\n        $cs=Get-WmiObject -Class Win32_Computersystem -ComputerName $computername<br \/>\n        $csdata=$cs | Select Status,Manufacturer,Model,SystemType,Number*<br \/>\n...<br \/>\n<\/code><\/p>\n<p>After everything is collected, then I can write output using an If\/ElseIf statement depending on what parameters were passed. If no parameters were specified then a custom object is assembled and written to the pipeline.<\/p>\n<p><code lang='PowerShell'><br \/>\n else {<br \/>\n        #Write data to the pipeline as part of a custom object<\/p>\n<p>        New-Object -TypeName PSObject -Property @{<br \/>\n         OperatingSystem=$osdata<br \/>\n         ComputerSystem=$csdata<br \/>\n         Services=$services.keys | foreach {$services.$_ | Select Name,Displayname,StartMode,State}<br \/>\n         FailedAutoStart=$failedAutoStart | Select Name,Displayname,StartMode,State<br \/>\n         Disks=$diskData<br \/>\n         Network=$nicData<br \/>\n         SystemLog=$syslogdata<br \/>\n         ApplicationLog=$applogdata<br \/>\n         ReportVersion=$reportVersion<br \/>\n         RunDate=Get-Date<br \/>\n         RunBy=\"$env:USERDOMAIN\\$env:USERNAME\"<br \/>\n        }<br \/>\n<\/code><\/p>\n<p>But perhaps you'd like to see this in action. Here's a sample HTML <a href='http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2012\/01\/SampleReport.html' target='_blank'>SampleReport<\/a>. In this report, there are no recent errors or warnings in the Application event log. <\/p>\n<p>Or if you have a few minutes, here's a short clip of the script in action.<\/p>\n<p><iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"http:\/\/www.youtube.com\/embed\/EuQXGNZ716g\" frameborder=\"0\" allowfullscreen><\/iframe><\/p>\n<p>I hope you find this a useful jumping off point for your own script, although I think I've already worked out information you are most likely interested in. Download <a href='http:\/\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2012\/01\/MorningReport.txt'>MorningReport.ps1<\/a> and try it out for yourself.<\/p>\n<p><strong>Update<\/strong>: <a href=\"http:\/\/jdhitsolutions.com\/blog\/2012\/02\/morning-report-revised\" target=\"_blank\">Read about a revised version that accepts pipelined input<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I love how easy it is to manage computers with Windows PowerShell. It is a great reporting tool, but often I find people getting locked into one approach. I&#8217;m a big believer in flexibility and re-use and using objects in the pipeline wherever I can. So I put together a PowerShell script that I can&#8230;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[4,8,99,135,19],"tags":[229,103,237,534,540,547],"class_list":["post-1977","post","type-post","status-publish","format-standard","hentry","category-powershell","category-scripting","category-windows-7","category-windows-server","category-wmi","tag-convertto-html","tag-get-wmiobject","tag-html","tag-powershell","tag-scripting","tag-wmi"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>The PowerShell Morning Report &#8226; The Lonely Administrator<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"The PowerShell Morning Report &#8226; The Lonely Administrator\" \/>\n<meta property=\"og:description\" content=\"I love how easy it is to manage computers with Windows PowerShell. It is a great reporting tool, but often I find people getting locked into one approach. I&#039;m a big believer in flexibility and re-use and using objects in the pipeline wherever I can. So I put together a PowerShell script that I can...\" \/>\n<meta property=\"og:url\" content=\"https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/\" \/>\n<meta property=\"og:site_name\" content=\"The Lonely Administrator\" \/>\n<meta property=\"article:published_time\" content=\"2012-01-10T18:18:31+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2012-02-13T16:02:11+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/www.lionking.org\/imgarchive\/Clip_Art\/zazu03.gif\" \/>\n<meta name=\"author\" content=\"Jeffery Hicks\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@JeffHicks\" \/>\n<meta name=\"twitter:site\" content=\"@JeffHicks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Jeffery Hicks\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/1977\\\/the-powershell-morning-report\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/1977\\\/the-powershell-morning-report\\\/\"},\"author\":{\"name\":\"Jeffery Hicks\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"headline\":\"The PowerShell Morning Report\",\"datePublished\":\"2012-01-10T18:18:31+00:00\",\"dateModified\":\"2012-02-13T16:02:11+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/1977\\\/the-powershell-morning-report\\\/\"},\"wordCount\":561,\"commentCount\":5,\"publisher\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"image\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/1977\\\/the-powershell-morning-report\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/www.lionking.org\\\/imgarchive\\\/Clip_Art\\\/zazu03.gif\",\"keywords\":[\"ConvertTo-HTML\",\"Get-WMIObject\",\"HTML\",\"PowerShell\",\"Scripting\",\"WMI\"],\"articleSection\":[\"PowerShell\",\"Scripting\",\"Windows 7\",\"Windows Server\",\"WMI\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/1977\\\/the-powershell-morning-report\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/1977\\\/the-powershell-morning-report\\\/\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/1977\\\/the-powershell-morning-report\\\/\",\"name\":\"The PowerShell Morning Report &#8226; The Lonely Administrator\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/1977\\\/the-powershell-morning-report\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/1977\\\/the-powershell-morning-report\\\/#primaryimage\"},\"thumbnailUrl\":\"http:\\\/\\\/www.lionking.org\\\/imgarchive\\\/Clip_Art\\\/zazu03.gif\",\"datePublished\":\"2012-01-10T18:18:31+00:00\",\"dateModified\":\"2012-02-13T16:02:11+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/1977\\\/the-powershell-morning-report\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/1977\\\/the-powershell-morning-report\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/1977\\\/the-powershell-morning-report\\\/#primaryimage\",\"url\":\"http:\\\/\\\/www.lionking.org\\\/imgarchive\\\/Clip_Art\\\/zazu03.gif\",\"contentUrl\":\"http:\\\/\\\/www.lionking.org\\\/imgarchive\\\/Clip_Art\\\/zazu03.gif\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/powershell\\\/1977\\\/the-powershell-morning-report\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"PowerShell\",\"item\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/category\\\/powershell\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"The PowerShell Morning Report\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/\",\"name\":\"The Lonely Administrator\",\"description\":\"Practical Advice for the Automating IT Pro\",\"publisher\":{\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/jdhitsolutions.com\\\/blog\\\/#\\\/schema\\\/person\\\/d0258030b41f07fd745f4078bdf5b6c9\",\"name\":\"Jeffery Hicks\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\",\"caption\":\"Jeffery Hicks\"},\"logo\":{\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"The PowerShell Morning Report &#8226; The Lonely Administrator","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/","og_locale":"en_US","og_type":"article","og_title":"The PowerShell Morning Report &#8226; The Lonely Administrator","og_description":"I love how easy it is to manage computers with Windows PowerShell. It is a great reporting tool, but often I find people getting locked into one approach. I'm a big believer in flexibility and re-use and using objects in the pipeline wherever I can. So I put together a PowerShell script that I can...","og_url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/","og_site_name":"The Lonely Administrator","article_published_time":"2012-01-10T18:18:31+00:00","article_modified_time":"2012-02-13T16:02:11+00:00","og_image":[{"url":"http:\/\/www.lionking.org\/imgarchive\/Clip_Art\/zazu03.gif","type":"","width":"","height":""}],"author":"Jeffery Hicks","twitter_card":"summary_large_image","twitter_creator":"@JeffHicks","twitter_site":"@JeffHicks","twitter_misc":{"Written by":"Jeffery Hicks","Est. reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/#article","isPartOf":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/"},"author":{"name":"Jeffery Hicks","@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"headline":"The PowerShell Morning Report","datePublished":"2012-01-10T18:18:31+00:00","dateModified":"2012-02-13T16:02:11+00:00","mainEntityOfPage":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/"},"wordCount":561,"commentCount":5,"publisher":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"image":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/#primaryimage"},"thumbnailUrl":"http:\/\/www.lionking.org\/imgarchive\/Clip_Art\/zazu03.gif","keywords":["ConvertTo-HTML","Get-WMIObject","HTML","PowerShell","Scripting","WMI"],"articleSection":["PowerShell","Scripting","Windows 7","Windows Server","WMI"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/","url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/","name":"The PowerShell Morning Report &#8226; The Lonely Administrator","isPartOf":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/#primaryimage"},"image":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/#primaryimage"},"thumbnailUrl":"http:\/\/www.lionking.org\/imgarchive\/Clip_Art\/zazu03.gif","datePublished":"2012-01-10T18:18:31+00:00","dateModified":"2012-02-13T16:02:11+00:00","breadcrumb":{"@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/#primaryimage","url":"http:\/\/www.lionking.org\/imgarchive\/Clip_Art\/zazu03.gif","contentUrl":"http:\/\/www.lionking.org\/imgarchive\/Clip_Art\/zazu03.gif"},{"@type":"BreadcrumbList","@id":"https:\/\/jdhitsolutions.com\/blog\/powershell\/1977\/the-powershell-morning-report\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"PowerShell","item":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},{"@type":"ListItem","position":2,"name":"The PowerShell Morning Report"}]},{"@type":"WebSite","@id":"https:\/\/jdhitsolutions.com\/blog\/#website","url":"https:\/\/jdhitsolutions.com\/blog\/","name":"The Lonely Administrator","description":"Practical Advice for the Automating IT Pro","publisher":{"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/jdhitsolutions.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/jdhitsolutions.com\/blog\/#\/schema\/person\/d0258030b41f07fd745f4078bdf5b6c9","name":"Jeffery Hicks","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","url":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg","caption":"Jeffery Hicks"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/832ae5d438fdcfc1420d720cd1991307927de8a0b12f2342e81c30f773e21098?s=96&d=wavatar&r=pg"}}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"jetpack-related-posts":[{"id":2809,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/2809\/powershell-morning-report-with-credentials\/","url_meta":{"origin":1977,"position":0},"title":"PowerShell Morning Report with Credentials","author":"Jeffery Hicks","date":"February 22, 2013","format":false,"excerpt":"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\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"morning report","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/02\/morningreport-revised-cred-1024x654.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/02\/morningreport-revised-cred-1024x654.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/02\/morningreport-revised-cred-1024x654.png?resize=525%2C300 1.5x"},"classes":[]},{"id":37,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/37\/get-active-directory-user-information-in-powershell\/","url_meta":{"origin":1977,"position":1},"title":"Get Active Directory User Information in PowerShell","author":"Jeffery Hicks","date":"July 5, 2006","format":false,"excerpt":"One feature that PowerShell will likely be missing when it first ships is solid support for ADSI and working with Active Directory. You can use .NET DirectoryEntry objects but it feels more like programming and less like scripting. Another option for working with Active Directory in PowerShell is to use\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":2848,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/2848\/wmi-explorer-from-the-powershell-guy\/","url_meta":{"origin":1977,"position":2},"title":"WMI Explorer from The PowerShell Guy","author":"Jeffery Hicks","date":"March 8, 2013","format":false,"excerpt":"Several years ago, The PowerShell Guy, aka MoW, wrote a fantastic graphical PowerShell script that was a WMI Explorer. With this script you could connect to a computer and namespace, browse classes and view instances. A great way for discovering things about WMI. However Marc has moved on to other\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"wmibrowser","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/03\/wmibrowser-1024x552.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/03\/wmibrowser-1024x552.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2013\/03\/wmibrowser-1024x552.png?resize=525%2C300 1.5x"},"classes":[]},{"id":5187,"url":"https:\/\/jdhitsolutions.com\/blog\/powershell\/5187\/get-antivirus-product-status-with-powershell\/","url_meta":{"origin":1977,"position":3},"title":"Get Antivirus Product Status with PowerShell","author":"Jeffery Hicks","date":"July 22, 2016","format":false,"excerpt":"I expect that most of you with enterprise-wide antivirus installations probably have vendor tools for managing all of your clients. If so, don't go away just yet. Even though I'm going to demonstrate how to get antivirus product status with PowerShell, the scripting techniques might still be useful. Or you\u2026","rel":"","context":"In &quot;PowerShell&quot;","block_context":{"text":"PowerShell","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell\/"},"img":{"alt_text":"antivirus information from WMI","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2016\/07\/image_thumb-7.png?resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2016\/07\/image_thumb-7.png?resize=350%2C200 1x, https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2016\/07\/image_thumb-7.png?resize=525%2C300 1.5x"},"classes":[]},{"id":1454,"url":"https:\/\/jdhitsolutions.com\/blog\/scripting\/1454\/teched-atlanta-managing-the-registry-with-powershell\/","url_meta":{"origin":1977,"position":4},"title":"TechEd Atlanta &#8211; Managing the Registry with PowerShell","author":"Jeffery Hicks","date":"May 23, 2011","format":false,"excerpt":"My second TechEd talk was about managing the registry with Windows PowerShell. If you were in the session you know that I stressed heavily using the PowerShell provider and cmdlets. For remote computers, leverage PowerShell's remoting infrastructure. But I also discussed using the \"raw\" .NET classes as well as WMI\u2026","rel":"","context":"In &quot;Conferences&quot;","block_context":{"text":"Conferences","link":"https:\/\/jdhitsolutions.com\/blog\/category\/conferences\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":636,"url":"https:\/\/jdhitsolutions.com\/blog\/scripting\/636\/select-wmi\/","url_meta":{"origin":1977,"position":5},"title":"Select WMI","author":"Jeffery Hicks","date":"May 13, 2010","format":false,"excerpt":"I\u2019ve been helping out on some WMI and PowerShell issues in the forums at ScriptingAnswers.com. As I was working on a problem I ended up taking a slight detour to address an issue that has always bugged me. When I run a command like this: get-wmiobject -query \"Select Name,Description,Disabled from\u2026","rel":"","context":"In &quot;PowerShell v2.0&quot;","block_context":{"text":"PowerShell v2.0","link":"https:\/\/jdhitsolutions.com\/blog\/category\/powershell-v2-0\/"},"img":{"alt_text":"selectwmi","src":"https:\/\/i0.wp.com\/jdhitsolutions.com\/blog\/wp-content\/uploads\/2010\/05\/selectwmi-300x89.png?resize=350%2C200","width":350,"height":200},"classes":[]}],"_links":{"self":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/1977","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/comments?post=1977"}],"version-history":[{"count":0,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/posts\/1977\/revisions"}],"wp:attachment":[{"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/media?parent=1977"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/categories?post=1977"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/jdhitsolutions.com\/blog\/wp-json\/wp\/v2\/tags?post=1977"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}