Skip to content

Powershell Snippets

Some handy code snippets for powershell :)

_is_it_worth_the_time.png

String manipulation

  • Overwrite JPEG files with MD5 hashsum: Get-ChildItem -Recurse -Include "*.jpg" | Get-FileHash -Algorithm MD5 | Rename-Item -NewName { $_.hash + ".jpg"} -Force
  • Rename all files of a folder with MD5 Hashsum: Get-ChildItem . *.* | where { ! $_.PSIsContainer } | select FullName, Extension, @{name='md5'; expression={(Get-FileHash $_ -Algorithm md5).Hash}} | foreach {Rename-Item $_.FullName -NewName "$($_.md5)$($_.extension)"}
  • Get only file names of a folder: Get-ChildItem . *.* -File | select Name

Base64 Decode/Encode

  • Decode: [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("dGVzdA=="))
  • Encode: [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("test"))

Create a password

Option 1

Function New-Password([int]$length=20, $pw="")
{    
    $rng = New-Object System.Random
    for($i=0;$i -lt $length;$i++) { $pw = $pw +[char]$rng.next(33,126) }
    return $pw
}
New-Password 15

Option 2

$buffer = New-Object byte[] 32;
[System.Security.Cryptography.RandomNumberGenerator]::Create().GetBytes(($buffer));
return [BitConverter]::ToString($buffer).Replace("-", [string]::Empty);

System information

get all the binaries in the path variable

$env:Path.split(";") | ForEach-Object {
    Get-ChildItem -Path $_ -ErrorAction SilentlyContinue
} | Where-Object { $env:PATHEXT.ToLower() -match $_.Extension.ToLower() } | Select-Object FullName

Programs that run on this system

Get-ScheduledTask | Get-ScheduledTaskInfo | FT
Get-Service
Get-Process

Last boot time

Write-Output "System boot:" (Get-CimInstance -ClassName win32_operatingsystem | Select-Object -ExpandProperty LastBootUpTime)

Last Installation Date

Write-Output "System install:" (Get-CimInstance -Class Win32_OperatingSystem).InstallDate

Installed OCR Packages

Get-WindowsCapability -Online | Where-Object { $_.Name -Like 'Language.OCR*' } | Sort-Object -Property State -Descending | Format-Table -AutoSize

Get WiFi Passwords (add more cultures if needed):

$keyword = @{"de-DE" = 'Schlüsselinhalt'; "en-US" = 'Key Content'}
Invoke-Expression -Command '(netsh wlan show profiles) | Select-String "\:(.+)$" | %{$name=$_.Matches.Groups[1].Value.Trim(); $_} | %{(netsh wlan show profile name="$name" key=clear)} | Select-String ($keyword[(get-culture).Name]+"\W+\:(.+)$") | %{$pass=$_.Matches.Groups[1].Value.Trim(); $_} | %{[PSCustomObject]@{ WiFi=$name;PASSWORD=$pass }} | Format-Table -AutoSize'

CPU Temperature

Get-WmiObject -Query "SELECT * FROM Win32_PerfFormattedData_Counters_ThermalZoneInformation" | Select-Object Name, @{Name='TemperatureInCelsius';Expression={$_.Temperature / 10}}

Run this to log the CPU Temp over time:

while ($true) {
    $date = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $tempInfo = Get-WmiObject -Query "SELECT * FROM Win32_PerfFormattedData_Counters_ThermalZoneInformation" | 
    Select-Object @{Name='Timestamp';Expression={$date}}, Name, @{Name='TemperatureInCelsius';Expression={"{0:N2}" -f ($_.Temperature / 10)}}
    $tempInfo | Out-String | Out-File -FilePath "TemperatureLog.txt" -Append
    Start-Sleep -Seconds 5
}

WinSAT information

# Get WinSAT Data (XML)
WinSAT formal
$path = Get-ChildItem -Path 'C:\Windows\Performance\WinSAT\DataStore\*Formal.*.xml' | Sort-Object -Property CreationTime -Descending | Select-Object -First 1 -ExpandProperty FullName 

# Parse as XML
$xml = [xml]::new()
$xml.Load($Path)

# Read XML
$node = $xml.WinSAT.Metrics.CPUMetrics.CompressionMetric
'CPU Compression Performance is {0} {1}' -f $node.'#text', $node.units
'CPU Manufacturer is {0} ' -f $xml.WinSAT.SystemConfig.Processor.Instance.Signature.Manufacturer.friendly

Windows Defender statistics/information

