Copyright(c) 2019-
Author: Chaitanya Tejaswi (github.com/CRTejaswi) License: GPL v3.0+
Personal notes.
Link | Description |
---|---|
IronScripter | Monthly PS challenges. |
powershell.org | PS news. |
MS DevBlog | Short pieces on PS use-cases. |
Awesome PS | Collection of PS projects/utilities. |
GitHub | Source-Code for PS Core. |
Jeff Hicks | The No-nonsense programmer; The 'David Beazley' of PS. |
Adam Bertram | |
Doug Finke | Guy who wrote ImportExcel - a module to access xlsx files without installing MSOffice. |
TechSnips [1] [2] | Short, infomative clips on various use-cases of PS. |
Warren Frame [PS recipies] | Guy who wrote PSSQLite - a module to access SQLite databases in PS. |
Prateek Singh | Indian guy who uses PS for fun. |
- General
- Windows
- myScripts
- System Help
- Exception Handling
- Variables
- Operators
- Control Flow
- Data Structures
- Objects
- Pipelining
- Item Access
- Formatting
- Filtering & Comparisons
- Background Processes (
Job
) - Regular Expressions
- Remote Access
- Providers
- Registry
- Structured Data (CSV, JSON, XML)
- Databases (SQLite, SQL Server)
- PDFs
- Compressed Files
- Text Editors
- Clipboard
- Git
- Modules
- Parameters
- Scripting
- Recipies
- MS Office
- Android SDK
- Linux
- C#/.NET
- PowerShell/Python
- PowerShell/JavaScript
- Unsorted
-
Update (from PS)
iex "& { $(irm https://aka.ms/install-powershell.ps1) } -UseMSI"
-
Clear Command History
PressCtrl + F7
-
Clear RecycleBin
Clear-RecycleBin
-
Disable Quick Access, Recent Items & File-Explorer History.
Quick Access (Right-Click) >> Options >> Open File Explorer to: "This PC" >> Uncheck Privacy Options. -
Uninstall built-in apps
Get-AppxPackage *3dbuilder* | Remove-AppxPackage Get-AppxPackage *getstarted* | Remove-AppxPackage Get-AppxPackage *windowsalarms* | Remove-AppxPackage Get-AppxPackage *windowscalculator* | Remove-AppxPackage Get-AppxPackage *windowscommunicationapps* | Remove-AppxPackage Get-AppxPackage *windowsmaps* | Remove-AppxPackage Get-AppxPackage *windowsphone* | Remove-AppxPackage Get-AppxPackage *windowsstore* | Remove-AppxPackage Get-AppxPackage *zunemusic* | Remove-AppxPackage Get-AppxPackage *zunevideo* | Remove-AppxPackage Get-AppxPackage *bingfinance* | Remove-AppxPackage Get-AppxPackage *bingnews* | Remove-AppxPackage Get-AppxPackage *bingweather* | Remove-AppxPackage Get-AppxPackage *bingsports* | Remove-AppxPackage Get-AppxPackage *photos* | Remove-AppxPackage Get-AppxPackage *soundrecorder* | Remove-AppxPackage Get-AppxPackage *xboxapp* | Remove-AppxPackage
-
Create/Modify Environment Variables
You can create/modify User/System environment variables using this one-liner in Powershell.[Environment]::SetEnvironmentVariable("Youtube_ApiKey", "<API_KEY>", "User") [Environment]::SetEnvironmentVariable("Youtube_ApiKey", "<API_KEY>", "Machine")
-
Create New File/Folder
ni -path 'C:\Users\CRTejaswi\Desktop' -ItemType 'directory' -name 'myTEST' ni -path 'C:\Users\CRTejaswi\Desktop\myTEST' -ItemType 'file' -name 'myTEST.md'
-
Get storage directory of binary file.
gps firefox | ls
-
Common Aliases
man -> Get-Help (to lookup command syntax) gcm -> Get-Command (to lookup command syntax) gm -> Get-Member (to learn more about an object) gal -> Get-Alias gc -> Get-Content (or 'cat'; Read from file) sc -> Set-Content (Write to file) gcb -> Get-Clipboard (Copy from clipboard) scb -> Set-Clipboard (Copy to clipboard) gps -> Get-Process ft -> Format-Table fl -> Format-List gsv -> Get-Service gin -> Get-ComputerInfo gtz -> Get-TimeZone gwmi -> Get-WmiObject gjb -> Get-Job cls -> Clear-Host ('clear shell') clc -> Clear-Content clv -> Clear-Variable cli -> Clear-Item clp -> Clear-ItemProperty pushd, popd -> Push-Location, Pop-Location copy, move -> Copy-Item, Move-Item history -> Get-History
-
Progress-Bar
eg. Display a countdown timer using a progressbar.$seconds = 60 1..$seconds | forEach { $percent = ($_ * 100)/$seconds; Write-Progress -Activity 'Waiting for You to Finish' ` -Status "$($seconds - $_) seconds remaining ..." ` -PercentComplete $percent; Start-Sleep -Seconds 1 }
-
Remove BOM from UTF-8 Files [BROKEN]
function Remove-BOM ($OldPath, $NewPath){ $content = Get-Content $OldPath -Raw $encoding = New-Object System.Text.UTF8Encoding $False [System.IO.File]::WriteAllLines($NewPath, $content, $encoding) } Remove-BOM -Path .\test.json
-
Work with file/folder
Save filepath in $PROFILE variable.
Open file/folder using editor/cd.$ImagingSatellite="B:\CRTejaswi\Codes\resources\topics\imaging_satellite\imaging_satellite.md" nano $ImagingSatellite cd (ls $ImagingSatellite).Directory
-
Check filesize before downloading
(iwr $url -Method Head).Headers.'Content-Length'/1MB
-
Execute lines from a text file
& { Invoke-Expression (Get-Content -Raw README.md) } & { iex (cat -Raw README.md) }
-
List all open GUI windows
gps | where {$_.MainWindowTitle -ne ""} | select MainWindowTitle
-
Binding Keyboard Shortcuts [BROKEN]
UsePSReadline
module cmdlets.
eg. PressCtrl+H
to display a GridView of command history. Select a cmd to execute.Set-PSReadlineKeyHandler -Chord Ctrl+H -ScriptBlock { Get-History | Out-GridView -Title 'Command History' -PassThru | Invoke-History }
-
Timing script executions
The naive way is to useGet-Date
.$start = Get-Date ... $stop = Get-Date $duration = $stop - $start; $duration.TotalMilliseconds;
You can also use
StopWatch
(.NET class).$stopwatch = [Diagnostics.StopWatch]::StartNew() ... $stopwatch.Stop() $stopwatch.ElapsedMilliseconds ... $stopwatch.Restart() ... $stopwatch.Stop() $stopwatch.ElapsedMilliseconds
Bulk
-
Move files to current directory
move ((ls B:\CRTejaswi\Downloads\) -match '^\d{1}.mp4').FullName .
Copy/Move files using regex.
ls $Path | where {$_.Name -match 'ca'} | forEach {copy $_.fullname .}
-
Emails
Send-MailMessage ` -from "aeronfinium@gmail.com" -To "abc@gmail.com","xyz@gmail.com" ` -SmtpServer "smtp.gmail.com" -usessl -Credential (Get-Credential) ` -Subject "Test Message" ` -Body "Sent from PS shell -- Chaitanya Tejaswi" ` -Attachments test.pdf,test.mp3,test.mp4
Get all email addresses from HTML object
$response.Links | forEach { if ($_.href.ToLower().StartsWith("mailto:")){ $_.href.SubString(7) } }
-
Merge files
Text files.Get-Content test.txt,test.md,test.html,test.py | Set-Content OUTPUT.md cat test.txt,test.md,test.html,test.py | sc OUTPUT.md
Image files - vertical/horizontal tiling of images.
magick *.webp -append merged.png magick *.webp +append merged.png
AV files.
$count = ((ls) -match '^\d+\.mp4$').count; $page = @(); $n=1; while ($n -ne $count+1) {$page += "file $n.mp4"; $n++}; $page | out-file -encoding ascii MERGE.txt; ffmpeg -f concat -safe 0 -i MERGE.txt -c copy OUTPUT.mp4 (ls) -match '^\d+\.mp4' | del
Add
-fflags +igndts
to ffmpeg options in case ofNon-monotonous DTS in output stream
error.Convert images to pdf, then merge them:
(ls) -match '^\d+\.jpg' | forEach {magick $_.FullName ($_.FullName).Replace('jpg','pdf')} # Use any one pdftk ((ls) -match '^\d+\.pdf' | sort {($_.Name) -replace '\D+' -as [int]}) cat output merged.pdf pdftk ((ls) -match '^\d+\.pdf' | sort @{expression = {[int]$_.name.split('.')[0]}}) cat output merged.pdf pdftk ((ls) -match '^\d+\.pdf' | sort @{expression = {[int]$_.basename}}) cat output merged.pdf del ((ls) -match '^\d+\.(pdf|jpg)')
-
Rename files
The$_.extension
is helpful when dealing with similar files but different encodings (eg. BMP, JPG, GIF, PNG, SVG).$i=1; ls | forEach {ren $_.name "$i$($_.extension)"; $i++}
Use regex to rename files.
eg. sparse_dca,denoising_dca,variational_dca -> dca_denoising,dca_sparse,dca_variational(ls).Name | ren -NewName {$_ -replace '(\w+)_dca','dca_$1'}
Multimedia
- Play in background (system tray)
vlc --qt-start-minimized --play-and-exit $Music
- Create & Play a playlist
(ls *.mp4) | Sort-Object {(.Name) -replace '\D+' -as [int]} | forEach { vlc --one-instance --playlist-enqueue --rate 2.0 $_ } (ls *.mp3).fullName | forEach { vlc --one-instance --playlist-enqueue --rate 2.0 $_ }
- Play music daily, at a specified time (7:30PM)
Register-ScheduledJob -Name myDailyJobs -ScriptBlock {vlc $Music} -Trigger (New-JobTrigger -Daily -At '19:30') -ScheduledJobOption (New-ScheduledJobOption -WakeToRun -RunElevated)
- Text to Speech
See: SpeechSynthesizerAdd-Type -AssemblyName System.Speech $tts = New-Object -TypeName System.Speech.Synthesis.SpeechSynthesizer $tts.SpeakAsync($(cat .\notes.txt)) $tts = [System.Speech.Synthesis.SpeechSynthesizer]::new() $tts.SetOutputToWaveFile("$($pwd)\test.wav") $tts.Speak($(cat .\notes.txt)) $tts.GetInstalledVoices().VoiceInfo $tts.SelectVoice("Microsoft Zira Desktop") $tts.SetOutputToWaveFile("$($pwd)\notes.wav") $tts.Speak($(cat .\notes.txt)) ffmpeg -i notes.wav notes.mp3; del notes.wav; Remove-Variable tts
$tts.SpeakAsync("The current date and time is $(Get-Date)") $services = Get-Service W* | Select-Object -First 5 forEach ($service in $services){ ` $tts.SpeakAsync("The Service $($service.displayname) is $($service.status)") | Out-Null ` }
Add Context-Menu Options [BROKEN]
A context-menu opens up when you right click a file.
This adds an option Open This With ST3 to the context-menu for .ps1
files.
$ContextOption = "Open This With ST3"
$ContextCommand = 'subl "%1"'
$baseKey = 'Registry::HKEY_CLASSES_ROOT\.ps1'
$id = (Get-ItemProperty $baseKey).'(Default)'
$ownId = $ContextOption.Replace(' ','')
$ContextOptionKey = "HKCU:\Software\Classes\$id\Shell\$ownId"
$ContextCommandKey = "$ContextOptionKey\Command"
New-Item -Path $ContextCommandKey -Value $ContextCommand -Force
Set-Item -Path $ContextOptionKey -Value $ContextOption
Location Access
To view physical location using GMaps, enable all location access features on Windows 10, then:
Add-Type -AssemblyName System.Device
$coordinates = [System.Device.Location.GeoCoordinateWatcher]::new()
$coordinates.Start()
$location = $coordinates.position.location
firefox "google.com/maps?q=$($location.latitude),$($location.longitude)"
Notifications
Use BurntToast to create toast-notifications. Use it with Register-ScheduledJob
cmdlet to create non-volatile jobs.
Register-ScheduledJob -Name HourlyReminder
-ScriptBlock {New-BurntToastNotification -Sound Call -Text "The time is $(Get-Date -Format 'hh:mm')"}
-Trigger (New-JobTrigger -Once -At '6:00 AM' -RepetitionInterval (New-TimeSpan -Minutes 5) -RepetitionDuration ([TimeSpan]::MaxValue))
-ScheduledJobOption (New-ScheduledJobOption -WakeToRun -RunElevated)
- Update help.
update-help -Force
- Get help.
man *service* man get-service man get-service -detailed man get-service -showwindow man get-service -examples man get-service -full man get-service -online man *eventlog* man about_*
- Nouns & Verbs
PS names cmdlets/functions in aVerb-Noun
manner, to make their names predictable. (eg.Get-Service
)
To lookup all PERMITTED verbs (98), use:get-verb get-verb | measure
- Write help for custom-cmdlets:
You can write help in two ways: using comment-strings (<##>
) within script files, or using XML files (<PSSnapInAssemblyName>.dll-Help.xml
).
-
Single & Double Quotes (
'
,"
)
Anything within a single-quote is a literal string.
Anything within a double-quote is a parsed string.PS> $var='LOCALHOST' PS> $var1='Try $var' PS> $var2="Try $var" PS> $var; $var1; $var2; LOCALHOST Try $var Try LOCALHOST
Using double-quotes, you can also assign cmdlet & the object with it's property/method that it generates.
PS> $services=get-service PS> $var="First Service Is $($services[0].name)" First Service Is ABLookupSvc
-
Escape Sequences
Just as C-syntax usesback-slash
(\) to escape sequences, PS-syntax usedback-tick
(`) -
Accessing Object Property/Method
PS3+ allows using Object.Property/Object.Method syntax.PS> $services=Get-Service PS> $services.name; $services.gettype()
Here,
Name
&GetType()
are property/method defined on objects returned byGet-Service
. Check usinggsv | gm
. -
Declaring Variable Types Use
[type]$var
notation.PS> [int]$var = Read-Host "Enter A Number" Enter A Number: 100 PS> $var | gm TypeName: System.Int32 ...
Type | Description |
---|---|
[int] ,[single] ,[double] |
integer, single/double precision floating values |
[char] ,[string] |
character, string of characters |
[xml] |
XML document |
[adsi] |
ActiveDirectory Service Interface (ADSI) query |
Initialize with a range of values
Use ..
operator to describe a range of integer values between any two values.
$x = 1..10; $y = 0.5..1
1 2 3 4 5
0 1
Run code within quotes ("..."
)
Quotes ("..."
) can be effectively used as formatted strings.
Use the $()
operator to execute code (commands, scripts, and scriptblocks {...}
) within a quoted expression.
$()
returns a single value by default. It may return an array as well.
PS> "The date is $(Get-Date -Format 'dd-MM-yy hh:mm tt')"
The date is 26-06-20 11:34 AM
PS> "Files in this directory are: $((ls -File).Name -join ', ')"
Files in this directory are: README.md, scripts.md, test.ps1
Run external code
Use &
& .
operators to run code (commands, scripts, and scriptblocks {...}
) from anywhere on your PC.
&
runs the code in a new (temporary) scope. All changes made here are lost as soon as the execution is over.
.
runs the code in current scope. All changes made here are retained in current scope (shell/script).
These are needed because a command like "B:\CRTejaswi\Codes\test.exe"
is interpreted as a string.
Syntax: [&/.] "[path/to/file]" [arguments]
& "B:\CRTejaswi\Codes\test.exe" 2 10 "B:\CRTejaswi\Files\test.txt"
. "B:\CRTejaswi\Codes\test.exe" 2 10 "B:\CRTejaswi\Files\test.txt"
$x=1; $x # 1
& {$x = $x*10}; $x # 1
. {$x = $x*10}; $x # 10
This is handy when you just want to run something repeatedly and are too lazy to source it in an environment variable.
An important feature of .
operator is that everything within the code's script is now available in the current scope.
eg. If you run a script . ./test.ps1
; every variable/function/cmdlet in test.ps1
is now available in the Shell.
if-else
Conditional execution.
Execution is based on certain well-defined conditions.
-
Syntax
if (<condition>){ ... } elseif (<condition>){ ... } else { ... }
-
Do something if today is Monday, post 12PM.
$now = get-date if ($now.dayofweek -eq 'Monday' -and $now.hour -gt 12){ ... }
switch
Conditional-Value execution.
Execution is based on certain properties/values of <object>
.
-
Syntax
switch (<object>){ <case> {...} <case> {...} default {...} }
-
Check if a string contains '1' or 'a'
$x = '123abc' switch -wildcard ($x){ "*1*" {"Contains 1"} "*a*" {"Contains a"} default {"No matches found"} }
for
Iterative Conditional execution.
-
Syntax
for (<start>; <condition>; <action>){ ... }
-
Print the number of characters in a string iteratively (*actually prints indices)
$x = '123abc' for ($i=0; $i -lt $x.Length; $i++){ Write-Host $i -foreground black -background yellow }
forEach
Iterative execution, for each item in items.
-
Syntax
forEach ($item in $items){ ... }
-
Print the squares of 1-10
$numbers = 1..10 forEach ($number in $numbers){ Write-Host ($number*$number) }
do-while
Execute until condition fails.
-
Syntax
[1]: Execute only when condition starts to hold $True. (May not be executed at all.)while (<condition>){ ... }
[2]: Execute atleast once.
do { ... } while (<condition>)
-
...
...
break
Abort execution abruptly.
- In a
switch
,for
,forEach
,ordo-while
construct,break
exits the construct only. - In an
if-else
construct,break
doesn't just exit the construct, but also the parent construct that contains theif-else
.
NOTE
Avoid these mistakes:
- Conditionally breaking from codeblock.
[NO] while ($True){ $choice = Read-Host 'Enter A Number' if ($choice -eq 0) { break } }
[YES] do { $choice = Read-Host 'Enter A Number' } while ($choice -ne 0)
Array
-
Create an empty array
$myArray = @(); $myArray.getType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array
-
Initialize an array
An array can contain values of different datatypes:# Array (flexible type) $myArray = 1,'Two',"$PSHome"
We can define fixed-type arrays as well:
# Array (fixed type) [int[]] $myArray = 1,2,3
- Example: Get process data
$myArray = gps firefox,powershell,sublime_text $myArray.length # 11
-
Array of Arrays
We can initialize an array of arrays (Jagged Array):# Array (array-of-arrays) $myArray = @( (1,2,3), (4,5), (6,7,8,9)) $myArray[1][1] # 5
We can initialize a matrix (Non-Jagged Array):
# Array (fixed-size matrix) $myArray = New-Object "int32[,]" 3,3 $myArray[1,1] = 5 $myArray[1,1] # 5
The two differ in that the former doesn't have fixed dimensions (depends on input arrays), but the latter does (3x3).
-
Access elements of an Array
To access an element:$myArray = 1,'Two',"$PSHome" $myArray[1] # Two
To access a range of elements (Array Slicing):
$myArray = 1,'Two',"$PSHome" $myArray[1..2 +0 +1] Two C:\Windows\System32\WindowsPowerShell\v1.0 1 Two
This accesses 2nd & 3rd values, then 0th & 1th value.
To iterate through an array, useforEach
:$myArray = 1..10; $sum = 0 $myArray | forEach {$sum += $_} $sum # 56
-
Sort an array
UseSort-Object
(akasort
). -
Add/Remove elements to/from an array
To add, simply use+=
.$myArray = 1..10 $myArray += 11,12,13 $myArray # 1 2 3 4 5 6 7 8 9 10 11 12 13
To remove, use conditional-operator or regex (
-ne
,-notlike
,-notmatch
) to describe the elements (to remove), and store the result back.$myArray = 1..13 $myArray = $myArray -notmatch '1.' $myArray # 1 2 3 4 5 6 7 8 9
-
Working with dynamic arrays
Use .NET'sSystem.Collections.ArrayList
class to work with dynamic arrays.
This is useful when you are frequently manipulating an array with large amounts of data.$myArray = New-Object System.Collections.ArrayList
Associative Array (Hash Table)
-
Create an empty hashtable
$myHash = @{}; $myHash.getType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Hashtable System.Object
-
Initialize a hashtable
We can initialize a hashtable usingkey=value
pairs:$myHash = @{'Name'='Chaitanya'; 'Directory'="$PSHome"} $myHash Name Value ---- ----- Name Chaitanya Directory C:\Windows\System32\WindowsPowerShell\v1.0
We can initialize a hashtable using
key
incrementally:$myHash = @{}; $myHash['Name']='Chaitanya'; $myHash.Directory="$PSHome" $myHash Name Value ---- ----- Name Chaitanya Directory C:\Windows\System32\WindowsPowerShell\v1.0
-
Sort a hashtable
Use.GetEnumerator()
method to access each element. Sort this byname
/value
to sort bykey
/value
.$myHash = @{}; $myHash['Name']='Chaitanya'; $myHash.Veto='Alpha' $myHash.GetEnumerator() | sort name Name Value ---- ----- Name Chaitanya Veto Alpha $myHash.GetEnumerator() | sort value Name Value ---- ----- Veto Alpha Name Chaitanya
NOTE: Following are some strongly-typed 'Generic' .NET data structures. These can be useful when you want to constrain the variables to fixed datatypes.
See System.Collections.Generic
for documentation.
List
-
Create an empty list
$myList = New-Object System.Collections.Generic.List[String] $myList = [System.Collections.Generic.List[String]]::new()
This syntax is better for use:
$myList = [System.Collections.Generic.List[String]]("Apple","Ball","Cat") $myList = [System.Collections.Generic.List[String]](cat $myLinks)
-
Add/Remove elements to/from a list
PS offers 4 add & remove methods each.add/addRange -> append one/many entries at the end of list. insert/insertRange -> insert one/many entries at specific index. remove -> remove one entry (by value) removeAt/removeRange -> remove one/many entries (by index) from a specific index. removeAll -> remove entries based on a criteria.
We can use ScriptBlock (
{}
) withinremoveAll()
to define criteria.
This example makes use ofparam($x)
to define a lambda function$myList.add("Ball") $myList.addRange([String[]]("Cat","Dog","Ear")) $myList # Ball Cat Dog Ear $myList.insert(0,"Apple") $myList.insertRange(5,[String[]]("Fish","Girl","Ice")) $myList # Apple Ball Cat Dog Ear Fish Girl Ice $myList.remove("Ice") # True <- value $myList # Apple Ball Cat Dog Ear Fish Girl $myList.removeAt(6) # <- index $myList # Apple Ball Cat Dog Ear Fish $myList.removeRange(3,2) # True <- index,count $myList # Apple Ball Cat Fish $myList.removeAll({param($x) $x -match "^f."}) # 1 <- count $myList # Apple Ball Cat
-
Select elements from a list
$myList[1] # Bat $myList.indexOf('Bat') # 1
-
Modify elements in a list
$myList[1] = 'Bat' $myList # Apple Bat Cat
-
Search/Sort a list
AlikeremoveAll()
, we can use ScriptBlock ({}
) withinfindAll()
to define criteria.
binarySearch()
implements Binary Search to iteratively shrink dataset. This is prefered overindexOf()
working with extremely large number of values.$myList.findAll({param($x) $x -match "^a."}) # 1 <- count # $myList.sort() ?? # $myList.binarySearch() ?? $myList = [System.Collections.Generic.List[Int]](1..1000000) $myList.binarySearch(1024); $myList.indexOf(1024); # 1023 1023
Dictionary
-
Create an empty dictionary
$myDict = New-Object System.Collections.Generic.Dictionary"[String,String]" $myDict = [System.Collections.Generic.Dictionary[String,String]]::new()
This syntax is better for use: [BROKEN]
# $myDict = [System.Collections.Generic.Dictionary[String,String]](("Name","Adam")("Group","Alpha")("Grade","A"))
-
Add/Remove elements to/from a dictionary
$myDict.add("Name","Chaitanya"); $myDict.Directory = "$PSHome"; $myDict.Age = 23; $myDict Key Value --- ----- Name Chaitanya Directory C:\Windows\System32\WindowsPowerShell\v1.0 Age 23 $myDict.remove('Age') $myDict Key Value --- ----- Name Chaitanya Directory C:\Windows\System32\WindowsPowerShell\v1.0
-
Select elements from a dictionary
$myDict['Name']; $myDict.Name; # Chaitanya Chaitanya
-
Modify elements in a dictionary
$myDict['Name']='Tejaswi'; $myDict.Name; # Tejaswi $myDict.Name='Chaitanya'; $myDict.Name; # Chaitanya
-
Check for key/value in a dictionary
$myDict.ContainsKey('Name'); $myDict.ContainsValue('Chaitanya'); # True True
- Add a key/value pair to an existing dictionary
if (-not $myDict.containsKey('Age')){ $myDict.add('Age',23) } $myDict.Age # 23
-
Enumerate a dictionary
$myDict.Keys; $myDict.values; # Name Directory Age # Chaitanya C:\Windows\System32\WindowsPowerShell\v1.0 23
Stack
-
Create an empty stack
$myStack = New-Object System.Collections.Generic.Stack[String] $myStack = [System.Collections.Generic.Stack[String]]::new()
This syntax is better for use:
$myStack = [System.Collections.Generic.Stack[String]]("Apple","Ball","Cat") $myStack = [System.Collections.Generic.Stack[String]](cat $myLinks)
-
Add/Remove elements to/from a stack
$myStack.push("Apple"); $myStack.push("Ball"); $myStack.push("Cat"); $myStack.pop() # Cat
-
Enumerate a stack We can peek at top-of-stack using
.peek()
. To index a stack, convert it to array using.toArray()
$myStack = [System.Collections.Generic.Stack[String]]('Apple','Ball','Cat') $myStack.peek() # Cat $myArray = $myStack.toArray() # Cat Ball Apple
Queue
-
Create an empty queue
$myQueue = New-Object System.Collections.Generic.Queue[String] $myQueue = [System.Collections.Generic.Queue[String]]::new()
This syntax is better for use:
$myQueue = [System.Collections.Generic.Queue[String]]("Apple","Ball","Cat") $myQueue = [System.Collections.Generic.Queue[String]](cat $myLinks)
-
Add/Remove elements to/from a queue
$myQueue.enqueue("Apple"); $myQueue.enqueue("Ball"); $myQueue.enqueue("Cat"); $myQueue.dequeue() # Apple
-
Enumerate a queue We can peek at top-of-queue using
.peek()
. To index a queue, convert it to array using.toArray()
$myQueue = [System.Collections.Generic.Queue[String]]('Apple','Ball','Cat') $myQueue.peek() # Apple $myArray = $myQueue.toArray() # Apple Ball Cat
Unlike UNIX, PS outputs objects (instead of text). This makes it easy to sort them.
This instruction gets all the members (properties/methods) of get-process
cmdlet, sorted by name.
get-process | get-member | sort Name
TypeName: System.Diagnostics.Process
Name MemberType Definition
---- ---------- ----------
__NounName NoteProperty string __NounName=Process
BasePriority Property int BasePriority {get;}
BeginErrorReadLine Method void BeginErrorReadLine()
BeginOutputReadLine Method void BeginOutputReadLine()
CancelErrorRead Method void CancelErrorRead()
CancelOutputRead Method void CancelOutputRead()
Close Method void Close()
CloseMainWindow Method bool CloseMainWindow()
Company ScriptProperty System.Object Company {get=$this.Mainmodule.FileVersionInfo.CompanyName;}
Container Property System.ComponentModel.IContainer Container {get;}
CPU ScriptProperty System.Object CPU {get=$this.TotalProcessorTime.TotalSeconds;}
CreateObjRef Method System.Runtime.Remoting.ObjRef CreateObjRef(type requestedType)
Description ScriptProperty System.Object Description {get=$this.Mainmodule.FileVersionInfo.FileDescription;}
Dispose Method void Dispose(), void IDisposable.Dispose()
Disposed Event System.EventHandler Disposed(System.Object, System.EventArgs)
EnableRaisingEvents Property bool EnableRaisingEvents {get;set;}
Equals Method bool Equals(System.Object obj)
ErrorDataReceived Event System.Diagnostics.DataReceivedEventHandler ErrorDataReceived(System.Object, System.Diagnostics.DataReceivedEventArgs)
ExitCode Property int ExitCode {get;}
Exited Event System.EventHandler Exited(System.Object, System.EventArgs)
ExitTime Property datetime ExitTime {get;}
FileVersion ScriptProperty System.Object FileVersion {get=$this.Mainmodule.FileVersionInfo.FileVersion;}
GetHashCode Method int GetHashCode()
GetLifetimeService Method System.Object GetLifetimeService()
GetType Method type GetType()
Handle Property System.IntPtr Handle {get;}
HandleCount Property int HandleCount {get;}
Handles AliasProperty Handles = Handlecount
HasExited Property bool HasExited {get;}
Id Property int Id {get;}
InitializeLifetimeService Method System.Object InitializeLifetimeService()
Kill Method void Kill()
MachineName Property string MachineName {get;}
MainModule Property System.Diagnostics.ProcessModule MainModule {get;}
MainWindowHandle Property System.IntPtr MainWindowHandle {get;}
MainWindowTitle Property string MainWindowTitle {get;}
MaxWorkingSet Property System.IntPtr MaxWorkingSet {get;set;}
MinWorkingSet Property System.IntPtr MinWorkingSet {get;set;}
Modules Property System.Diagnostics.ProcessModuleCollection Modules {get;}
Name AliasProperty Name = ProcessName
NonpagedSystemMemorySize Property int NonpagedSystemMemorySize {get;}
NonpagedSystemMemorySize64 Property long NonpagedSystemMemorySize64 {get;}
NPM AliasProperty NPM = NonpagedSystemMemorySize64
OutputDataReceived Event System.Diagnostics.DataReceivedEventHandler OutputDataReceived(System.Object, System.Diagnostics.DataReceivedEventArgs)
PagedMemorySize Property int PagedMemorySize {get;}
PagedMemorySize64 Property long PagedMemorySize64 {get;}
PagedSystemMemorySize Property int PagedSystemMemorySize {get;}
PagedSystemMemorySize64 Property long PagedSystemMemorySize64 {get;}
Path ScriptProperty System.Object Path {get=$this.Mainmodule.FileName;}
PeakPagedMemorySize Property int PeakPagedMemorySize {get;}
PeakPagedMemorySize64 Property long PeakPagedMemorySize64 {get;}
PeakVirtualMemorySize Property int PeakVirtualMemorySize {get;}
PeakVirtualMemorySize64 Property long PeakVirtualMemorySize64 {get;}
PeakWorkingSet Property int PeakWorkingSet {get;}
PeakWorkingSet64 Property long PeakWorkingSet64 {get;}
PM AliasProperty PM = PagedMemorySize64
PriorityBoostEnabled Property bool PriorityBoostEnabled {get;set;}
PriorityClass Property System.Diagnostics.ProcessPriorityClass PriorityClass {get;set;}
PrivateMemorySize Property int PrivateMemorySize {get;}
PrivateMemorySize64 Property long PrivateMemorySize64 {get;}
PrivilegedProcessorTime Property timespan PrivilegedProcessorTime {get;}
ProcessName Property string ProcessName {get;}
ProcessorAffinity Property System.IntPtr ProcessorAffinity {get;set;}
Product ScriptProperty System.Object Product {get=$this.Mainmodule.FileVersionInfo.ProductName;}
ProductVersion ScriptProperty System.Object ProductVersion {get=$this.Mainmodule.FileVersionInfo.ProductVersion;}
PSConfiguration PropertySet PSConfiguration {Name, Id, PriorityClass, FileVersion}
PSResources PropertySet PSResources {Name, Id, Handlecount, WorkingSet, NonPagedMemorySize, PagedMemorySize, PrivateMemorySize, VirtualMemorySize, Threads.Count, TotalProcessorTime}
Refresh Method void Refresh()
Responding Property bool Responding {get;}
SafeHandle Property Microsoft.Win32.SafeHandles.SafeProcessHandle SafeHandle {get;}
SessionId Property int SessionId {get;}
SI AliasProperty SI = SessionId
Site Property System.ComponentModel.ISite Site {get;set;}
StandardError Property System.IO.StreamReader StandardError {get;}
StandardInput Property System.IO.StreamWriter StandardInput {get;}
StandardOutput Property System.IO.StreamReader StandardOutput {get;}
Start Method bool Start()
StartInfo Property System.Diagnostics.ProcessStartInfo StartInfo {get;set;}
StartTime Property datetime StartTime {get;}
SynchronizingObject Property System.ComponentModel.ISynchronizeInvoke SynchronizingObject {get;set;}
Threads Property System.Diagnostics.ProcessThreadCollection Threads {get;}
ToString Method string ToString()
TotalProcessorTime Property timespan TotalProcessorTime {get;}
UserProcessorTime Property timespan UserProcessorTime {get;}
VirtualMemorySize Property int VirtualMemorySize {get;}
VirtualMemorySize64 Property long VirtualMemorySize64 {get;}
VM AliasProperty VM = VirtualMemorySize64
WaitForExit Method bool WaitForExit(int milliseconds), void WaitForExit()
WaitForInputIdle Method bool WaitForInputIdle(int milliseconds), bool WaitForInputIdle()
WorkingSet Property int WorkingSet {get;}
WorkingSet64 Property long WorkingSet64 {get;}
WS AliasProperty WS = WorkingSet64
- Objects: Sorting & Selecting
UseSort-Object
(sort
) &Select-Object
(select
).# Sort processes based on ID & VM-usage (descending). Display only ID, Name, VM, PM. gps | select ID,Name,VM,PM | sort VM,ID -desc # Save above table as HTML. gps | select ID,Name,VM,PM | sort VM,ID -desc | convertto-html | out-file TEST.html
Group-Object
We can group objects based on like values/properties.
$Object | Group-Object <switch>
- Group email addresses by provider
Here,$emails = @('abc@gmail.com', 'xyz@gmail.com', 'abc@yahoo.com', 'abc@yahoo.com') $emails | group { ($_ -split '@')[1] }
-split
splits result into two parts, accessible using [0] & [1].
Measure-Object
We can perfom certain arithmetic operations on objects.
$Object | Measure-Object <switch>
Type | Switch | Meaning |
---|---|---|
Numeric | -Max , -Min , -Average |
max/min & average of the values |
String | -Char , -Word , -Line |
#chars, #words, #lines in string |
Compare-Object
We can compare entries within two objects.
Compare-Object -reference $A -difference $B -includeEqual -excludeDifferent
Compare-Object -reference 1,2,3,4 -difference 1,2 -includeEqual
InputObject SideIndicator
----------- -------------
1 ==
2 ==
3 <=
4 <=
-
Compare two folders; return files with same name & size.
$ref = ls ('C:\Windows\System32' -file); $diff = (ls 'C:\Windows\SysWOW64' -file); compare = -ref $ref -diff $diff -property Name,Length -includeEqual -excludeDifferent Name Length SideIndicator ---- ------ ------------- @AppHelpToast.png 232 == @AudioToastIcon.png 308 == @EnrollmentToastIcon.png 330 == @VpnToastIcon.png 404 == ...
-
Objects: Selecting (
Sort-Object
vWhere-Object
)
Sort-Object
lets you select/filter objects based on properties.
Where-Object
lets you select/filter objects based on a criteria.# List all processes with ID >= 1000, sorted in ascending order. gps | where {$_.Handles -ge 1000} | sort -Property Handles
Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName ------- ------ ----- ----- ------ -- -- ----------- 1011 42 39560 23564 4664 0 LenovoVantageService 1060 22 11932 24380 1044 0 svchost 1073 6 8740 12100 14168 0 Windows.WARP.JITService 1136 52 50488 41276 4136 0 Lenovo.Modern.ImController 1201 17 7516 11760 1208 0 svchost 1209 91 102380 165036 18.14 8500 1 SearchUI 1376 22 7248 13288 976 0 lsass 1453 93 179728 231288 42.13 3016 1 firefox 2075 81 384764 151604 4332 0 MsMpEng 3523 9 1868 3972 8632 1 rundll32 3538 137 119552 132228 153.25 7980 1 explorer 5508 0 188 136 4 0 System
-
Study
ls
,sort
,select
,where
cmdlets. -
Get current date & time. Then, show only time.
get-date; get-date | select Hour,Minute,Second
Saturday, May 9, 2020 11:49:03 AM
Hour : 11
Minute : 49
Second : 3
-
Display a list of installed hotfixes. Display installation date, installed by, and ID, sorted by installation date.
get-hotfix | select installedon,installedby,hotfixid | sort installedon InstalledOn installedby hotfixid ----------- ----------- -------- 3/13/2020 12:00:00 AM NT AUTHORITY\SYSTEM KB4538674 3/13/2020 12:00:00 AM NT AUTHORITY\SYSTEM KB4541338 3/13/2020 12:00:00 AM NT AUTHORITY\SYSTEM KB4537759 3/13/2020 12:00:00 AM NT AUTHORITY\SYSTEM KB4537572 3/13/2020 12:00:00 AM NT AUTHORITY\SYSTEM KB4517245 4/22/2020 12:00:00 AM NT AUTHORITY\SYSTEM KB4549951 4/22/2020 12:00:00 AM NT AUTHORITY\SYSTEM KB4552152
-
Display a list of 10 latest Security Event-logs. Display index, time, source for each file, with the oldest entries appearing first (and same-time entries sorted by index).
get-eventlog -logname system -newest 10 | select index,timegenerated,source | sort timegenerated,index | out-gridview Index TimeGenerated Source ----- ------------- ------ 19167 5/9/2020 10:09:26 AM Microsoft-Windows-TPM-WMI 19168 5/9/2020 10:09:26 AM Microsoft-Windows-Winlogon 19169 5/9/2020 10:09:27 AM Microsoft-Windows-TPM-WMI 19170 5/9/2020 10:11:22 AM DCOM 19171 5/9/2020 10:11:22 AM DCOM 19172 5/9/2020 10:11:22 AM DCOM 19173 5/9/2020 10:11:25 AM Microsoft-Windows-FilterManager 19174 5/9/2020 10:15:16 AM Service Control Manager 19175 5/9/2020 10:17:21 AM Service Control Manager 19176 5/9/2020 10:19:17 AM Microsoft-Windows-Kernel-General
-
Import/Export
man export* man import*
Export-Clixml Cmdlet Export-Csv Cmdlet Export-FormatData Cmdlet Export-PSSession Cmdlet Export-BinaryMiLog Cmdlet Export-WindowsDriver Cmdlet Export-WindowsCapabilitySource Cmdlet Export-WindowsImage Cmdlet Export-Counter Cmdlet Export-ODataEndpointProxy Function Export-Certificate Cmdlet Export-PfxCertificate Cmdlet Export-ProvisioningPackage Cmdlet Export-Trace Cmdlet Export-ScheduledTask Function Export-StartLayoutEdgeAssets Cmdlet Export-StartLayout Cmdlet Export-TlsSessionTicketKey Cmdlet ImportSystemModules Function Import-PowerShellDataFile Function Import-Module Cmdlet Import-Alias Cmdlet Import-Clixml Cmdlet Import-Csv Cmdlet Import-LocalizedData Cmdlet Import-PSSession Cmdlet Import-PackageProvider Cmdlet Import-BinaryMiLog Cmdlet Import-IseSnippet Function Import-Counter Cmdlet Import-PfxCertificate Cmdlet Import-Certificate Cmdlet Import-StartLayout Cmdlet Import-TpmOwnerAuth Cmdlet
-
Import/Export CSV, XML
gps | export-csv process.csv gps | export-clixml process.xml
-
Convert to HTML
gps | convertto-html | out-file TEST.html ls | convertto-html | out-file -append TEST.html
-
Select/Sort & save necessary columns to
TEST.html
-
Using CSS, beautiful
TEST.html
-
Compare two structured files (XML)
# List different processes running in two PCs (reference, difference). diff -reference (import-clixml reference.xml) -difference (gps) -property Name name SideIndicator ---- ------------- calc => mspaint => notepad <=
-
Output
out-file -> O/P to file. out-gridview -> O/P to table in new GUI window. (*) out-printer -> O/P to printer (SaveAs PDF).
Instead of piping
>
output to a file, useout-file
.
out-file
lets you specify:-append -> append, not replace contents -encoding -> file encoding (ascii, unicode, utf8, oem, string) -width -> set column width (default = 80 characters/line)
# Append outputs instead of replacing. ls | out-file -append -width 100 TEST.txt
Pipeline Parameter-Binding
Given: cmdA | cmdB
; What exactly goes through the |
?
Ans: Objects
- Display processes/services from a list of computers connected to your PC.
# computers.csv hostname,operatingsystem Feynman,windows ...
# Processes gps -ComputerName (import-csv .\computers.csv | select -ExpandProperty hostname) | out-gridview # Services gsv -ComputerName (import-csv .\computers.csv | select -ExpandProperty hostname) | select Name,Status | sort Name | out-gridview
File/Folder are collectively called Item.
-
Current location
TheGet-Location
(akapwd
) gets current directory path. If you are working with multiple locations, you can push/pop those locations to/from a stack usingPush-Location
/Pop-Location
(akapushd
/popd
).# Get current location; Save current location to stack & move to another; Goto previous location (stored on stack) pwd; push 'B:\PowerShell'; popd
-
List items
-Force
displays hidden items as well;-Recurse
recursively lists items.Get-ChildItem -Path C:\ -Force ls C:\ -Force
- Find all binaries within
Program Files
that were last modified after October 1, 2005 and size is 1-10MB
ls $env:ProgramFiles *.exe -Recurse | where {($_.LastWriteTime -gt '2005-10-01') -and ($_.Length -ge 1mb) -and ($_.Length -le 10mb)} | select Name,@{name='LastWriteTime';expression={Get-Date -Format 'dd-MM-yy hh:mm:ss tt' $_.LastWriteTime}}
- Find all binaries within
File Metadata
See: Properties based on File-Type
$shell = new-object -com shell.application
$folder = $shell.namespace((pwd).Path)
$file = $folder.Items().Item('01.mp4')
$folder | gm; $file | gm;
-
Format-Table, Format-List, Format-Wide, Format-Custom
-
Customized Formatting
-
Display process names, IDs, responding (to Windows or not) in a table
gps | format-table Name,ID,Responding -autosize -wrap
-
Display process names, IDs, virtual/physical memory usage (in MB) in a table
gps | format-table Name,ID, @{name='Virtual(MB)';expression={$_.vm/1MB};formatstring='F2'}, @{name='Physical(MB)';expression={$_.workingset/1MB};formatstring='F2'} -autosize
-
Display available event-logs - their names and retention periods in a table
get-eventlog -list | format-table @{name='Name';expression={$_.LogDisplayName}}, @{name='Retention(days)';expression={$_.MininumRetentionDays}}
-
Display service grouped-by their status (start/stop)
[OUTPUT]gsv | sort status -desc | format-table -groupby status
-
Display a list of all binaries (.exe) in
C:\Windows
with their name, versionInfo & fileSize
[OUTPUT]ls C:\Windows\*.exe | format-list Name,VersionInfo,@{Name='Size';Expression={$_.length}}
NOTE
- Prefer outputting Objects over formatted-tables.
[NO] gwmi win32_logicaldisk | format-table deviceid, @{name='Total Memory (GB)';e={$_.size/1GB};formatstring='F2'}, @{name='Free Memory (GB)';e={$_.freespace/1GB};formatstring='F2'}
Here we've used[YES] gwmi win32_logicaldisk | select deviceid, @{name='Total Memory (GB)';e={$_.size/1GB -as [int]}}, @{name='Free Memory (GB)';e={$_.freespace/1GB -as [int]}}
-as [int]
to round off, asSelect-Object
doesn't offerformatstring
option.
Outputting objects allows us to do this (something which formatted tables don't):.\test.ps1 | export-csv test.csv
The Approach
-
A. Specify what you need.
-
B. Filter out what you need from what PS gives you.
eg. To get a specific service, you can specify it with
get-service
.gsv -name e*,*seo*
But if you want a list of ONLY running services, you have to filter.
gsv -name e*,*seo* | where {$_.status -eq 'running'}
Don't rely on headers O/P by cmdlets like
get-service
to infer it's properties.
Always useget-member
to lookup cmdlet property names.gsv | gm
The Operators
Refer about_comparison_operators
.
Name | Description | Note |
---|---|---|
-eq ,-ceq |
equal to | c implies case-sensitive |
-ne ,-cne |
not equal to | . |
-ge ,-cge ,-le ,-cle |
greater/lesser than OR equal to | . |
-gt ,-cgt ,-lt ,-clt |
greater/lesser than | . |
-and ,-or ,-not |
and, or, not | . |
-like ,-clike |
checks matching strings | c implies case-sensitive |
-match ,-cmatch |
matches RegEx | . |
-
Example (
-not
): Both these commands check if the process isn't responding.$_.responding -eq $False -not $_.responding
-
Display all binaries (EXE) in
C:\Windows\System32
larger than 5MB.ls C:\Windows\System32\*.exe | where {$_.length -gt 5MB}
-
Get all hotfixes that are security updates.
get-hotfix -Description 'Security Update'
-
Display a list of all running processes with the name
Conhost
orSvchost
.gps -name svchost,conhost | format-table -groupby name
PS calls 'background process', a job
.
-
Create a local background process (
job
)
Use [1] for on-spot instructions. Use [2] if instructions are retrieved from a file.start-job -scriptblock {...} start-job -filepath ...
Although this can also work for remote execution, prefer WMI cmdlets.
start-job -scriptblock {get-eventlog security -computerName server1,server2}
-
Create a remote background process (
job
)
By default, WMI cmdlets, even if they're running on multiple PCs, do so synchronously.
This means, if PC1 has a long list of commands to execute, it will take forever to execute commands on PC2.
To do this asynchronously using background process (job
), attach the-asJob
parameter to the cmdlet.gwmi Win32_OperatingSystem -computerName (cat allservers.txt) -asJob
-
Managing background processes (
job
)Get-Job -> Retrieve status of all jobs. Receive-Job -> Retrieve results of all jobs. Remove-Job -> Deletes job alongwith all cached memory. Stop-Job -> Terminates a blocked job. Wait-Job -> Forces Shell to wait until a job is finished executing.
Retrieving results of a job removes it from memory. To avoid this deletion, use
-keep
parameter.receive-job -id 1 -keep
-
Scheduling background processes (
job
)
Start by creating a trigger usingNew-JobTrigger
.
Set additional options usingNew-ScheduledTaskOption
.
Register the job with the Task Scheduler usingRegister-ScheduledJob
.
The last step defines the job in 'Task Scheduler' by writing to an XML file.
For me, this is located atC:\Users\Chaitanya Tejaswi\AppData\Local\Microsoft\Windows\PowerShell\ScheduledJobs
. -
Play an audio daily at 7:30PM
register-scheduledjob -name myDailyJobs -scriptblock {vlc "B:\CRTejaswi\Music\Anna McLuckie - Little Man On The Moon.mp3"} -trigger (new-jobtrigger -daily -at '19:30')
While this isn't neccesary for this particular example, use this template to run with elevated privileges.
register-scheduledjob -name myDailyJobs -scriptblock {vlc "B:\CRTejaswi\Music\Anna McLuckie - Little Man On The Moon.mp3"} -trigger (new-jobtrigger -daily -at '19:30') -scheduledjoboption (new-scheduledjoboption -waketorun -runelevated)
Scheduled tasks are non-volatile, meaning they don't get erased when you close the Shell. This is because it is stored in XML files on disk (
C:\Users\Chaitanya Tejaswi\AppData\Local\Microsoft\Windows\PowerShell\ScheduledJobs
).
Pattern matching is done using -match
&-cmatch
operators, and select-string
cmdlet.
Expression | Meaning |
---|---|
. |
Any character (except newline) |
\d , \D |
Digit (0-9), !Digit |
\w , \W |
Word (a-z, A-Z, 0-9, _), !Word |
\s , \S |
Whitespace (space, tab, newline), !Whitespace |
\b , \B |
WordBoundary, !WordBoundary |
^ , $ |
Beginning/End of String |
[] ,[^] ,() ,{} |
CharacterSet, !CharacterSet, WordGroup, #Values |
Quantifiers
Expression | Meaning |
---|---|
0 |
>=0 |
+ |
>=1 |
? |
0 or 1 |
{n} |
Exact value (=n) |
{start, stop} |
Range of values (min, max) |
- Get all files that have a 2-digit value in their name.
ls | where {$_.name -match "\d{2}"}
- Display process id, name & company of all processes that are from MicroSoft.
gps | where {$_.company -match "^Microsoft"} | select name,id,company
- Retrieve all DNS entries where Data property is an IPv4 address.
Get-DnsClientCache | where {$_.data -match "^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"}
- Retrieve IIS logfile records that contain 40x errors.
ls *.log -recurse | select-string -pattern "\s40[0-9]\s" | format-table Filename,LineNumber,Line -wrap
Refer: Get-WmiObject (gwmi), Get-CimInstance (gcim)
- Windows Remote Management (WinRM)
- Windows Management Instrumentation (WMI) [OLD] & the Common Information Model (CIM) [NEW]
Get-WmiObject
,Invoke-WmiMethod
,GetCimInstance
,Invoke-CimMethod
WMI commands work over RPCs. CIM commands work over WS-MAN (WinRM).
CIM instructions need WinRM to be enabled on every PC. So, prefer the old WMI instructions. - Classes
win32_logicaldisk:
win32_process:
win32_service:
win32_bios:
- Display all HDD partitions with total/free memory.
gwmi win32_logicaldisk | format-table deviceid, @{name='Total Memory (GB)';e={$_.size/1GB};formatstring='F2'}, @{name='Free Memory (GB)';e={$_.freespace/1GB};formatstring='F2'}
- Display list of services sorted by mode (auto, manual)
gwmi -class win32_service -Filter "state = 'running'" | sort startmode,name
Refer: Providers
Also See: Registry
A provider represents a data storage as a filesystem.
Windows FileSystem has this heirarchy:
File -> Folder -> Drive
File/Folder are collectively called Item, and so we have items associated with a drive. Since a Provider maps physical storage to drives (even if they're not a filesystem object, eg. Registry): we have cmdlets that deal with items.
These verbs apply to all items:
Get/Set, Copy/Move, New/Remove/Rename/Clear
Each provider has certain 'capabilities' for its associated cmdlets.
ShouldProcess -> We can use `-WhatIf` & `-Confirm` to test before executing it.
Filter -> We can use `-Filter` to filter out content.
Credentials -> We can specify credentials to be provided each time a cmdlet is run.
Transactions -> We can commit or rollback changes made by the cmdlet.
Built-In Providers
Provider | Drive(s) | OutputType | Capabilities |
---|---|---|---|
Alias | Alias: |
System.Management.Automation.AliasInfo |
ShouldProcess |
Certificate | Cert: |
Microsoft.PowerShell.Commands.X509StoreLocation |
? |
System.Security.Cryptography.X509Certificates.X509Certificate2 |
. | ||
Environment | Env: |
System.Collections.DictionaryEntry |
ShouldProcess |
FileSystem | C: |
System.IO.FileInfo |
ShouldProcess, Filter, Credentials |
System.IO.DirectoryInfo |
. | ||
Function | Function: |
System.Management.Automation.FunctionInfo |
ShouldProcess |
Registry | HKLM: HKCU: |
Microsoft.Win32.RegistryKey |
ShouldProcess, Transactions |
Variable | Variable: |
System.Management.Automation.PSVariable |
ShouldProcess |
WSMan | WSMan: |
Microsoft.WSMan.Management.WSManConfigContainerElement |
Credentials |
Refer: Registry
Registry is a database that stores low-level settings for any Windows OS.
Registry files are stored in %SystemRoot%\System32\Config
Refer: Talk (Jeff Hicks) + Files, Talk (Jason Horner)
Also See: myScripts
NOTE
All file conversion cmdlets use verbs like Import
,Export
,ConvertTo
,ConvertFrom
.
These have specific meaning.
Import/Export -> convert & save to a file. ConvertTo/ConvertFrom -> only convert (to be displayed or piped further).
CSV
We use Import-Csv
& Export-Csv
to read from & write to CSV files.
-
Create new aliases
Createaliases.csv
Name,Value gotodir,Get-ChildItem sel,Select-Object clip,Get-Clipboard
Import these aliases using:
import-csv aliases.csv | new-alias
-
CSV files are all strings
When you export objects to CSV, you lose type (end up having only Strings).
Cast each header as a specific type.import-csv .\test.csv | forEach { [PSCustomObject]@{ DeviceID = $_.DeviceID 'Total Memory (GB)' = $_.'Total Memory (GB)' -as [int32] 'Free Memory (GB)' = $_.'Free Memory (GB)' -as [int32] } } | gm Name MemberType Definition ---- ---------- ---------- Equals Method bool Equals(System.Object obj) GetHashCode Method int GetHashCode() GetType Method type GetType() ToString Method string ToString() DeviceID NoteProperty string DeviceID=A: Free Memory (GB) NoteProperty int Free Memory (GB)=250 Total Memory (GB) NoteProperty int Total Memory (GB)=250
-
Create a CSV marksheet for 5 students containing Name & Marks in Science, Maths, English, Hindi & ComputerScience. Import file, add TotalMarks & Percentage columns, then append them to file.
JSON
We use ConvertFrom-Json
& ConvertTo-Json
to read from & write to JSON objects.
Since these aren't Import
& Export
cmdlets, we have to use Out-File
to write to file.
Use -depth n
to define the depth to which you want to parse the file. The default is 2. This is useful to know if you have a file with several levels of heirarchy.
-
Create a JSON file
Wrap raw JSON data inside literal-strings'...'
.$json = ' [ { "Country": "India", "Capital": "New Delhi" }, { "Country": "US", "Capital": "Washington DC" } ]' $json | convertfrom-json Country Capital ------- ------- India New Delhi US Washington DC
Another way is to iteratively add rows to an empty array, then
ConvertTo-Json
.$page = @() $info = '' | select Country,Capital $info.Country = 'India'; $info.Capital = 'New Delhi'; $page += $info $info = '' | select Country,Capital $info.Country = 'US'; $info.Capital = 'Washington DC'; $page += $info $json = $page | convertto-json $json | convertfrom-json
Country Capital ------- ------- India New Delhi US Washington DC
-
Read a JSON file
PS> cat .\test.json -Raw | convertfrom-json DeviceID Total Memory (GB) Free Memory (GB) -------- ----------------- ---------------- A: 250 250 B: 681 124 C: 118 39
-
ConvertTo-Json
(eg. from CSV)import-csv .\test.csv DeviceID Total Memory (GB) Free Memory (GB) -------- ----------------- ---------------- A: 250 250 B: 681 124 C: 118 39 import-csv .\test.csv | convertto-json [ { "DeviceID": "A:", "Total Memory (GB)": "250", "Free Memory (GB)": "250" }, { "DeviceID": "B:", "Total Memory (GB)": "681", "Free Memory (GB)": "124" }, { "DeviceID": "C:", "Total Memory (GB)": "118", "Free Memory (GB)": "39" } ]
Use the
-Compress
switch to strip all extra spaces (and minify the JSON file). -
ConvertFrom-Json
When weConvertFrom-Json
, we get aSystem.Object[]
array. It doesn't actually create objects of the expected data type.
UsingForEach
, operate on each entry & format it in the desired way.cat .\test.json | convertfrom-json | gm TypeName: System.Object[] ... cat .\test.json | convertfrom-json | forEach { $_ | select Name,Size,@{name='TS'; expression={$_.timestamp -as [timespan]}} }
-
Modify JSON content
To modify is to create a new file. To modify, access each entry usingforEach
, modify it, then save as new file.- Your JSON file has student marks for an exam. Initially, you had filled it with test entries, but now, marks have been appended even for these test entries. Default marks of test entries to Null, so it doesn't skew calculations for entire class.
$json = cat test.json | convertfrom-json $json.update | forEach { if ($_.Name -eq 'test'){ $_.Marks = $Null } } | convertto-json -depth |
- Modify JSON: Example where good forEach logic is used.
- Your JSON file has student marks for an exam. Initially, you had filled it with test entries, but now, marks have been appended even for these test entries. Default marks of test entries to Null, so it doesn't skew calculations for entire class.
-
Use a simple REST API & operate on its headers to make a table.
http://ramblingcookiemonster.github.io/SQLite-and-PowerShell/ https://www.darkartistry.com/2019/08/create-insert-and-query-sqlite-with-powershell/ https://www.tutorialspoint.com/sqlite/index.htm
See: [1], [2], iText (examples), iText (videos)
iText offers a .NET API to deal with PDFs (C#, PS).
The latest version is iText7, but due to a lack of proper documentation, we'll use iText5.
- Export pdf from text file [BROKEN]
function Export-Pdf {
<#
.SYNOPSIS
Exports PDF from a text file.
.EXAMPLE
PS> Export-Pdf -FilePath test.txt
PS> Export-Pdf -FilePath test.ps1
#>
[cmdletBinding()]
param(
[string]$FilePath
)
# Invoke contents of binary
$DLLPath = 'C:\Program Files\myBinaries\itext5\itextsharp.dll'
Add-Type -Path $DLLPath -ErrorAction Stop
# Convert TXT -> PDF
$OutFile = "$($FilePath.BaseName).pdf"
$File = New-Object -TypeName iTextSharp.text.Document
$FileStream = New-Object -TypeName IO.FileStream -ArgumentList ($OutFile, [System.IO.FileMode]::Create)
$Paragraph = New-Object -TypeName iTextSharp.text.Paragraph
[iTextSharp.text.pdf.PdfWriter]::GetInstance($File, $FileStream)
[iTextSharp.text.FontFactory]::RegisterDirectories()
$Paragraph.add((Get-Content -Path $($FilePath.FullName) |
forEach {"$_ `n"}
))
$File.open(); $File.add($Paragraph); $File.close();
}
PDFtk is another useful shell utility.
# Download PDF (Python3.8.6 documentation)
iwr 'https://docs.python.org/3/archives/python-3.8.6-docs-pdf-a4.zip' -OutFile python.zip
# Extract content (use either 7zip or .NET module)
7z e .\python.zip -r
Add-Type -AssemblyName System.IO.Compression.FileSystem
[System.IO.Compression.ZipFile]::ExtractToDirectory("$(pwd)\python.zip", "$(pwd)")
# Retain only 'reference.pdf'
ls *.pdf | where {$_.BaseName -notmatch '^ref'} | del
ren .\reference.pdf .\test.pdf;
# Get number-of-pages in file
(pdftk test.pdf dump_data) -match 'NumberOfPages'
# Encrypt file
pdftk test.pdf output test_encrypted.pdf user_pw password allow printing
# Decrypt file
pdftk test_encrypted.pdf input_pw password output test.pdf
# Merge files
pdftk .\A.pdf .\B.pdf cat output mix.pdf
pdftk *.pdf cat output mix.pdf
# Split files
pdftk test.pdf cat 1-10 21-30 31-40 output mix.pdf
# Alternate & Merge files ('odd.pdf' is in ascending/descending order)
pdftk A=even.pdf B=odd.pdf shuffle A B output mix.pdf
pdftk A=even.pdf B=odd.pdf shuffle A Bend-1 output mix.pdf
# Split entire file into individual page-files
pdftk test.pdf burst
Refer: System.IO.Compression.ZipFile
-
List contents of a compressed file
Add-Type -AssemblyName System.IO.Compression.FileSystem $zip = [System.IO.Compression.ZipFile]::Open('test.zip',2) $zip.Entries.fullName ... $zip.Dispose()
-
Compress a file/folder
$Source = '..\test\'; $Destination = 'test.zip'; Add-Type -AssemblyName System.IO.Compression.FileSystem [System.IO.Compression.ZipFile]::CreateFromDirectory($Source, $Destination)
-
De-Compress a file
$Source = 'test.zip'; $Destination = '..\test\'; Add-Type -AssemblyName System.IO.Compression.FileSystem [System.IO.Compression.ZipFile]::ExtractToDirectory($Source, $Destination)
-
Add files to an existing compressed file
Open the file as aZipFile
object usingOpen()
. Here,0,1,2 = Read, Write, R/W
denotes the R/W access.
UseCreatEntryFromFile()
method to add entries. Here,0,1,2 = Fast, Best, NoCompression
denotes the compression mode.$Path = 'test.zip'; $file1 = 'test.pdf'; $file2 = 'test.mp4' Add-Type -AssemblyName System.IO.Compression.FileSystem $zip = [System.IO.Compression.ZipFile]::Open($Path,2) [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip, $file1, 'test.pdf', 0) [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip, $file2, 'test.mp4', 1) ... $zip.Dispose()
-
Compress/De-Compress specific files
This compresses .txt files, and adds them to a ZIP archive.
Add-Type -AssemblyName System.IO.Compression.FileSystem $zip = [System.IO.Compression.ZipFile]::Open('test.zip',2) ls *.txt | forEach { [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zip, $_.FullName, $_.Name, 0) } ... $zip.Dispose()
This de-compresses .txt files & files modified in the last month.
Add-Type -AssemblyName System.IO.Compression.FileSystem $zip = [System.IO.Compression.ZipFile]::Open('test.zip',2) $zip.Entries | where Name -like *.txt | forEach { [System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, $_.Name) } $zip.Entries | where {$_.LastWriteTime.DateTime -gt (Get-Date).AddMonths(-1)} | forEach { [System.IO.Compression.ZipFileExtensions]::ExtractToFile($_, $_.Name) } ... $zip.Dispose()
See: .nanorc
Installation
- Download latest binary from here.
- Extract all
*.nanorc
files toC:/Users/USERNAME/nanorc/
, and.nanorc
toC:/Users/USERNAME/
. - After opening
nano .nanorc
, uncomment necessary lines & insertinclude "C:/Users/USERNAME/nanorc/*.nanorc"
for syntax-highlighting.
Custom Behaviour
Option | Description |
---|---|
set linenumbers |
display line-numbers |
set mouse |
enable mouse drag/click support |
set nohelp |
don't display help lines at bottom of screen |
set regexp |
enable regex search by default |
set rebinddelete |
enable backspace/delete keys to work correctly |
set rebindkeypad |
enable numeric keypad |
set zap |
delete entire selection using backspace/delete |
set smooth |
enable smooth scrolling |
set tabsize 4 |
set tab-size to 4 spaces |
set tabstospaces |
convert tabs to spaces when saving file |
set tempfile |
auto-save file on exit |
set noconvert |
don't convert from dos/mac to unix format |
Custom Key-Bindings
# Help, Find/Replace, Comment/Uncomment
bind F1 help all
bind M-F whereis all
bind M-W findnext all
bind M-Q findprevious all
bind M-R replace all
bind ^/ comment all
# Copy/Cut/Paste
bind M-C copy main
bind M-X cut main
bind M-V paste main
bind M-Z undo main
bind M-Y redo main
#bind ^H chopwordleft main
#bind ^H chopwordright main
Key-Bindings
Key-Binding | Description |
---|---|
ESC+ESC+<0-255> |
Prints ASCII character corresponding to 0-255 |
Alt+3 | Comment/Uncomment |
Alt+Shift+3 | Display line numbers |
Ctrl+K/U | Cut/Paste |
Alt+6 | Copy current line |
Alt+U/E | Undo/Redo |
Ctrl+C | Cursor position (row, column, character index) |
F2 | Exit |
Ctrl+S; F3 | Save/Save-As |
Ctrl+W,Alt+W | Find/Find-Next |
Alt+R | Replace |
- select/delete all
UseAlt+T
to cut from current line to eof. - work with several files at once
Open multiple files usingnano test.ps1 test.py test.txt
; go back-and-forth usingAlt+,
andAlt+.
. - insert text from files
UseCtrl+R
to insert-from-file. Enter filename, then press enter. - save backup files
Runnano -BC .\backup test.txt
. B/C => backup/path-to-backup-directory.
Configuration
- Login
gh auth login
gh auth login --with-token $Token_GitHub
gh auth logout
gh auth status
Here $Token_Github is an environment variable storing the token string.
- Setup usage access limit
gh auth refresh # Sets min access scope
gh auth refresh --scopes write:org,read:public_key # Sets additional scopes
- Setup default editor
gh config set editor nano # GNUNano
gh config set editor subl # SublimeText
Gist
- List all gists
gh gist list
$Gists=@(); gh gist list | forEach {$Gists += $_.ToString().Split('')[0]}
- Create a new gist (multiple files: code, text, stdin)
gh gist create --public test.ps1 test.py test.txt - -d 'Gist: Test'
- View files from a gist
gh gist view 90dd9b9ed4402a8ea82ec8048935ec59
gh gist view $Gists[0]
gh gist view $Gists[1] -f gistfile2.txt
- Edit files from a gist
gh gist edit 90dd9b9ed4402a8ea82ec8048935ec59 -f gistfile2.txt
gh gist edit $Gists[1] -f gistfile2.txt
Repo
- View repo (README)
gh repo view
gh repo view crtejaswi/quiz
Release
- List all releases of a repo
gh release --repo opencv/opencv list
- List all releases of a repo with full info
gh release --repo opencv/opencv view
- Download a release for a repo
gh release --repo opencv/opencv download 4.5.0
gh release --repo opencv/opencv download --pattern '*docs.zip'
# Ensure that the complete file has been downloaded
(ls .\opencv-4.5.0-docs.zip).Length/1MB
Alias
You can set aliases for routine commands using:
gh alias set <alias> <expansion>
# USAGE: gh <alias>
gh alias set pv 'pr view'
gh pv -w 123
Authentication using SSH Keys
See: [1], [2].
Ensure that OpenSSH is enabled on Windows, then:
cd ~; ssh-keygen
Get-Service ssh-agent | Set-Service -StartupType Manual
ssh-agent -s
ssh-add ~/.ssh/id_rsa
cat ~/.ssh/id_rsa | scb
Paste this SSH key to your Github account.
Check SSH key status using ssh -T git@github.com
, then move to project repo and:
# Check connection protocol (HTTPS/SSH)
git remote -v
# HTTPS -> SSH
git remote set-url origin git@<GIT-PROVIDER>:<USERNAME>/<REPO>.git
#git remote set-url origin git@github.com:CRTejaswi/resources.git
# Check connection protocol (HTTPS/SSH)
git remote -v
Common Parameters
Common parameters are universal cmdlet parameters.
-Debug (-db)
-ErrorAction (-ea)
-ErrorVariable (-ev)
-InformationAction (-infa)
-InformationVariable (-iv)
-OutBuffer (-ob)
-OutVariable (-ov)
-PipelineVariable (-pv)
-Verbose (-vb)
-WarningAction (-wa)
-WarningVariable (-wv)
Parameter Names
For consistent names of parameters, PS lists 7 categories of parameter names:
Category | Parameters |
---|---|
Activity | Append, Insert, Include, Create, Erase, Force, Filter, Log, Recurse, |
Date & Time | Created, Accessed, Modified, Before, After |
Formatting | As, Encoding, Width, Wrap |
Property | Count, Id, Name, Value, Property, Regex |
Quantity | All, Allocation, Count, Scope |
Resource | Attribute, Drive, Port, Interface, Domain, Job, LiteralPath, Path, URL, Type |
Security | Credential, Privilege |
Passing Parameters to a script
Arguments to a script/cmdlet can be passed in 3 equivalent ways:
Get-ChildItem -Path $env:windir -Filter *.dll -Recurse
Get-ChildItem `
-Path $env:windir `
-Filter *.dll `
-Recurse
$myargs = @{
Path = "$env:windir"
filter = '*.dll'
Recurse = $true
}
Get-ChildItem @myargs
Specifying Parameters in a Script
- Passing args by index
You can access the Shell arguments in the called script using$args
array. - Passing args by name
You can access the Shell arguments in the called script usingparam(...)
statement.
By specifying CmdletBinding
(at the top of script), we can add several features to our parameters.
-
Enabling the features
All of these features listed below needCmdletBinding
to be enabled.<# # Comments #> [CmdletBinding()]
-
Mandatory parameters
Here, we make$myVar
a mandatory parameter. (TheHelpMessage
is optional).param ( [Parameter (Mandatory=$True, HelpMessage='A variable-name is mandatory')] [string]$myVar, [int]$Var1, [int]$Var2, )
-
Parameter aliases
Here, we give an alias (name
) to$myVar
.param ( [Parameter (Mandatory=$True)] [Alias ('name')] [string]$myVar, [int]$Var1, [int]$Var2, )
-
Validating parameter input
Here, we specify a set of valid inputs for$Var1
&$Var2
.param ( [string]$myVar, [ValidateSet(0,1)] [int]$Var1, [ValidateSet(0,1)] [int]$Var2, )
Read more about validation tricks, here.
-
Using
Write-Verbose
to print progress information
UsingWrite-Verbose
(instead ofWrite-Host
) in our scripts allows us to optionally determine the progress of our code.
Verbose output is visible only when the script is run with-verbose
switch. But, you cannot set its foreground/background colors (as you can withWrite-Host
), since PS has predefined color-codes for Verbose/Debug/Warning.Write-Verbose "Using $myVar Values"
Referencing Passed Parameters in a Script
A system hashtable, $PSBoundParameters
contains all the parameters & their values passed to a script.
See Get-Login for the actual script.
function Get-myLogin{
[cmdletBinding()]
param(
[string]$Site,
[switch]$List,
[switch]$Browser
)
$logins = import-csv $myLogins
switch ($PSBoundParameters.keys){
'Site' {$match = $logins | where site -eq $Site; $match.username,$match.password | scb}
'List' {$logins.site}
'Browser' {firefox $match.link}
}
}
Default Parameters
Refer $PSDefaultParameterValues
.
You can set default values for parameters such as -Path
, -Credential
, ... by adding these values into a built-in variable, $PSDefaultParameterValues
.
Note that the scope of $PSDefaultParameterValues
is limited to the shell when specified in PS, and to the script when specified in a .ps1
file. This trick can be handy to specify defaults for a script in the script itself and not affect the shell's defaults.
-
Specify default-credentials for every cmdlet that has a
-Credential
parameter.$credential = Get-Credential -UserName Administrator -Message "Enter Admin's Password" $PSDefaultParameterValues.add('*:Credential', $credential)
-
Ask for credentials everytime an
invoke-command
cmdlet is executed.$PSDefaultParameterValues.add('Invoke-Command:Credential', {Get-Credential -UserName Administrator -Message "Enter Admin's Password"})
Since invoke-command runs on local/remote PCs, this works as a basic security measure.
Review: Control Flow, Filtering & Comparisons.
Also See: myScripts
Operators
Refer about_operators
.
Name | Description | Example |
---|---|---|
-as |
type casts an object | 1000/3 -as [int] => 333 |
-is |
type checks an object | 12.45 -is [int] => False |
-replace |
replace substring within a string | 'Hello World' -replace 'e',3 => H3llo World |
-join |
convert array to delimited-string | `1,2,3,4,5 -join ' |
-split |
convert delimited-string to array | "1 2 3 4 5" -split " " => 1, 2, 3, 4, 5 |
-like |
wildcarded substring matching | 'this' -like '*his*' => True |
-contains |
checks if an object exists in a collection | 'abc','bcd','cde' -contains 'bcd' => True |
-in |
checks if an object exists in a collection | 'bcd' -in 'abc','bcd','cde' => True |
Manipulating Strings & Dates
- Pipe any string to
get-member
to list all associated properties/methods.'Test' | gm
- Pipe
get-date
to list all associated properties/methods.When working withget-date | gm
WMI
objects, the dates may not be straight-forward.For this, usegwmi win32_operatingsystem | select lastbootuptime lastbootuptime -------------- 20200602222520.500000+330
ConvertFromDateTime()
&ConvertToDateTime()
methods. (Check usinggwmi win32_operatingsystem | gm
)$os = gwmi win32_operatingsystem $os.ConvertToDateTime($os.LastBootUpTime) Tuesday, June 2, 2020 10:25:20 PM
Script Blocks ({}
)
Refer about_script_blocks
.
Anything within {}
is a script block.
https://www.youtube.com/watch?v=u6tdj1IFbpw https://www.sconstantinou.com/powershell-script-blocks/ https://www.youtube.com/watch?v=WP_Olf8GH_g https://www.youtube.com/watch?v=uoH6mnzwSZc
See: Clipboard, Get/Set Clipboard, xclip
Operations (gcb
/scb
)
- Copy filepaths
scb; scb (ls B:\CRTejaswi\Codes).FullName -Append
- Copy documentation
scb; scb (man Set-Clipboard -Append) -Append
- Copy contents of a file
scb; scb (cat $Notes)
- Cmdlets to copy clipboard to file [1]
Start-ClipboardCopy -FilePath $Clipboard
Stop-ClipboardCopy
-
Print/Create PDF from copied text
gcb | out-printer
-
Copy a filepath(s) to clipboard (So it becomes easy to paste in GUI)
ls *.pdf | % {$_.fullname} | scb (ls file.pdf).fullname | scb
-
Convert text (from docx) to epub/html/pdf
start input.docx gcb | pandoc $_ --metadata title='Title' +RTS -Ksize -RTS -o output.epub gcb | pandoc $_ --metadata title='Title' -o output.html gcb | pandoc $_ --metadata title='Title' --pdf-engine=xelatex -o output.pdf
-
Generate epub/mobi from text files.
(ls) -match $Pattern | forEach {pandoc $($_.FullName) --metadata title="$($_.BaseName)" --epub-cover-image="$($_.BaseName).jpg" -o "$($_.BaseName).epub"} ls *.epub | forEach {kindlegen $_.FullName}
-
Copy code(s)/text & save as code-file/text-file
ascii
is ideal.utf8
givesUTF-8 with BOM
, so, you'll have to re-encode in editor.gcb | out-file -Encoding ascii output.py gcb | out-file -Encoding utf8 output.py
Instead of creating a new file each time, simply append to the original:
gcb | out-file -Append -Encoding ascii output.md
This is ideal for simultaneous Copy & Paste (if you are too lazy to use
Ctrl+C
,Ctrl+V
repeatedly). -
Open links in Firefox
# Copied firefox (gcb) # From text-file firefox (cat .\input.txt)
A better way is to create a PS User-Profile
notepad $profile -> Add variables/methods... and save. -> Run them from Shell
To
$profile
, append path of file containing links$mylinks=B:\CRTejaswi\Documents\Links.txt
.
Open links using:firefox (cat $mylinks)
Use
subl $mylinks
to update links you want to visit now.
Read more about PS User-Profiles using:man about_profiles -ShowWindow
Setup
# Enable WSL
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
# Enable VM
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
# Download/Install WSL2 Kernel Package (x86-64)
iwr https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi -OutFile wsl.msi
wsl.msi
# Set WSL2 as default
wsl --set-default-version 2
# Install Linux Distribution (Debian)
firefox https://www.microsoft.com/en-in/p/debian/9msvkqc78pk6
# Check WSL Version
wsl -l -v
Configuring Linux OSes
sudo apt-get clean
sudo apt-get install -f
sudo dpkg --configure -a
sudo apt-get update && sudo apt-get dist-upgrade
Installing Linux Binaries
Ensure that you have configured your OS. Then, refer the installation steps for your binary.
eg. For telegram-cli, ensure OS setup, then:
sudo apt-get install libreadline-dev libconfig-dev libssl-dev lua5.2 liblua5.2-dev libevent-dev libjansson-dev libpython-dev make
Install Snap to install telegram as indicated here.
See: Microsoft Reference, Microsoft Videos, C# In A Nutshell.
-
$driveEject = New-Object -comObject Shell.Application $driveEject.Namespace(17).ParseName("D:").InvokeVerb("Eject")
-
Write templated strings to a file
This writesfile i.mp4; (i = 1-20)
toMERGE.txt
, and then, attempts to merge these video files.$page = @(); $n=1; while ($n -ne 21) {$page += "file $n.mp4"; $n++} $page | out-file -encoding ascii MERGE.txt ffmpeg -f concat -safe 0 -i MERGE.txt -c copy OUTPUT.mp4
We create an empty array
$page
, append entries to it, and pipe it toMERGE.txt
. -
Print strings following a matching sub-string
From CONFIG, I want to query the cmd to merge files using FFmpeg.
Logic: -> print 10 lines after a 'merge' (inclusive) is encountered.These cmd gets
ffmpeg
lines out of CONFIG.(cat $myconfig) -match 'ffmpeg'
Create/Delete A Temporary File
$tmp = New-TemporaryFile
...
del $tmp.FullName -Force
- Append source-code & outputs of code-files
Assuming you have a temporary file$tmp
, and source file namestest
;py .\test.py | out-file $tmp.fullname; cat .\test.py,$tmp.fullname | out-file -encoding ascii Py3.md -append .\test.exe | out-file $tmp.fullname; cat .\test.c,$tmp.fullname | out-file -encoding ascii C.md -append
PS gives Invoke-WebRequest
(aka curl
) to work with webpages.
- WebScraping (Prateek Singh)
- https://www.youtube.com/watch?v=QrC3ErlxpII
- https://www.youtube.com/watch?v=yCaS8UTmd88
- https://www.youtube.com/watch?v=va0WI9EyR2g
- https://www.youtube.com/watch?v=7liyba6YEG0
- https://www.youtube.com/watch?v=7A_RtRKhMcs
- https://www.youtube.com/watch?v=0DWM3xZbI2Y
- https://www.youtube.com/watch?v=9Patluspez4
NOTE:
Before doing anything useful, make sure to install & configure Internet Explorer. (Although you can make do without this by using -UseBasicParsing
switch; this is an absolutely fuckall workaround. This is because using it doesn't give you access to the webpage's DOM, which means, you cannot parse it, or get anything useful out of it. It's like standing with a gun - a water gun. So, just install the damn thing!)
-
Install from here.
-
To configure:
Win+I
>> Apps & Features >> Optional Features >> Add a feature >> Internet Explorer 11. Then,Win+R
>> Control >> Turn Windows Features ON/OFF >> [x] Internet Explorer. Restart PC. -
Open up Internet Explorer, set to
Recommended Settings
. Done! -
Get contents of a URL
This generates a local copy of my CV.$response = Invoke-WebRequest -Uri crtejaswi.github.io/CV $response.Content | out-file -encoding utf8 test.html
-
Get all links from a webpage
This gets all links from my CV.$links = (curl crtejaswi.github.io/CV).links.href
-
Get weather (temperatures)
Retrieving data for Delhi (28.7041° N, 77.1025° E).$URI = 'https://weather.com/en-IN/weather/today/l/28.7041,77.1025?temp=c' $response = curl -Uri $URI ($response.allelements | where { $_.class -Match "\w+--location--\w+" -or $_.class -Match "\w+--tempHiLoValue--\w+" }).innerText Rohini Sector 2, Delhi Weather 35°/26°
-
Get HTML (WebRequest) & Get JSON (RestMethod).
$response = Invoke-WebRequest -Uri 'https://github.com/CRTejaswi/API/blob/master/CV.json' $response.content | out-file -encoding ascii test.html; firefox test.html $response = Invoke-RestMethod -Uri 'https://raw.githubusercontent.com/CRTejaswi/API/master/CV.json' $response | convertto-json | out-file -encoding ascii test.json; firefox test.json
-
Get all of my Youtube playlists.
$response = curl -Uri 'https://www.youtube.com/channel/UC5NM5NZrw1hV6hgxnaPQPNw/playlists' $links = $response.links $links.href -match '^/playlist' /playlist?list=PL3pGy4HtqwD10u_vC6AksMg_RrIPMzvIA /playlist?list=PL3pGy4HtqwD3gyn8LDKSjCVDCbeyhbMTt ...
Assuming absolute links; this opens all of them in a browser:
$links.href -match '^/playlist' | out-file -encoding ascii $tmp.fullname firefox (cat $tmp.fullname)
This won't work, since all links are relative. This works:
$page = @() $page += ($links.href -match '^/playlist') $page = $page.replace('/playlist','www.youtube.com/playlist') $page | out-file -encoding ascii $tmp.fullname firefox (cat $tmp.fullname)
-
Append to my Youtube playlist.
Given a playlist; append it to my own playlist, so I can easily watch it on my phone/pc/tv.
Since, we'll send a POST request, we need to use YouTube's API.
To manually insert videos from a playlist, we add&disable_polymer=true
to the original link, thenAdd All
. Is this any useful for querying the API?
REST APIs
- https://www.youtube.com/watch?v=Uk0IHzR57hQ
- https://www.youtube.com/watch?v=7mEmQgGowMY
- https://www.youtube.com/watch?v=9piyM38it_8
- https://www.youtube.com/watch?v=RgwrHpE0IK4
- https://www.youtube.com/watch?v=t66ZgGeykug
- https://www.youtube.com/watch?v=mYcGV5BwMt4
- https://www.youtube.com/watch?v=oUl-Mmwvgec
- https://www.youtube.com/watch?v=_WjT2mrKXuE
- https://www.youtube.com/watch?v=yfwTAnfMhzw
- https://www.youtube.com/watch?v=AAPxI4QXPw8
Windows offers assembly-level (.dll) .NET API to access MS Office (Core), MS Word, MS Excel, and a few other Office utilities.
Instances can be accessed using COM objects in .NET/PS.
These can also be accessed without having MS Office installed on your PC by making use of PS modules available through PSGallery.
Word
See: Word.Application, Documents
[Needs MSOffice installed on your PC.]
$FilePath = 'test.docx'
$MSWord = New-Object -ComObject Word.Application
$MSWord.visible = $True
$file = $MSWord.Documents.Add()
$content = $MSWord.selection
$content.typeParagraph()
$content.typeText('This is a test document.')
$content.typeText("`nContent added by $($env:USERNAME) on $(Get-Date -Format 'dd-MM-yyyy hh:mm')")
$content.font.bold = 1; $content.typeText("`nBold Text"); $content.font.bold = 0;
$content.font.italic = 1; $content.typeText("`nItalic Text"); $content.font.italic = 0;
$content.font.underline = 1; $content.typeText("`nUnderlined Text"); $content.font.underline = 0;
$file.saveAs($FilePath, 16); $file.close();
$MSWord.quit(); $null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$MSWord);
Remove-Variable MSWord
- I/O from text files
$content.typeParagraph()
$content.font.bold = 1; $content.typeText("`nContent added by $($env:USERNAME) on $(Get-Date -Format 'dd-MM-yyyy hh:mm')`n"); $content.font.bold = 0;
$content.typeText("$(cat test.md)")
If you do not have MS Office installed, you can use the PSWriteWord
module (Install-Module PSWriteWord
) to deal with docx
files.
See: [1] [2] [3]
Excel
See: Excel.Application, Worksheets
[Needs MSOffice installed on your PC.]
$FilePath = 'test.xlsx'
$MSExcel = New-Object -ComObject Excel.Application
$MSExcel.visible = $True
$file = $MSExcel.Workbooks.Add()
$worksheet = $file.Worksheets.Item(1)
$worksheet.cells.item(1,1) = "ProcessName"
$worksheet.cells.item(1,2) = "Id"
$worksheet.cells.item(1,3) = "Handles"
$row = 2; $column = 1;
gps | select processName,id,handles | forEach {
$worksheet.cells.item($row,1) = $_.processName
$worksheet.cells.item($row,2) = $_.id
$worksheet.cells.item($row,3) = $_.handles
$worksheet.columns.autofit()
$row++
}
$file.saveAs($FilePath); $file.close();
$MSExcel.quit(); $null = [System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$MSExcel);
Remove-Variable MSExcel
If you do not have MS Office installed, you can use the ImportExcel
module (Install-Module ImportExcel
) to deal with xlsx
files.
See: [1] [2] [3] [4]
gps | Export-Excel test.xlsx -Show
See: Android SDK, Setup.
Also, finish review exercises & put code in relevant sections.
Execute Py3 scripts from PS, loading/storing data directly from the latter.
https://www.apress.com/gp/book/9781484245033 https://github.com/Apress/powershell-and-python-together
- Using firefox/js for routine tasks from PS. PS functions that aid in web application development or makes use of JS apis.
- Executing PS Core instructions from NodeJS app. https://www.jeansnyman.com/posts/executing-powershell-commands-in-a-nodejs-api/ https://github.com/IonicaBizau/powershell
-
Lenovo BIOS Settings https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/managing-lenovo-bios-settings-part-1 https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/managing-lenovo-bios-settings-part-2 https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/managing-lenovo-bios-settings-part-3 https://community.idera.com/database-tools/powershell/powertips/b/tips/posts/managing-lenovo-bios-settings-part-4
-
Copy file-path
scb (ls .\test.txt).FullName
scb (ls $Directory -File).FullName
scb (ls (ls $NotesPS).Directory -File).FullName
- Copy file-content
scb (cat .\test.txt)
- Open files from the same directory as a file whose path is known
nano "$((ls $NotesPS).Directory)/scripts.md"
- Edit multiple files
nano test.txt test.py test.ps1
subl test.txt test.py test.ps1
- Rename files
The$_.extension
is helpful when dealing with similar files but different encodings (eg. BMP, JPG, GIF, PNG, SVG).
$i=1; ls | forEach {ren $_.name "$i$($_.extension)"; $i++}
- Stop process
gps | where {$_.Name -match 'vlc'} | kill
- Play music as system-tray app
vlc --qt-start-minimized --play-and-exit $Music
- Change directory to that of a file whose path is known
pushd (ls $NotesPS).Directory
popd
- Save/Open Bookmarks
- Structure/Save bookmarks to folder.
eg. Lookup Youtube for videos on "Reddit API".
- Copy bookmarks folder, save to file, delete folder.
- Open files in browser
firefox (cat $myLinks -Last 10)
- Custom Web-Search cmdlets
Search-Web
$Name = $Name.ToLower().Replace(' ','+')
$Option = 0
$Google = "https://www.google.com/search?q=$Name&tbm=$Option" # Option: isch, vid, bks, shop, fin
$Youtube = "https://www.youtube.com/results?search_query=$Name"
$Twitter = "https://twitter.com/search?q=$Name"
$Wikipedia = "https://en.wikipedia.org/wiki/Special:Search?search=$Name"
$StackOverflow = "https://stackoverflow.com/search?q=$Name"
$Reddit = "https://www.reddit.com/search/?q=$Name"
Search-Specs
$Phone = "https://www.gsmarena.com/res.php3?sSearch=$Name"
$Laptop = "https://laptopmedia.com/specs/?q=$Name"
- FFMpeg: remove audio
ffmpeg -i 720p.mp4 -vcodec copy -an 720p-nosound.mp4
- FFMpeg: resize video
ffmpeg -y -i .\INPUT.mp4 -vf scale=-2:720,setsar=1:1 -c:v libx264 -c:a copy 720p.mp4
ffmpeg -y -i .\INPUT.mp4 -vf scale=-2:480,setsar=1:1 -c:v libx264 -c:a copy 480p.mp4
- FFMpeg: merge audio/video tracks
Here, the chosen audio was 1:00 min, while the video was 1:30 min. So, the audio was looped twice and the output was clipped according to the video's duration (shortest duration).
Ideally, you should use-stream_loop -1
(infinite loop) for audio & clip for video duration (so you don't need to know durations of individual audio/video), but this option is buggy right now.
If the-stream_loop -1
works, it'll be helpful for bulk merges.
# Clip AV to one which is the shortest
ffmpeg -i 720p-nosound.mp4 -i INPUT.mp3 -shortest -c copy 720p.mp4
# Loop audio twice, and clip at the shortest
ffmpeg -i .\720p-nosound.mp4 -stream_loop 2 -i INPUT.mp3 -shortest -c copy 720p.mp4
- Remove audio from video
- Download Youtube audio
- Merge AV
ffmpeg -i 720p.mp4 -vcodec copy -an 720p-nosound.mp4
youtube-dl --no-cache-dir --extract-audio --audio-format mp3 -o "INPUT.%(ext)s" <URL>
ffmpeg -i 480p-nosound.mp4 -i INPUT.mp3 -shortest -c copy 480p.mp4
- Concatenate/Copy strings to clipboard
scb (-join('$README = ',(ls README.md).FullName))
# $README = B:\CRTejaswi\Codes\MarkDown\Daily\README.md
scb (-join('$ContestCoding = ',(pwd).Path))
# $ContestCoding = B:\CRTejaswi\Codes\contest-coding
- Rename selected files
ls | where {$_.BaseName -match $REGEX} | forEach {ren $_ "$($_.Basename.replace($CHAR,''))$($_.Extension)"}
- Clear History
vim (Get-PSReadlineOption).HistorySavePath
- List all current environment variables
The
env:
drive contains this.
ls env: