OSTools.psm1

$messages = DATA {
    # culture="de-de"
    ConvertFrom-StringData @"
        Connecting = Gonna talk to
        Failed = That did not work
"@

}
#Import-LocalizedData -BindingVariable messages
function Get-SysDiskDetails {
    [CmdletBinding()]
    param (
        [Alias("Name","Hostname")]
        [Parameter(
            Mandatory=$true,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true
        )]
        [string[]]$ComputerName = "localhost"
    )
    PROCESS {
        foreach ($computer in $ComputerName) {

            Write-Verbose "$($messages.Connecting) $computer"

            try{
                $os     = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $computer -ErrorAction Stop
                $cs     = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $computer
                $bios   = Get-WmiObject -Class Win32_BIOS -ComputerName $computer
                $disks  = Get-WmiObject -Class Win32_LogicalDisk -ComputerName $computer

                #First Create Nested Object
                $diskcollection = @()
                foreach ($disk in $disks) {
                    $diskprops = @{
                        'DriveLetter'   =   $disk.deviceid;
                        'DriveType'     =   $disk.DriveType;
                        'Size'          =   $disk.Size
                    }
                    $diskobj        =   New-Object -TypeName psobject -Property $diskprops
                    $diskcollection +=  $diskobj
                }

                $props  = @{
                    'ComputerName'  =   $cs.__SERVER;
                    'OSVersion'     =   $os.version;
                    'SPVersion'     =   $os.servicepackmajorversion;
                    'OSBuild'       =   $os.buildnumber;
                    'Manufacturer'  =   $cs.Manufacturer;
                    'Model'         =   $cs.model;
                    'BIOSSerial'    =   $bios.serialnumber;
                    'Disks'         =   $diskcollection
                }
                $obj = New-Object -TypeName psobject -Property $props
                $obj.psobject.typenames.insert(0,'CriticalSolutions.OSTools.SysDiskDetails')
                Write-Output $obj
            } 
            catch{
                Write-Warning "$($messages.failed) $computer"
            }
        }
    } 
}

function Get-SystemDetails {
    <#
    .SYNOPSIS
        Gets basic system information from one or more computers via WMI
    .DESCRIPTION
        See synopsis. This is not complex.
    .PARAMETER ComputerName
        The name of the Host to Query
    .EXAMPLE
        Get-SystemDetails -Computername DC
        Gets system info from the computer named DC.
    .INPUTS
        Inputs (if any)
    .OUTPUTS
        Output (if any)
    .NOTES
        General notes
    #>

    [CmdletBinding()]
    param (
        [Alias("Name","Hostname")]
        [Parameter(
            Mandatory=$true,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true
        )]
        [string[]]$ComputerName = "localhost"
    )
    PROCESS {
        foreach ($computer in $ComputerName) {
            $os     = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $computer
            $cs     = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $computer
            $bios   = Get-WmiObject -Class Win32_BIOS -ComputerName $computer

            $props  = @{
                'ComputerName'  =   $cs.__SERVER;
                'OSVersion'     =   $os.version;
                'SPVersion'     =   $os.servicepackmajorversion;
                'OSBuild'       =   $os.buildnumber;
                'Manufacturer'  =   $cs.Manufacturer;
                'Model'         =   $cs.model;
                'BIOSSerial'    =   $bios.serialnumber
            }
            $obj = New-Object -TypeName psobject -Property $props
            $obj.psobject.typenames.insert(0,'CriticalSolutions.OSTools.SystemDetails')
            Write-Output $obj
        }
    }
}#

function Get-DiskDetails {
    <#
    .SYNOPSIS
        Gets information on local disks.
    .DESCRIPTION
        See Synopsis, uses WMI.
    .PARAMETER ComputerName
        One or more Computers or IP's to query.
    .EXAMPLE
        Get-DiskDetails -ComputerName DC,CLIENT
        Get disk space details from Computers DC and CLIENT.
    .INPUTS
        Inputs (if any)
    .OUTPUTS
        Output (if any)
    .NOTES
        General notes
    #>

    [CmdletBinding()]
    param (
        [Alias("Name","Hostname")]
        [Parameter(
            Mandatory=$true,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true
        )]
        [string[]]$ComputerName = "localhost"
    )
    PROCESS {
        foreach ($computer in $ComputerName) {
            $disks      = Get-WmiObject -Class Win32_LogicalDisk -Filter "DriveType='3'" -ComputerName $computer | Where-Object {$_.size -ne $null}
            $ram        = (Get-WmiObject Win32_PhysicalMemory -ComputerName $computer | Measure-Object -Property capacity -Sum).sum /1gb
            foreach ($disk in $disks) {
                $props  = @{
                    'ComputerName'  =   $computer;
                    'Drive'         =   $disk.DeviceID;
                    'FreeSpace'     =   "{0:N2}" -f ($disk.FreeSpace / 1GB);
                    'Size'          =   "{0:N2}" -f ($disk.size / 1GB);
                    'FreePercent'   =   "{0:N2}" -f ($disk.FreeSpace / $disk.size * 100 -as [int]);
                    'Collected'     =   (Get-Date)
                    'Ram (GB)'      =   $ram
                }
                $obj = New-Object -TypeName psobject -Property $props
                $obj.psobject.typenames.insert(0,'Report.OSTools.DiskDetails')
                Write-Output $obj
            }
        }
    }
} #

