I’ve been using PowerShell for a while now and in that time I’ve come up with a few tips and tricks that I find myself using a lot. Below you’ll find a handful of commands I find myself using most often:
1) Run a command with elevated permissions
Ever needed to run a command from PowerShell as an administrator? Of course you have. Here is a neat trick that makes the process of process elevation easy. I use this line below as a shortcut on my desktop to edit my local hosts file.
Start-Process notepad.exe-ArgumentList c:\windows\system32\drivers\etc\hosts-Verb RunAs
2) URI Validation
When you’re working on a script, you often need to validate if an input path is well formed. This can be in the format of a webpage, an FTP site or even a path on the local file system (provided it’s in the format of file://). Here is an easy way to validate if that URL is in fact correctly formed. This is also an example of being able to call .NET classes directly (in this case the system.uri class)
$URL="http://www.google.com" if ([system.uri]::IsWellFormedUriString($URL,[System.UriKind]::Absolute)) { "Yes" } else { "No" }
3) Rapid Creation of Custom Objects
There are countless situations in Powershell where you need to create a custom object. Perhaps you want to combine data from multiple commands into a single object for later output. There are countless blog posts on custom objects but I’ve always found myself looking for a one liner to do so and I eventually managed to create one myself. It’s not perfect but during the prototyping and data collection phase, it’s a miracle worker. Basically all you need to do is create a array at the top of your script that will contain whatever it is you want. Then paste in the function below. Now whenever you want to add a new row to an object, simply call the function and pass in the parameters! I use this as a simplistic but surprising effective logging mechanism where inside my loops I can output the results for each processed row into a log file containing whatever I want!
$myobj = @() FunctionAddToObject{ $script:myObj+=New-Object PSObject -Property @{ EntryDate =$args[0]; ProcessName =$args[1]; ServiceName =$args[2]; } } AddToObject "A" "B" "C"
4) Output directly to the clipboard
This one really should be number 1. I use this trick constantly! When you’re working with data you often want to further manipulate it in something like Excel. For the longest time, the only way I knew to do that was to output my results to a file and then open up the file in Excel. When you iterate and need to do this 20 or 30 times, it gets annoying very quickly. I then discovered that you can pipe the output of your results directly to the clipboard by piping to the standalone windows executable “clip.exe”. That technically isn’t a PowerShell command but it still gets the job done. The only problem with this approach is that it’ll output all of the text with a fixed number of characters, padding the unused ones with spaces. This makes it difficult to work with in something like Excel. To get rid of those extra spaces, I found the easiest thing to do is just convert the results to CSV first. Magical!
Get-Service | select name | ConvertTo-Csv-NoTypeInformation | clip.exe
5) Return only string that contain x number of characters
Imagine a situation where you need to grab all of the users in Active Directory that match the format of “FirstName LastName” but you explicitly want to exclude those that are “Firstname LastName Initital” How would you do that? Well one way is to only include those entries that contain a single space. But how can you do that? Regex to the rescue! This command is only scratching the surface of what Regex can do of course and I’m excited to see what else I can come up with.
Get-Service | Where { [regex]::matches($_.DisplayName,"").count -eq 1 }
6) Use PowerShell arrays to rapidly iterate through data
Another simple one I use all the time. Let’s say your working on a problem and that generates a list of data. It could be users or computer names or folders or anything like that. You then want to perform some operation against all of those objects. How can you do that? The traditional way is to save them into a CSV and then import them but that’s a pain in the butt. If I’m prototyping I’d rather just paste them directly into the file so I can tweak them inline. To do that, create a PowerShell Array. You can then do whatever you want with it as it is now a PowerShell object! You can even grab individual index items if you want using the [ ] notation as shown below.
$List= @( "Bob Smith" "Joe Jackson" "Billy Jay" ) ForEach($Item in $List) { Write-Output $Item } $List[0]
7) Measure how long a command took to run – after it finished
This one is cool. PowerShell includes a command called “Measure-Command” that can be used to time how long a command takes to complete. But to use it you have to wrap your command in it and even worse, you don’t get to see the output. Thankfully it turns out that behind the scenes, PowerShell automatically measures the execution time of every command! Therefore, let’s say you just ran a command and you want to know how long it took, you can simply do this:
(Get-History)[-1].EndExecutionTime - (Get-History)[-1].StartExecutionTime | select TotalSeconds
8) Remove the column header from PowerShell output
Sometimes when I’m moving data into Excel for processing, I don’t want the column header in the output each time. It turns out there is an easy way to get rid of it and that is to use the skip parameter in the select cmdlet to simply not include the first line (aka the column header)
Get-Service | select name, DisplayName | ConvertTo-Csv -NoTypeInformation | select-Skip 1 | clip.exe
9) Figure out what properties are available for a command
When you run a command and it spits out some output, that output is almost never all of the information that command has about the object. If you want to see everything that the command has to give you, run this command where gm is an alias for “Get-Member”:
Get-Service | gm -MemberType "Property"
10) Left justify output from the Select command
This one is just a personal annoyance. When you display data to the screen using Select-Object, it always right justifies. That annoys me to no end. The best way I’ve found to “correct” this is to then pipe that output to the Format-Table command with the Autosize parameter. Your output is now left justified.
Get-Process | select WorkingSet -First10 | ft -AutoSize
11) Bonus: Rename columns, perform some math and round the results
You’ll inevitably find a need where you want to change the name of a column output. You can override the default names by providing your own hash table with the existing and the new name using the “name/expression” hash pair. You can then use “accelerators” to perform rounding and conversion math as shown below
Get-Process | select @{Name=“Used (MB)“; Expression={[decimal]::Round($_.WorkingSet/1MB)}} -First 10 | ft –AutoSize