Quantification.psm1

<#
▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄
                       Write Quantification Module
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                        Author: Jason A. Yoder
▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
#>


Function Write-Quantification {
<#
.SYNOPSIS
Writes information to a central repository to quantify the time savings of a
task performed with PowerShell.
 
.DESCRIPTION
This function is designed to be added to and called from within your code.
The concept is to have this function execute as the final item in your code,
once the rest of the code completes. This will allow you to record the
time that PowerShell saves you, and others.
 
 
.PARAMATER LogPath
The full path to where you log file is stored. For Example
\\SVR1\Log\Quantification.csv
 
.PARAMATER DateTime
A string in the format of YYY/MM/DD HH:MM:SS. This is automatically generated
for you.
 
.PARAMATER UserName
The name of the user utilizing your code. For code running with a logged in
user, this is automatically generated for you. For scripts running as a
scheduled task, provide a value to let you know this is an automated
task such as "Automated".
 
.PARAMATER ScriptName
The name of the script or cmdlet executed.
 
.PARAMATER ComputerName
The name of the computer where this code is executed. It is automatically
generated for you.
 
.PARAMATER TimeSavedMin
The total number of minutes saved.
 
Do not embellish this number. Be accurate.
 
.PARAMATER Message
If you need to provide an message in the log.
 
.PARAMATER EventID
Use the following EVENTID Numbers.
1 - Successfully Completed
 
.Example
Write-Quantification -ScriptName Test1 -TimeSavedMin 15 -Message "This is a test." -EventID 1 -LogPath "\\dc1\QuantificationLog\QuantificationLog.CSV"
 
Adds a new log entry to a log stored at "\\dc1\QuantificationLog\QuantificationLog.CSV".
The name of the script is "Test1" and the estimated tiem saved is 15 minutes.
#>

[CmdletBinding(SupportsShouldProcess=$False)]
Param (
    [String]
    $LogPath = "\\dc1\QuantificationLog\QuantificationLog.CSV",

    [String]
    $DateTime = (Get-date -Format "YYYY/MM/DD hh:mm:ss"),

    [String]
    $UserName = $ENV:USERNAME,

    [parameter(Mandatory=$true,
     HelpMessage="Provide a name for the script or cmdlet used.")]
    [String]
    $ScriptName,

    [String]
    $ComputerName = $env:COMPUTERNAME,

    [parameter(Mandatory=$true,
     HelpMessage="Provide the total number of minutes this code saved the user.")]
    [Int]
    $TimeSavedMin,

    [parameter(Mandatory=$true,
     HelpMessage="Provide any message information here.")]
    [String]
    $Message,

    [parameter(Mandatory=$true,
     HelpMessage="Provide an EventID. Look at the help file for details.")]
    [Int]
    $EventID

    )
BEGIN {
    Function New-QuantificationLog-Object {
        $Obj = New-Object -TypeName psobject -Property @{
            'DateTime' = $Null
            'UserName' = $Null
            'ScriptName' = $Null
            'ComputerName' = $Null
            'TimeSavedMin' = $Null
            'Message' = $Null
            'EventID' = $Null
        }
        Write-Output $Obj
    } # END: Function New-QuantificationLog-Object
} # END: BEGIN Block
PROCESS {
    
    # Create the object to be sent to the event log.
    $Obj = New-QuantificationLog-Object
    $Obj.DateTime = $DateTime
    $Obj.UserName = $UserName
    $Obj.ScriptName = $ScriptName
    $Obj.ComputerName = $ComputerName
    $Obj.TimeSavedMin = $TimeSavedMin
    $Obj.Message = $Message
    $Obj.EventID = $EventID

    # Verify the event log exists.
    Try {
        #$TestPath = $LogPath.Remove($LogPath.LastIndexOf("\"),$LogPath.Length-$Logpath.LastIndexOf("\"))
            #Test-Path -Path $LogPath -ErrorAction Stop
            #Write-Host $LogPath -ForegroundColor Green

            $Obj | Export-Csv -Path $LogPath -Append -ErrorAction Stop
        } # END: TRY
    Catch {$_ <# Do nothing... No big deal.#>}

} # END: PROCESS Block
END {} #END: END Block
} # END: Function Write-Quantification

#Write-Quantification -ScriptName Test1 -TimeSavedMin 15 -Message "This is a test." -EventID 1
#Import-CSV -Path "\\dc1\QuantificationLog\QuantificationLog.CSV" | Ft

<# █████████████████████████████████████████████████████████████████████████ #>

Function Get-Quantification {
<#
.SYNOPSIS
Reads a Quantification log into the pipeline.
 
.DESCRIPTION
Reads a Quantification log into the pipeline in a format to be passed
to Measure-Quantification.
 
.EXAMPLE
Get-Quantification -LogPath C:\ps\Quantification.csv
 
Gathers log information from C:\ps\Quantification.csv and places it
into an object in the pipeline.
#>

[CmdletBinding(SupportsShouldProcess=$False)]
Param (
    [parameter(Mandatory=$true,
     HelpMessage="Provide a path where to Get the log files.")]
    [String]
    $LogPath
)
BEGIN {} # END: BEGIN Block
PROCESS {
    # Verify the event log exists.
    Try {
            Test-Path -Path $LogPath -ErrorAction Stop | Out-Null

            Import-Csv -Path $LogPath 
        } # END: TRY
    Catch {Write-Warning "Cannot access the Log."}

} # END: PROCESS Block
END {} #END: END Block
} # END: Function Get-Quantification

# Get-Quantification -LogPath C:\ps\Quantification.txt

<# █████████████████████████████████████████████████████████████████████████ #>

Function Measure-Quantification {
<#
.SYNOPSIS
Aggregates the data from a log based on user requirements.
 
.DESCRIPTION
Aggregates the data from a quantification log based on usage by users, computers,
or script usage.
 
.PARAMETER QuantificationData
Accepts the data object produced by the cmdlet 'Get-Quantification'.
 
.PARAMETER ReportByUser
This is the default setting. This quantifies the use of your code based on
user activity.
 
.PARAMETER ReportByComputer
This quantifies the use of your code based on computer activity.
 
.PARAMETER ReportByScript
This quantifies the use of your code based on code usage.
 
.EXAMPLE
Get-Quantification -LogPath \\dc1\QuantificationLog\QuantificationLog.CSV | Measure-Quantification -ReportByComputer
 
Gathers log information from \\dc1\QuantificationLog\QuantificationLog.CSV and
quantifies the time saved based on usage by computer.
#>

[CmdletBinding(DefaultParameterSetName="User",SupportsShouldProcess=$False)]
Param (
    [parameter(Mandatory=$true,
               ValueFromPipeline=$true)]
    [PSObject[]]
    $QuantificationData,

    [parameter(ParameterSetName="User")]
    [Switch]
    $ReportByUser,


    [parameter(ParameterSetName="Computer")]
    [Switch]
    $ReportByComputer,

    [parameter(ParameterSetName="Script")]
    [Switch]
    $ReportByScript

    
)
BEGIN {
    # Initialize the array.
    $Data = New-Object -TypeName System.Collections.ArrayList

    # Check to see if one of the switch parameters are used.
    # If not, Set to report by user.
    If ($PSBoundParameters.Keys -contains 'ReportByComputer') {$Mode = 'ReportByComputer'}
    ElseIf ($PSBoundParameters.Keys -contains 'ReportByScript') {$Mode = 'ReportByScript'}
    Else {$Mode = 'ReportByUser'}

    # Generate the output object template.
    Function New-OutputObject {
        $Obj = New-Object -TypeName PSObject -Property @{
            "Principal" = $Null
            "TimeSavedMin" = $Null
            "NumberOfEvents" = $Null
            "TimeSavedHours" = $Null
            "TimeSavedDays" = $Null
        }
        $Obj.PSObject.TypeNames.Insert(0,'MCTExpert.Quantification')
        Write-Output $Obj
    } # END: Function New-OutputObject

    # Populate the output object.
    Function Populate-Output-Object {
        Param ($Principal, $TimeSaved, $NumberOfEvents)

        $Obj = New-OutputObject
        $Obj.Principal = $Principal
        $Obj.TimeSavedMin = $TimeSaved
        $Obj.NumberOfEvents = $NumberOfEvents
        $Obj.TimeSavedHours = (($TimeSaved / 60).ToString('#.##') -as [Single])
        $Obj.TimeSavedDays = ((($TimeSaved / 60) / 24).ToString('#.##') -as [Single])

        Write-Output $OBJ       
    } # END: Function Populate-Output-Object

    # Extract information based on user activity.
    Function Mode-ReportByUser {
        Param ($Data )
        $Users = $data | Select-Object -Property UserName -Unique

        ForEach ($User in $Users.UserName) {
            $NumberOfEvents = 0
            $TimeSaved = 0
            $Data |
                Where-Object {$_.UserName -eq $User} |
                ForEach-Object {
                    $NumberOfEvents++
                    $TimeSaved += $_.TimeSavedMin
                }
            Populate-Output-Object -Principal $User -TimeSaved $TimeSaved -NumberOfEvents $NumberOfEvents
        }
    } # END: Function Mode-ReportByUser

    # Extract information based on user node.
    Function Mode-ReportByComputer {
        Param ($Data )
        $Computers = $data | Select-Object -Property ComputerName -Unique
        
        ForEach ($Computer in $Computers.ComputerName) {
            $NumberOfEvents = 0
            $TimeSaved = 0
            $Data |
                Where-Object {$_.ComputerName -eq $Computer} |
                ForEach-Object {
                    $NumberOfEvents++
                    $TimeSaved += $_.TimeSavedMin
                }
            Populate-Output-Object -Principal $Computer -TimeSaved $TimeSaved -NumberOfEvents $NumberOfEvents
        }
    } # END: Function Mode-ReportByComputer

    # Extract information based on user code.
    Function Mode-ReportByScript {
        Param ($Data )
        $Scripts = $data | Select-Object -Property ScriptName -Unique
        
        ForEach ($Script in $Scripts.ScriptName) {
            $NumberOfEvents = 0
            $TimeSaved = 0
            $Data |
                Where-Object {$_.ScriptName -eq $Script} |
                ForEach-Object {
                    $NumberOfEvents++
                    $TimeSaved += $_.TimeSavedMin
                }
            Populate-Output-Object -Principal $Script -TimeSaved $TimeSaved -NumberOfEvents $NumberOfEvents
        }
    }



} # END: BEGIN Block
PROCESS {

    # Read in the data and add the data to the arraylist.
    ForEach ($Item in $QuantificationData) {
        $Data.Add($Item) | Out-Null
    } # END: ForEach ($Item in $QuantificationData)



} # END: PROCESS Block
END {
    
    # Determine how to report the data.
    Switch ($Mode) {
        "ReportByUser" {Mode-ReportByUser -Data $Data}
        "ReportByComputer" {Mode-ReportByComputer -Data $Data}
        "ReportByScript" {Mode-ReportByScript -Data $Data}
    }


} #END: END Block
} # END: Function Measure-Quantification


Get-Quantification -LogPath \\dc1\QuantificationLog\QuantificationLog.CSV | Measure-Quantification -ReportByComputer


<# █████████████████████ End of Quantification Module ██████████████████████ #>