A common request from management is how many of each version of Windows are currently in use, especially in regards to Microsoft dropping support for an OS. This script will get all computers with "Windows" in the OS name, sort them by version and total each version, then send the results as an HTML-formatted email. By default, it will only get computer accounts where the lastLogon attribute has been updated within the past 30 days but this can be changed.

Common symbols such as trademark and registered are removed (they screw up the alphabetical order) but you may need to further edit this section to suit your needs. The names of the French and Chinese version of Windows are also replaced.

PowerShell
Edit|Remove
$Computer.OperatingSystem = $Computer.OperatingSystem -replace '®' -replace '™' -replace '专业版','Professional (Chinese)' -replace 'Professionnel','Professional (French)'
UPDATE #1: I added a variable to grab the domain name and then included it in the subject line to make it more obvious this report only covers one AD domain. Whenever anyone saw the report, their initial reaction was that the server totals seemed low. To verify the script was accurate, I manually added up the servers across our sites. The primary issue was the totals don't include workgroup servers in the DMZ or servers that are joined to trusted domains from acquisitions but physically live in our DC or vCenter.
UPDATE #2: Changed lastLogon to lastLogontimeStamp for more accuracy.
 
Sample email:

PowerShell
Edit|Remove
<#     
.SYNOPSIS     
     
  Get all computer objects from Active Directory with "Windows" in the OS name, sort by version and email HTML-formatted results 
         
.COMPATABILITY      
      
  Tested on PS v4.  
       
.EXAMPLE   
  PS C:\> Get-OSCount.ps1   
  All options are set as variables in the GLOBALS section so you simply run the script.   
   
.NOTES     
         
  NAME:       Get-OSCount.ps1     
     
  AUTHOR:     Brian D. Arnold     
     
  CREATED:    8/28/14   
     
  LASTEDIT:   9/3/14    
#> 
 
# Import AD module 
Import-Module ActiveDirectory 
 
################### 
##### GLOBALS ##### 
################### 
 
# Get domain 
$DomainName = (Get-ADDomain).NetBIOSName  
 
# How many days ago was the lastLogon attribute updated? 
$days = 30 
$lastLogonDate = (Get-Date).AddDays(-$days).ToFileTime() 
 
# SMTP settings 
$smtpServer = "smtp.contoso.com" 
$smtpFrom = "report@contoso.com" 
$smtpTo = "user@contoso.com" 
$messageSubject = "$DomainName Windows OS Counts - lastLogon within $days days" 
 
# HTML settings 
$style = "<style>BODY{font-family: Arial; font-size: 10pt;}" 
$style = $style + "TABLE{border: 1px solid black; border-collapse: collapse;}" 
$style = $style + "TH{border: 1px solid black; background: #dddddd; padding: 5px; }" 
$style = $style + "TD{border: 1px solid black; padding: 5px; }" 
$style = $style + "< /style>" 
 
################ 
##### MAIN ##### 
################ 
 
# Query AD 
$Computers = @(Get-ADComputer -Properties Name,operatingSystem,lastLogontimeStamp -Filter {(OperatingSystem -like "*Windows*"-AND (lastLogontimeStamp -ge $lastLogonDate)}) 
foreach($Computer in $Computers) 
{ 
    $Computer.OperatingSystem = $Computer.OperatingSystem -replace '®' -replace '™' -replace '专业版','Professional (Ch)' -replace 'Professionnel','Professional (Fr)' 
} 
 
# Send output as email 
$message = New-Object System.Net.Mail.MailMessage $smtpfrom$smtpto 
$message.Subject = $messageSubject 
$message.IsBodyHTML = $true 
$message.Body = $Computers | Group-Object operatingSystem | Select Count,Name | Sort Name | ConvertTo-Html -Head $style 
 
$smtp = New-Object Net.Mail.SmtpClient($smtpServer$smtp.Send($message)