function Save-DiskDetailsToDatabase {
    [CmdletBinding()]
    param (
        [Parameter(
            Mandatory=$true,
            ValueFromPipeline=$true
        )]
        [object[]]$inputobject
    )
    BEGIN {
        $connection = New-Object -TypeName System.Data.SqlClient.SqlConnection
        $connection.ConnectionString = "Server=CSNSQLU;Database=DiskDetails;User Id=pshell;Password=Wcdi2010!@#;"
        $connection.Open() | Out-Null
    }
    PROCESS{
        $command = New-Object -TypeName System.Data.SqlClient.SqlCommand
        $command.Connection = $connection
        
        $sql = "DELETE FROM DiskData WHERE ComputerName = '$($inputobject.ComputerName)' AND DriveLetter = '$($inputobject.Drive)'"
        
        Write-Debug "Executing $sql"  
        $command.CommandText = $sql
        $command.ExecuteNonQuery() | Out-Null

        $sql = "INSERT INTO DiskData (
            ComputerName,
            DriveLetter,
            FreeSpace,
            Size,
            FreePercent
            )
            VALUES(
            '$($inputobject.computername)',
            '$($inputobject.Drive)',
            '$($inputobject.FreeSpace)',
            '$($inputobject.Size)',
            '$($inputobject.FreePercent)'
            )"

        Write-Debug "Executing $sql"
        
        $command.CommandText = $sql
        $command.ExecuteNonQuery() | Out-Null
    }
    END {
        $connection.Close()
    }
}

function Get-ComputerNamesForDiskDetailsFromDatabase {
    
    $connection = New-Object -TypeName System.Data.SqlClient.SqlConnection
    $connection.ConnectionString = "Server=CSNSQLU;Database=DiskDetails;User Id=pshell;Password=Wcdi2010!@#;"
    $connection.Open() | Out-Null

    $command = New-Object -TypeName System.Data.SqlClient.SqlCommand
    $command.Connection = $connection
    
    $sql = "SELECT ComputerName FROM DiskData"
    Write-Debug "Executing $sql"
    $command.CommandText = $sql

    $reader = $command.ExecuteReader()

    while ($reader.read()) {
        $computername = $reader.GetSqlString(0).Value
        Write-Output $computername
    }


    $connection.Close()
}

function Set-ComputerState {
    [CmdletBinding(
        SupportsShouldProcess=$true,# Turns on Whatif
        ConfirmImpact='High' # and confirm.
    )]
    param (
        [Parameter(
            Mandatory=$true,
            ValueFromPipeline=$true
        )]
        [string]$ComputerName,

        # Action
        [Parameter(
            Mandatory=$true
        )]
        [ValidateSet(
            'LogOff',
            'PowerOff',
            'Shutdown',
            'Restart'
        )]
        [string]$Action,

        [switch]$Force
    )

    PROCESS{
        foreach ($computer in $ComputerName) {
            
            switch ($Action) {
                'LogOff'    { $x = 0 }
                'Shutdown'  { $x = 1 }
                'Restart'   { $x = 2 }
                'PowerOff'  { $x = 8 }
            }
            if ($Force) {
                $x += 4
            }

            $os = Get-WmiObject -Class Win32_OperatingSystem -ComputerName $computer -EnableAllPrivileges

            if ($pscmdlet.ShouldProcess("$Action $computer")) {
                $os.Win32Shutdown($x) | Out-Null
            }
        }
    }
}