$DefenderStatus = (Get-Service WinDefend -ErrorAction SilentlyContinue).Status
if ($DefenderStatus -ne "Running") {
    throw "The Windows Defender service is not currently running"
}
Get-MpComputerStatus

Win10 key

(Get-WmiObject -query ‘select * from SoftwareLicensingService’).OA3xOriginalProductKey

List installed apps

# Get install apps from app-store
Get-AppxPackage | Select-Object -Property Name, Status, Version, InstallLocation | Format-Table

# List all programs installed on Windows (and ignore the ones from Microsoft)
Get-WMIObject -Query "SELECT * FROM Win32_Product Where Not Vendor Like '%Microsoft%'" | Format-Table

List installed Windows Store Apps (and ignore some):

#Requires -RunAsAdministrator

Import-Module Appx
$Packages = Get-AppxPackage
$Whitelist = @('*WindowsCalculator*', '*MSPaint*', '*Office.OneNote*', '*Microsoft.net*', '*MicrosoftEdge*', '*Microsoft*') ## Ignore MS Stuff

## Remove all things to ignore
ForEach($App in $Packages){
    $Matched = $false
    Foreach($Item in $Whitelist){
        If($App -like $Item){
            $Matched = $true
            break
        }
    }

    if($matched -eq $false){
        [PSCustomObject]@{
        Name = $App.Name
        Location = $App.InstallLocation
        }
    }
}

List all Start Menu Programs and their paths

ForEach ($Item in Get-ChildItem "$Env:ProgramData\Microsoft\Windows\Start Menu\Programs" -Recurse -Include *.lnk) {
    $Shell = New-Object -ComObject WScript.Shell
    $Properties = @{ ShortcutName = $Item.Name; Target = $Shell.CreateShortcut($Item).targetpath }
    New-Object PSObject -Property $Properties
}

System Config

Enable Remote Desktop

(Get-WmiObject Win32_TerminalServiceSetting -Namespace root\cimv2\TerminalServices).SetAllowTsConnections(1,1) | Out-Null
(Get-WmiObject -Class "Win32_TSGeneralSetting" -Namespace root\cimv2\TerminalServices -Filter "TerminalName='RDP-tcp'").SetUserAuthenticationRequired(0) | Out-Null
Get-NetFirewallRule -DisplayName "Remote Desktop*" | Set-NetFirewallRule -enabled true

Run Repair-Volume on all valid drives

Get-Volume | Where { $_.OperationalStatus -eq "OK" -and $_.DriveType -ne "CD-ROM" -and $_.FileSystemType -ne "Unknown" -and $_.DriveLetter.length -ne 0} | Foreach-Object { Write-Host("Checking Drive: " + $_.DriveLetter); Repair-Volume -DriveLetter $_.DriveLetter }

Take a screenshot

Take a screenshot and save the image on your desktop:

Add-Type -AssemblyName System.Windows.Forms
Add-type -AssemblyName System.Drawing
$Screen = [System.Windows.Forms.SystemInformation]::VirtualScreen
$bitmap = New-Object System.Drawing.Bitmap $Screen.Width, $Screen.Height
$graphic = [System.Drawing.Graphics]::FromImage($bitmap)
$graphic.CopyFromScreen($Screen.Left, $Screen.Top, 0, 0, $bitmap.Size)
$bitmap.Save([Environment]::GetFolderPath("Desktop") + "\Screenshot.bmp")

Encryption

Encrypt or Decrypt a File with Powershell and PFX Cert

$path = "D:\test.txt"
$pwcert = "password"

$hascert=Read-Host -Prompt 'Do you have a certificate for file encryption? (Y/N)?'
If ($hascert -eq 'Y') {
    Write-Host 'Select Certificate.' 
    $mycert=Get-Childitem Cert:\CurrentUser\My
    $cert=$mycert | Where-Object hasprivatekey -eq 'true' | Select-Object -Property Issuer,Subject,HasPrivateKey | Out-GridView -Title 'Select Certificate' -PassThru
}
If ($hascert -eq 'N') {
    Write-Host 'This section creates a new self signed certificate. Provide certificate name.'
    $newcert=Read-Host 'Enter Certificate Name'
    New-SelfSignedCertificate -DnsName $newcert -CertStoreLocation "Cert:\CurrentUser\My" -KeyUsage KeyEncipherment,DataEncipherment,KeyAgreement -Type DocumentEncryptionCert
    $cert=Get-ChildItem -Path Cert:\CurrentUser\My\ | Where-Object subject -like "*$newcert*"
    $thumb=$cert.thumbprint
    Export-PfxCertificate -Cert Cert:\CurrentUser\My\$thumb -FilePath $home\"cert_"$env:username".pfx" -Password $pwcert 
}

