AdministrativeAddOn.psm1

function Get-LastBoot (
    [Parameter(Mandatory=$false)][string]$ComputerName,
    [Parameter(Mandatory=$false)][ValidateNotNull()]
    [System.Management.Automation.PSCredential][System.Management.Automation.Credential()]
        $Credential = [System.Management.Automation.PSCredential]::Empty
)
{
    <#
        .Synopsis
            Retrieves last system boot time
        .Description
            The Get-LastBoot function queries the system to report the last OS boot time. This command may be run locally or remotely using the 'ComputerName' parameter. `
            The 'Credential' parameter may be necessary when querying remote systems.
        .Inputs
            N/A
        .Outputs
            System.DateTime
        .Example
            Get-LastBoot
 
            Saturday, November 20, 2020 4:32:06 AM
        .Example
            $Creds = Get-Credential
            Get-LastBoot -ComputerName 'Server1' -Credential $Creds
 
            Wednesday, April 14, 2018 6:05:01 AM
        .Link
            N/A
    #>


    # RETRIEVES OS START TIME
    If ($ComputerName -ne $null) {
        (Get-CimInstance -ClassName Win32_OperatingSystem -ComputerName $ComputerName).LastBootUpTime
    } Else {
        (Get-CimInstance -ClassName Win32_OperatingSystem).LastBootUpTime
    }
}

function Get-UpTime (
    [Parameter(Mandatory=$false)][string]$ComputerName,
    [Parameter(Mandatory=$false)][ValidateNotNull()]
    [System.Management.Automation.PSCredential][System.Management.Automation.Credential()]
        $Credential = [System.Management.Automation.PSCredential]::Empty
)
{
    <#
        .Synopsis
            Calculates uptime for system
        .Description
            The Get-UpTime function calculates the amount of time since the last system boot time. This command may be run locally or remotely using the 'ComputerName' `
            parameter. The 'Credential' parameter may be necessary when querying remote systems.
        .Inputs
            N/A
        .Outputs
            System.TimeSpan
        .Example
            Get-UpTime
 
            Days Hours Minutes Seconds
            ---- ----- ------- -------
               2 19 11 42
        .Example
            Get-UpTime -ComputerName 'Server1'
 
            Days Hours Minutes Seconds
            ---- ----- ------- -------
              52 12 55 17
 
        .Link
            N/A
    #>


    # GATHERS DATA
    $CompData = Get-CimInstance -ClassName Win32_OperatingSystem

    # CALCULATES UP TIME AND REMOVES UNUSABLE DATA
    $CompData.LocalDateTime - $CompData.LastBootUpTime | Select-Object -Property Days,Hours,Minutes,Seconds
}

