Click an Ad

If you find this blog helpful, please support me by clicking an ad!

Thursday, May 3, 2012

Powershell Task Automation

Powershell Task Automation

So, after my Powershell abilities progressed a bit, I had an epiphany. Holy Cow! Think of all of the things I'm doing manually that I could automate!!!

First, I went and installed Quest's PowerGUI application from This is a GUI and script editor for Powershell that I find very helpful. They have a ton of other add-ons available for it, but I haven't delved to deeply into all of that yet.

Then, I looked through my IT team's helpdesk logs for common problems we having. We have a couple of problematic applications in use here, and I noticed we had many instances where we had to kill process for our users. Normally, this process required us to remote control the user's computer, open task manager, and kill the application. There's some stumbling blocks here, too. Sometimes Windows will report back in a few seconds that the application is not responding. So then you have to click on the "End Task" button. And again, sometimes this will pause for a couple of seconds. Once in a while Windows isn't very responsive and sort of sputters along, so that can increase the time that it takes to resolve the issue. Also, it's kind of tedious. I'm going to post the whole script, and use the Powershell-style comments to describe what it is I'm doing.

Filename: killprocess.ps1
Author: Charles Stemaly

$cpname = read-host "Enter the computer name"
#Prompt the user for the host name of target computer
do {
#Here, I have started a 'Do' loop. This block of code will execute until some condition is met.
$procname = read-host "Enter the process name (i.e. notepad.exe)"
#Prompt the user for the name of the process to kill
get-wmiobject -computername $cpname win32_process|where-object {$_.processname -eq "$procname"}| foreach-object {$_.terminate()}
#Here I'm interacting with WMI on the target computer: Get the running process, then pare down #the list for only the exe that I specified in the $procname variable, then use the terminate method #to kill that process. Note that this would kill multiple instances of the program.
$answer = read-host "Press 1 to kill another process, or q to quit"
#Prompt the user to do another or to quit the script. This variable sets the condition of the 'Do' #loop.
#This marks the end of the 'Do' block of code
while ($answer -eq 1)
# This is what looks at the condition of the 'Do' block and decides whether to run the loop again or #exit.

Using this script, we cut the response time on these calls down dramatically. We no longer need to fumble through the GUI, waiting for Windows to behave itself. WMI terminates the offending process almost instantly. As an added bonus to the faster resolution time, you look like a fricking magician to the end user.

The next type of support call I decided to craft an automated solution for was the Windows password reset.

Filename: ResetPassword.ps1
Author: Charles Stemaly

$UsernameToReset = Read-Host "Username"
# Prompt the user for the username that needs to be reset
$UserQuery = (Get-QADUser $UsernameToReset)
#construct the first part of the command; this makes for easier reading later.
If ($UserQuery.AccountIsLockedOut -eq $true){
#This portion detects whether the account is locked out or not.
    Unlock-ADAccount $UsernameToReset
#If the account is locked out, this command unlocks it.
    Write-Host -ForegroundColor Yellow "Account unlocked for $UsernameToReset"
#This writes to the screen telling me that the account was unlocked.
#This marks the end of the 'If' block of code.
Set-QADUser $UsernameToReset -UserPassword "password"
#This line resets the user's password to "password". Obviously, I use something different in my #duties :)
Write-Host -ForegroundColor Yellow "Password was reset for $UsernameToReset to password"
#This line writes to the screen telling me that the password has been reset.

While I love the Active Directory Users and Computers snap-in for the Microsoft Management Console (don't we all?), it's just a lot faster to open Powershell, and type a couple of lines. I should point out here that the code above requires that the Quest ActiveRoles commandlets snap-in is installed and loaded by Powershell. Also, you obviously need the correct permissions in Active Directory to be resetting passwords.

While I won't get into the individual scripts themselves, I also have automated the following situations:
  • Creating, disabling, and deleting users
  • Finding the answer to "Who printed this?" calls
  • Resetting the print spooler on our print server when a print job gets irrevocably stuck
  • Rebooting a remote computer from WMI
  • Finding out which Terminal Server in our farm a particular user is logged in to
  • Notify users via email when their password is expiring within 7 days. We find that Windows 7 tends to bury this notification in the system tray.
Tomorrow, I will lay out how Powershell is handling automated reporting about our environment.


  1. Would love to know how you locate a user in the terminal server farm!

  2. It's a doozy of a script with lots of customization built in for the environment. But since you asked nicely, I'll make it my next post, and I may even get to it tonight. :)

  3. After stripping out all of the other customization stuff (I had multiple Terminal Server farms) it all boils down to this (I think, I don't have terminal servers anymore to test it on):

    Write-Host -ForegroundColor Yellow "Enter the terminal server's hostname"
    $TerminalServerName = read-host
    $TSSessions = (Get-TSSession -ComputerName $TerminalServerName | where {$_.clientipaddress -ne $null})