Weekend Scripter: Use PowerShell to Clean Out Temp Folders

Weekend Scripter: Use PowerShell to Clean Out Temp Folders

  • Comments 10
  • Likes

Summary: Guest blogger, Bob Stevens, talks about using Windows PowerShell to clean out temporary folders on desktops following a malware infection.

Microsoft Scripting Guy, Ed Wilson, is here. Today, we welcome back our newest guest blogger, Bob Stevens. Yesterday Bob wrote about a quick script that he developed to pick out comments from a Windows PowerShell script: Weekend Scripter: Pick Comments from a PowerShell Script.

I made Bob’s virtual acquaintance recently when I did a Live Meeting presentation to the Twin Cities PowerShell User Group.

Here is Bob’s contact information:

Blog: Help! I’m Stuck In My Powershell!
Twitter: @B_stevens6
LinkedIn: Robert Stevens

Take it away, Bob…

For a local service desk systems analyst, nothing is more frustrating than malware. Not only is it a time sink—it also has the indented potential to cause irreparable damage. No network that connects to the Internet is immune to it.

Most organizations have their own standard operating procedures regarding malware removal. Even so, individuals technician have their special tweaks and tricks to increase the likelihood of success. I like to target the malware where it resides: Temp Folders. And after cleaning and clearing a number of workstations, it occurred to me that I could use a Windows PowerShell script to do just that, saving myself five minutes of hoping that the computer will let me open a folder.

I started by creating a list of the locations that temporary files are automatically placed by the Windows XP operating system (starting with Windows Vista, they are in the C:\Users folder):

  • C:\Windows\Temp
  • C:\Windows\Prefetch
  • C:\Documents and Settings\*\Local Settings\Temp
  • C:\Users\*\Appdata\Local\Temp

Now that I have defined our locations, I need to define what I want to do. For this, I create a flowchart:

Image of flowchart

I start with the Set-Location command and define the location as “C:\Windows\Temp”:

            Set-Location “C:\Windows\Temp”

Now that I am located in the Windows temp folder, I need to delete the files. This can be done with the old DOS command Del, but I prefer using the Windows Powershell cmdlet Remove-Item to standardize the script. The items need to be removed indiscriminately, so I use a wildcard character. A wildcard character is a special character that represents one or more other characters. The question mark (?) wildcard stands for one character and the asterisk (*) wildcard stands for any number of characters. Because I do not want to discriminate between different files, I use the asterisk.

Remove-Item *

Next I tell the Remove-Item cmdlet to also remove all files in subdirectories with the -recurse switch:

Remove-Item * -recurse

And I tell it to select hidden files with the -force switch:

Remove-Item * -recurse -force

Together the two lines looked like this:

Set-Location “C:\Windows\Temp”
Remove-Item * -recurse -force

I do the same for the rest of the folders and the complete script begins to take shape:

Set-Location “C:\Windows\Temp”
Remove-Item * -recurse -force

Set-Location “C:\Windows\Prefetch”
Remove-Item * -recurse -force

Set-Location “C:\Documents and Settings”
Remove-Item “.\*\Local Settings\temp\*” -recurse -force

Set-Location “C:\Users”
Remove-Item “.\*\Appdata\Local\Temp\*” -recurse -force

Wait. Why is there an asterisk in the middle of the last path? You can use wildcard characters to do this:

Remove-Item “.\*\Appdata\Local\Temp\*” -recurse -force

This says, “Look in all folders in this directory with the path structure that matches this.” In my case, this is all of the user profile Local Settings\temp folders.

But this looks very busy, so at Ed Wilson’s suggestion, an array would prevent all the unnecessary jumping around with the Set-Location command. So we change our flowchart to look something like this:

Image of flowchart

Arrays are a nifty programming feature that groups a number of strings together into one variable, while remaining individual strings. They are defined much like a normal variable—they start with the variable ($) indicator followed by the array name:

$tempfolders

Just like a variable, I use the equal sign (=) to define it.

$tempfolders =

Here is where the arrays and variables differ when defining. I start with the array indicator (@):

$tempfolders = @

And I follow it with parentheses to group strings together:

$tempfolders = @()

What you put inside the parentheses is your choice. For my purposes, I fill it with temp folder paths:

$tempfolders = @( "C:\Windows\Temp\*", "C:\Windows\Prefetch\*", "C:\Documents and Settings\*\Local Settings\temp\*", "C:\Users\*\Appdata\Local\Temp\*" )

