"Friends, Romans, countrymen, lend me your ears!" Ok, this isn't a Shakespeare blog but PowerShell continues to be sung from the mountain tops and it's only getting louder. So much so, that I wish I had a nickel for every time I heard the phrase "you can do that easy in PowerShell."

Well, my dad used to say, "Nuthin's easy." However, with a bit of basic PowerShell under your belt, many, many things get easier (note, I didn't say 'easy' J ). By 'things' I mean A LOT of things. AD? Check. Hyper-V? Affirmative. Azure? Ci, senior. Got hotfixes? Indeed. DNS? Uh-huh. DHCP? Yep. You get the point.

So, let's cover some of the basics of PowerShell and get you some One-liners to get you rolling:

  1. The 'real-world' workflow of PowerShell is one of iteration – you will likely have to try variations/CMDlets/parameters a few (dozen? hundred?) times before you get just what you want, just how you want it. Don't be afraid of this. Very few people I know can open up a PowerShell console and bang it out right on their first try.
    1. When you DO get what you want, how you want it, you can save the code as a PowerShell script file (a TXT file with a PS1 extension) and run it over and over.
    2. At a minimum, save the code to a OneNote or something and before you know it, you'll have built up an enviable "PowerShell OneLiner Repertoire."
  2. Get your environment setup for PowerShell (and remoting). This post is going to assume you've dug into the pre-reqs, enabled WINRM, installed WMF v3 or newer, proper RSAT tools, etc. Note, Windows 8.1 needs a specific version of the RSAT tools vs Windows 8.0 (if you're running Win8.1, you can download them here - http://www.microsoft.com/en-us/download/details.aspx?id=39296). You'll need the RSAT tools to get some of the modules and CMDlets for AD, DHCP, etc. Start there, then come back
    1. Also, you can/should update the PowerShell help: Update-Help –Force
      1. This command hits the Internet, but you can use the –Path parameter and setup an internal share for your systems to go get pre-downloaded help files (here: http://www.microsoft.com/en-us/download/details.aspx?id=36475 )
  3. The Get- commandlets are very handy to return information about your system(s)
    1. I think of many of the Get- commandlets as used in One-liners as "things I always wanted to do with VBScript" but was too scriptologically challenged to achieve
  4. Once you learn how easy it is to use one Get- command (any one – pick one), it makes the next thing you want to Get- easier. Upon that base, it will make the Set-, New-, and other PowerShell CMDlets easier, too.
  5. Get- CMDlets are pretty safe to run in production because you're just querying for information – you're not setting, changing or creating anything but as with ALL code, test it out in a lab first.
  6. Warnings and reminders
    1. Code efficiently
      1. Try to remember "filter – left :: format –right"
        1. http://technet.microsoft.com/en-us/magazine/2009.09.windowspowershell.aspx
        2. For best performance, the goal should be to keep the query as narrow as possible.
          1. Asking up front for "only the red trucks with extended cab and chrome bumpers" and then outputting that to a list is more efficient than asking for "all trucks," then filtering out the "non-red" ones, then filtering out the "non-extended cab" ones, then filtering out the "non-chrome bumper" ones
        3. Use the CMDlet filters first ("filter-left"), then only use Where-Object if there are no other options (format-right)
        4. For example, don't blast AD with -Filter * -Property *
          1. This is the PowerShell equivalent of 'tell me everything you know about everything you know' and is just not a good idea.
    2. In most cases, you'll need to run PowerShell 'elevated'
    3. Be aware of 'copy - paste' problems due to fonts - I have spent a lot of time troubleshooting why a certain CMDlet or One-liner was failing before I realized the quotation marks or the dash characters were not being digested but PowerShell properly from when I pasted the text into the PowerShell console.     

Now, I present a fistful of handy PowerShell One-Liners from myself and a few PFE Brothers in Arms (Tom Moser of Ask PFE Plat fame and one Mr. Ashley McGlone, whose own blog is a PowerShell buffet: http://blogs.technet.com/b/ashleymcglone/

Take note in the code how we snuck in a variety of output switches … this is yet another helpful element of PowerShell.

Let's roll …

The server rebooted recently - who did it and when exactly?

  • Notes:
    • Event ID 1074 covers a few activities beyond reboots, such as shutdown

     

  • From the local system itself:
    • Get-EventLog -log system –newest 1000 | where-object {$_.eventid –eq '1074'} | format-table machinename, username, timegenerated –autosize

     

  • Notes
    • With Get-EventLog, I used –newest 1000 above to save the time of parsing all of the events. You may need to adjust this in your enviro.
    • Get-EventLog has been somewhat superseded by Get-WinEvent (which is faster and can use the –MaxEvent parameter to easily narrow down the results. Below, I used -MaxEvent 3 to get the 3 most-recent 1074 events.
  • Using Get-WinEvent
    • Get-WinEvent -LogName System -maxevent 3 -FilterXPath '*[System[(EventID=1074)]]' | Format-Table MachineName,UserID,TimeCreated –autosize
  • Notes:
    • Get-WinEvent returns the SID - not the actual userID - but we can use another easy One-liner to copy/paste/resolve the SID to a friendly logon name:
    • ([System.Security.Principal.SecurityIdentifier]"S-1-5-21-3056634948-2127158635-3742099687-500").Translate([System.Security.Principal.NTAccount]).value
    • If I enter that into the PowerShell console and hit <Enter>, I get this in my lab: DOMAIN\Administrator

     

  • Query a remote system:
    • Get-WinEvent -LogName System -maxevent 3 -FilterXPath '*[System[(EventID=1074)]]' -ComputerName WIN8-DOT1 | format-table machinename, userid, timecreated –autosize

 

  • Parse a list of system names:
    • Get-Content c:\serverlist.txt | ForEach-Object {Get-WinEvent -LogName System -maxevent 3 -FilterXPath '*[System[(EventID=1074)]]' –ComputerName $_} | format-table machinename, userid, timecreated –autosize

 

Here's a timely post from Ed Wilson about Get-WinEvent: http://blogs.technet.com/b/heyscriptingguy/archive/2014/06/04/data-mine-the-windows-event-log-by-using-powershell-and-xml.aspx

 

Is there an easy way to see if KB2862152 is installed?

  • From the local system itself:
    • Get-Hotfix -id kb2862152

If the patch is installed, you'll get a nice formatted output of where/what/who/when:

Source Description HotFixID InstalledBy InstalledOn

------ ----------- -------- ----------- -----------

DC01 Security Update KB2862152 DC01\User-01      4/22/2014 12:00:00 AM

If the patch isn't installed, you'll get an error stating so:

Get-Hotfix : Cannot find the requested hotfix on the 'WS2012r2-dc01' computer. Verify the input and run the command again.

 

  • Query a remote system:
    • Get-Hotfix –id kb2862152 –computername WS2008R2-DC01

 

  • Parse a handful of system names:
    • Get-Hotfix –id kb2862152 -computername WS2012R2-DC01,WIN8-DOT1| Out-Gridview –Title "KB2862152 Status"

     

I need to backup all of the GPOs in the domain every day

  • Create a Scheduled Task in each domain that runs the following:
    • Backup-GPO –all –path \\AdminServer\GPO-Backups

 

What are the IP settings on my system(s)?

  • From the local system itself
    • Get-WMIobject win32_networkadapterconfiguration | where {$_.IPEnabled -eq "True"} | Select-Object pscomputername,ipaddress,defaultipgateway,ipsubnet,dnsserversearchorder,winsprimaryserver | format-Table -Auto
  • Query a remote system
    • Get-WMIobject –computername WS2008-DC01 win32_networkadapterconfiguration | where {$_.IPEnabled -eq "True"}| Select-Object pscomputername,ipaddress,defaultipgateway,ipsubnet,dnsserversearchorder,winsprimaryserver | format-Table –Auto
  • Parse a list of system names and use Get-CIMInstance - a newer CMDlet and faster than Get-WMIObject
    • Get-CIMInstance Win32_NetworkAdapterConfiguration -Filter 'IPEnabled = true' -ComputerName (Get-Content C:\SERVERLIST.TXT) | Select-Object pscomputername,ipaddress,defaultipgateway,ipsubnet,dnsserversearchorder,winsprimaryserver | Format-Table -AutoSize | out-file c:\IPSettings.txt

 

What are the BIOS versions on my systems?

  • From the local system itself:
    • Get-WMIobject win32_bios | Select-Object pscomputername,name
  • Query a remote system
    • Get-WMIobject -computername WS2008R2-DC01 win32_bios| Select-Object pscomputername,name
  • Parse a list of system names
    • Get-Content c:\serverlist.txt | Foreach-Object {Get-WMIobject -computername $_ win32_bios}| Out-Gridview
    • Or another way…
    • Get-WMIobject -computername (Get-Content c:\serverlist.txt) win32_bios | Select-Object pscomputername,name| out-file c:\BIOSversions.txt

A few more …

  • Are all of my DCs GCs?
    • Get-AdDomainController -Filter * | Select hostname,isglobalcatalog | Format-table -auto
  • Which accounts in my domain are enabled and set to never expire the password?
    • Search-ADAccount -PasswordNeverExpires | Select-Object Name, Enabled | convertto-html > c:\pwdneverexpire.html
  • How can I parse an input file of some AD attribute for users (SAM Account name in this case) and map those entries to another attribute for those users (the DN in this case)?
    • Get-Content C:\userlist.csv | foreach {Get-ADuser $_ | select distinguishedname,samaccountname} | export-csv –path c:\newuserlist.csv
  • What is the OS version and Service Pack level for all of my Windows systems in a certain OU?
    • Get-ADComputer -SearchScope Subtree -SearchBase "OU=PCs,DC=DOMAIN,DC=LAB" –Filter {OperatingSystem -Like "Windows*"} -Property * | Format-Table Name, OperatingSystem, OperatingSystemServicePack
  • Stop and/or Start all of your lab VMs
    • Get-VM | Stop-VM
    • Get-VM | Start-VM

At this point, you should have noticed some patterns to those One-liners (and to the PowerShell syntax in general). That is one of the key elements that makes PowerShell easier. If you get a handle on how to get event log info out to a CSV file, it isn't much different to get hotfixes, or AD user attributes.

If you have yet to get going with PowerShell, now is as good of a time as any – take 15 minutes each day over the next week (first thing in the morning or after lunch are often good times) and work through these examples. If these one-liners didn't pique your interest, make a list of 5 things you think would be easier with automation and figure out how to do them in PowerShell. Ping us in the comments if you need some help.

If you're still feeling a bit timid, hit up your Technical Account Manager to bring in a PFE for a PowerShell Workshop and we'll get your whole team up to scratch in no time. In the meantime, you can get two days of free PowerShell training at Microsoft Virtual Academy:

 

Lastly, here's a great reference for PowerShell to wander through and a search-results link for some of our prior AskPFEPlat PowerShell goodness:

Cheers!