Thursday, June 29, 2017

Cleanup WSUS content folder with PowerShell

WSUS drive alerting for low disk space? Run this script and go get some coffee!

This script is the equivalent of running the WSUS cleanup wizard with all checkboxes checked.


Function Start-WSUSCleanup{
<#
.SYNOPSIS
Cleans up a WSUS content folder.

.DESCRIPTION
This script is the equivalent of running a WSUS cleanup with all checkboxes checked from within the WSUS console> options > WSUS Cleanup. `
It scrunbs the WSUS content folder for unneeded data.

.EXAMPLE
PS C:\> Start-WSUSCleanup

.NOTES
Version : 3.0+
Author/Copyright : © Matthew Kerfoot - All Rights Reserved
Email/Blog/Twitter : mkkerfoot@gmail.com www.TheOvernightAdmin.com @mkkerfoot

Disclaimer : THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK
OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
While these scripts are tested and working in my environment, it is recommended
that you test these scripts in a test environment before using in your production environment
Matthew Kerfoot further disclaims all implied warranties including, without limitation, any
implied warranties of merchantability or of fitness for a particular purpose. The entire risk
arising out of the use or performance of this script and documentation remains with you.
In no event shall Matthew Kerfoot, its authors, or anyone else involved in the creation, production,
or delivery of this script/tool be liable for any damages whatsoever (including, without limitation,
damages for loss of business profits, business interruption, loss of business information, or other
pecuniary loss) arising out of the use of or inability to use the sample scripts or documentation,
even if Matthew Kerfoot has been advised of the possibility of such damages.

Assumptions : ExecutionPolicy of AllSigned (recommended), RemoteSigned or Unrestricted (not recommended)
Limitations : not all functions work with PSv1
Ideas/Wish list : Now working with PSv2, PSv3, PSv4 and PSv5
Known issues : None
Authors notes : I found this somewhere on the internet and adapted it.. not sure where..
#>


[CmdletBinding(SupportsShouldProcess=$True)]
    param(
                [Parameter(Mandatory=$false,ValueFromPipeline=$true)]
                $Date = (Get-date -Format MMddyyyy),
                [Parameter(Mandatory=$false,ValueFromPipeline=$true)]
                $OutFilePath = "$env:USERPROFILE\Desktop\wsusCleanUpResults_$date.txt"
             )
            # Loads the WSUS .NET assembly - should probably be changed to load as loadwithpartial name is outdated
            # This is piped to out-null so that the next line won't run until the WSUS assembly is fully loaded
            [reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration") | out-null

                # retrieves the primary WSUS servers information
                $wsusServer = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer();

                # Gets the Cleanup scope options, this is the same as the radio buttons in the WSUS console `
                # Switch any of them to false to disable cleaning up that kind of data
                $cleanupScope = new-object Microsoft.UpdateServices.Administration.CleanupScope;

                        # $True means that item will be scrubbed and data will be deleted!
                        $cleanupScope.DeclineSupersededUpdates    = $true       
                        $cleanupScope.DeclineExpiredUpdates       = $true
                        $cleanupScope.CleanupObsoleteUpdates      = $true
                        $cleanupScope.CompressUpdates             = $true
                        $cleanupScope.CleanupObsoleteComputers    = $true
                        $cleanupScope.CleanupUnneededContentFiles = $true

                # Opens WSUS cleanup console as a background task
                $cleanupManager = $wsusServer.GetCleanupManager();

                    # Initiats the cleanup and writes outputs to $OutputFile
                    $cleanupManager.PerformCleanup($cleanupScope) | Out-File -FilePath $OutFilePath -Verbose

                    # Opens the output file so you can see how many items this script cleaned up
                    Invoke-Item $OutFilePath -Verbose

} Start-WSUSCleanup

Tuesday, June 27, 2017

Automate Folder Cleanup

Here is a script I wrote to help automate the scrubbing\cleanup of my security camera footage.

     In its current unmodified configuration, it is set to keep the security_Camera folder on my K:\ drive above 10% free space. This is accomplished by scanning the folding or drive to figure out the used space percentage, if the used space percentage is less than the configured $FreeSpaceThreshold then it will remove the oldest file, rescan, if needed and remove the oldest file again. This will continue to happen until the $PercentageFree is over the threshold.

Download the script from the Microsoft Script Repository!


