#########################################################################################
#                                                                                        #
#    NAME: Partition Alignment Report                                                    #
#    VERSION: 1                                                                            #
#    AUTHOR: Jonathan Kehayias (The Rambling DBA)                                        #
#    BASED ON: Workstation/Server Audit script by Alan Renouf (Virtual-AL)                #
#                                                                                        #
#    USAGE: PartitionAlignmentReport.ps1 ‘C:pathtolistofservers’                        #
#                                                                                        #
#    COMMENT: The file is optional and needs to be a plain text list of computers to be    #
#    audited one on each line.                                                            #
#                                                                                        #
#    05-12-2011: Minor changes by Arjen Huitema                                              #
#                                                                                        #
#########################################################################################

param( [string] $auditlist)

if ($auditlist -eq ""){
    Write-Host "No list specified, using $env:computername"
    $targets = Get-Content C:Test.txt
}
else
{
    if ((Test-Path $auditlist) -eq $false)
    {
        Write-Host "Invalid audit path specified: $auditlist"
        exit
    }
    else
    {
        Write-Host "Using Audit list: $auditlist"
        $Targets = Get-Content C:Test.txt
    }
}

$Date = Get-Date

$Filename = ".Partition_Alignment_Report_" + $date.Hour + $date.Minute + "_" + $Date.Day + "-" + $Date.Month + "-" + $Date.Year + ".htm"

Write-Host ""
Write-Host "Building Report"