function Get-UserSession
(
    [Parameter(Mandatory=$false)][string]$ComputerName,
    [Parameter(Mandatory=$false)][string]$UserName,
    [Parameter(Mandatory=$false)][ValidateSet("Active","Disc","Idle")][string]$State
)
{
    <#
        .Synopsis
            Reports all console, RDP, and ICA sessions.
        .Description
            The Get-UserSession function executes a 'quser' command but converts it into a custom PS object. This can then be piped into a Remove-UserSession command to force log off of all sessions on a system or specific sesssions.
        .Inputs
            N/A
        .Outputs
            System.Management.Automation.PSCustomObject
        .Example
            Get-UserSession
 
            USERNAME : john.doe
            SESSIONNAME : console
            ID : 4
            STATE : Active
            IDLE_TIME : none
            LOGON_TIME : 11/24/2020 9:54 AM
            SERVER : Workstation1
 
            USERNAME : jane.doe
            SESSIONNAME : rdp-tcp#10
            ID : 5
            STATE : Idle
            IDLE_TIME : 16:45
            LOGON_TIME : 11/24/2020 3:10 PM
            SERVER : Workstation1
        .Example
            Get-UserSession -State Active
 
            USERNAME : john.doe
            SESSIONNAME : console
            ID : 4
            STATE : Active
            IDLE_TIME : none
            LOGON_TIME : 11/24/2020 9:54 AM
            SERVER : Workstation1
        .Example
            Get-UserSession -UserName jane.doe
 
            USERNAME : jane.doe
            SESSIONNAME : rdp-tcp#10
            ID : 5
            STATE : Idle
            IDLE_TIME : 16:45
            LOGON_TIME : 11/24/2020 3:10 PM
            SERVER : Workstation1
        .Link
            N/A
    #>


    # RESERVES VARIABLES
    $UserSession = @()
    $Session = $null
    $SessionCnt = $null

    # RUNS QUSER AND CAPTURES DATA, REMOVES ALL BULK SPACES AND REPLACES WITH A SINGLE SPACE
    If ($ComputerName -eq "") {
        $QResults = quser
        $ComputerName = $env:COMPUTERNAME
    } Else {
        $QResults = quser /SERVER:$ComputerName
    }

    $QResults = $QResults -replace '\s+', ' '

    # CREATES OBJECT FOR EACH RETURNED RESULT
    Foreach ($Line in $QResults[1..$QResults.GetUpperBound(0)]) {
        #Separates the data
        $Split = $Line.Split(' ').Split('>')

        # SESSIONNAME IS BLANK WHEN THE SESSION IS DISCONNECTED. MODIFIES DATA ACCORDINGLY.
        If ($Split[3] -eq 'Disc') {
            $Session = ""
            $SessionCnt = 1
        }  Else {
            $Session = $Split[2]
            $SessionCnt = 2
        }

        # CREATES OBJECTS
        $UserSession += [pscustomobject]@{
            USERNAME = $Split[1]
            SESSIONNAME = $Session
            ID = $Split[$SessionCnt + 1]
            STATE = $Split[$SessionCnt + 2]
            IDLE_TIME = $Split[$SessionCnt + 3]
            LOGON_TIME = ($Split[($SessionCnt + 4)..($SessionCnt + 6)] -join ' ')
            SERVER = $ComputerName
        }

        # RESETS LOOP VARIABLES
        $Session = $null
        $SessionCnt = $null
    }

    # FILTERS ALL USER SESSIONS BY USERNAME
    If ($UserName -ne "") {
        $UserSession = $UserSession | Where-Object {$_.UserName -eq $UserName}
    }

    # FILTERS ALL USER SESSIONS BY STATE
    If ($State -ne "") {
        $UserSession = $UserSession | Where-Object {$_.State -eq $State}
    }

    # RETURNS ALL REQUESTED USER SESSIONS
    Return $UserSession
}

function Remove-UserSession (
    [Parameter(ParameterSetName="ID", Mandatory=$true)][int]$ID,
    [Parameter(ParameterSetName="ID", Mandatory=$false)][string]$ComputerName,
    [Parameter(ParameterSetName="InputObject", ValueFromPipeline, Mandatory=$true)]$InputObject
)
{
    <#
        .SYNOPSIS
            Forces a logoff of the selected session by Id number.
        .DESCRIPTION
            The Remove-UserSession function logs off all user sessions provide by the 'ID' parameter or from the pipeline. The 'ComputerName' parameter can be utilized to logoff users on remote computers.
        .INPUTS
            System.Management.Automation.PSCustomObject
        .OUTPUTS
            N/A
        .EXAMPLE
            Remove-UserSession -Id 5
        .EXAMPLE
            Get-UserSession -State Disc | Remove-UserSession
        .LINK
            N/A
    #>


    # LOGS OFF THE SESSION EITHER LOCALLY OR REMOTELY BASED UPON USAGE OF SERVER PARAMETER
    If ($null -ne $InputObject) {
        Foreach ($InObj in $InputObject) {
            logoff $($InObj.ID) /SERVER:$($InObj.SERVER)
        }
    } ElseIf ($null -ne $ID) {
        If ($ComputerName -eq "") {
            $ComputerName = $env:COMPUTERNAME
        } 
            logoff $ID /SERVER:$ComputerName
    }
}