$enc=Read-Host -Prompt 'Do you want to [e]ncrypt or [d]ecrypt the file? (E/D)?'
If ($enc -eq 'E') {
    Get-Content $path | Protect-CmsMessage -To $cert.Subject -OutFile $path
}
If ($enc -eq 'D') {
    $message = Unprotect-CmsMessage -Path $path -To $cert.Subject
    Set-Content -Path $path -Value $message
}

Write-Host "Done"

Sound

Tune the guitar

82, 110, 146, 196, 246, 329 | Foreach-Object {[console]::beep($_,4000)} # E,A,D,G,B,E

Speech

Here are two examples using System.Speech.Synthesis.SpeechSynthesizer to read out some given text with powershell (doesn't work with powershell 7):

[Reflection.Assembly]::LoadWithPartialName('System.Speech') | Out-Null
$tts = New-Object System.Speech.Synthesis.SpeechSynthesizer
$tts.Speak("OMG I can speak!")

It is possible to add SSML to set pitch and language:

Add-Type -AssemblyName System.speech
$tts = New-Object System.Speech.Synthesis.SpeechSynthesizer

$Phrase = '
<speak version="1.0" xmlns="http://www.w3.org/2001/10/synthesis" 
    xml:lang="en-US">
    <voice xml:lang="en-US">
    <prosody rate="1">
        <p>Normal pitch. </p>
        <p><prosody pitch="x-high"> High Pitch. </prosody></p>
    </prosody>
    </voice>
</speak>
'
$tts.SpeakSsml($Phrase)

This version uses the SAPI.SpVoice COM object and works with powershell 5 and 7:

$sp = New-Object -ComObject SAPI.SpVoice
$sp.Speak("Time for the $((Get-Date).DayOfWeek) shuffle")

Web

Download Images

$url = [System.Uri]"https://example.org"
$regex = '(http(s)?:\/\/)([^\s(["<,>/]*)(\/)[^\s[",><]*(.png|.jpg|.gif|.jpeg|.svg)(\?[^\s[",><]*)?'
$useragent = "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)"

$FilePath = (([System.Environment]::GetFolderPath([System.Environment+SpecialFolder]::Desktop))+"\"+$url.Authority)
New-Item -ItemType Directory -Force -Path $FilePath | Select-Object | Out-Null

Add-Type -AssemblyName System.Web
$webClient = New-Object System.Net.WebClient
$webClient.Headers.Add("user-agent", $useragent)
$webClient.Headers.Add("Content-Type","application/x-www-form-urlencoded")
$webpage = $webclient.DownloadString($url)
$listImgUrls = $webpage.ToLower() | Select-String -pattern $regex -Allmatches | ForEach-Object {$_.Matches} | Select-Object $_.Value -Unique

foreach($imgUrlString in $listImgUrls) {
    try {
        [System.Uri]$imgUri = New-Object System.Uri -ArgumentList $imgUrlString
        $imgSaveDestination = $FilePath+"\"+([System.IO.Path]::GetFileName($imgUri.LocalPath))
        $webClient.DownloadFile($imgUri, $imgSaveDestination)       
        Write-Output("Downloaded '$imgUrlString' to '$imgSaveDestination'")
    }
    catch { Write-Host("Error: " + $imgUrlString + " - ") -ForegroundColor Yellow -NoNewline; Write-Host($_.Exception.Message) -ForegroundColor Red }
}

SQlite

Example on how to create a new SQLite DB and add a row (Requires SQLite.dll).

add-type -Path "sqlite-netFx46-binary-x64-2015-1.0.109.0\System.Data.SQLite.dll"            

$connectionstring = "data source=C:\Users\fabia\desktop\gpstestdb.db"             
$sqliteconnection = New-Object -TypeName System.Data.SQLite.SQLiteConnection          
$sqliteconnection.ConnectionString = $connectionstring        
$sqliteconnection.Open()  

function createDB($sqlitecommandcreate, $connectionstring){            
    $newDBquery = $sqliteconnection.CreateCommand()          
    $newDBquery.CommandText = $sqlitecommandcreate     
    $newDBquery.ExecuteNonQuery()           
    $newDBquery.Dispose()      
}            

$sqlitecommandcreate = "CREATE TABLE example (string varchar(20), number int)"
createDB $sqlitecommandcreate $connectionstring

function insertRow($sqlitecommandinsert, $connectionstring) {            
    $newInsertQuery = $sqliteconnection.CreateCommand()            
    $newInsertQuery.CommandText = $sqlitecommandinsert # pass your query            
    $newInsertQuery.Parameters.AddWithValue("@string", "example-name")            
    $newInsertQuery.ExecuteNonQuery()
    $newInsertQuery.Dispose()        
}            

$sqlitecommandinsert = "INSERT INTO example (string, number) VALUES (@string, 4)"
insertRow $sqlitecommandinsert $connectionstring

$sqliteconnection.Dispose()

Email and Calendar

Sind Mail with deprecated Send-MailMessage command

$From = "[email protected]"
$To = "[email protected]"
$Attachment = "D:\test.txt"
$Subject = "Subject"
$Body = "Hi"
$SMTPServer = "smtp.gmail.com"
$SMTPPort = "587"
Send-MailMessage -From $From -to $To -Subject $Subject -Body $Body -SmtpServer $SMTPServer -port $SMTPPort -UseSsl -Credential (Get-Credential) -Attachments $Attachment

Get a list of meetings occurring today

$ns = New-Object -ComObject Outlook.Application.GetNamespace('MAPI')
$Start = (Get-Date).ToShortDateString()
$End = (Get-Date).ToShortDateString()
$appointments = $ns.GetDefaultFolder(9).Items
$appointments.IncludeRecurrences = $true
$appointments.Restrict("[MessageClass]='IPM.Appointment' AND [Start] > '$Start' AND [End] < '$End'") |  
ForEach-Object {
    if (-Not $_.IsRecurring ) { $_;  } else {
        try { $_.GetRecurrencePattern().GetOccurrence((Get-Date).ToString("yyyy-MM-dd") + " " + $_.Start.ToString("HH:mm")) } 
        catch {  }
        }
    } | Sort-Object -property Start | ForEach-Object { 
    $arrr = ($_.RequiredAttendees.split(';') | ForEach-Object { $_.Trim() } | ForEach-Object { $_.split(' ')[1] + ' ' + $_.split(' ')[0] } )
    $attendees = ($arrr -join " ").Replace(", ",",").TrimEnd(',')
    "`n`t`t[ ] $($_.Start.ToString("HH:mm")) - $($_.Subject.ToUpper()) with: $attendees"
}

HyperV

Install and config

  • Install Hyper V Feature: Install-WindowsFeature -Name Hyper-V -ComputerName localhost -IncludeManagementTools -Restart
  • Check Hyper V Installation: Get-WindowsFeature -Name Hyper-V -ComputerName HOSTNAME
  • Reconfigure the service sc config vmms start=auto
  • Stop and start the service sc stop vmms; sc start vmms
  • Remove VM Remove-VM -Name "Linux" -Force

Get VHD owner

param ($HyperVNodes,$VHDName)

Foreach ($HyperVNode in $HyperVNodes)
{
    $VMs = Get-WmiObject -Namespace "root\virtualization" -ComputerName $HyperVNode -class Msvm_ComputerSystem | where {$_.Caption -match "Virtual Machine"}
    Foreach ($VM in $VMs)
    {
        $VMSettingData = Get-WmiObject -Namespace "root\virtualization" -ComputerName $HyperVNode `
        -Query "Associators of {$VM} Where ResultClass=Msvm_VirtualSystemSettingData AssocClass=Msvm_SettingsDefineState" 
        $VirtualDiskResource = Get-WmiObject -Namespace "root\virtualization" -ComputerName $HyperVNode `
        -Query "Associators of {$VMSettingData} Where ResultClass=Msvm_ResourceAllocationSettingData AssocClass=Msvm_VirtualSystemSettingDataComponent" | `
        Where-Object { $_.ResourceSubType -match "Microsoft Virtual Hard Disk" }
        $VHDPath = $null
        Foreach ($VHD in $VirtualDiskResource)
        {
            $VHDPath = $VHDPath + $VHD.Connection[0] + ","
        }
        if ($VHDPath -Match $VHDName)
        {
            Write-Output "The VM named $($VM.ElementName) is connected to the VHD $VHDName"
        }
    }
}

KMS

To set a KMS Server into Windows Managed Server’s configuration you need to execute the following command:

slmgr /skms <KMS-FQDN>:1688

To trigger Windows activation you need to execute the following command:

slmgr /ato

IIS

IIS Passwords

foreach ($site in Get-ChildItem IIS:\Sites) { "Site: " + $site.name + " - " + "User: " + $site.userName + "PW: " + $site.password }

Add website to pool and update binding

Set-ItemProperty 'IIS:\\Sites\\$Site' ApplicationPool $AppPoolName  
Set-ItemProperty IIS:\\Sites\\$Site -Name bindings -Value (@{protocol="https";bindingInformation="\*:$Port:$Site"})

Start-WebSite -Name $site
Stop-WebSite -Name $site

Clear-ItemProperty IIS:\\Sites\\$Site -Name bindings

Get Binding Info

[string]$BindingInfo = $Binding.Collection
[string]$IP = $BindingInfo.SubString($BindingInfo.IndexOf(" "),$BindingInfo.IndexOf(":")-$BindingInfo.IndexOf(" "))
[string]$Port = $BindingInfo.SubString($BindingInfo.IndexOf(":")+1,$BindingInfo.LastIndexOf(":")-$BindingInfo.IndexOf(":")-1)

Random (sort this)

  • Format new, raw disk: Get-Disk | Where-Object {$_.partitionstyle -eq 'raw' -and $_.OperationalStatus -like 'Online' } | Initialize-Disk -PartitionStyle MBR -PassThru | New-Partition -AssignDriveLetter -UseMaximumSize | Format-Volume -FileSystem NTFS -NewFileSystemLabel "newDisk" -Confirm:$false
  • Check if a specific port is open e.g. port 8080netstat -ano | Select-String "8080"
  • Get all "svchost" process-ids: Get-Process "svchost" | select -expand id
  • View open connections for a given service: get-nettcpconnection | select local*,remote*,state,@{Name="Process";Expression={(Get-Process -Id $_.OwningProcess).ProcessName}} | Where-Object {$_.Process -eq "svchost"} | Format-Table
  • Check for Windows Updates: (New-Object -ComObject Microsoft.Update.AutoUpdate).DetectNow()
  • Export PowerShell command history to a file: Get-History | Export-CSV $env:USERPROFILE\Desktop\CommandHistory.CSV
  • Export all available powershell commands: Get-Command | Export-CSV $env:USERPROFILE\Desktop\CommandsAvailable.CSV
  • Get last 10 installations: get-wmiobject Win32_ReliabilityRecords -computername 127.0.0.1 | Select-Object -first 10 Message | format-list *
  • Last 10 security event log entries: Get-EventLog Security -Newest 10
  • Get all help examples: Get-Command -CommandType cmdlet | % { (get-help $\_.name).examples }
  • Get Last Server Boot Time: ([wmi]"").ConvertToDateTime((Get-WmiObject -Class Win32_OperatingSystem).LastBootuptime)
  • Search recursively for a certain string within filesdir –r | select string "searchforthis"
  • Top5 processes using the most memory: ps1 | sort –property ws | select –last 5
  • Get all self-signed certs: Get-ChildItem -path cert:\\LocalMachine\\My
  • Create NIC Teaming: New-NetLBfoTeam –Name Guest –TeamMembers Guest-A,Guest-B -TeamingMode SwitchIndependent
  • Find something in (large) files: Get-Content myTestLog.log -wait | where { $\_ -match "WARNING" }
  • Read Registry Key: Get-ItemProperty -Path Registry::"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\" | format-list
  • Report all of the USB devices installed: gwmi Win32_USBControllerDevice -computername SERVER1 |fl Antecedent,Dependent
  • NTFS folder permissions for D:\Temp: Get-Acl "D:\Temp"
  • NTFS folder permissions for all files below D:\Temp: Get-ChildItem "D:\Temp" -recurse | Get-Acl
  • Get SHA1 hash sum of all files of the current folder: ForEach ($Item in Get-ChildItem $PWD -Include *.*) {Write-Host((Get-FileHash $Item.Name -Algorithm "SHA1").hash) $Item.Name }
  • Find largest files in a given Folder (and subfolders): Get-ChildItem . -r | sort Length -desc | Select-Object fullname, length -f 20 | Format-Table
  • List files and folders with attributes: gci -rec | Select-Object Mode, Name, CreationTime, LastAccessTime, LastWriteTime | ft -autosize

Add WebDAV to local path

(Invoke-WebRequest https://webdav.domain.com/ -Method Options).Headers.DAV  
[String]$WebDAVShare = '\\webdav.domain.com@SSL/path/to/files'
New-PSDrive -Name S -PSProvider FileSystem -Root $WebDAVShare -Credential '[email protected]'

Set network location to Private for all networks:

$networkListManager = [Activator]&#x3A;:CreateInstance([Type]&#x3A;:GetTypeFromCLSID([Guid]"{DCB00C01-570F-4A9B-8D69-199FDBA5723B}")) 
$connections = $networkListManager.GetNetworkConnections() 
$connections | % {$\_.GetNetwork().SetCategory(1)}