A collection of commands, code snippets, and scripts tailored for managing and automating tasks in a Windows environment. Designed for experienced administrators, this resource delves beyond basic PowerShell usage, offering practical solutions for variety of scenarios.
Invoke-WebRequest -Uri "https://github.com/microsoft/winget-cli/releases/latest/download/Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle" -OutFile "C:\WinGet.msixbundle"
Add-AppxPackage "C:\WinGet.msixbundle"
Add-AppxPackage -RegisterByFamilyName -MainPackage Microsoft.Winget.Source_8wekyb3d8bbwe
Not sure if the slack channel is active usually it's the name of the exercise with a 1 at the end like century1
If a wsl2 distro is installed commands from the default distro can be called withwsl
this can be combined with Convert-To-JSON
to use common linux data-wrangling tools like awk
, sed
, and grep
get-hotfix | ConvertTo-Json | wsl jq '.[] | .HotFixID' | wsl sort
Get-Process | Where-Object { $_.MainWindowTitle } | Stop-Process
Like when you can't uninstall Creative Cloud
Get-Process | Where-Object {$_.Company -like "*Adobe*"} | Stop-Process -Force
Get-WinEvent -LogName System | Where-Object { $_.ID -eq 6006 -or $_.ID -eq 6008 -or $_.ID -eq 1074 } | Format-List -Property TimeCreated, ID, Message
Get-ADUser -Filter "Name -like '*partofname*'"
$domain = []::GetCurrentDomain().Name
Resolve-DnsName -Name "_ldap._tcp.dc._msdcs.$domainName" -QueryType SRV
.\WinDump.exe -i 3 icmp and icmp[icmp-echoreply]=icmp-echo
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False
Set-NetFirewallRule -DisplayGroup "File And Printer Sharing" -Enabled True
Enable Linked Connections (Administrative and regular user accounts can see the same network shares)
reg add HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System /v EnableLinkedConnections /t REG_DWORD /d 1 /f
netsh advfirewall firewall add rule name="Allow incoming ping requests IPv4" dir=in action=allow protocol=icmpv4
This adjusts the IPv6 prefix policies so that IPv4 addresses are preferred (Ping, DNS Resolution, etc.). Run both commands.
netsh int ipv6 set prefixpolicy ::ffff:0:0/96 46 4
netsh int ipv6 set prefixpolicy ::/0 45 6
netsh int ip reset
netsh winsock reset
mshta.exe "javascript:open();close();"
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
Set-ItemProperty ‘HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp\‘ -Name “UserAuthentication” -Value 1
Enable-NetFirewallRule -DisplayGroup “Remote Desktop”
iex ((New-Object System.Net.WebClient).DownloadString('https://git.io/debloat'))
Set-NetFirewallRule -DisplayGroup 'Remote Event Log Management' -Enabled True -PassThru
Invoke-WuJob -ComputerName $Computers -Script { ipmo PSWindowsUpdate; Install-WindowsUpdate -AcceptAll -IgnoreReboot | Out-File "C:\Windows\PSWindowsUpdate.log"} -RunNow -Confirm:$false -Verbose -ErrorAction Ignore
Add-Type -TypeDefinition 'using System;using System.Runtime.InteropServices;public class Keyboard {[DllImport("user32.dll")]public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, int dwExtraInfo);}' ; [Keyboard]::keybd_event(0x11, 0, 0, 0); [Keyboard]::keybd_event(0x10, 0, 0, 0); [Keyboard]::keybd_event(0x5B, 0, 0, 0); [Keyboard]::keybd_event(0x42, 0, 0, 0); [Keyboard]::keybd_event(0x42, 0, 2, 0); [Keyboard]::keybd_event(0x5B, 0, 2, 0); [Keyboard]::keybd_event(0x10, 0, 2, 0); [Keyboard]::keybd_event(0x11, 0, 2, 0);
powershell -nop -exec bypass -c “IEX (New-Object Net.WebClient).DownloadString(‘http://bit.ly/2K75g15’)"
[void][Windows.Security.Credentials.PasswordVault,Windows.Security.Credentials,ContentType=WindowsRuntime] $vault = New-Object Windows.Security.Credentials.PasswordVault $vault.RetrieveAll() | ForEach {$vault.Remove($_)}
Get-Mailbox | Group-Object -Property:Office | Select-Object name,count
Get-ADComputer -Filter "Name -like 'PC-*'" | Select-String -Pattern PC-\d+
Get-ADComputer -Filter * | Select-Object -ExpandProperty Name
Get-ADComputer -Filter * -Properties Name,OperatingSystem ,lastlogontimestamp | Select Name,OperatingSystem ,@{N='lastlogontimestamp'; E={[DateTime]::FromFileTime($_.lastlogontimestamp)}}
query user /server:$SERVER
Get-ADComputer -Filter * -Properties * | Sort LastLogon | Select Name, LastLogonDate,@{Name='LastLogon';Expression={[DateTime]::FromFileTime($_.LastLogon)}}
Search-ADAccount -AccountDisabled -UsersOnly | Where {$_.DistinguishedName -notlike "*OU=Disabled Users,OU=USERS,DC=EXAMPLE,DC=COM"}
Get-ADUser -Identity “username” -Properties “LastLogonDate”
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All
Set-SmbServerConfiguration -EnableSMB1Protocol $false -Force
powershell.exe Set-ExecutionPolicy Bypass -Force
Invoke-Command -ComputerName COMPUTER-01 -ScriptBlock { winget list}
shutdown -r -t $([int]([datetime]"11PM"-(Get-Date)).TotalSeconds)
gps explorer | spps
Get-NetConnectionProfile | Set-NetConnectionProfile -NetworkCategory Private
Enable-PSRemoting -force
w32tm /query /status
w32tm /config /manualpeerlist:"time.google.com,time.cloudflare.com,time.windows.com" /syncfromflags:manual /reliable:YES /update
Restart-Service w32time
w32tm /resync
$filename = Join-Path -Path \\osdri-dc22\IT-Inventory\ -ChildPath "${env:COMPUTERNAME}.txt"
Get-ComputerInfo |
Select-Object CsName, CsManufacturer, CsModel, BiosSeralNumber, CsProcessors, CsPhyicallyInstalledMemory, OsName, OsVersion, CsUserName |
Sort-Object |
out-file -FilePath $filename
# Get the current directory
$currentDirectory = Get-Location
# Define the output CSV file name
$outputCsv = "$currentDirectory\output.csv"
# Initialize an empty array to store the data
$dataArray = @()
# Loop through each file in the current directory
Get-ChildItem -Path $currentDirectory -File | ForEach-Object {
$file = $_.FullName
# Read the file contents
$content = Get-Content -Path $file
# Create a hashtable to store the data for each file
$dataHash = @{}
# Parse each line and extract key-value pairs
foreach ($line in $content) {
if ($line -match "^(.*)\s+:\s+(.*)$") {
$key = $matches[1].Trim()
$value = $matches[2].Trim()
# Add the key-value pair to the hashtable
$dataHash[$key] = $value
}
}
# Convert the hashtable to a custom object and add to the data array
$dataArray += New-Object PSObject -Property $dataHash
}
# Define the custom column headers
$columnHeaders = @{
"CsName" = "Computer Name"
"CsManufacturer" = "Manufacturer"
"CsModel" = "Model"
"BiosSeralNumber" = "BIOS Serial Number"
"CsProcessors" = "Processor"
"CsPhyicallyInstalledMemory" = "Physical Memory (Bytes)"
"OsName" = "Operating System"
"OsVersion" = "OS Version"
"CsUserName" = "User Name"
}
# Create a new array with custom headers
$customDataArray = $dataArray | Select-Object @{Name='Computer Name';Expression={$_.CsName}},
@{Name='Manufacturer';Expression={$_.CsManufacturer}},
@{Name='Model';Expression={$_.CsModel}},
@{Name='BIOS Serial Number';Expression={$_.BiosSeralNumber}},
@{Name='Processor';Expression={$_.CsProcessors}},
@{Name='Physical Memory (Bytes)';Expression={$_.CsPhyicallyInstalledMemory}},
@{Name='Operating System';Expression={$_.OsName}},
@{Name='OS Version';Expression={$_.OsVersion}},
@{Name='User Name';Expression={$_.CsUserName}}
# Export the data to a CSV file
$customDataArray | Export-Csv -Path $outputCsv -NoTypeInformation
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
function Select-FolderDialog {
$folderBrowser = New-Object System.Windows.Forms.FolderBrowserDialog
$folderBrowser.Description = "Select the folder containing HEIC images"
$result = $folderBrowser.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
return $folderBrowser.SelectedPath
}
return $null
}
function Select-SaveFileDialog {
$saveFileDialog = New-Object System.Windows.Forms.SaveFileDialog
$saveFileDialog.Filter = "PDF files (*.pdf)|*.pdf"
$saveFileDialog.Title = "Save PDF As"
$saveFileDialog.DefaultExt = "pdf"
$result = $saveFileDialog.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK) {
return $saveFileDialog.FileName
}
return $null
}
function Convert-HEICtoPDF {
[System.Windows.Forms.Application]::EnableVisualStyles()
$inputDir = Select-FolderDialog
if (-not $inputDir) {
[System.Windows.Forms.MessageBox]::Show("No folder selected. Exiting.")
return
}
$outputPdf = Select-SaveFileDialog
if (-not $outputPdf) {
[System.Windows.Forms.MessageBox]::Show("No output file selected. Exiting.")
return
}
$heicFiles = Get-ChildItem -Path $inputDir -Filter *.heic
if ($heicFiles.Count -eq 0) {
[System.Windows.Forms.MessageBox]::Show("No HEIC files found in the directory.")
return
}
foreach ($file in $heicFiles) {
$jpgFile = [System.IO.Path]::ChangeExtension($file.FullName, ".jpg")
& magick "$($file.FullName)" "$jpgFile"
}
$jpgFiles = Get-ChildItem -Path $inputDir -Filter *.jpg
& magick convert $jpgFiles.FullName $outputPdf
[System.Windows.Forms.MessageBox]::Show("PDF created successfully at $outputPdf")
}
Convert-HEICtoPDF
$Computers = @("PMC01","PMC04","PMC06","PMC08","PMC-JOAN","PMC-SARA","LAWOFFICE-2","PMC03","PMC07")
$OnlineComputers = @()
foreach ($Computer in $Computers) {
if (Test-Connection -ComputerName $Computer -Count 1 -Quiet) {
$OnlineComputers += $Computer
}
else {
Write-Host "$Computer is offline."
}
}
Invoke-WuJob -ComputerName $OnlineComputers -Script {
ipmo PSWindowsUpdate;
Install-WindowsUpdate -AcceptAll -IgnoreReboot -MicrosoftUpdate | Out-File "C:\Windows\PSWindowsUpdate.log"
} -RunNow -Confirm:$false -Verbose -ErrorAction Ignore
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
$CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments
Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
Exit
}
}
$COMPUTER_LIST = Get-ADComputer -Filter * | Select-Object -ExpandProperty Name
foreach ($COMPUTER in $COMPUTER_LIST) {
echo [$COMPUTER]
query user /server:$COMPUTER
echo `n
}
Portable tools and programs are placed in a directory, loops over the directory and adds subfolders to PATH environment variable if they don't already exist.
$binPath = "C:\bin"
Get-ChildItem -Path $binPath -Directory | ForEach-Object {
$currentPath = [System.Environment]::GetEnvironmentVariable("PATH", "Machine")
$newPath = $_.FullName
If (-Not $currentPath.Contains($newPath)) {
[System.Environment]::SetEnvironmentVariable("PATH", "$currentPath;$newPath", "Machine")
}
}
$action = New-ScheduledTaskAction -Execute 'Powershell.exe' -Argument '-NoProfile -WindowStyle Hidden -command "& {Restart-Computer -Force -wait}"'
$trigger = New-ScheduledTaskTrigger -Once -At 3am
$taskname = 'ScheduledReboot'
$params = @{
Action = $action
Trigger = $trigger
TaskName = $taskname
}
if(Get-ScheduledTask -TaskName $params.TaskName -EA SilentlyContinue) {
Set-ScheduledTask @params
}
else {
Register-ScheduledTask @params
}
$TouchScreenDevices = Get-PnpDevice | Where-Object { $_.FriendlyName -like "*HID-compliant touch screen*" }
foreach ($Device in $TouchScreenDevices) {
if ($Device.Status -eq 'OK') {
Write-Output "Disabling device: $($Device.FriendlyName)..."
Disable-PnpDevice -InstanceId $Device.InstanceId -Confirm:$false
} else {
Write-Output "Enabling device: $($Device.FriendlyName)..."
Enable-PnpDevice -InstanceId $Device.InstanceId -Confirm:$false
}
}
$keys = dir HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall | where { $_.GetValueNames() -contains 'DisplayName' }
$keys += dir HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall | where { $_.GetValueNames() -contains 'DisplayName' }
$k = $keys | where { $_.GetValue('DisplayName') -eq 'DISPLAYNAMEHERE' }
Requires PatchMyPC
# Windows Update
if ((Get-Module -ListAvailable -Name PSWindowsUpdate) -eq $null)
{
Write-Host -ForegroundColor Yellow "Windows Update module not found, installing..."
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force
Install-Module -Name PSWindowsUpdate -Force
}
Write-Host -ForegroundColor Yellow "Getting Windows Updates..."
Import-Module PSWindowsUpdate
Install-WindowsUpdate -AcceptAll -IgnoreReboot
# Patch Software
Write-Host -ForegroundColor Yellow "Patching installed software..."
& C:\Users\ITAdmin\Downloads\PatchMyPC.exe /auto -Wait
# System File Check
sfc /scannow
# Cleanup disk
cleanmgr.exe /full
# PowerShell script to organize files into subdirectories based on file type, without moving existing directories
# ! Use with caution there is no confirmation or undo !
# Prompt user to enter the directory path
$directoryPath = Read-Host -Prompt 'Enter the directory path'
# Check if the directory exists
if (-Not (Test-Path $directoryPath)) {
Write-Host "The directory does not exist."
exit
}
# Define subdirectory names and file extensions
$subdirectories = @{
"Photos" = @("*.jpg", "*.jpeg", "*.png", "*.gif", "*.bmp", "*.tiff");
"Videos" = @("*.mp4", "*.mov", "*.wmv", "*.flv", "*.avi", "*.mkv");
"Documents" = @("*.doc", "*.docx", "*.pdf", "*.txt", "*.xls", "*.xlsx", "*.ppt", "*.pptx");
"Bin" = @("*.exe", "*.bin", "*.dll", "*.bat", "*.msi");
"Other" = @()
}
# Function to move files to their respective subdirectories
function Move-Files {
param(
[string]$SubDir,
[string[]]$Extensions
)
# Create the subdirectory if it doesn't exist
$subDirPath = Join-Path $directoryPath $SubDir
if (-Not (Test-Path $subDirPath)) {
New-Item -Path $subDirPath -ItemType Directory | Out-Null
}
# Move files to the subdirectory
foreach ($extension in $Extensions) {
Get-ChildItem -Path $directoryPath -Filter $extension -File | Move-Item -Destination $subDirPath
}
}
# Move files based on extensions
foreach ($subDir in $subdirectories.Keys) {
Move-Files -SubDir $subDir -Extensions $subdirectories[$subDir]
}
# Move remaining files to 'Other' directory
Get-ChildItem -Path $directoryPath -File |
Where-Object { $_.Extension -notin $subdirectories.Values -and !($_.PSIsContainer) } |
Move-Item -Destination (Join-Path $directoryPath "Other")
$profiles = (netsh wlan show profiles) | Select-String "\:(.+)$" | %{$_.Matches.Groups[1].Value.Trim()}
foreach ($profile in $profiles) {
# Get details about the profile, including the password in clear text
$password = (netsh wlan show profile name=$profile key=clear) | Select-String "Key Content\W+\:(.+)$" | %{$_.Matches.Groups[1].Value.Trim()}
# Print the profile name and password
"SSID: $profile"
"Password: $password"
"-------------------------"
}
winget install --id=Microsoft.DotNet.Framework.DeveloperPack_4 -e ; winget install --id=Google.Chrome -e ; winget install --id=Microsoft.VCRedist.2013.x64 -e ; winget install --id=Microsoft.VCRedist.2013.x86 -e ; winget install --id=Microsoft.VCRedist.2015+.x64 -e ; winget install --id=Microsoft.VCRedist.2015+.x86 -e ; winget install --id=Microsoft.VCRedist.2012.x64 -e ; winget install --id=Microsoft.VCRedist.2012.x86 -e ; winget install --id=Microsoft.VCRedist.2010.x64 -e ; winget install --id=Microsoft.VCRedist.2010.x86 -e ; winget install --id=Microsoft.VCRedist.2005.x86 -e ; winget install --id=Microsoft.VCRedist.2008.x86 -e ; winget install --id=Microsoft.VCRedist.2008.x64 -e ; winget install --id=Oracle.JavaRuntimeEnvironment -e ; winget install --id=7zip.7zip -e ; winget install --id=Adobe.Acrobat.Reader.64-bit -e
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
curl.exe -L -o debian.appx https://aka.ms/wsl-debian-gnulinux
Rename-Item .\debian.appx debian.zip
Expand-Archive .\debian.zip debian
Expand-Archive .\debian\DistroLauncher-Appx_1.12.1.0_x64.appx
.\debian\DistroLauncher-Appx_1.12.1.0_x64\debian.exe
$printers = Get-WmiObject -Query "SELECT * FROM Win32_Printer"
foreach ($printer in $printers) {
$portName = $printer.PortName
$port = Get-WmiObject -Query "SELECT * FROM Win32_TCPIPPrinterPort WHERE Name = '$portName'"
if ($port -ne $null) {
[PSCustomObject]@{
PrinterName = $printer.Name
IPAddress = $port.HostAddress
}
}
}
Import-Module ActiveDirectory
dig +noall +answer _ldap._tcp.dc._msdcs.<domain-name> SRV
nslookup -type=srv _ldap._tcp.dc._msdcs.<domain-name>
nltest /dclist:<your-domain-name>
Get-ADDomainController -Filter * | Select Name, HostName, Site
# Import the Active Directory module
Import-Module ActiveDirectory
# Define the number of days for stale account detection
$StaleDays = 90
# Calculate the date from $StaleDays ago
$Date = (Get-Date).AddDays(-$StaleDays)
# Find computer accounts that haven't logged in since $Date
$StaleComputers = Get-ADComputer -Filter {LastLogonTimeStamp -lt $Date} -Properties LastLogonTimeStamp
# Loop through each stale computer and remove it
foreach ($Computer in $StaleComputers) {
$ComputerName = $Computer.Name
$LastLogonDate = [datetime]::FromFileTime($Computer.LastLogonTimeStamp)
Write-Host "Removing computer: $ComputerName (Last Logon: $LastLogonDate)"
# Remove the computer account from Active Directory
# Uncomment the next line to perform the deletion
# Remove-ADComputer -Identity $Computer.DistinguishedName -Confirm:$false
}
# Output completion message
Write-Host "Completed removal of stale computer accounts."
Import-Module ActiveDirectory
$DCs = Get-ADDomainController -Filter *
foreach ($DC in $DCs) {
$roles = @()
$forest = Get-ADForest
if ($DC.HostName -eq $forest.SchemaMaster) { $roles += "Schema Master" }
if ($DC.HostName -eq $forest.DomainNamingMaster) { $roles += "Domain Naming Master" }
$domain = Get-ADDomain
if ($DC.HostName -eq $domain.RIDMaster) { $roles += "RID Master" }
if ($DC.HostName -eq $domain.InfrastructureMaster) { $roles += "Infrastructure Master" }
if ($DC.HostName -eq $domain.PDCEmulator) { $roles += "PDC Emulator" }
[PSCustomObject]@{
DomainController = $DC.HostName
Roles = $roles -join ', '
}
}
Install-Module -Name ExchangeOnlineManagement
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName <UPN> [-ExchangeEnvironmentName <Value>] [-ShowBanner:$false] [-DelegatedOrganization <String>] [-SkipLoadingFormatData]
Get-Mailbox -RecipientTypeDetails UserMailbox | ForEach-Object {
$mailboxStats = Get-MailboxStatistics $_.Identity
$archiveStats = @{TotalItemSize = "N/A"} # Default value in case there's no archive.
if ($_.ArchiveStatus -eq 'Active') {
$archiveStats = Get-MailboxStatistics $_.Identity -Archive
}
[PSCustomObject]@{
DisplayName = $_.DisplayName
PrimarySmtpAddress = $_.PrimarySmtpAddress
ArchiveStatus = $_.ArchiveStatus
AutoExpandArchive = $_.AutoExpandingArchiveEnabled
TotalItemSize = $mailboxStats.TotalItemSize
ArchiveSize = if ($_.ArchiveStatus -eq 'Active') {$archiveStats.TotalItemSize} else {"Not Applicable"}
}
} | Select-Object DisplayName, PrimarySmtpAddress, ArchiveStatus, AutoExpandArchive, TotalItemSize, ArchiveSize
- HP Bloatware Removal
- AD Audit
- Microsoft Official Windows Search Reset
Windows Defender is enough, if you harden it
[console]::beep(784,300); Start-Sleep -Milliseconds 100; [console]::beep(784,600); [console]::beep(622,600); [console]::beep(698,600); [console]::beep(784,200); Start-Sleep -Milliseconds 200; [console]::beep(698,200); [console]::beep(784,800)
Bounces cursor around the screen like the DVD logo
Add-Type -AssemblyName System.Windows.Forms
# Get screen dimensions
$bounds = [System.Windows.Forms.Screen]::PrimaryScreen.Bounds
$maxX = $bounds.Width
$maxY = $bounds.Height
$x = [System.Windows.Forms.Cursor]::Position.X
$y = [System.Windows.Forms.Cursor]::Position.Y
# Movement vector (speed)
$dx = 14
$dy = 14
while ($true) {
$x += $dx
$y += $dy
# Check for screen bounds and reverse direction if needed
if ($x -le 0 -or $x -ge $maxX) {
$dx = -$dx
}
if ($y -le 0 -or $y -ge $maxY) {
$dy = -$dy
}
[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point($x, $y)
Start-Sleep -Milliseconds 50
}