function Get-InstalledSoftware (
    [CmdletBinding(DefaultParameterSetName="Name")]
    [Parameter(ParameterSetName="Name", Mandatory=$false)][string]$Name,
    [Parameter(ParameterSetName="All", Mandatory=$false)][switch]$All,
    [Parameter(ParameterSetName="Filter", Mandatory=$false)][string]$Filter
)
{
    <#
        .SYNOPSIS
            Gathers list of non-metro applications that are installed.
        .DESCRIPTION
            The Get-InstalledSoftware function gathers a list from the registry of standard installed applications. The 'Name' parameter can be used if you know the exact name of the software otherwise 'Filter' should be used as it will provide all software with a matching name. The 'All' parameter will output all install software.
        .INPUTS
            N/A
        .OUTPUTS
            System.Management.Automation.PSCustomObject
        .EXAMPLE
            Get-InstalledSoftware -All
 
            Name : PuTTY release 0.70 (64-bit)
            Publisher : Simon Tatham
            Version : 0.70.0.0
            InstallDate : 20201126
            InstallLocation :
            UninstallString : MsiExec.exe /X{45B3032F-22CC-40CD-9E97-4DA7095FA5A2}
            QuietUninstallString :
 
            Name : Google Chrome
            Publisher : Google LLC
            Version : 87.0.4280.66
            InstallDate : 20201126
            InstallLocation : C:\Program Files\Google\Chrome\Application
            UninstallString : "C:\Program Files\Google\Chrome\Application\87.0.4280.66\Installer\setup.exe" --uninstall --system-level --verbose-logging
            QuietUninstallString :
 
        .EXAMPLE
            Get-InstalledSoftware -Name "Google Chrome"
 
            Name : Google Chrome
            Publisher : Google LLC
            Version : 87.0.4280.66
            InstallDate : 20201126
            InstallLocation : C:\Program Files\Google\Chrome\Application
            UninstallString : "C:\Program Files\Google\Chrome\Application\87.0.4280.66\Installer\setup.exe" --uninstall --system-level --verbose-logging
            QuietUninstallString :
 
        .EXAMPLE
            Get-InstalledSoftware -Filter "Chrome"
 
            Name : Google Chrome
            Publisher : Google LLC
            Version : 87.0.4280.66
            InstallDate : 20201126
            InstallLocation : C:\Program Files\Google\Chrome\Application
            UninstallString : "C:\Program Files\Google\Chrome\Application\87.0.4280.66\Installer\setup.exe" --uninstall --system-level --verbose-logging
            QuietUninstallString :
        .LINK
            N/A
    #>


    # ENSURES FUNCTION VARIABLES ARE RESET
    $OutputArray = @()
    $SoftData = @()

    # GATHERS INSTALLED PROGRAMS
    $SoftData += Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*"
    $SoftData += Get-ItemProperty -Path "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*"

    # CREATES CUSTOM OUTPUT OBJECTS
    Foreach ($Soft in $SoftData) {
        If (($null -ne $Soft.DisplayName) -and ($null -ne $Soft.Publisher)) {
            $OutputArray += [PSCustomObject]@{
                Name = $Soft.DisplayName
                Publisher = $Soft.Publisher
                Version = $Soft.DisplayVersion
                InstallDate = $Soft.InstallDate
                InstallLocation = $Soft.InstallLocation
                UninstallString = $Soft.UninstallString
                QuietUninstallString = $Soft.QuietUninstallString
            }
        }
    }
    
    # OUTPUTS BASED UPON PARAMETER SELECTION
    If ($All) {
        Return $OutputArray
    } ElseIf ($Name -ne "") {
        Return $OutputArray | Where-Object {$_.Name -eq $Name}
    } ElseIf ($Filter -ne "") {
        Return $OutputArray | Where-Object {$_.Name -match $Filter}
    }
}

