Scripting Games Advanced – Event 3 My Submission
Lets first jote down the Event Requirement:
Input:
ComputerName(s) as string (from pipeline possible).
A Path to save output file.
Output:
An html file for each computer name provided.
The output should look like this:
Additional Requirements:
- Paramaterize the inputs
- Use Pipeline for ComputerName
- The browser displays “Disk Free Space Report” in the page tab when viewing the report.
- “Local Fixed Disk Report” is in the H2 (“Heading 2”) HTML style. If you can actually add the computer name to that – bonus!
- The report ends with an HTML horizontal rule and the date and time that the report was generated.
- The size and free space values are shown as gigabytes (GB) and megabytes (MB) respectively, each to two decimal places.
Here is the break down of my script:
Requirement one is to get free space, capacity, and drive letter of “Fixed” disks on a given machine. we can use Win32_LogicalDisk WMI Class to get this information. to filter and take only fixed disks we can use “DriveType=3″ as filter. you can read more about this class here.
Here is my parameter definitions:
Param ( #ComputerName to Generate Report For [Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [ValidateNotNullOrEmpty()] [Alias("CN","__SERVER","SERVER","host","PSComputerName","DNSHostName","MachineName")] [String[]] $ComputerName = $env:COMPUTERNAME, #Path (Directory) to store the html file [Parameter()] [ValidateScript({Test-Path -Path $_ -PathType Container})] [String] $Path = [environment]::GetFolderPath(“MyDocuments”), #Credential to use if required [Parameter()] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty )
- ComputerName is defined as a String Array, which accepts value from pipeline and by property name. There are also alisases defined here. The default is set to local machine
- Path is defined and a validation is done using Test-Path, the Default is set to Documents folder of the logged on user.
- A third paramter Credential is defined as a feature to use if the target machine needs alternate credentials.
The Credential is added to the wmioptions hash table defined in the Begin Block based on its presence:
Begin { #Define WMI Query Options $WmiOptions = @{} $WmiOptions.Class = 'Win32_LogicalDisk' $WmiOptions.Property = 'Name','Size','FreeSpace' $WmiOptions.Filter = 'DriveType = 3' $WmiOptions.ErrorAction = 'Stop' $WmiOptions.ErrorVariable = 'WmiError' #Add Credential to the WMI Options if it was specified if ($PSBoundParameters['Credential']) { $wmiOptions.Credential = $Credential } }
Credential is removed / preserverved based on the computer being processed, if its pointing to local machine credential is not used. we define an array for defining local hosts. and check the presense of computer name in it.
Begin { $LocalIPAddresses = [net.dns]::GetHostAddresses($env:COMPUTERNAME) | Select-Object -ExpandProperty IpAddressToString $Localhost = @('', '.', 'localhost', $env:COMPUTERNAME, '::1', '127.0.0.1',"$env:COMPUTERNAME.$env:USERDNSDOMAIN") + $LocalIPAddresses } process { #If Local Host Remove Credential from the Query Else Maintain/Add Credential to the Query if ($Localhost -contains $computer) { $wmiOptions.Remove('Credential') } else {$wmiOptions.Add('Credential',$Credential)} }
Next is the WMI Query:
$WmiOptions.ComputerName = $Computer $DiskInfo = Get-WmiObject @WmiOptions $DiskInfo = $DiskInfo | Select-Object Name, @{n='Size(GB)';e={"{0:N2}" -f ($_.Size/1Gb)}}, @{n='FreeSpace(MB)';e={"{0:N2}" -f ($_.FreeSpace/1Mb)}}
Preparing and Generating and Saving the Output File:
$HtmlDataSection = @{} $HtmlDataSection.As = 'Table' $HtmlDataSection.PreContent = "<h2>Local Fixed Disk Report For : $($Computer.ToUpper()) </h2>" $HtmlDataSection.PostContent = "<hr/>`n$(Get-Date)" $HtmlDataSection.Head = "$css`n<title>Drive Free Space Report</title>" $Html = $DiskInfo | ConvertTo-Html @HtmlDataSection $Html | Out-File -FilePath $(Join-Path -Path $Path -ChildPath "$computer.html") -Force -ErrorAction Stop
I have also applied a short css style to the html report. and here is the output of my script:
<# .Synopsis This fucntion Get-DiskInfo Get Fixed Disks Free Space Report .DESCRIPTION The Get-DiskInfo Collects disk info using WMI. It Only takes into account fixed disk. Fixed disks are identified using "DriveType" property of Win32_LogicalDisk WMI Instance. The Resulting Data is converted to a format suitable for html style display. .PARAMETER ComputerName The computer name to collect data from, default is local machine. This can be a one or more computernames as strings .PARAMETER Path The Directory Path to store resulting html file. Defaults to My Documents folder of currently logged on user. .PARAMETER Credential The Credential parameter is used when specified for remote machines. This is useful when the logged on user doesnt have necessary rights to the target machine. .EXAMPLE Get-DiskInfo This Provides the report of local machine as an html file in currently logged on users My Documents Folder .EXAMPLE "RemoteHost","localhost","MyPC" | Get-DiskInfo -Path C:\Temp This Cmdlet will provide three html file output for each computer name provided and will be stroed in C:\Temp folder .EXAMPLE "RemoteHost","localhost","MyPC" | Get-DiskInfo -Path C:\Temp -Credential Get-Credential This Cmdlet will provide three html file output for each computer name provided and will be stroed in C:\Temp folder In Addition it will use the alternate credential provided to query Remote PCs, for local Credential will not be used. .INPUTS System.String .OUTPUTS HTML File (No Output to Host Display) .NOTES Version: 1.0 #> function Get-DiskInfo { [CmdletBinding()] Param ( #ComputerName to Generate Report For [Parameter(ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)] [ValidateNotNullOrEmpty()] [Alias("CN","__SERVER","SERVER","host","PSComputerName","DNSHostName","MachineName")] [String[]] $ComputerName = $env:COMPUTERNAME, #Path (Directory) to store the html file [Parameter()] [ValidateScript({Test-Path -Path $_ -PathType Container})] [String] $Path = [environment]::GetFolderPath(“MyDocuments”), #Credential to use if required [Parameter()] [System.Management.Automation.Credential()] $Credential = [System.Management.Automation.PSCredential]::Empty ) Begin { Write-Verbose "Initializing Function Environment" #Define WMI Query Options $WmiOptions = @{} $WmiOptions.Class = 'Win32_LogicalDisk' $WmiOptions.Property = 'Name','Size','FreeSpace' $WmiOptions.Filter = 'DriveType = 3' $WmiOptions.ErrorAction = 'Stop' $WmiOptions.ErrorVariable = 'WmiError' #Add Credential to the WMI Options if it was specified if ($PSBoundParameters['Credential']) { $wmiOptions.Credential = $Credential } #Defining entries which will be pointing at the local host from which the funtion/script is called $LocalIPAddresses = [net.dns]::GetHostAddresses($env:COMPUTERNAME) | Select-Object -ExpandProperty IpAddressToString $Localhost = @('', '.', 'localhost', $env:COMPUTERNAME, '::1', '127.0.0.1',"$env:COMPUTERNAME.$env:USERDNSDOMAIN") + $LocalIPAddresses $css = @' <style type="text/css"> body { font-family: Tahoma, Geneva, Verdana, sans-serif;background-color: #DDDDDD} h2 { color:#6699CC} table {font-family:"Trebuchet MS", Arial, Helvetica, sans-serif; width:50%; border-collapse:collapse; background-color: #abcdef; border: 3px solid #ffffff;} th {font-size:14px; border:1px solid #ffffff; padding-top:5px; padding-bottom:4px; text-align:left; background-color:#abcdff; color:#ffffff; font-weight: bold;} tr {font-size:12px; border:1px solid #ffffff; padding:3px 7px 2px 7px; margin: 3px; vertical-align: top; color: #000;} td {font-size:12px; border:1px solid #ffffff; padding:3px 7px 2px 7px; margin: 3px; vertical-align: top; color: #000;} hr {background-color:#123456; border-width:1; color:#000000; height:2px; line-height:0; text-align:left; width:50%;} </style> '@ } Process { foreach($computer in $ComputerName) { Write-Verbose "Working on Computer:$computer" if(Test-Connection -ComputerName $computer -Count 1 -Quiet) { #If Local Host Remove Credential from the Query Else Maintain/Add Credential to the Query if ($Localhost -contains $computer) { $wmiOptions.Remove('Credential') } else {$wmiOptions.Add('Credential',$Credential)} Write-Verbose "Collecting Disk Info from $computer using WMI" #collect WMI Data from computer $WmiOptions.ComputerName = $Computer try { $DiskInfo = Get-WmiObject @WmiOptions $DiskInfo = $DiskInfo | Select-Object Name, @{n='Size(GB)';e={"{0:N2}" -f ($_.Size/1Gb)}}, @{n='FreeSpace(MB)';e={"{0:N2}" -f ($_.FreeSpace/1Mb)}} } catch { Write-Warning "Unable to fetch wmi data from $computer" Write-Verbose "Unable to fetch wmi data from $computer, below error occured : `n $_" Write-Verbose "Completed Processing $Computer" } #prepare output only if WMI call was successful if(-not $WmiError) { Write-Verbose "Generating HTML File Stream to create output file" #Generating HTML File Stream $HtmlDataSection = @{} $HtmlDataSection.As = 'Table' $HtmlDataSection.PreContent = "<h2>Local Fixed Disk Report For : $($Computer.ToUpper()) </h2>" $HtmlDataSection.PostContent = "<hr/>`n$(Get-Date)" $HtmlDataSection.Head = "$css`n<title>Drive Free Space Report</title>" $Html = $DiskInfo | ConvertTo-Html @HtmlDataSection } try { Write-Verbose "Saving Output to File $(Join-Path -Path $Path -ChildPath "$computer.html")" $Html | Out-File -FilePath $(Join-Path -Path $Path -ChildPath "$computer.html") -Force -ErrorAction Stop Write-Verbose "Completed Processing $Computer" } catch { Write-Error "Unable to Save the Output File $(Join-Path -Path $Path -ChildPath "$computer.html")" Write-Verbose "Completed Processing $Computer" } } else { Write-Error "Unable to reach $computer on Network" Write-Verbose "Completed Processing $Computer" } } } End { Remove-Variable -Name WmiOptions,LocalIPAddresses,Localhost,css -Force -ErrorAction SilentlyContinue } }
You can download the complete script here.
Cheers