function Convert-WuaResultCodeToName {
    #doug rios modified
    param( [Parameter(Mandatory=$true)]
    [int] $ResultCode
    )
    $Result = $ResultCode
    switch($ResultCode) {
        2 {$Result = "Succeeded"}
        3 {$Result = "Succeeded With Errors"}
        4 {$Result = "Failed"}
    }
    return $Result
}
function Get-WuaHistory {
    
    # Get a WUA Session
    $session = (New-Object -ComObject 'Microsoft.Update.Session')
    
    # Query the latest History starting with the first record
    $history = $session.QueryHistory("",0,100) | `
    
    ForEach-Object {
        $Result = Convert-WuaResultCodeToName -ResultCode $_.ResultCode
        # Make the properties hidden in com properties visible.
        $_ | Add-Member -MemberType NoteProperty -Value $Result -Name Result
        $Product = $_.Categories | Where-Object {$_.Type -eq 'Product'} | Select-Object -First 1 -ExpandProperty Name
        $KBs = $_.Title | Select-String -Pattern "KB\d*"
        $KB = $KBs.Matches.Value
        $_ | Add-Member -MemberType NoteProperty -Value $_.UpdateIdentity.UpdateId -Name UpdateId
        $_ | Add-Member -MemberType NoteProperty -Value $_.UpdateIdentity.RevisionNumber -Name RevisionNumber
        $_ | Add-Member -MemberType NoteProperty -Value $Product -Name Product -PassThru
        $_ | Add-Member -MemberType NoteProperty -Value $KB -Name KBArticle -PassThru
        Write-Output $_
    }
    #Remove null records and only return the fields we want
    $history |
    Where-Object {![String]::IsNullOrWhiteSpace($_.title)} |
    Select-Object Result, Date, Title, KBArticle, SupportUrl, Product, UpdateId, RevisionNumber
}

function Get-UsersToDisable {
    [CmdletBinding()]
    param (  
        [Parameter(
            ValueFromPipeline = $true,
            ValueFromPipelineByPropertyName = $true,
            Position = 0
        )]
        [string]$DirPath = "C:\Temp",
        
        [Parameter(
            ValueFromPipelineByPropertyName = $true
        )]
        [int]$DaysToExpire = 90,

        [Parameter(
            ValueFromPipelineByPropertyName = $true
        )]
        [string]$SMTPUsername,

        [Parameter(
            ValueFromPipelineByPropertyName = $true
        )]
        [string]$SMTPPass

    )
    Begin {
        Write-Host "Checking for users not active in $DaysToExpire days." -ForegroundColor Yellow
        Write-Host "Output directory is $DirPath" -ForegroundColor Yellow
        
        $DirPathCheck = Test-Path -Path $DirPath
        If (!($DirPathCheck)) {
            Try {
                #If not present then create the dir
                New-Item -ItemType Directory $DirPath -Force
            }
            Catch {
                Write-Output 'The Directory'$DirPath'was not created.'
            }
        
        }

    }

    Process {

        $Header = @"
<style>
TABLE {border-width: 1px; border-style: solid; border-color: black; border-collapse: collapse;}
TH {border-width: 1px; padding: 3px; border-style: solid; border-color: black; background-color: #6495ED;}
TD {border-width: 1px; padding: 3px; border-style: solid; border-color: black;}
</style>
"@
 





        # Paths
        $csvpath = "$DirPath\$env:USERDOMAIN.ADAudit.$((get-date).ToString('MM-dd-yyyy.hh.mm.ss')).csv"
        $htmlpath = "$DirPath\$env:USERDOMAIN.ADAudit.$((get-date).ToString('MM-dd-yyyy.hh.mm.ss')).html"

        # Days inactive
        $time = (Get-Date).AddDays( - ($DaysToExpire))

        Try {
            # Get inactive enabled users
            $output = Get-ADUser -Filter { LastLogonTimeStamp -gt $time -and enabled -eq $true } `
                -Properties UserPrincipalName, LastLogonTimeStamp, PasswordLastSet, LockedOut, `
                CannotChangePassword, LastBadPasswordAttempt, SamAccountName, Title | `
                Where-Object { $_.name -ne "krbtgt" } | `
                Select-Object Name, SamAccountName, UserPrincipalName, Title, `
                PasswordLastSet, LockedOut, LastBadPasswordAttempt, CannotChangePassword, `
            @{Name = "LastLogon"; Expression = { [DateTime]::FromFileTime($_.lastLogonTimestamp) } }, `
            @{Name = "Confirmed?"; Expression = { "" } } | `
                Sort-Object LastLogon -Descending
        }
        catch {
            Write-Output "The users were not able to be retrieved"
        }
        try {
            # Export output to csv without type information
            $output | Export-CSV -Path $csvpath -NoTypeInformation
            Write-Host "The path to the CSV is: " -ForegroundColor Green
            Write-Output $csvpath
        }
        catch {
            Write-Output "The csv was not created"
        }
            
        try {
            # Export Preformatted Table in HTML
            $output | ConvertTo-Html -Title "$($env:USERDOMAIN) AD Inactive User Audit" -Head $Header | Out-File -Encoding utf8 $htmlpath
            Write-Host "The path to the HTML is: " -ForegroundColor Green
            Write-Output $htmlpath
        }
        catch {
            Write-Output "The html was not created"
        }
    }
    end {
        
        <#
        function Send-ToEmail([string]$email ) {
         
            $message = new-object Net.Mail.MailMessage;
            $message.From = $Username;
            $message.To.Add($email);
            $message.Subject = "Active Directory Enabled Users Audit";
            $message.Body = "Audit of active enabled users who have not logged on in $DaysToExpire days.";
         
            write-host "attaching"
            $file = $csvpath
            $att = new-object Net.Mail.Attachment($file)
            $message.Attachments.Add($file)
             
            write-host "new smtp"
            $smtp = new-object Net.Mail.SmtpClient("smtp.office365.com", "587");
            $smtp.EnableSSL = $true;
            $smtp.Credentials = New-Object System.Net.NetworkCredential($Username, $Password);
         
            write-host "new send"
            $smtp.send($message);
            write-host "pre dispose"
            $att.Dispose()
            write-host "**Mail Sent" ;
        }
        Send-ToEmail -email "recipient@yourdomain.com";
         
        #>

    }
}