Function Automated-FolderCleanup {

<# Matthew Kerfoot 6-26-17
.Synopsis
Cleans up aged files.

.DESCRIPTION
Monitors a folder and deletes the oldest files until the percent free Space reaches the configured threshold.

.EXAMPLE
PS:\>Automate-FolderCleanup -Path "K:\Security_Camera" -FreeSpaceThreshold "10"

.FUNCTIONALITY
This script was put together to scrub the oldest files from my security camera footage storage space.

.NOTES

Version : 3.0+

Author/Copyright : © Matthew Kerfoot - All Rights Reserved

Email/Blog/Twitter : mkkerfoot@gmail.com www.TheOvernightAdmin.com @mkkerfoot

Disclaimer : THIS CODE IS MADE AVAILABLE AS IS, WITHOUT WARRANTY OF ANY KIND. THE ENTIRE RISK
OF THE USE OR THE RESULTS FROM THE USE OF THIS CODE REMAINS WITH THE USER.
While these scripts are tested and working in my environment, it is recommended
that you test these scripts in a test environment before using in your production environment
Matthew Kerfoot further disclaims all implied warranties including, without limitation, any
implied warranties of merchantability or of fitness for a particular purpose. The entire risk
arising out of the use or performance of this script and documentation remains with you.
In no event shall Matthew Kerfoot, its authors, or anyone else involved in the creation, production,
or delivery of this script/tool be liable for any damages whatsoever (including, without limitation,
damages for loss of business profits, business interruption, loss of business information, or other
pecuniary loss) arising out of the use of or inability to use the sample scripts or documentation,
even if Matthew Kerfoot has been advised of the possibility of such damages.

Assumptions : ExecutionPolicy of AllSigned (recommended), RemoteSigned or Unrestricted (not recommended)

Author's notes : In its current unmodified configuration, it is set to keep the security_Camera `
folder on my K:\ drive above 10% free space. This is accomplished by scanning the folding `
or drive to figure out the used space percentage, if the used space percentage is less `
then the configured $FreeSpaceThreshold then it will remove the oldest file, rescan, `
if needed and remove the oldest file again. This will continue to happen until the `
$PercentageFree is over the threshold.
#>

    [Cmdletbinding(SupportsShouldProcess)]
        Param(
                [Parameter(Mandatory = $false,
                           ValueFromPipelineByPropertyName = $true,
                           Position = 0,
                           HelpMessage = "Please enter the full path of the folder or drive you would like to monitor and clean")]
                           [string[]]$Path = "K:\Security_Camera",
                [Parameter(Mandatory = $false,
                           ValueFromPipelineByPropertyName = $true,
                           Position = 1,
                           HelpMessage = "What free space percentage do you want to set the threshold for?")]
                           [int]$FreeSpaceThreshold = "10", # What percentage do you want the drive to free up until?
                [Parameter(Mandatory = $false,
                           ValueFromPipelineByPropertyName = $true,
                           Position = 2,
                           HelpMessage = "Please enter the full path to where you would like a transaction log stored.")]
                           $TranscriptLog = "C:\windows\Temp\Automated-FolderCleanup.log"
        )
        Begin{
                Start-Transcript -Path $TranscriptLog
                [string]$Drive = Split-Path -Qualifier $Path
                [WMI]$Disk = "Win32_LogicalDisk.DeviceID='$Drive'"
                [int]$PercentFree = $Disk.FreeSpace / $Disk.Size * 100
        }
        Process{
            while ($PercentFree -lt $FreeSpaceThreshold) {
                Get-ChildItem $Path -Recurse -File |
                    Sort-Object CreationTime |
                    Select-Object -First 1 |
                    Remove-Item
                $PercentFree = $Disk.FreeSpace / $Disk.Size * 100
            }
        }
        end{
                Write-Output "Procesing has completed"
                Stop-Transcript -Verbose
            }
} Automated-FolderCleanup -WhatIf

Simply remove the -WhatIf from the last line to allow processing if the script is run with -WhatIf it will run the script but won't actually make changes it will just give you a verbose output as to what it would do if the -WhatIf switch isn't specified.

Download the script from the Microsoft Script Repository!


Enjoy!

AutoHotKey - Control Your Mouse With Your Keyboard

     A month ago I bought a 40% keyboard. Some people might be wondering what a 40% keyboard is, it is just what you would think it is, it is 40% of the size of the standard 105 key layout. All the keys that have been removed are now stored in programmable layers. so for instance to make an exclamation mark I have to hold down, Fn1 + right shift + Capslock, this might seem insane but it is actually very intuitive after a week or so and now that I have fully adjusted I can hit any key without moving my fingers from the home row. Good-bye wrist pain!

Vortex Core



To be completely honest I did not think I would like using a 40% keyboard, especially as a daily driver. But after a week or two I found myself enjoying typing like seriously, typing is now fun and enjoyable.


Vortex Core



Alright now that we have gotten that out of the way, the point of this post is to share an AutoHotKey script that I have been running which allows me to control my mouse without actually having a mouse!

This script was developed using the AutoHotKey programming language and was aimed towards a 40% keyboard but with some slight modifications, it can work on any keyboard. Please review the comments and adjust accordingly for a full-size keyboard.









Here's the script in all its glory!
;
; MouseControl.ahk
; Hold down Control and then use the arrow keys to move the mouse cursor around the screen
; Updated on June 22nd, 2017 by Matt Kerfoot.
; Updated on June 27nd, 2017
; www.TheOvernightAdmin.com
;