function Remove-InstalledSoftware (
    [Parameter(ParameterSetName="Name", Mandatory = $false)][string]$Name,
    [Parameter(ValueFromPipeline, ParameterSetName="InputObject", Mandatory=$false)]$InputObject,
    [Parameter(ParameterSetName="Name", Mandatory=$false)][Parameter(ParameterSetName="InputObject")][switch]$Quiet
)
{
    <#
        .SYNOPSIS
            Kicks off uninstallation of designated software.
        .DESCRIPTION
            The Remove-InstalledSoftware function initiates an uninstallation of software provide by name or provided from the pipeline from Get-InstalledSoftware. The 'Quiet' switch will initiate quiet uninstallations of each piece of software selected. If the UninstallString in the registry refers to MsiExec the standard switches for quiet uninstall '/qn' are appended to initiate uninstallation.
        .INPUTS
            System.Management.Automation.PSCustomObject
        .OUTPUTS
            N/A
        .EXAMPLE
            Remove-InstalledSoftware -Name "Google Chrome"
        .EXAMPLE
            Get-InstalledSoftware -Filter "PuTTY" | Remove-InstalledSoftware -Quiet
        .LINK
            N/A
    #>

    Process {
        # GETS VALID PIPELINE DATA
        If ($null -ne $InputObject) {
            $Name = $InputObject.Name
            $UninstallString = $InputObject.UninstallString
            $QuietUninstallString = $InputObject.QuietUninstallString
        }

        # ADJUSTS APPROACH IF QUIET WAS SELECTED
        If ($Quiet) {
            If ($Name -ne "") {
                $Soft = Get-InstalledSoftware -Name $Name
                $UninstallString = $Soft.UninstallString
                $QuietUninstallString = $Soft.QuietUninstallString
            }

            # ADDS STANDARD QUIET UNINSTALL PARAMETERS FOR MSIEXEC PROGRAMS
            If ($UninstallString -match "MsiExec.exe") {
                $QuietUninstallString = "$UninstallString /qn"
            }

            # RETURNS ERROR IF THERE IS NO QUIET UNINSTALL DATA
            If ($null -eq $QuietUninstallString) {
                Write-Error -Message "Quiet uninstall string unavailable for selected software: $($Name)."
                Break
            }

            # PASSES QUIET UNINSTALL FOR FUTURE PROCESSING
            $UninstallString = $QuietUninstallString

            Write-Host -ForegroundColor Yellow "Beginning uninstallation of `'$Name`'..."
        } Else {
            If ($Name -ne "") {
                $Soft = Get-InstalledSoftware -Name $Name
                $UninstallString = $Soft.UninstallString
            }
        }

        # PARSES UNINSTALLSTRING TO GET THE EXECUTABLE PATH AND ARGUMENT LIST
        $UninstallSplit = $UninstallString.TrimStart('"').Replace('.exe ','.exe" ').Split('"').TrimStart()
        $UninstallPath = $UninstallSplit[0]
        $UninstallParameters = $UninstallSplit[1]

        # INITIATES UNINSTALL
        If ($UninstallParameters -ne "") {
            Start-Process -FilePath $UninstallPath -ArgumentList $UninstallParameters -Wait
        } Else {
            Start-Process -FilePath $UninstallPath -Wait
        }
    }

    End {

    }
}

