AdminToolkit.psm1
#Region $AdminToolkitADComputernameArgCompleter $AdminToolkitADComputernameArgCompleter = { param ($CommandName, $ParameterName, $StringMatch) if ($null -eq $StringMatch) { $Filter = "*" } else { $Filter = "*$StringMatch*" } (Get-ADComputer -filter { Name -like $Filter }).Name } Register-ArgumentCompleter -CommandName Deploy-LocalScheduledTask -ParameterName ComputerName -ScriptBlock $AdminToolkitADComputernameArgCompleter #EndRegion $AdminToolkitADComputernameArgCompleter #Region $AdminToolkitScheduledTaskNameArgCompleter $AdminToolkitScheduledTaskNameArgCompleter = { param ($CommandName, $ParameterName, $StringMatch) $Tasks = (Get-ScheduledTask | Where-Object { $_.TaskName -match "$StringMatch" }).TaskName $QuotedTasks = foreach ($Task in $Tasks) { $QuotedTask = "`"$Task`"" $QuotedTask } return $QuotedTasks } Register-ArgumentCompleter -CommandName Push-LocalScheduledTask -ParameterName TaskName -ScriptBlock $AdminToolkitScheduledTaskNameArgCompleter #EndRegion $AdminToolkitScheduledTaskNameArgCompleter #Region Aliases Set-Alias -Name GD -Value Get-Definition Set-Alias -Name Watch -Value Watch-Command #EndRegion Aliases #Region Clear-Arp <# .SYNOPSIS Use Netsh to clear ArpCache .DESCRIPTION Clears the local arp table .EXAMPLE PS> Clear-Arp Description ----------- This will clear the arpcache on the local machine. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> function Clear-Arp() { [CmdletBinding()] param() netsh.exe interface ip delete arpcache } #EndRegion Clear-Arp #Region Copy-WithProgress <# .SYNOPSIS This function performs a copy of a specified object recursively to a specified location. .DESCRIPTION This function is a glorified Copy-Item in that it will show progress data. If moving 10,000 files that equal 2GB in size, it will show you what file you are currently on as well as how much data has been moved / what is left using Write-Progress. .PARAMETER Source Source should specify the object to be copied by name. This value must be the FullPath and cannot be shortened. An example would be if you were in the C:\Scripts directory, you could not specify '.\TestFile.ps1' as the source location, you must specify 'C:\Scripts\TestFile.ps1' in this case. .PARAMETER Destination Destination should specify the target location of the specified Source by name. This value must be the FullPath and cannot be shortened. An example would be if you were in the C:\Scripts directory, you could not specify '.\TestFile.ps1' as the Destination location, you must specify 'C:\Scripts\TestFile.ps1' in this case .INPUTS System.String[] This function does not accept pipeline data. The values for all parameters must be specified. .OUTPUTS None This function does not produce output except for the Write-Progress data. .EXAMPLE PS>Copy-WithProgress -Source "C:\Scripts\TestFile.ps1" -Destination "C:\Temp\TestFile.ps1" Description ----------- This will copy the source file to the file specified in Destination. Note that the filename for Destination can be anything and does not have to match the original. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> function Copy-WithProgress() { [CmdletBinding()] Param ( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, Position = 0)] $Source, [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, Position = 1)] $Destination ) Write-Progress -Activity "Gathering data from $Source" $Source = $Source.tolower() $Destination = $Destination.tolower() $Filelist = Get-Childitem $Source -Recurse $Total = $Filelist.count $Position = 0 $Size = ($Filelist | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum Write-Progress -Activity "Gathering data from $Source" -Completed foreach ($File in $Filelist) { switch ($Size) { { $_ -ge '1000000000' } { $TotalSize = "{0:N2} GB" -f ($_ / 1GB) } { ($_ -lt '1000000000') -and ($_ -ge '10000000') } { $TotalSize = "{0:N2} MB" -f ($_ / 1MB) } { $_ -lt '1000000' } { $TotalSize = "{0:N2} KB" -f ($_ / 1KB) } } $FileSize = ($File | Measure-Object -Property Length -Sum -ErrorAction SilentlyContinue).Sum $Filename = $File.Fullname.ToLower().Replace($Source, '') $DestinationFile = ($Destination + $Filename) $Position++ $Percent = [int]$(($Position / $Total) * 100) Write-Progress -Activity "Copying data from '$Source' to '$Destination'" -Status "Copying File $Position of $total - $TotalSize remaining..." -PercentComplete (($Position / $total) * 100) -CurrentOperation "$Percent% complete" #$null = New-Item -Name $File.FullName -Path $DestinationFile -ItemType File -Force Copy-Item $File.FullName -Destination $DestinationFile -Force -ErrorAction SilentlyContinue -Container | Out-Null $Size = ($Size - $FileSize) } Write-Progress -Activity "Moving data from '$Source' to '$Destination'" -Completed } #EndRegion Copy-WithProgress #Region DateStamp <# .SYNOPSIS This is a filter used to place timestamps on any output messages. .DESCRIPTION The function `TimeStamp` is a colorized version of this command `DateStamp`, but `TimeStamp` output cannot be written to a file. You will want to use `DateStamp` if you are going to output your messages into a log or txt file. .EXAMPLE "ERROR: Something bad happened on this line of the script" | DateStamp [08/04/2020 11:34:35]: ERROR: Something bad happened on this line of the script Description ----------- This line will place a time stamp at the beginning of the line that can be written to a file. .NOTES Author: Matthew J. DeGarmo Site: https://matthewjdegarmo.github.io #> filter DateStamp() { [CmdletBinding()] param() process { Write-Output "[$(Get-Date -Format "MM/dd/yyyy HH:mm:ss")]: $_" } } #EndRegion DateStamp #Region Enable-Remoting <# .Synopsis Enable PSRemoting via PSEXEC remotely. .Description This Command will enable PowerShell Remoting on a remote PC. .EXAMPLE PS> Enable-PSRemoting -computer PCName -username domain\username Description ----------- This will enable remoting and then prompt for credentials .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo Change Log: Version: 1.0 - Function Creation. This Function requires psexec. If you do not, download it with the sysinternals suite. Add psexec to one of your enviroment variable paths. #> Function Enable-Remoting { [CmdletBinding()] Param ( [Parameter(Position = 0, Mandatory)] [string] $Computer, [Parameter(Position = 1, Mandatory)] [string] $Username, [Parameter(Position = 2)] [SecureString] $Password ) #Enabling PSRemoting PsExec.exe \\$Computer -s winrm.cmd quickconfig -q PsExec.exe \\$Computer -u $Username -p $Password powershell.exe cmd /c "enable-psremoting -force" try { Test-WSMan $Computer } catch { Write-Error "Failed to enable PSRemoting via PSEXEC" } } #EndRegion Enable-Remoting #Region Get-Applications <# .SYNOPSIS List locally installed applications .DESCRIPTION Query local registry for installed applications. .EXAMPLE PS> Get-Applications Description ----------- This will generate all installed applications on the local system. .NOTES Author: Matthew J. DeGarmo Site: https://matthewjdegarmo.github.io #> Function Get-Applications { [CmdletBinding()] param() Get-ItemProperty HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | Sort-Object DisplayName } #EndRegion Get-Applications #Region Get-CIDRNotationBySubnetMask <# .SYNOPSIS Quickly generate the CIDR "slash" notation for a given subnet mask. .DESCRIPTION This will provide the CIDR value for a subnet mask. This function will also error if the subnet mask is not valid. .EXAMPLE PS> Get-CIDRNotationBySubnetMask 255.255.255.0 24 Description ----------- Providing the SubnetMask, this returns the correct CIDR abreviation. CIDR is used like this: 192.168.1.0/24 .NOTES Author: Matthew J. DeGarmo Site: https://matthewjdegarmo.github.io #> function Get-CIDRNotationBySubnetMask() { [CmdletBinding()] param ( [Parameter(Mandatory,Position=0)] [String] $SubnetMask ) $cidr = 0 $octet = 0 $SubnetMask.split(".") | Foreach-Object { switch ($_) { 255 { $cidr += 8 ; $CorrectSubnet += "$_." } 254 { $cidr += 7 ; $CorrectSubnet += "$_." } 252 { $cidr += 6 ; $CorrectSubnet += "$_." } 248 { $cidr += 5 ; $CorrectSubnet += "$_." } 240 { $cidr += 4 ; $CorrectSubnet += "$_." } 224 { $cidr += 3 ; $CorrectSubnet += "$_." } 192 { $cidr += 2 ; $CorrectSubnet += "$_." } 128 { $cidr += 1 ; $CorrectSubnet += "$_." } 0 { $cidr += 0 ; $CorrectSubnet += "$_." } default { $SplitSubnet = $SubnetMask.Split('.') $SplitSubnet[$octet] = "[$($SplitSubnet[$octet])]" $ErrorSubnet = $SplitSubnet -join '.' Write-Error -Message "Invalid Subnet Mask value: `'$_`' in $ErrorSubnet" ` -Category InvalidArgument ` -RecommendedAction "Provide a proper SubnetMask" ` -ErrorAction Stop $BadMask = $true } } $octet++ } if (-Not ($BadMask)) { $cidr } } #EndRegion Get-CIDRNotationBySubnetMask #Region Get-ContentWithLineNumbers <# .Synopsis Mimic Unix / Linux tool nl number lines .Description Print file content with numbered lines no original nl options supported .Example PS> Get-ContentWithLineNumbers -FileName C:\Foo.txt Description ----------- This will append line numbers to the begninning of each line in the Foo.txt file. .NOTES Author: Matthew J. DeGarmo Site: https://matthewjdegarmo.github.io #> function Get-ContentWithLineNumbers() { [CmdletBinding()] param ( [parameter(mandatory = $true, Position = 0, ValueFromPipeline, ParameterSetName = 'File')] [String]$FileName, [Parameter(ParameterSetName = 'Input')] $InputObject ) process { if ($PSBoundParameters.ContainsKey('FileName')) { If (Test-Path $FileName) { $Data = Get-Content $FileName | ForEach-Object { "{0,5} {1}" -f $_.ReadCount, $_ } } $Data } elseif ($PSBoundParameters.ContainsKey('Input')) { $inData = New-Object -TypeName System.IO.StringReader -ArgumentList $InputObject $Data = While ($Line = $InData.ReadLine()) { $Line } $Data | ForEach-Object { "{0,5} {1}" -f $_.ReadCount, $_ } } } } #EndRegion Get-ContentWithLineNumbers #Region Get-Definition <# .SYNOPSIS Gets the back-end definition of a function. .DESCRIPTION This function will export a string of the code that defines a function. .PARAMETER Function This parameter takes a function name, or an alias name, to generate the function definition. .EXAMPLE PS> Get-Definition Get-Definition Description ----------- This will get the function definitnion for the `Get-Definition` command itself. .EXAMPLE PS> Get-Definition glo | Clip Description ----------- This will get the definition for the `glo` aliased command, and pipe it into your clipboard using the clip.exe file. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> function Get-Definition() { [CmdletBinding()] param( [Parameter(Mandatory)] [string] $Function ) $null = Get-Command -Name $Function -ErrorAction SilentlyContinue $Alias = (Get-Alias -Name $Function -ErrorAction SilentlyContinue).ResolvedCommand.Name if ($Alias) { Write-Warning "'$Function' is an alias for '$Alias'. Running 'Get-Definition -Function $Alias'." $Function = $Alias } $FunctionDefinition = (Get-Command -name $Function | Select-Object -ExpandProperty Definition) $returnDefinition = [System.Text.StringBuilder]::New() $null = $returnDefinition.Append("function $Function`() {") $null = $returnDefinition.Append($FunctionDefinition) $null = $returnDefinition.Append('}') $returnDefinition.ToString() } #EndRegion Get-Definition #Region Get-FileOwner <# .Synopsis Display the owner of an item(s) .Description This Function lists file owners within a given path .Example PS> Get-FileOwner C:\Users Description ----------- This will list file owners recursively for this directory. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> Function Get-FileOwner { [CmdletBinding()] param( [Parameter(Mandatory, Position = 0)] [string] $Path, [switch]$Recursive ) $LastWrite = @{ Name = 'Last Write Time' Expression = { $_.LastWriteTime.ToString('u') } } $Owner = @{ Name = 'File Owner' Expression = { (Get-Acl $_.FullName).Owner } } $HostName = @{ Name = 'Host Name' Expression = { $env:COMPUTERNAME } } Get-ChildItem @PSBoundParameters | Select-Object $HostName, $Owner, Name, Directory, $LastWrite, Length } #EndRegion Get-FileOwner #Region Get-FolderSize <# .SYNOPSIS Quickly calculate the size of a directory. .DESCRIPTION This function will calculate the disk space used by a specified directory. This uses the current directory by default. .EXAMPLE PS> Get-FolderSize Description ----------- This will display the folder size of the current folder location `Get-Location` .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> Function Get-FolderSize { [CmdletBinding()] Param ( [Parameter(Position = 0)]$Folder = (Get-Location) ) $Size = (Get-ChildItem $Folder -Recurse | Measure-Object -Property Length -Sum -ErrorAction Stop).Sum switch ($Size) { { ($_ -lt '1000000000000000') -and ($_ -ge '1000000000000') } { $TotalSize = "{0:N2} TB" -f ($_ / 1TB) } { ($_ -lt '1000000000000') -and ($_ -ge '1000000000') } { $TotalSize = "{0:N2} GB" -f ($_ / 1GB) } { ($_ -lt '1000000000') -and ($_ -ge '1000000') } { $TotalSize = "{0:N2} MB" -f ($_ / 1MB) } { $_ -lt '1000000' } { $TotalSize = "{0:N2} KB" -f ($_ / 1KB) } } $TotalSize } #EndRegion Get-FolderSize #Region Get-Management <# .SYNOPSIS Open Computer management .DESCRIPTION Opens Computer management connected for a PC, local or remote. Default is local. .Example PS> Get-Management CGO-999999-H Description ----------- This will open computer management for this remote PC, if you are an admin on that PC. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> Function Get-Management { [CmdletBinding()] Param ( [Parameter(Position = 0)]$ComputerName = $env:ComputerName ) compmgmt.msc /computer:$ComputerName } #EndRegion Get-Management #Region Get-PasswordExpired <# .SYNOPSIS Generates list of ActiveDirectory users who have expired passwords .DESCRIPTION Returns a list of Active Directory Accounts with expired passwords .EXAMPLE PS> Get-PasswordExpired Description ----------- This will get all of the current accounts with expired passwords. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> Function Get-PasswordExpired { [CmdletBinding()] param () Search-ADAccount -PasswordExpired } #EndRegion Get-PasswordExpired #Region Get-PCInfo <# .Synopsis Gather useful information from a remote PC. .Description Returns useful informaion on the local endpoint or another. .EXAMPLE PS> Get-PCInfo -ComputerName Computer1 Description ----------- This will generate information from the remote computer using CIM Instances. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> Function Get-PCInfo { [CmdletBinding()] Param ( [string]$ComputerName = $env:ComputerName ) try { $SystemEnclosure = Get-CimInstance win32_systemenclosure -computername $ComputerName -ErrorAction Stop $OS = Get-CimInstance Win32_OperatingSystem -Computername $ComputerName -ErrorAction Stop } catch { Write-Error "$($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" break } #Creating Hash table from variables $PCInfo = @{ Manufacturer = $SystemEnclosure.Manufacturer PCName = $OS.CSName OS = $OS.Caption Architecture = $OS.OSArchitecture AssetTag = $systemenclosure.serialnumber; OSVersion = $OS.Version InstallDate = $OS.InstallDate LastBootUpTime = $OS.LastBootUpTime } #Writing to Host Write-Host " " Write-Host "Computer Info" -Foregroundcolor Cyan Write-Host "If not run on a Dell machine AssetTag is the Serial Number" -Foregroundcolor Yellow #Display Hash Table $PCInfo.getenumerator() | Sort-Object -property name | Format-Table -autosize #Writing to Host Write-Host "Computer Disk Info" -Foregroundcolor Cyan #Display Drives Get-CimInstance win32_logicaldisk -filter "drivetype=3" -computer $ComputerName | Format-Table -Property DeviceID, Volumename, ` @{Name = "SizeGB"; Expression = { [math]::Round($_.Size / 1GB) } }, ` @{Name = "FreeGB"; Expression = { [math]::Round($_.Freespace / 1GB, 2) } }, ` @{Name = "PercentFree"; Expression = { [math]::Round(($_.Freespace / $_.size) * 100, 2) } } #Writing to Host Write-Host "Network Information" -Foregroundcolor Cyan Get-CimInstance win32_networkadapterconfiguration -computer $ComputerName | Where-Object { $null -ne $_.IPAddress } | Select-Object IPAddress, DefaultIPGateway, DNSServerSearchOrder, IPSubnet, MACAddress, Caption, DHCPEnabled, DHCPServer, DNSDomainSuffixSearchOrder | Format-List } #EndRegion Get-PCInfo #Region Get-PCUpTime <# .SYNOPSIS Get the amount of time since the last boot-up sequence for a computer. .DESCRIPTION This cmdlet uses Get-CimInstance to gather the .LastBootUpTime for the local or remote computer. PowerShell 7 comes with a `Get-Uptime` cmdlet, so if called from PowerShell, it will simply call or invoke that cmdlet. otherwise when called from Windows Powershell, it will invoke a CimInstance. .PARAMETER ComputerName Specify the remote computer to query using CIM. .EXAMPLE PS> Get-PCUpTime Description ----------- This will return the current UpTime value for the local computer. .EXAMPLE PS> Get-PCUpTime Remote-Server Description ----------- This will query `Remote-Server` for it's uptime data. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> function Get-PCUpTime() { [CmdletBinding()] param( [Parameter(ValueFromPipeline)] $ComputerName ) begin { $Version = $PSVersionTable.PSEdition } process { try { switch($Version) { 'Desktop' { if ($null -ne $ComputerName) { $SplatMe = @{ ClassName = 'Win32_OperatingSystem' ComputerName = $ComputerName} } else { $SplatMe = @{ ClassName = 'Win32_OperatingSystem' } } $Now = Get-Date $LastBootUpTime = (Get-CimInstance @SplatMe -ErrorAction Stop).LastBootUpTime $Return = $Now - $LastBootUpTime return $Return } 'Core' { if ($null -ne $ComputerName) { $PCFunctionDefinition = Get-Definition Get-PCUpTime $Script = @" $PCFunctionDefinition Get-PCUpTime "@ $ScriptBlock = { param ($Script) . ([ScriptBlock]::Create($Script)) } $params = @{ ComputerName = $ComputerName ScriptBlock = $ScriptBlock ArgumentList = $Script } Invoke-Command @params } else { Get-Uptime } } DEFAULT {} } } catch { Write-Error "$($_.Exception.Message)" } } } #EndRegion Get-PCUpTime #Region Get-Printers <# .SYNOPSIS Get printers for local or remote PC .Description This function will attempt to gather printer information for a local or remote PC. .EXAMPLE PS> Get-Printers Description ----------- This will generate local printer information. .EXAMPLE PS> Get-Printers -ComputerName Some-Remote-Computer1 Description ----------- This will generate printer information for the remote computer `Some-Remote-Computer1' via a Cim Instance. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> Function Get-Printers { [CmdletBinding()] Param ( [Parameter(Mandatory = $false)] [String] $ComputerName ) $Params = @{ ClassName = 'CIM_Printer' } if ($ComputerName) {$Params += @{ComputerName = $ComputerName}} Get-CimInstance @Params | Select-Object Name, Drivername, Portname, Status, SystemName, local, shared, CapabilityDescriptions } #EndRegion Get-Printers #Region Get-PrintManagement <# .SYNOPSIS Quickly launch Print Management MSC Snap-in .DESCRIPTION Opens Print Management for the local PC and one remote PC using -ComputerName .EXAMPLE PS> Get-PrintManagement -ComputerName Computer1 Description ----------- This will open PrintManagement on the local machine and connect to the remote `Computer1` .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> Function Get-PrintManagement { [CmdletBinding()] param ( [string[]]$ComputerName = $env:COMPUTERNAME ) printmanagement.msc /computer:$ComputerName } #EndRegion Get-PrintManagement #Region Get-PublicIP <# .SYNOPSIS Generates your current Public IP Information .DESCRIPTION Returns WhoIS public IP info for your location or any specified public IP. By Default, returns your current public IP info. .EXAMPLE PS> Get-PublicIP Description ----------- Returns local Public IP Info Get-PublicIP .Example PS> Get-PublicIP -IP 8.8.8.8 Description ----------- Returns Public IP Info for 8.8.8.8 Get-PublicIP -IP 8.8.8.8 .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> Function Get-PublicIP { [CmdletBinding()] Param ( [Parameter(Position = 0)]$IP ) try { if ($IP) { $ipinfo = Invoke-RestMethod http://ipinfo.io/$IP/json } else { $ipinfo = Invoke-RestMethod http://ipinfo.io/json } $PublicIP = @{ IP = $ipinfo.ip City = $ipinfo.city Region = $ipinfo.region Country = $ipinfo.country Coord = $ipinfo.loc Organization = $ipinfo.org Postal = $ipinfo.Postal TimeZone = $ipinfo.timezone } $PublicIP.getenumerator() | Sort-Object Key } catch { Write-Error "$($_.Exception.Message)" } } #EndRegion Get-PublicIP #Region Get-WindowsBuild <# .SYNOPSIS Gets Windows Build information. .DESCRIPTION This will query the local PC OR an array of remote PC's .PARAMETER ComputerName .INPUTS System.String[] You must specify the value for Credential. You cannot pipe a value to this function. .OUTPUTS None There are no outputs. .EXAMPLE PS> ConnectTeams Description ----------- This will attempt a connection to portal.office.com. This will prompt you for account information like what password to use. .EXAMPLE PS> ConnectTeams -Credential 'SomeAccount@Email.com' Description ----------- This will attempt a connection to portal.office.com. This will prompt you for account information like what password to use. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> function Get-WindowsBuild() { [CmdletBinding()] param ( [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true )] [string[]]$ComputerName = $env:COMPUTERNAME ) begin { $Table = New-Object System.Data.DataTable $Table.Columns.AddRange(@("ComputerName", "Windows Edition", "Version", "OSBuild")) } process { Foreach ($Computer in $ComputerName) { $Code = { $ProductName = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name ProductName).ProductName try { $Version = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name ReleaseID -ErrorAction Stop).ReleaseID } catch { $Version = "N/A" } $CurrentBuild = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name CurrentBuild).CurrentBuild $UBR = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name UBR).UBR $OSVersion = $CurrentBuild + "." + $UBR $TempTable = New-Object System.Data.DataTable $TempTable.Columns.AddRange(@("ComputerName", "Windows Edition", "Version", "OSBuild")) [void]$TempTable.Rows.Add($env:COMPUTERNAME, $ProductName, $Version, $OSVersion) return $TempTable } if ($Computer -eq $env:COMPUTERNAME) { $Result = Invoke-Command -ScriptBlock $Code [void]$Table.Rows.Add($Result.Computername, $Result.'Windows Edition', $Result.Version, $Result.'OSBuild') } else { if (Test-Connection $Computer -count 1 -ErrorAction SilentlyContinue) { try { $Result = Invoke-Command -ComputerName $Computer -ScriptBlock $Code -ErrorAction Stop [void]$Table.Rows.Add($Result.Computername, $Result.'Windows Edition', $Result.Version, $Result.'OSBuild') } catch { $_ } } else { [void]$Table.Rows.Add($Computer, "OFFLINE", "OFFLINE", "OFFLINE") } } } } end { Return $Table } } #EndRegion Get-WindowsBuild #Region grep <# .SYNOPSIS Basic version of the linux command `grep` on Windows. .DESCRIPTION This is a windows version of the linux `grep` command. I still need to figure out how to NOT import this command when on a linux system. This is basically a shorter `Select-String`, and does not support other grep flags as on a Linux system. .EXAMPLE Get-Process | grep powershell Description ----------- This will filter the `Get-Process` output with the regex 'powershell'. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> function grep { # [CmdletBinding()] # This is to pass the advanced function pester tests. param( $regex ) process { $_ | Where-Object { $_ -match $regex } } } #EndRegion grep #Region Invoke-Speech <# .SYNOPSIS Translate a string into an audible message. .DESCRIPTION This function calls the SAPI.SPVoice class to invoke audio given a string. This is useful when running long processes, you can audibly be alerted that a task is finished. .EXAMPLE PS> Get-SomeDataThatTakesAnHour;Invoke-Speech -Message "Your data is ready, sir." Description ----------- This will generated audio for the string 'Your data is ready, sir." depending on your volume level. .NOTES Author: Matthew J. DeGarmo Site: https://matthewjdegarmo.github.io #> function Invoke-Speech { [CmdletBinding()] param ( [Parameter(ValueFromPipeline = $true)] [string]$Message ) begin { #Set Variables for the Invoke-Speech Function $voice = New-Object -ComObject SAPI.SPVoice $voice.Rate = -2 } process { $voice.Speak($Message) | out-null; } } #EndRegion Invoke-Speech #Region LL <# .SYNOPSIS This is a colorized version of Get-ChildItem (dir, ls). .DESCRIPTION This function will change the color of object names using Get-ChildItem based on the object type or extension. You can define more extensions and their associated colors if you wish. .EXAMPLE PS> LL C:\Temp Description ----------- Display a colorized output for `Get-ChildItem` at C:\Temp. .EXAMPLE PS> ll Description ----------- Display a colorized output for `Get-ChildItem` at the current working directory. .NOTES Author: Matthew J. DeGarmo Site: https://matthewjdegarmo.github.io #> function LL { [CmdletBinding()] param ( [String] $Directory = ".", $All = $false ) $originalForeground = $host.ui.rawui.foregroundColor if ( $All ) { $toList = Get-ChildItem -force $Directory } else { $toList = Get-ChildItem $Directory } foreach ($Item in $toList) { Switch ($Item.Extension) { ".Exe" { $host.ui.rawui.foregroundColor = "Yellow" } ".cmd" { $host.ui.rawui.foregroundColor = "Red" } ".lnk" { $host.ui.rawui.foregroundColor = "Red" } ".msh" { $host.ui.rawui.foregroundColor = "Red" } ".vbs" { $host.ui.rawui.foregroundColor = "Red" } ".ps1" { $host.ui.rawui.foregroundColor = "Cyan" } ".psm1" { $host.ui.rawui.foregroundColor = "Cyan" } ".psd1" { $host.ui.rawui.foregroundColor = "Cyan" } ".ps1xml" { $host.ui.rawui.foregroundColor = "Cyan" } ".txt" { $host.ui.rawui.foregroundColor = "DarkCyan" } ".xml" { $host.ui.rawui.foregroundColor = "Magenta" } ".cvs" { $host.ui.rawui.foregroundColor = "Magenta" } ".doc" { $host.ui.rawui.foregroundColor = "Magenta" } ".csv" { $host.ui.rawui.foregroundColor = "Magenta" } ".bat" { $host.ui.rawui.foregroundColor = "Yellow" } ".docx" { $host.ui.rawui.foregroundColor = "Magenta" } ".pdf" { $host.ui.rawui.foregroundColor = "Magenta" } ".xls" { $host.ui.rawui.foregroundColor = "Magenta" } ".xlsx" { $host.ui.rawui.foregroundColor = "Magenta" } ".log" { $host.ui.rawui.foregroundColor = "DarkCyan" } Default { $host.ui.rawui.foregroundColor = $originalForeground } } if ($item.Mode.StartsWith("d")) { $host.ui.rawui.foregroundColor = "Green" } $item } $host.ui.rawui.foregroundColor = $originalForeground } #EndRegion LL #Region LLM <# .SYNOPSIS This is a quick way to lock your workstation. .DESCRIPTION LLM is to stand for 'Lock Local Machine'. This will lock the current session on a windows workstation. Will need to add functionality to lock a linux or mac. .EXAMPLE PS> llm Description ----------- This will quickly lock the current workstation. .NOTES Author: Matthew J. DeGarmo Site: https://matthewjdegarmo.github.io #> Function llm { [CmdletBinding()] param () $signature = @" [DllImport("user32.dll", SetLastError = true)] public static extern bool LockWorkStation(); "@ Write-Host "Locking local machine: $Env:COMPUTERNAME" -ForegroundColor Yellow $LockWorkStation = Add-Type -memberDefinition $signature -name "Win32LockWorkStation" -namespace Win32Functions -passthru $LockWorkStation::LockWorkStation() | Out-Null } #EndRegion LLM #Region Locate <# .SYNOPSIS Quickly search a location for a file, folder, hidden file, etc... This should return the same object that Get-ChildItem returns. .DESCRIPTION This function takes a -Filter and applies dual-wildcards for maximum search results. By default this will search recursively in the local directory, but you can specify any custom location. .PARAMETER Directory [<SwitchParameter>] Gets directories (folders). To get only directories, use the Directory parameter and omit the File parameter. To exclude directories, use the File parameter and omit the Directory parameter. To get directories, use the Directory parameter. .PARAMETER File [<SwitchParameter>] Gets files. To get only files, use the File parameter and omit the Directory parameter. To exclude files, use the Directory parameter and omit the File parameter. To get files, use the File parameter. .PARAMETER Hidden [<SwitchParameter>] Gets only hidden files and directories (folders). By default, Get-ChildItem gets only non-hidden items, but you can use the Force parameter to include hidden items in the results. To get only hidden items, use the Hidden parameter. To exclude hidden items, omit the Hidden parameter. .PARAMETER ReadOnly [<SwitchParameter>] Gets only read-only files and directories (folders). To get only read-only items, use the ReadOnly parameter, its "ar" alias, or the ReadOnly value of the Attributes parameter. To exclude read-only items, use the Attributes parameter. .PARAMETER System [<SwitchParameter>] Gets only system files and directories (folders). To get only system files and folders, use the System parameter. .PARAMETER Force [<SwitchParameter>] Gets hidden files and folders. By default, hidden files and folder are excluded. You can also get hidden files and folders by using the Hidden parameter or the Hidden value of the Attributes parameter. .PARAMETER Exclude <String[]> Specifies, as a string array, an item or items that this cmdlet excludes in the operation. The value of this parameter qualifies the Path parameter. Enter a path element or pattern, such as *.txt. Wildcards are permitted. .PARAMETER Include <String[]> Specifies, as a string array, an item or items that this cmdlet includes in the operation. The value of this parameter qualifies the Path parameter. Enter a path element or pattern, such as *.txt. Wildcards are permitted. The Include parameter is effective only when the command includes the Recurse parameter or the path leads to the contents of a directory, such as C:\Windows\*, where the wildcard character specifies the contents of the C:\Windows directory. .PARAMETER Filter <String> Specifies a filter in the provider's format or language. The value of this parameter qualifies the Path parameter. The syntax of the filter, including the use of wildcards, depends on the provider. Filters are more efficient than other parameters, because the provider applies them when retrieving the objects, rather than having Windows PowerShell filter the objects after they are retrieved. .PARAMETER Path <String[]> Specifies a path to one or more locations. Wildcards are permitted. The default location is the current directory (.). .PARAMETER Recurse [<SwitchParameter>] Indicates that this cmdlet gets the items in the specified locations and in all child items of the locations. In Windows PowerShell 2.0 and earlier versions of Windows PowerShell, the Recurse parameter works only when the value of the Path parameter is a container that has child items, such as C:\Windows or C:\Windows\ , and not when it is an item does not have child items, such as C:\Windows\ .exe. By Default, this is set to True. Use -Recurse:$false to turn off recursive results. .EXAMPLE PS> Locate AdminToolkit.psd1 -Recurse Description ----------- This will search from the current working directory for files or folders mathing the filter 'AdminToolkit.psd1' .EXAMPLE PS> locate foo.txt C:\temp Description ----------- This will search for the file foo.txt in the directory C:\temp. .EXAMPLE PS> locate test -Recurse -Exclude *.tests.* Directory: C:\Temp\HelpDesk\Functions\Public Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 8/5/2020 11:51 AM 6985 Test-Administrator.ps1 Directory: C:\Temp\HelpDesk Mode LastWriteTime Length Name ---- ------------- ------ ---- d---- 8/5/2020 2:07 PM Tests Description ----------- This will search recursively using the filter 'test' and exclude files/folders that match '*.tests.*' .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo Change Log: Version: 1.0 - Function Creation. #> Function Locate() { [CmdletBinding()] param ( [Parameter(Position = 0)] [string]$Filter, [Parameter(Position = 1)] [string]$Path = (Get-Location), [string[]]$Include, [string[]]$Exclude, [switch]$Force, [switch]$Recurse, [switch]$Directory, [switch]$File, [switch]$System, [switch]$Hidden, [switch]$ReadOnly ) if (-Not($PSBoundParameters.Filter)) { $PSBoundParameters.Filter = '*' } else { $PSBoundParameters.Filter = "*$Filter*" } Get-ChildItem @PSBoundParameters -ErrorAction SilentlyContinue } #EndRegion Locate #Region New-Folder <# .SYNOPSIS Easily create a new folder in the current working directory. .DESCRIPTION This will create a new directory in the current working directory. .EXAMPLE PS> New-Folder Foobar Description ----------- This will create a new folder 'Foobar' if there currently is not a folder of the same name. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> function New-Folder() { [CmdletBinding()] param ( [Parameter(Mandatory,Position=0)] [string] $FolderName ) Write-Verbose "Checking to see if folder ``$FolderName`` exists at $(Get-Location)" if (-Not (Test-Path -Path ".\$FolderName")) { Write-Verbose "Folder ``$FolderName`` does not exist. Creating..." New-Item -Name $FolderName -ItemType Directory } else { Write-Error "Folder ``$FolderName`` already exists at $(Get-Location)." } } #EndRegion New-Folder #Region PSRemote <# .SYNOPSIS Starts an Enter-PSSession with the specified Server. .DESCRIPTION PSRemote will attempt to enter a PSSession with a specified host with a specified account. If no Credential is specified, it will use the currently signed in account to connect. .PARAMETER ComputerName This parameter specifies what host to attempt an Enter-PSSession with. .PARAMETER Credential This parameter is used to change the current account for the PSSession. .INPUTS System.String[] You must specify the value for Computername. You cannot pipe a value to this function. .OUTPUTS None There are no outputs except for Write-Host messages. .EXAMPLE PS> PSRemote -ComputerName Computer1 -Credential matthewjd Description ----------- This will attempt to start a PSSession with Computer1 as matthewjd. This will prompt for a password for matthewjd. .EXAMPLE PS> PSRemote Computer1 -IncludeModule AdminToolkit Description ----------- This will use the currently signed in account to connect to attempt a connection with Computer1 and import the module Helpdesk. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo Change Log: Version: 2.0 - Added -IncludeModule parameter. This will allow you to import a local module into your remote session. Version: 1.0 - Function Creation. #> function PSRemote() { [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 0)] [string]$ComputerName, [Parameter(Mandatory = $false, Position = 1)] [PSCredential]$Credential, [Parameter(Mandatory = $false)] [string[]]$IncludeModule, [Parameter(Mandatory = $false)] [string]$IncludeProfile ) begin { function Import-ModuleRemotely { Param ( [string] $moduleName, [System.Management.Automation.Runspaces.PSSession] $session ) Import-Module $moduleName -ErrorAction SilentlyContinue $Script = @" if (get-module $moduleName) { remove-module $moduleName; } New-Module -Name $moduleName { $($(Get-Module $moduleName).Definition) } | Import-Module "@ Invoke-Command -Session $Session -ScriptBlock { Param($Script) . ([ScriptBlock]::Create($Script)) #Get-Module } -ArgumentList $Script } } process { try { if ($Credential) { $Session = New-PSSession -ComputerName $ComputerName -Credential $credential -ErrorAction Stop } else { $Session = New-PSSession -ComputerName $ComputerName -ErrorAction Stop } if ($PSBoundParameters.ContainsKey('IncludeProfile')) { Invoke-Command -FilePath $IncludeProfile -Session $Session -ErrorAction Stop } if ($IncludeModule) { foreach ($Module in $IncludeModule) { Import-ModuleRemotely -moduleName $Module -session $Session } } Enter-PSSession -Session $Session -ErrorAction Stop } catch { Write-Error "$($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" } } } #EndRegion PSRemote #Region Push-LocalScheduledTask <# .SYNOPSIS Deploy a local scheduled task to a remote machine .DESCRIPTION This function exports the XML for a local scheduled task and creates that task on a remote machine. .PARAMETER ComputerName This parameter specifies the remote host(s) to create the task(s) on. This parameter supports tab-completion based on the current domain. I can type '-ComputerName cgo-2' and this will tab-complete computer objects in the current domain that match the string 'cgo-2' .PARAMETER TaskName This parameter specifies the local task name to export and create on a remote machine. I have not tested how to export nested tasks (See Register-ScheduledTask '-TaskPath' parameter) You can specify multiple task names, separated by comma please. .PARAMETER Credential Specifies a user account that has permission to perform this action. The default is the current user. This credential is used for a task against the local pc, and the remote PC. because of this, the account used must have rights to do the required tasks on all computers involved. Type a user name, such as User01 or Domain01\User01 , or enter a PSCredential object generated by the `Get-Credential` cmdlet. If you type a user name, you're prompted to enter the password. Credentials are stored in a PSCredential (/dotnet/api/system.management.automation.pscredential)object and the password is stored as a SecureString (/dotnet/api/system.security.securestring). > [!NOTE] > For more information about SecureString data protection, see > How secure is SecureString? (/dotnet/api/system.security.securestring#how-secure-is-securestring). .PARAMETER Force Instructs the cmdlet to perform the operation without prompting for confirmation. Additionally this will overwrite any remote tasks with the same name. If you attempt to deploy a local task on a remote machine without using -Force, the export will fail. .PARAMETER PassThru I haven't gotten this switch to be accurate. Currently this function will ALWAYS spit out Scheduled Task objects that it creates whether -PassThru is present or not. The goal is to have the function not return objects if -PassThru is not present... like every other advanced function. .EXAMPLE PS>Deploy-LocalScheduledTask -ComputerName Computer1,Computer2 -TaskName "Task1","Task2" Description ----------- This will export both Task1 and Task2 scheduled tasks to both Computer1 and Computer2. .EXAMPLE PS>Deploy-LocalScheduledTask -ComputerName Computer1 -TaskName "Task1" -Credential (Get-Credential) -Force Description ----------- This will export the task Task1 to Computer1 using the provided credentials. You can also save the results of Get-Credential to a variable and use the '-Credential $cred' method. This will also overwrite a possible existing task named Task1 since -Force is used. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> function Push-LocalScheduledTask() { [CmdletBinding()] param( [Parameter(Mandatory)] [string[]] $ComputerName, [Parameter(Mandatory)] [string[]] $TaskName, [PSCredential] $Credential, [switch] $Force, #? Should this switch just be tossed? #TODO This switch doesn't do anything. Need to figure out how to supress Invoke-Command output for Register-ScheduledTask command. [switch] $PassThru ) begin { $ComputerName = foreach ($Computer in $ComputerName) { if (Test-Connection -ComputerName $Computer -Count 1 -ErrorAction SilentlyContinue) { $Computer } else { Write-Warning "Test-Connection to '$ComputerName' failed." } } } process { try { foreach ($Computer in $ComputerName) { $InvokeParams = @{ ComputerName = $Computer } if ($PSBoundParameters.ContainsKey('Credential')) { $InvokeParams += @{Credential = $Credential } } foreach ($Task in $TaskName) { if ($PSBoundParameters.ContainsKey('Credential')) { $TaskXML = Invoke-Command -ComputerName $env:COMPUTERNAME -Credential $Credential -Command { Export-ScheduledTask $using:Task | Out-String } } else { $TaskXML = Export-ScheduledTask $Task | Out-String } $TaskParams = @{ Xml = $TaskXML TaskName = $Task } if ($PSBoundParameters.ContainsKey('Force')) { $TaskParams += @{Force = $true } } if (-Not($PSBoundParameters.ContainsKey('PassThru'))) { $TaskParams += @{InformationAction = 'Ignore' } } Invoke-Command @InvokeParams -ScriptBlock { Register-ScheduledTask @using:TaskParams } } } } catch { Write-Error "$($_.Exception.Message) - Line Number: $($_.InvocationInfo.ScriptLineNumber)" } } end {} } #EndRegion Push-LocalScheduledTask #Region Remove-AllTempFiles <# .Synopsis Generic Cleanup of temp files on a computer. .Description This Command removes log files, temp files, and empties the recycle bin. Access denied errors do not indicate a failure of the script. Run for the local or a remote PC. .EXAMPLE PS> Remove-All Description ----------- Free up space on the local computer .EXAMPLE PS> Remove-All -Computer Test-PC-01 Description ----------- Free up space on a remote PC. May be more effective if run locally depending on in place security. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> Function Remove-AllTempFiles() { [CmdletBinding(SupportsShouldProcess)] param ( [Parameter()]$ComputerName ) #Statement of Free Space before Cleaning Write-Host " " Write-Host "Free Space Before Cleaning" -ForegroundColor Yellow Get-CimInstance win32_logicaldisk -filter "drivetype=3" -computer $ComputerName | Format-Table -Property DeviceID, Volumename, ` @{Name = "SizeGB"; Expression = { [math]::Round($_.Size / 1GB) } }, ` @{Name = "FreeGB"; Expression = { [math]::Round($_.Freespace / 1GB, 2) } }, ` @{Name = "PercentFree"; Expression = { [math]::Round(($_.Freespace / $_.size) * 100, 2) } } #Statement that the function is freeing up space Write-Host "Freeing up space. Enjoy your Coffee!" -BackgroundColor Black -ForegroundColor Green #Free up space on the local or remote computer if ($null -ne $ComputerName) { $ErrorActionPreference = 'SilentlyContinue' Get-Service -ComputerName $ComputerName TrustedInstaller | Stop-Service -Force Get-ChildItem -path "\\$ComputerName\C$\windows\logs" -Include '*.log' -Recurse -force | Remove-Item -force -Recurse Get-ChildItem -path "\\$ComputerName\C$\windows\logs" -Include '*.cab' -Recurse -force | Remove-Item -force -Recurse Get-ChildItem -path "\\$ComputerName\C$\ProgramData\Microsoft\Windows\WER" -Include '*.*' -Recurse -force | Remove-Item -force -Recurse Get-ChildItem -path "\\$ComputerName\C$\$recycle.bin" -Include '*' -Recurse -force | Remove-Item -force -Recurse Get-ChildItem -path "\\$ComputerName\C$\Users\*\AppData\Local\Google\Chrome\User Data\Default\Cache\" -include '*.*' -Recurse -force | Remove-Item -force -Recurse Get-ChildItem -path "\\$ComputerName\C$\Users\*\AppData\Local\Microsoft\Terminal Server Client\" -include '*.*' -Recurse -force | Remove-Item -force -Recurse $tempfolders = @("\\$ComputerName\C$\Windows\Temp\*", "\\$ComputerName\C$\Windows\Prefetch\*", "\\$ComputerName\C$\Documents and Settings\*\Local Settings\temp\*", "\\$ComputerName\C$\Users\*\Appdata\Local\Temp\*") Remove-Item $tempfolders -force -recurse -errorAction SilentlyContinue $tempinternetfolders = @("\\$ComputerName\C$\Users\*\Appdata\Local\Microsoft\Windows\INetCache\*", "\\$ComputerName\C$\Users\*\Appdata\Local\Microsoft\Windows\Cookies\*", "\\$ComputerName\C$\Users\*\AppData\Local\Microsoft\Windows\Temporary Internet Files\*.*") Remove-Item $tempinternetfolders -force -recurse -errorAction SilentlyContinue Get-Service -ComputerName $ComputerName -Name TrustedInstaller | Start-Service $ErrorActionPreference = 'Continue' Write-Host " " Write-Host "Free Space After Cleaning" -ForegroundColor Yellow Get-CimInstance win32_logicaldisk -filter "drivetype=3" -computer $ComputerName | Format-Table -Property DeviceID, Volumename, ` @{Name = "SizeGB"; Expression = { [math]::Round($_.Size / 1GB) } }, ` @{Name = "FreeGB"; Expression = { [math]::Round($_.Freespace / 1GB, 2) } }, ` @{Name = "PercentFree"; Expression = { [math]::Round(($_.Freespace / $_.size) * 100, 2) } } } else { $ErrorActionPreference = 'SilentlyContinue' Stop-Service TrustedInstaller -Force Get-ChildItem -path "C:\windows\" -Include '*.log' -Recurse -force | Remove-Item -force -Recurse Get-ChildItem -path "C:\windows\logs" -Include '*.cab' -Recurse -force | Remove-Item -force -Recurse Get-ChildItem -path "C:\ProgramData\Microsoft\Windows\WER" -Include '*.*' -Recurse -force | Remove-Item -force -Recurse Get-ChildItem -path "c:\$recycle.bin" -Include '*' -Recurse -force | Remove-Item -force -Recurse Get-ChildItem -path "C:\Users\*\AppData\Local\Google\Chrome\User Data\Default\Cache\" -include '*.*' -Recurse -force | Remove-Item -force -Recurse Get-ChildItem -path "C:\Users\*\AppData\Local\Microsoft\Terminal Server Client\" -include '*.*' -Recurse -force | Remove-Item -force -Recurse $tempfolders = @("C:\Windows\Temp\*", "C:\Windows\Prefetch\*", "C:\Documents and Settings\*\Local Settings\temp\*", "C:\Users\*\Appdata\Local\Temp\*") Remove-Item $tempfolders -force -recurse -errorAction SilentlyContinue $tempinternetfolders = @("C:\Users\*\Appdata\Local\Microsoft\Windows\INetCache\*", "C:\Users\*\Appdata\Local\Microsoft\Windows\Cookies\*", "C:\Users\*\AppData\Local\Microsoft\Windows\Temporary Internet Files\*.*") Remove-Item $tempinternetfolders -force -recurse -errorAction SilentlyContinue powercfg.exe /hibernate off Remove-Item c:\hiberfil.sys -force -ErrorAction SilentlyContinue Start-Service TrustedInstaller $ErrorActionPreference = 'Continue' Write-Host " " Write-Host "Free Space After Cleaning" -ForegroundColor Yellow Get-CimInstance win32_logicaldisk -filter "drivetype=3" -computer $ComputerName | Format-Table -Property DeviceID, Volumename, ` @{Name = "SizeGB"; Expression = { [math]::Round($_.Size / 1GB) } }, ` @{Name = "FreeGB"; Expression = { [math]::Round($_.Freespace / 1GB, 2) } }, ` @{Name = "PercentFree"; Expression = { [math]::Round(($_.Freespace / $_.size) * 100, 2) } } } } #EndRegion Remove-AllTempFiles #Region Remove-Application <# .Synopsis Attempt to Uninstall an application. .DESCRIPTION This command uninstalls an application. Good for when elevated privileges are needed from a user session. .EXAMPLE Specify the installed application being uninstalled. The full application name must be used. Remove-AppName -AppName 'App Name has spaces' .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo Change Log: Version: 1.0 - Function Creation. #> Function Remove-Application { [CmdletBinding()] Param ( [Parameter(Mandatory = $true)]$AppName ) WMIC.exe product where name="$AppName" call uninstall } #EndRegion Remove-Application #Region Remove-OlderThan <# .Synopsis Remove files in a directory recursively based on how many days since the files was changed. Use negative values for -DaysBack. .Description This scripts function is to delete files and folders older than x days recursively. .Example Delete-OlderThan -Path "C:\Folder" -DaysBack 90 .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo Change Log: Version: 1.0 - Function Creation. #> Function Remove-OlderThan { [CmdletBinding()] Param ( [Parameter(Mandatory = $true)]$Path, [Parameter(Mandatory = $true)][ValidateScript( { $_ -gt 0 })][int]$DaysBack, [Parameter(Mandatory = $false)][Switch]$Recurse ) $CurrentDate = Get-Date $DatetoDelete = $CurrentDate.AddDays("-$Daysback") Get-ChildItem $Path | Where-Object { $_.LastWriteTime -lt $DatetoDelete } | Remove-Item -Force } #EndRegion Remove-OlderThan #Region Remove-Path <# .Synopsis Deletes folder recursively, so be careful. If -Include is empty, it will delete all files, otherwise it will delete only the ones you -Include. .DESCRIPTION This command deletes all files recursively in a path that match the included filename. .EXAMPLE PS>Remove-Path C:\temp Description ----------- Specify the parent folder from which the command runs and specify file names to include. Wildcards are supported. Remove-Path -path c:\Folder -include "*.logs" .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> Function Remove-Path { [CmdletBinding()] Param ( [Parameter(Mandatory = $true)]$Path, [Parameter(Mandatory = $true)]$Include ) Get-ChildItem -path "$Path" -Include "$Include" -Recurse -force | Remove-Item -force -Recurse } #EndRegion Remove-Path #Region Remove-PrintQueue <# .Synopsis Quickly clear print que from all installed printers. .DESCRIPTION This command clears print queues for all printers, including network printers. If you specify a single printer using -Printer, you will NOT clear all installed printers. .EXAMPLE PS> Remove-PrintQueue -Printer Some_printer_name1 Description ----------- This will delete all of the current print jobs on the network printer 'Some_printer_name1' .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo Change Log: Version: 1.0 - Function Creation. #> Function Remove-PrintQueue { [CmdletBinding()] param ( [string]$Printer ) if ($Printer) { $Printers = Get-Printer -Name *$Printer* } else { $Printers = Get-Printer } foreach ($printer in $printers) { $printjobs = Get-PrintJob -PrinterObject $printer foreach ($printjob in $printjobs) { Remove-PrintJob -InputObject $printjob } } } #EndRegion Remove-PrintQueue #Region Reset-NetworkAdapter <# .SYNOPSIS Reset a network interface. .DESCRIPTION Reset a specified interface with -Interface. .EXAMPLE Reset-NetworkAdapter -Interface "Local Area Connection" .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo Change Log: Version: 1.0 - Function Creation. #> Function Reset-NetworkAdapter { [CmdletBinding()] param ( [Parameter(Mandatory = $true)]$Interface ) netsh.exe interface set interface $Interface admin=disable netsh.exe interface set interface $Interface admin=enable } #EndRegion Reset-NetworkAdapter #Region Reset-NetworkStack <# .SYNOPSIS Reset Network Stack. Will require a reboot. .DESCRIPTION Resets the TCP/IP and Winsock Stacks .EXAMPLE PS> Reset-NetworkStack Description ----------- This will reset the winsock and ip, ipv4, and ipv6 interfaces. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo Change Log: Version: 1.0 - Function Creation. #> Function Reset-NetworkStack { [CmdletBinding()] param ( ) netsh.exe winsock reset netsh.exe int ip reset netsh.exe int ipv4 reset reset.log netsh.exe int ipv6 reset reset.log Write-Output "[-] You will need to restart this computer." } #EndRegion Reset-NetworkStack #Region SU <# .SYNOPSIS Windows version of the linux command `SU` .DESCRIPTION Immitate SU on Linux. This creates new PoSH Session as an admin. .EXAMPLE PS> su Description ----------- Depending on what edition of powershell is running, this will start an elevated process. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> function su() { [CmdletBinding()] param () switch ($($PSVersionTable.PSEdition)) { "Desktop" { Start-Process Powershell -Verb RunAs } "Core" { Start-Process Pwsh -Verb RunAs } } } #EndRegion SU #Region TimeStamp <# .SYNOPSIS This is a filter used to place colorized timestamps on any output messages. .DESCRIPTION The function `TimeStamp` is a colorized version of this command `DateStamp`, but `TimeStamp` output cannot be written to a file. You will want to use `DateStamp` if you are going to output your messages into a log or txt file. .EXAMPLE "ERROR: Something bad happened on this line of the script" | TimeStamp [08/04/2020 11:55:39] : ERROR: Something bad happened on this line of the script Description ----------- This line will place a time stamp at the beginning of the line that can only be written to the console and not to a file. .EXAMPLE "ERROR: Something bad happened on this line of the script" | TimeStamp Red [08/04/2020 11:56:40] : ERROR: Something bad happened on this line of the script Description ----------- This will colorize the timestamp, and turn the provided string red. You can provide any color usable by Write-Host -ForegroundColor. .EXAMPLE "ERROR: " | TimeStamp Red NoNewLine;"Something bad happened on this line fo the script" [08/04/2020 11:58:54] : ERROR: Something bad happened on this line fo the script Description ----------- This will colorize the TimeStamp, and make "ERROR: " Red, and with `NoNewLine` provided, you can add additional non-colorized text to the same line. .NOTES Author: Matthew J. DeGarmo Site: https://matthewjdegarmo.github.io #> filter TimeStamp($color, $NoNewLine) { # [CmdletBinding()] # This is to pass the advanced parameter pester tests. # param () # This is to pass the advanced parameter pester tests. # function # This is to pass the advanced parameter pester tests. if ($color -eq 'NoNewLine') { $color = 'White' $NoNewLine = 'NoNewLine' } Write-Host "[" -ForegroundColor Yellow -NoNewLine Write-Host $(Get-Date -Format "MM/dd/yyyy HH:mm:ss") -ForegroundColor Green -NoNewLine Write-Host "] " -ForegroundColor Yellow -NoNewLine Write-Host ": " -ForegroundColor Red -NoNewLine if ($NoNewLine) { Write-Host "$_" -ForegroundColor $color -NoNewline } elseif (!$Color) { Write-Host "$_" } else { Write-Host "$_" -ForegroundColor $color } } #EndRegion TimeStamp #Region Update-PowerShell <# .SYNOPSIS This will both Install the latest release of PowerShell or update your current PowerShell. .DESCRIPTION This one-liner is provided by [Tyler Leonhardt](https://github.com/TylerLeonhardt). I have added some parameters to help customize the install of the .MSI .PARAMETER Preview Specifying this switch will install the latest preview version of PowerShell. Otherwise this will install / update the latest stable release. .PARAMETER Quiet Specifying this switch will install or update quietly with no gui popup, taking all defaults of the install. You need to run as admin to use this switch. .EXAMPLE PS> Update-Powershell -Preview Description ----------- This will update or install PowerShell with the latest Preview release. .EXAMPLE PS> Update-Powershell -Quiet Description ----------- This will update or install the latest General Release version of PowerShell. .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> function Update-PowerShell() { [CmdletBinding()] param( [switch] $Preview, [switch] $Quiet ) if ($PSBoundParameters.ContainsKey('Preview')) { $PreviewOption = '-Preview' } if ($PSBoundParameters.ContainsKey('Quiet')) { $QuietOption = '-Quiet' } Invoke-Expression -Command "& {$(Invoke-RestMethod https://aka.ms/install-powershell.ps1)} -UseMSI $PreviewOption $QuietOption" } #EndRegion Update-PowerShell #Region Watch-Command <# .SYNOPSIS Loop through a command forever until canceled (Ctrl + C) .DESCRIPTION This is meant to be a powershell equivalent to the linux `watch` command. .PARAMETER Command This parameter takes in a command to evaluate. This parameter takes in a string, and uses Invoke-Expression to run the command. This means that complex commands must be wrapped within quotation marks. .PARAMETER WaitSeconds This parameter takes in an Int (number) which equates to the number of seconds to wait after the completion of the command before executing again. .PARAMETER Differences This switch will not overwrite the original text displayed if something in the output has changed. It will place a timestamp in between the previous output and the current (changed) output. This also breaks out what items were `Added` or `Removed` from the previous output to assist with monitoring visually. .EXAMPLE PS> Watch-Command -Command Get-Process Description ----------- This will run Get-Process, wait 5 seconds (the default amount of time) and run it again. .EXAMPLE PS> Watch-Command "Get-Process | Select-Object -First 12" -Differences -WaitSeconds 3 Description ----------- This will run the Get-Process command through the pipeline, and monitor for differences every 3 seconds. Notice this command is treated as a string and `"wrapped in quotes"` .NOTES Author: Matthew J. DeGarmo Handle: @matthewjdegarmo #> function Watch-Command() { [CmdletBinding()] param( [Parameter(Mandatory, Position = 0)] [string] $Command, [Parameter(Position = 1)] [int] $WaitSeconds = 5, [switch] $Differences ) begin { $Output = $null $PreviousOutput = $null $Difference = $null $SaveX = [console]::CursorLeft $SaveY = [console]::CursorTop + 1 } process { try { Write-Output "Watching command: '$Command' | Interval: $WaitSeconds`s | Time: $([datetime]::Now)" While ($true) { [console]::SetCursorPosition($SaveX, $SaveY) $Output = (Invoke-Expression -Command $Command -ErrorAction SilentlyContinue) if ($PreviousOutput -and $Output -and $Differences.IsPresent) { # $Properties = $PreviousOutput | Get-Member -MemberType "*Property*" $Difference = (Compare-Object $PreviousOutput $Output -PassThru) if ($Difference) { ($PreviousOutput | Out-String).Trim() "|-------------------------------| |-----------------|" "There was a change in the output: $([datetime]::Now)" "|-------------------------------| |-----------------|" $AddedDifferences = $Difference | Where-Object { $_.SideIndicator -eq "=>" } $RemovedDifferences = $Difference | Where-Object { $_.SideIndicator -eq "<=" } if ($AddedDifferences) { "Added:"; ($AddedDifferences | Out-String).Trim(); "" } if ($RemovedDifferences) { "Removed:"; ($RemovedDifferences | Out-String).Trim(); "" } # ($Difference | Out-String).Trim() # $Difference = $null # $AddedDifferences = $null # $RemovedDifferences = $null ""; Write-Output "Watching command: '$Command' | Interval: $WaitSeconds`s | Time: $([datetime]::Now)" $SaveX = [console]::CursorLeft $SaveY = [console]::CursorTop } } if ($Differences.IsPresent) { $PreviousOutput = $Output } ($Output | Out-String).Trim() Start-Sleep -Seconds $WaitSeconds } } finally { $SaveX = $null $SaveY = $null $Output = $null $PreviousOutput = $null # $Difference = $null } } end {} } #EndRegion Watch-Command |