This page is my one-stop-shop for all sorts of PowerShell-related, tips, tricks, hacks, suggestions, and other bits of wisdom I've gleaned over the last 15 years. These are not intended to carry biblical weight, but many are now part of accepted PowerShell community standards. I encourage you to try things out for yourself and see if they make sense to you. Feel free to ping me on Twitter if you have questions or comments about anything on this page.
This page is divided into sections. PowerShell Tweet Tips is a collection of short tips I occasionally post on my social media channels. The PowerShell Scripting and Toolmaking section contains a list of recommendations and advice. Many of these come from my classes and conference presentations. Most of these suggestions are targeted at PowerShell beginners. As your PowerShell experience grows you may find the need to bend some of the suggestions.
Finally, PowerShell One-Liners is a collection of what I hope are useful one-line PowerShell commands. These are the types of expressions that are often the seeds of functions and scripts. They can also demonstrate PowerShell concepts and techniques. You can find additional code snippets at https://gist.github.com/jdhitsolutions.
I intend to update this page periodically so I hope you will bookmark this and check back frequently. I will try to mention something on Twitter when I make major changes to the content.
If you are new to PowerShell, I encourage you to also take a look at my PowerShell Essentials page.
PowerShell Tweet Tips
- If you can't run PowerShell effectively in the console, you'll never be able to write an effective script.
- Always be testing the latest version of PowerShell. It will eventually be a part of your day-to-day work.
- The PowerShell ISE and VS Code are for development. Run commands and scripts you need for your job in a PowerShell console.
- Using PowerShell interactively at the console to do your job and writing PowerShell scripts and tools are separate tasks each with its own set of best practices and recommendations.
- Take advantage of Tee-Object. This will allow you to see the results of your command and save them to a variable: get-process | tee -Variable p
- Consider Get-WmiObject deprecated. Learn to use the CIM cmdlets like Get-CimInstance.
- Run Update-Help once a month. Better yet, learn how to set it up as a scheduled job in Windows PowerShell.
- Use Invoke-Item or its alias ii, to open a folder in Windows Explorer: ii c:\windows
- Expose yourself to PowerShell every day. Even if you do nothing but closely read full help and examples for a few cmdlets or an about topic.
- Those who fail to automate are doomed to repeat their work.
- Don't forget to look through the PowerShell about topics for help.
- If you don't do something with PowerShell every day, you'll never really learn it.
- Enabling PowerShell Remoting is the easy first step. You still need to do your job and properly secure it.
- View the content of any loaded function: (get-item function:prompt).scriptblock Or get-content function:prompt
- The forums at PowerShell.org are your best option for accurate and timely help and answers.
- Open the current directory in VSCode. Great when working on a PowerShell module: code .
- Get in the habit of using -full when looking at cmdlet help. You could even add a PSDefaultParameterValue.
- Take advantage of the Is* variables in your PowerShell scripts like $IsLinux and $IsWindows.
- Is your expression not working the way you expect? Learn how to use Trace-Command.
- Do you miss being able to run the PowerShell ISE from a prompt in PowerShell 7 on a Windows platform? All you need to do is define the missing alias in your PowerShell Core profile script: Set-Alias -name ise -value powershell_ise.exe
- Are you stuck using the PowerShell ISE but want to code with PowerShell 7? Start a remoting session in the ISE. The ISE will then detect and use PowerShell 7 for Intellisense : Enter-PSSession -ComputerName localhost -ConfigurationName powershell.7
- Having trouble installing for finding things from the PowerShell Gallery or GitHub? Add this line to your PowerShell profile script: [Net.ServicePointManager]::SecurityProtocol=[Net.SecurityProtocolType]::Tls12
- Once you understand the object-nature of PowerShell, you can do a lot with object notation. This is a one-line command using the gcim alias of Get-CimInstance:
(gcim win32_operatingsystem).LastBootUpTime.Date.DayofWeek
PowerShell Scripting and ToolMaking
- Know who will use the tool and how they will use it. What will be their expectation?
- Write one type of object to the pipeline.
- Use full cmdlet and parameter names in your scripts. No aliases.
- Be flexible and modular. Always think about re-use.
- Don't hard code yourself into a corner. Aim for flexibility.
- Documentation is critical and not just internal comments.
- Use the Verb-Noun naming convention for your function and commonly accepted parameter names. Don't re-invent the wheel.
- Use meaningful variable names that don't use Hungarian notation. $strComputername is bad. $Computername is good.
- Standardize script layout with templates and snippets. Especially important in team environments.
- White space and formatting is your friend. VSCode can format your scripts for you. Use it.
- Write your code for the next person. It could be you.
- Include Write-Verbose messages from the beginning. They will help you develop your code.
- Learn how to use Write-Progress in place of Write-Host to provide execution details.
- Avoid using the value localhost as a default parameter value. Use $env:computername which will always resolve to a "real" name. If you need to script cross-platform you can use [environment]::machinename.
- Just because you can use a long, one-line pipelined expression doesn't mean you should.
- Separate the data you need to run your code from the code itself.
- Avoid using .NET code when a cmdlet will work.
- Recognize that sometimes PowerShell is not the right solution or tool for the task at hand.
- Test your code in a PowerShell session with no profile. Even better, test in a virtual machine of the Windows Sandbox to avoid unintended dependencies.
- Understand the PowerShell paradigm. Don't write a VBScript using PowerShell commands and think you're done.
- If you are creating a graphical PowerShell tool, start with a console-based script or function that already works.
- Your first step in creating a new script or function is to read help and examples. Not Google or Bing.
- Leverage splatting to simplify your code.
- Think about how your code will scale. Don't write a function that only works with one remote computer. How would you write it to work with 10 or 100 or 1000? Think "managing at scale".
- If you need credentials in your script or function use a PSCredential type parameter. Never a username and plain text password.
- Learn how to use the Platyps module to create help documentation for commands in your PowerShell module.
PowerShell One-Liners
These one-line commands are intended to be used in a PowerShell session. They are written so that you can get maximum benefit, often with minimum typing and without having to write a script. Because these are intended for use at the command prompt aliases are allowed and encouraged. I'll assume you can figure out the alias if you don't recognize it.
As written, many of them should not be copied and pasted into a script without reworking. Note that some of these expressions will work on Windows PowerShell and PowerShell 7 or require a Windows platform. You'll have to try them out for yourself and adjust as necessary. You'll need to add things like parameters and error handling. It may also be easier to break some of these into several steps when used in a script.
- Get the scriptblock content of a loaded function. Substitute the name of a function.
(get-item Function:\prompt).scriptblock
- Copy a function to a remote computer using a PSSession.
$f = $(get-item function:\Get-Foo).scriptblock
Invoke-Command { New-Item -Name Get-Foo -Path Function: -Value $($using:f)} -session $s
- Get running scheduled tasks on a Windows system.
(get-scheduledtask).where({$_.state -eq 'running'})
- Get system uptime from multiple computers where $computers is an array of computer names running PowerShell v3 or later.
Get-CimInstance Win32_operatingsystem -ComputerName $computers |
Select-Object PSComputername,LastBootUpTime,
@{Name="Uptime";Expression = {(Get-Date) - $_.LastBootUptime}}
- Another way to get drive utilization using PSDrives.
Get-PSDrive -PSProvider filesystem | where-object {$_.used -gt 0} |
select-Object -property Root,@{name="SizeGB";expression={($_.used+$_.free)/1GB -as [int]}},
@{name="UsedGB";expression={($_.used/1GB) -as [int]}},
@{name="FreeGB";expression={($_.free/1GB) -as [int]}},
@{name="PctFree";expression={[math]::round(($_.free/($_.used+$_.free))*100,2)}}
- List installed applications and a few details. But use with caution. It is slow, not necessarily complete, and could have unexpected consequences. Here's a good link about using this class and alternatives.
gcim win32_product -computername $env:computername |
Sort-Object -property Vendor,Name | Select-Object -property Vendor,Name,
@{Name="Installed";Expression = {($_.InstallDate.Insert(4,"-").insert(7,"-") -as [datetime]).ToShortDateString()}},
InstallLocation,InstallSource,PackageName,Version
- Get details about all external scripts in your %PATH%.
gcm -commandtype externalscript | Get-Item |
Select-Object Directory,Name,Length,CreationTime,LastwriteTime,
@{name="Signature";Expression={(Get-AuthenticodeSignature $_.fullname).Status }}
- Get folder utilization for a given directory.
dir -path C:\Scripts -file -recurse -force |
measure-object length -sum -max -average |
Select-Object @{name="Total Files";Expression={$_.count}},
@{name="Largest File(MB)";Expression={"{0:F2}" -f ($_.maximum/1MB)}},
@{name="Average Size(MB)";Expression={"{0:F2}" -f ($_.average/1MB)}},
@{name="Total Size(MB)";Expression={"{0:F2}" -f ($_.sum/1MB)}}
- Get event log utilization for remote computers defined in $computers. The remote computers must be running PowerShell v3 or later.
gcim Win32_NTEventLogFile -computer $computers -filter "NumberOfRecords > 0" |
Select-Object @{Name="Computername";Expression={$_.CSName}},
LogFileName,
NumberOfRecords,
@{Name="Size(KB)";Expression={$_.FileSize/1kb}},
@{Name="MaxSize(KB)";Expression={($_.MaxFileSize/1KB) -as [int]}},
@{name="PercentUsed";Expression={[math]::round(($_.filesize/$_.maxFileSize)*100,2)}} |
Sort Computername,PercentUsed |
Format-Table -GroupBy Computername -property LogFileName,NumberOfRecords,*Size*,PercentUsed
- Get free space for drive C on the local computer formatted in GB
(gcim win32_logicaldisk -filter "deviceid = 'C:'").FreeSpace/1gb
#or use the PSDrive
(gdr c).Free/1gb
- Get a date string in the format year-month-day-hour-min-second. The abbreviations in the format string are case-sensitive.
get-date -format yyyyMMddhhmmss
- Get the last time your computer booted. Can be modified to query remote computers.
(gcim win32_operatingsystem).LastBootUpTime
#or modify to get uptime
(get-date) - ((gcim win32_operatingsystem).LastBootUpTime)
- Get configured TrustedHosts.
(get-wsmaninstance wsman/config/client).trustedhosts
- Get all drives identified by a standard drive letter. I'm suppressing errors to ignore non-existent drive letters.
get-volume -driveletter (97..122) -ErrorAction SilentlyContinue
- Get total physical memory formatted as GB.
gcim win32_computersystem -computer SRV1,SRV2 | Select PSComputername,@{Name="Memory";Expression={$_.TotalPhysicalMemory/1GB -as [int]}}
- Get IPv4 addresses on your local adapters.
Get-NetIPAddress -AddressFamily IPv4 | where-object IPAddress -notmatch "^(169)|(127)" | Sort-Object IPAddress | select IPaddress,Interface*
- Find all processes that use a given module (dll). You can filter by the dll name or use part of a path.
get-process | Where { $_.Modules.filename -match "netapi32.dll"}
- Since PowerShell Core and PowerShell 7 do not include the Get-Eventlog cmdlet, here's a one-liner to list the last 10 errors in the System event log. A level value of 3 will give you warnings.
get-winevent -FilterHashtable @{Logname = 'System';Level=2} -MaxEvents 10 | sort-Object ProviderName,TimeCreated
- List all PowerShell profile script settings. You will see different values for different hosts, such as the PowerShell ISE, as well as between Windows PowerShell and PowerShell 7.
$profile | select *host* | format-list
- Show what PowerShell profile scripts exist.
$profile.psobject.properties).where({$_.name -ne 'length'}).where({Test-Path $_.value }) | Select-Object Name,Value
- Get the current date and time formatted as UTC time.
(get-date).ToUniversalTime()
#or pretty it up
"$((get-date).ToUniversalTime()) UTC"
"$((Get-Date).ToUniversalTime().tolongdatestring()) UTC"
- Get a formatted report of all commands with a synopsis.
(Get-Command).where({ $_.source }) | Sort-Object Source, CommandType, Name | Format-Table -GroupBy Source -Property CommandType, Name, @{Name = "Synopsis"; Expression = {(Get-Help $_.name).Synopsis}}
- How long has your PowerShell session been running?
(Get-Date) - (get-process -id $pid).starttime
Last updated 2021-04-01 16:40:11Z