function Get-HardwareInfo (
    [Parameter(Mandatory=$false)][string]$ComputerName,
    [Parameter(Mandatory=$false)][ValidateNotNull()]
    [System.Management.Automation.PSCredential][System.Management.Automation.Credential()]
        $Credential = [System.Management.Automation.PSCredential]::Empty
)
{
    <#
        .SYNOPSIS
            Gathers all major hardware component info to provide a picture of the core hardware of the system.
        .DESCRIPTION
            The Get-HardwareInfo function gets info from the motherboard, processor(s), RAM DIMM(s), GPU(s), Drive(s) and NIC(s). If there are mulitple items for any component except motherboard each items information will be emunerated.
        .INPUTS
            N/A
        .OUTPUTS
            System.Management.Automation.PSCustomObject
        .EXAMPLE
            Get-HardwareInfo
 
            Gathering system data, please wait...
 
            Computer : System1
            Manufacturer : Micro-Star International Co., Ltd.
            Model : MS-7A33
            Motherboard : X370 KRAIT GAMING (MS-7A33)
            SerialNumber : 6301-3908-3237-3716-4735-3460-25
            BIOSVerions : 1.H0
            BIOSReleaseDate : 1/20/2019 5:00:00 PM
            CPU0 : AMD Ryzen 5 1600X Six-Core Processor
            CPU0_Socket : AM4
 
            There is more data but is cut off by the limitations of the Example function.
        .LINK
            N/A
    #>


    # RESETS BASE VARIABLES TO ENSURE CLEAN EXECUTION
    $cnt = 0
    $HData = $null
    $CrossRefNIC = $null

    If ($ComputerName -eq "") {
        Write-Host -ForegroundColor Yellow "Gathering system data, please wait..."

        # GET MOTHERBOARD INFO
        $CompData = Get-CimInstance -ClassName CIM_ComputerSystem -Property *
        $MoboData = Get-CimInstance -ClassName CIM_PhysicalPackage -Property *
        $BIOSData = Get-CimInstance -ClassName CIM_BIOSElement -Property *

        # GETS PROCESSOR INFO
        $ProcData = Get-CimInstance -ClassName CIM_Processor -Property *

        # GETS RAM INFO
        $DIMMData = Get-CimInstance -ClassName CIM_PhysicalMemory -Property *

        # GETS GRAPHICS CARD INFO
        $GPUData = Get-CimInstance -ClassName CIM_VideoController -Property *

        # GETS DISK DRIVE INFO
        $DriveData = Get-CimInstance -ClassName CIM_DiskDrive -Property *

        # GETS NETWORK INTERFACE CARD INFO
        $NetData = Get-NetAdapterHardwareInfo
        $MoreNetData = Get-NetAdapter
    } Else {
        Write-Host -ForegroundColor Yellow "Gathering system data, please wait..."
        
        # GET MOTHERBOARD INFO
        $CompData = Invoke-Command -ScriptBlock {Get-CimInstance -ClassName CIM_ComputerSystem -Property *} -ComputerName $ComputerName -Credential $Credential
        $MoboData = Invoke-Command -ScriptBlock {Get-CimInstance -ClassName CIM_PhysicalPackage -Property *} -ComputerName $ComputerName -Credential $Credential
        $BIOSData = Invoke-Command -ScriptBlock {Get-CimInstance -ClassName CIM_BIOSElement -Property *} -ComputerName $ComputerName -Credential $Credential

        # GETS PROCESSOR INFO
        $ProcData = Invoke-Command -ScriptBlock {Get-CimInstance -ClassName CIM_Processor -Property *} -ComputerName $ComputerName -Credential $Credential

        # GETS RAM INFO
        $DIMMData = Invoke-Command -ScriptBlock {Get-CimInstance -ClassName CIM_PhysicalMemory -Property *} -ComputerName $ComputerName -Credential $Credential

        # GETS GRAPHICS CARD INFO
        $GPUData = Invoke-Command -ScriptBlock {Get-CimInstance -ClassName CIM_VideoController -Property *} -ComputerName $ComputerName -Credential $Credential

        # GETS DISK DRIVE INFO
        $DriveData = Invoke-Command -ScriptBlock {Get-CimInstance -ClassName CIM_DiskDrive -Property *} -ComputerName $ComputerName -Credential $Credential

        # GETS NETWORK INTERFACE CARD INFO
        $NetData = Invoke-Command -ScriptBlock {Get-NetAdapterHardwareInfo} -ComputerName $ComputerName -Credential $Credential
        $MoreNetData = Invoke-Command -ScriptBlock {Get-NetAdapter} -ComputerName $ComputerName -Credential $Credential
    }

    # CREATES OUPUT OBJECT
    $HData = [pscustomobject]@{
        Computer = $CompData.DNSHostName
        Manufacturer = $CompData.Manufacturer
        Model = $CompData.Model
        Motherboard = ($MoboData | Where-Object {$_.Name -match "Base Board"}).Product
        SerialNumber = $BIOSData.SerialNumber
        BIOSVerions = $BIOSData.SMBIOSBIOSVersion
        BIOSReleaseDate = $BIOSData.ReleaseDate
    }

    # GENERATES OUTPUT FOR EACH PROCESSOR
    Foreach ($Proc in $ProcData) {
        $HData | Add-Member -MemberType NoteProperty -Name "CPU$cnt" -Value $Proc.Name
        $HData | Add-Member -MemberType NoteProperty -Name "CPU$($cnt)_Socket" -Value $Proc.SocketDesignation
        $HData | Add-Member -MemberType NoteProperty -Name "CPU$($cnt)_Clock" -Value $Proc.CurrentClockSpeed
        $HData | Add-Member -MemberType NoteProperty -Name "CPU$($cnt)_Cores" -Value $Proc.NumberOfCores
        $HData | Add-Member -MemberType NoteProperty -Name "CPU$($cnt)_Threads" -Value $Proc.ThreadCount
        $HData | Add-Member -MemberType NoteProperty -Name "CPU$($cnt)_L3CacheSize" -Value "$($Proc.L3CacheSize / 1024) MBs"

        $cnt++
    }

    $cnt = 0

    # GENERATES OUTPUT FOR EACH STICK OF RAM
    Foreach ($DIMM in $DIMMData) {
        $HData | Add-Member -MemberType NoteProperty -Name "DIMM$cnt" -Value $DIMM.PartNumber
        $HData | Add-Member -MemberType NoteProperty -Name "DIMM$($cnt)_Capacity" -Value "$($DIMM.Capacity / 1073741824) GBs"
        $HData | Add-Member -MemberType NoteProperty -Name "DIMM$($cnt)_Speed" -Value $DIMM.Speed
        $HData | Add-Member -MemberType NoteProperty -Name "DIMM$($cnt)_ClockSpeed" -Value "$($DIMM.ConfiguredClockSpeed) MHz"

        $cnt++
    }

    $cnt = 0

    # GENERATES OUTPUT FOR EACH GRAPHICS CARD
    Foreach ($GPU in $GPUData) {
        $HData | Add-Member -MemberType NoteProperty -Name "GPU$cnt" -Value $GPU.Name
        $HData | Add-Member -MemberType NoteProperty -Name "GPU$($cnt)_RAM" -Value "$([math]::Round($GPU.AdapterRAM / 1073741824,2)) GBs"
        $HData | Add-Member -MemberType NoteProperty -Name "GPU$($cnt)_DriverVersion" -Value $GPU.DriverVersion
        $HData | Add-Member -MemberType NoteProperty -Name "GPU$($cnt)_DriverReleaseDate" -Value $GPU.DriverDate
        $HData | Add-Member -MemberType NoteProperty -Name "GPU$($cnt)_RefreshRate" -Value $GPU.CurrentRefreshRate
        $HData | Add-Member -MemberType NoteProperty -Name "GPU$($cnt)_MaxRefreshRate" -Value $GPU.MaxRefreshRate

        $cnt++
    }

    $cnt = 0

    # GENERATES OUTPUT FOR EACH DISK DRIVE
    Foreach ($Drive in $DriveData) {
        $HData | Add-Member -MemberType NoteProperty -Name "Drive$cnt" -Value $Drive.Model
        $HData | Add-Member -MemberType NoteProperty -Name "Drive$($cnt)_Interface" -Value $Drive.InterfaceType
        $HData | Add-Member -MemberType NoteProperty -Name "Drive$($cnt)_Capacity" -Value "$([math]::Round($Drive.Size / 1073741824,2)) GBs"
        $HData | Add-Member -MemberType NoteProperty -Name "Drive$($cnt)_FirmwareRevision" -Value $Drive.FirmwareRevision

        $cnt++
    }

    $cnt = 0

    # GENERATES OUTPUT FOR EACH NETWORK INTERFACE CARD
    Foreach ($NIC in $NetData) {
        $CrossRefNIC = $MoreNetData | Where-Object {$_.InterfaceDescription -eq $NIC.InterfaceDescription}

        $HData | Add-Member -MemberType NoteProperty -Name "NIC$($cnt)_Name" -Value $CrossRefNIC.Name
        $HData | Add-Member -MemberType NoteProperty -Name "NIC$($cnt)_Description" -Value $CrossRefNIC.InterfaceDescription
        $HData | Add-Member -MemberType NoteProperty -Name "NIC$($cnt)_LinkSpeed" -Value $CrossRefNIC.LinkSpeed
        $HData | Add-Member -MemberType NoteProperty -Name "NIC$($cnt)_MacAddress" -Value $CrossRefNIC.MacAddress

        $cnt++
    }

    # RETURNS ALL GATHERED DATA
    Return $HData
}