#region Report Header
    $Report = @"
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html ES_auditInitialized=’false’><head><title>Audit</title>
    <META http-equiv=Content-Type content=’text/html; charset=windows-1252′>
    <STYLE type=text/css>   
        DIV .expando {DISPLAY: block; FONT-WEIGHT: normal; FONT-SIZE: 8pt; RIGHT: 10px; COLOR: #ffffff; FONT-FAMILY: Tahoma; POSITION: absolute; TEXT-DECORATION: underline}
        TABLE {TABLE-LAYOUT: fixed; FONT-SIZE: 100%; WIDTH: 100%}
        #objshowhide {PADDING-RIGHT: 10px; FONT-WEIGHT: bold; FONT-SIZE: 8pt; Z-INDEX: 2; CURSOR: hand; COLOR: #000000; MARGIN-RIGHT: 0px; FONT-FAMILY: Tahoma; TEXT-ALIGN: right; TEXT-DECORATION: underline; WORD-WRAP: normal}
        .heading0_expanded {BORDER-RIGHT: #bbbbbb 1px solid; PADDING-RIGHT: 5em; BORDER-TOP: #bbbbbb 1px solid; DISPLAY: block; PADDING-LEFT: 8px; FONT-WEIGHT: bold; FONT-SIZE: 8pt; MARGIN-BOTTOM: -1px; MARGIN-LEFT: 0px; BORDER-LEFT: #bbbbbb 1px solid; WIDTH: 100%; CURSOR: hand; COLOR: #FFFFFF; MARGIN-RIGHT: 0px; PADDING-TOP: 4px; BORDER-BOTTOM: #bbbbbb 1px solid; FONT-FAMILY: Tahoma; POSITION: relative; HEIGHT: 2.25em; BACKGROUND-COLOR: #CCCC00}
        .heading_collapsed {BORDER-RIGHT: #bbbbbb 1px solid; PADDING-RIGHT: 5em; BORDER-TOP: #bbbbbb 1px solid; DISPLAY: block; PADDING-LEFT: 16px; FONT-WEIGHT: bold; FONT-SIZE: 8pt; MARGIN-BOTTOM: -1px; MARGIN-LEFT: 5px; BORDER-LEFT: #bbbbbb 1px solid; WIDTH: 100%; CURSOR: hand; COLOR: #ffffff; MARGIN-RIGHT: 0px; PADDING-TOP: 4px; BORDER-BOTTOM: #bbbbbb 1px solid; FONT-FAMILY: Tahoma; POSITION: relative; HEIGHT: 2.25em; BACKGROUND-COLOR: #7BA7C7}
        .heading_expanded {BORDER-RIGHT: #bbbbbb 1px solid; PADDING-RIGHT: 5em; BORDER-TOP: #bbbbbb 1px solid; DISPLAY: block; PADDING-LEFT: 16px; FONT-WEIGHT: bold; FONT-SIZE: 8pt; MARGIN-BOTTOM: -1px; MARGIN-LEFT: 5px; BORDER-LEFT: #bbbbbb 1px solid; WIDTH: 100%; CURSOR: hand; COLOR: #ffffff; MARGIN-RIGHT: 0px; PADDING-TOP: 4px; BORDER-BOTTOM: #bbbbbb 1px solid; FONT-FAMILY: Tahoma; POSITION: relative; HEIGHT: 2.25em; BACKGROUND-COLOR: #A5A5A5}
        .tableDetail {BORDER-RIGHT: #bbbbbb 1px solid; BORDER-TOP: #bbbbbb 1px solid; DISPLAY: block; PADDING-LEFT: 16px; FONT-SIZE: 8pt;MARGIN-BOTTOM: -1px; PADDING-BOTTOM: 5px; MARGIN-LEFT: 5px; BORDER-LEFT: #bbbbbb 1px solid; WIDTH: 100%; COLOR: #000000; MARGIN-RIGHT: 0px; PADDING-TOP: 4px; BORDER-BOTTOM: #bbbbbb 1px solid; FONT-FAMILY: Tahoma; POSITION: relative; BACKGROUND-COLOR: #f9f9f9}
        .filler {BORDER-RIGHT: medium none; BORDER-TOP: medium none; DISPLAY: block; BACKGROUND: none transparent scroll repeat 0% 0%; MARGIN-BOTTOM: -1px; FONT: 100%/8px Tahoma; MARGIN-LEFT: 43px; BORDER-LEFT: medium none; COLOR: #ffffff; MARGIN-RIGHT: 0px; PADDING-TOP: 4px; BORDER-BOTTOM: medium none; POSITION: relative}
        .Solidfiller {BORDER-RIGHT: medium none; BORDER-TOP: medium none; DISPLAY: block; BACKGROUND: none transparent scroll repeat 0% 0%; MARGIN-BOTTOM: -1px; FONT: 100%/8px Tahoma; MARGIN-LEFT: 0px; BORDER-LEFT: medium none; COLOR: #000000; MARGIN-RIGHT: 0px; PADDING-TOP: 4px; BORDER-BOTTOM: medium none; POSITION: relative; BACKGROUND-COLOR: #000000}
        td {VERTICAL-ALIGN: TOP; FONT-FAMILY: Tahoma}
        th {VERTICAL-ALIGN: TOP; COLOR: #000000; TEXT-ALIGN: left}
    </STYLE>
    <SCRIPT language=vbscript>
        strShowHide = 1
        strShow = "show"
        strHide = "hide"
        strShowAll = "show all"
        strHideAll = "hide all"
   
    Function window_onload()
        If UCase(document.documentElement.getAttribute("ES_auditInitialized")) <> "TRUE" Then
            Set objBody = document.body.all
            For Each obji in objBody
                If IsSectionHeader(obji) Then
                    If IsSectionExpandedByDefault(obji) Then
                        ShowSection obji
                    Else
                        HideSection obji
                    End If
                End If
            Next
            objshowhide.innerText = strShowAll
            document.documentElement.setAttribute "ES_auditInitialized", "true"
        End If
    End Function
   
    Function IsSectionExpandedByDefault(objHeader)
        IsSectionExpandedByDefault = (Right(objHeader.className, Len("_expanded")) = "_expanded")
    End Function
   
    Function document_onclick()
        Set strsrc = window.event.srcElement
        While (strsrc.className = "sectionTitle" or strsrc.className = "expando")
            Set strsrc = strsrc.parentElement
        Wend
        If Not IsSectionHeader(strsrc) Then Exit Function
        ToggleSection strsrc
        window.event.returnValue = False
    End Function
   
    Sub ToggleSection(objHeader)
        SetSectionState objHeader, "toggle"
    End Sub
   
    Sub SetSectionState(objHeader, strState)
        i = objHeader.sourceIndex
        Set all = objHeader.parentElement.document.all
        While (all(i).className <> "container")
            i = i + 1
        Wend
        Set objContainer = all(i)
        If strState = "toggle" Then
            If objContainer.style.display = "none" Then
                SetSectionState objHeader, "show"
            Else
                SetSectionState objHeader, "hide"
            End If
        Else
            Set objExpando = objHeader.children.item(1)
            If strState = "show" Then
                objContainer.style.display = "block"
                objExpando.innerText = strHide
   
            ElseIf strState = "hide" Then
                objContainer.style.display = "none"
                objExpando.innerText = strShow
            End If
        End If
    End Sub
   
    Function objshowhide_onClick()
        Set objBody = document.body.all
        Select Case strShowHide
            Case 0
                strShowHide = 1
                objshowhide.innerText = strShowAll
                For Each obji In objBody
                    If IsSectionHeader(obji) Then
                        HideSection obji
                    End If
                Next
            Case 1
                strShowHide = 0
                objshowhide.innerText = strHideAll
                For Each obji In objBody
                    If IsSectionHeader(obji) Then
                        ShowSection obji
                    End If
                Next
        End Select
    End Function
   
    Function IsSectionHeader(obj) : IsSectionHeader = (obj.className = "heading_collapsed") Or (obj.className = "heading_expanded"): End Function
    Sub HideSection(objHeader) : SetSectionState objHeader, "hide" : End Sub
    Sub ShowSection(objHeader) : SetSectionState objHeader, "show": End Sub
    </SCRIPT>
    </HEAD>
    <BODY>
    <p><b>    <font face="Arial" size="5"><b><i>Server Partition Alignment Report<hr size="4" color="#CCCC00"></i></b></font>
    <font face="Arial" size="1"><b><i><a href="http://sqlblog.com/blogs/jonathan_kehayias/archive/2010/03/01/getting-partition-offset-information-with-powershell.aspx">Version 1.0 by Jonathan Kehayias</a></i></b></font><br>
    <font face="Arial" size="1">Report generated on $Date </font></p>
    <TABLE cellSpacing=0 cellPadding=0>
        <TBODY>
            <TR>
                <TD>
                    <DIV id=objshowhide tabIndex=0><FONT face=Arial></FONT></DIV>
                </TD>
            </TR>
        </TBODY>
    </TABLE>
"@
#endregion

$header = "
        <DIV class=container>
            <DIV class={0}>
                <SPAN class=sectionTitle tabIndex=0>{1}</SPAN>
                <A class=expando href=’#’></A>
            </DIV>
            <DIV class=container>
                <DIV class=tableDetail>"
$footer = "
                </DIV>
            </DIV>
        </DIV>
        <DIV class=filler></DIV>"

Foreach ($Target in $Targets)
{
$Report+= $header -f "heading_collapsed", $Target

#region Disk Configuration

$drives = Get-WmiObject Win32_DiskDrive -ComputerName $Target

$s = New-Object System.Management.ManagementObjectSearcher
$s.Scope = "\$Targetrootcimv2"
$s2 = New-Object System.Management.ManagementObjectSearcher
$s2.Scope = "\$Targetrootcimv2"

$qPartition = new-object System.Management.RelatedObjectQuery
$qPartition.RelationshipClass = ‘Win32_DiskDriveToDiskPartition’

$qLogicalDisk = new-object System.Management.RelatedObjectQuery
$qLogicalDisk.RelationshipClass = ‘Win32_LogicalDiskToPartition’

$Report+= $header -f "heading_expanded", "Partitions"

$Report += "
                <TABLE>
                    <tr>
                        <th width=’15%’><b>Name</b></th>
                        <th width=’10%’><b>Drive Letter</b></th>
                        <th width=’10%’><b>Label</b></th>
                        <th width=’5%’><b>Size(GB)</b></th>
                        <th width=’10%’><b>File System</b></th>
                        <th width=’10%’><b>BlockSize</b></th>
                        <th width=’10%’><b>Offset</b></th>
                        <th width=’5%’><b>Index</b></th>
                        <th width=’5%’><b>IsPrimary</b></th>
                        <th width=’10%’><b>Disk Free Space</b></th>
                        <th width=’10%’><b>% Free Space</b></th>
                    </tr>"
   
$drives | Sort-Object DeviceID | % {
   $qPartition.SourceObject = $_
   $s.Query= $qPartition
   $s.Get()| where {$_.Type -ne ‘Unknown’} |% {
  
   $partition = $_;
  
   $partitionSize = ([math]::round(($($_.Size)/1GB),1))
       $qLogicalDisk.SourceObject = $_
       $s2.Query= $qLogicalDisk.QueryString
       $s2.Get()|% {
      
           $disksize = [math]::round(($_.size / 1048576))
        $freespace = [math]::round(($_.FreeSpace / 1048576))
        $percFreespace=[math]::round(((($_.FreeSpace / 1048576)/($objDisk.Size / 1048676)) * 100),0)

       $Report += "
                    <tr>
                        <td width=’15%’>$($partition.Name)</td>
                        <td width=’10%’>$($_.DeviceID)</td>
                        <td width=’10%’>$($_.VolumeName)</td>
                        <td width=’5%’>$PartitionSize GB</td>
                        <td width=’10%’>$($_.FileSystem)</td>
                        <td width=’10%’>$($partition.BlockSize)</td>
                        <td width=’10%’>$($partition.StartingOffset)</td>
                        <td width=’5%’>$($partition.DiskIndex)</td>
                        <td width=’5%’>$($partition.PrimaryPartition)</td>
                        <td width=’10%’>$Freespace MB</td>
                        <td width=’10%’>$percFreespace%</td>
                    </tr>
"      
        }
    }
}
$Report+= "
                </TABLE>
"
$Report+= $footer
$Report+= $footer
$Report+= $footer

#endregion  Disk Configuration
}

$Report+= @"
    </body>
    </html>
"@
$Report | out-file -encoding ASCII -filepath $Filename