#Persistent ; Keeps the script permanently running (that is, until the user closes it or ExitApp is encountered)

SetDefaultMouseSpeed, 1 ; Mouse speed, kind of like reaction time I do believe
distance = 30        ; how far the mouse moves each turn of the timer
multiplier = 1.16    ; how much farther (exponentially) the mouse moves in a direction the longer you hold that direction down
CFKM = 30            ; how often to run the timer
SetTimer, CheckForKeyMouse, %CFKM% ; Controls mouse movement speed
return ; end of mouse control movement control function

CheckForKeyMouse: ; Beginning of Function statement
if not GetKeyState("Control") ; Requires Ctrl to be held down
return ; required otherwise down control will not work

GetKeyState("Down")  ? (d*=multiplier) : (d:=1) ; While holding down shift, the down arrow will allow you to move the mouse to the down
GetKeyState("Up")    ? (u*=multiplier) : (u:=1) ; While holding down shift, the up arrow will allow you to move the mouse to the up
GetKeyState("Right") ? (r*=multiplier) : (r:=1) ; While holding down shift, the right arrow will allow you to move the mouse to the down
GetKeyState("Left")  ? (l*=multiplier) : (l:=1) ; While holding down shift, the left arrow will allow you to move the mouse to the left

y := (d-u) * distance ; math to tell how far to move the cursor
x := (r-l) * distance ; more math to define how far the cursor moves per key press

MouseMove, x, y, , R ; Initiates the action of moving the mouse
^PgDn::Click,      right ; Sets Ctrl + PgDn to perform a right click
^BackSpace::Click, right ; Sets Ctrl + backspace to perform a left click
^PgUp::Click,      left  ; Sets Ctrl + PgUp to perform a left click
^Esc::Click,       left  ; Sets Ctrl + Escape to perform a left click
^r::Reload  ; Assign Ctrl-R as a hotkey to restart the script.
Return ; End of Function statement


 I hope you enjoy it as much as I do! Any questions, just ask!

-Matt Kerfoot

Monday, June 12, 2017

Add Devices to LogicMonitor with Speed!

Here is a short PowerShell function that was written to speed up the time it takes to add servers to LogicMonitor.

I use this when a Domain Admin account cannot be obtained, this helps to keep security tight. This gets around it by adding the domain user account to the local Administrators and Distributed COM users group. It does even more than that even, it sets the PS execution policy, PS Remoting and it allows WMI through the windows firewall.

This script was developed for use with Server 2012R2 and newer however it should be backwards compatible all the way back to PowerShell version 2.0!

Function Add-ToLogicMonitor {
<#
.Synopsis
   Prepares a server to be added to LogicMonitor.
.DESCRIPTION
   This function will prepare a server to be added to LogicMonitor by enabling PS remoting, `
   setting the PS execution policy, adding LogicMonitorServiceAccountName to both the local administrator's group `
   and the Distributed DCOM Users group.
.EXAMPLE
   PS C:\> Add-ToLogicMonitor
.FUNCTIONALITY
   Used to speed up onboarding of servers into  LogicMonitor
#>

    [CmdletBinding()]
      
        Param(
               $Computer = $env:computername,
               $User = "LogicMonitorServiceAccountName",
               $ErrorActionPreference = "SilentlyContinue"
             )

                        # Enables PowerShell Remoting
                        Enable-PSRemoting -Force
                        Write-Host "PowerShell Remoting has been enabled." -BackgroundColor Black -ForegroundColor Green

                    # Sets the PowerShell Scripting Execution Policy to allow from the domain.
                    Set-ExecutionPolicy remotesigned -force
                    Write-Host "The Windows PowerShell Execution Policy has been set to allow scripts that are remotesigned." -BackgroundColor Black -ForegroundColor Green

                # Opens firewall for LogicMonitor support.
                netsh advfirewall firewall set rule group="windows management instrumentation (wmi)" new enable=yes
                netsh firewall set service RemoteAdmin enable

                Write-Host "Enables the required firewall rules for LogicMonitor to speak to the collector." -BackgroundColor Black -ForegroundColor Green

            # Enables remote WMI and DCOM
            Start-Service RemoteRegistry -Verbose
            Set-Service RemoteRegistry -StartupType Automatic -Verbose
            Write-Host "Remote WMI and DCOM have been enabled, the remote registry service has also been started and set to automatic startup." -BackgroundColor Black -ForegroundColor Green

        # Adds $User to the local administrators group
        $Administrators = [ADSI]("WinNT://$Computer/Administrators,group")
        $Administrators.add("WinNT://$User,user")
        Write-Host "$User has been added to the local Administrators group." -BackgroundColor Black -ForegroundColor Green

    # Adds $User to the Distributed COM users group
    $Administrators = [ADSI]("WinNT://$Computer/Distributed COM Users,group")
    $Administrators.add("WinNT://$User,user")
    Write-Host "$User has been added to the Distributed COM Users group." -BackgroundColor Black -ForegroundColor Green

}