Notice that each string is neatly encapsulated by double quotation marks (“ ”) and separated by a comma and a space (, ). The quotation marks are necessary for any string with a space in it, and the comma with a space separates the values. Both are essential to define an array. Additionally you can see that each string ends with a wildcard character. This is going to remove the necessity for me to define exactly what to remove in the next line.

Now I use the Remove-Item cmdlet again; but this time for the -path operator, I use the $tempfolders array variable:

Remove-Item $tempfolders -force -recurse

This line instructs Windows Powershell to do exactly the same as previously, but for every item in the array.

Side-by-side, here are the two versions of the script:

1 Set-Location “C:\Windows\Temp”

2 Remove-Item * -recurse -force

3 Set-Location

4 “C:\Windows\Prefetch”

5 Remove-Item * -recurse -force

6 Set-Location “C:\Documents and Settings”

7 Remove-Item “.\*\Local

8 Settings\temp\*” -recurse -force

9 Set-Location “C:\Users”

10 Remove-Item “.\*\Appdata\Local\Temp\*” -recurse -force

 

1 $tempfolders = @("C:\Windows\Temp\*", "C:\Windows\Prefetch\*", "C:\Documents and Settings\*\Local Settings\temp\*", "C:\Users\*\Appdata\Local\Temp\*")

2 Remove-Item $tempfolders -force -recurse

 

With two lines of code, I was able to save myself between three minutes and 30 minutes of work. This is the purpose of scripting at its finest: automate repetitive tasks to allow the technician to do more in-depth work. Thank you all for reading, and as always, let me know if you have developed a better way!

~Bob

Bob, thanks again for a real world example and a great suggestion. Join us tomorrow for a blog post by Boe Prox about installing WSUS on Windows Server 2012. It is a great blog and I am sure you will enjoy it.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Hi Ed,

    In the above script, Remove-Item * -force will also work in the same way as Remove-Item * -recurse -force. Any reason why you used recurse here????

    Chaitanya.

  • Bob

    Nicely done!  Automation is a breeze with just a little Powershell.

    Coolest thing is if you had to TEST this and you had no test environment?   You can add a -whatif to your Remove-Item to show you what it is about to do without ACTUALLY doing it :)

  • Think you have a typo.

    Shouldn't "-temp" be "-force" ?

  • Hi Ed,

    I'm wondering, what if we had different OSes (ex. XP, Vista\7) in organization and we want to clean "TEMP's" on all client systems ? It will be right to use Test-Path before any Set-Location and then Remove-Item, something like this:

    $tempfolders = @('..','..')

    foreach($t in $tempfolders) {

     if(Test-Path $t)

     {

       set-location ......

       ....

     }

     else

     {

       Write-Host "There  is no: "$t

     }

    }

    Kamil

  • Sorry, I've just got it :)

    $tempfolders = @( "C:\Windows\Temp\*", "C:\Windows\Prefetch\*", "C:\Documents and Settings\*\Local Settings\temp\*", "C:\Users\*\Appdata\Local\Temp\*" )

    $tempfolders = @( "C:\Windows\Temp\*", "C:\Windows\Prefetch\*", $env:Temp) -> i think it will be better :) and "Test-Path" is not necessary.

    Kamil

  • @kt

    That won't work because there is no mapping from "C:\Users\*\Appdata\Local\Temp\*"   to $env:temp.

    $env:temp only works for the admin account and you need to purge ALL temp folders when cleaning up from malware.

  • Jk,

    Your absolutly right!

    That should be -force.

    I cant believe I missed it.

    -Bob Stevens

  • This is great!  I work as an on-site tech (2nd level) and have a HARD time finding PS tools/scripts/etc. that folks like us can use to work with end-users.  I work in a global enterprise and we don't have domain admin rights; we've got some admin rights through a custom securtity group.  This means that we don't have access to to servers other than to read the info - and that's only on some of the servers.

    I look forward to more PS that can help those of us who work with end-users day-in and day-out.

  • Sean,

    I did use the -Whatif parameter while writing the code, but I tested it in a safe enviorment first.  It's my standing policy to be carefull when working with the Remove-Item command.

    Sean Kearney 14 Apr 2013 11:08 AM

    Bob

    Nicely done!  Automation is a breeze with just a little Powershell.

    Coolest thing is if you had to TEST this and you had no test environment?   You can add a -whatif to your Remove-Item to show you what it is about to do without ACTUALLY doing it :)

  • i am trying to run this script and i get permission error saying it is in use by another person or process