Hey, Scripting Guy! Question

Hey, Scripting Guy! It seems that every single piece of software I install adds a stub application that starts automatically. I know software makers do not do it out of maliciousness, but good grief these people act as if theirs is the most important software on my computer. In the old days, it was pretty easy. I’d go to the Startup folder and delete their icon. Now they start hiding their stuff in 25 different places in the registry. When people started finding their software in those locations, these software makers began masquerading as services with obscure names. It is enough to make a person remove patches of their own hair. Can you provide a low-stress, low-hair-loss way of controlling these offending applications?

- JB

SpacerHey, Scripting Guy! Answer

Hi JB,

I can definitely sympathize with follicly challenged individuals, and do not wish to do anything that would cause you to remove more of the precious stuff. If you take a look at the script below, you will see that we read a text file that has a list of processes we wish to kill. We total the memory being consumed by the processes and ask if you, the user, wish to terminate them. For a similar VBScript, you can refer to this Dr. Scripto article. For more information about WMI, you may want to look at the WMI Secrets page or check out the Microsoft Press book, Microsoft Windows Scripting with WMI: Self-Paced Learning Guide. Here's the script:

$mem = 0
$procFile = "c:\FSO\annoyingProcesses.txt" 
Get-process -name (Get-Content $procFile) -ErrorAction continue |
Foreach-Object { $mem += $_.WorkingSet }
"{0:N2}"-f ($mem/1MB) +" meg of ram is being consumed by $procFile Processes" 
$rtnPrompt = Read-Host -Prompt `
  " 
   would like to kill $procfile processes? 
   <y / n>
  "
switch($rtnPrompt) 
{
 "y"     { 
          Write-Host -BackgroundColor green "$procfile processes will be killed..." 
          stop-process -name $(Get-Content $procFile) -ErrorAction continue 
         }
 "n"     { 
          Write-Host -BackgroundColor yellow "$procfile processes will not be killed" 
         }
 default { 
           Write-Host -BackgroundColor red "Response y or n expected. exiting..." ;
           exit
         }
} #end switch

The script uses a text file for input. Working with text files in VBScript is covered here. The first thing it does is initialize two variables. The first variable, $mem, is used to hold the amount of memory that will be saved by deleting the processes. The second variable, $procFile, is used to hold the path to the text file with the processes to kill:

$mem = 0
$procFile = "c:\FSO\annoyingProcesses.txt"

The text file is simply a list of process names:

Image of the list of process names in a text file

 

Next it is time to read the text file and retrieve the process information for each of the processes. This can be done on a single line. The trick is that the Get-Process cmdlet will accept an array of process names for the –name parameter. To provide this array of process names, we use the Get-Content cmdlet and have it read the content from the file. Because we have the Get-Content cmdlet in parentheses, this forces it to be read first. The –ErrorAction continue is the same as placing On Error Resume Next in a script. It causes error messages to be ignored. After we have the process information for each of the processes, we pipeline the results to the next command. This line of code is seen here:

Get-Process -name (Get-Content $procFile) -ErrorAction continue |

Because we have a stream of process information, we want to work with each process individually. To do this, we use the Foreach-Object cmdlet. We wish to tally up the WorkingSet property of each of the processes. To do this, we use the $_ variable, which refers to the individual process object that is currently residing on the pipeline. We then query the WorkingSet value and add it to the current total of $mem. The += construction is the same as saying $mem = $mem + $_.WorkingSet. This line of code is seen here:

Foreach-Object { $mem += $_.WorkingSet }

The next line of code is used to print out the amount of memory that is being consumed. {0:N2} is a .NET framework format specifier that says we want to display numbers with two decimal places. The strange thing is that it appears in front of the –f instead of behind it. 1MB is called an administrative constant, and it is used to convert bytes to megabytes:

"{0:N2}"-f ($mem/1MB) +" meg of ram is being consumed by $procFile Processes"

Here is how memory being consumed is displayed:

Image of the display of memory being consumed

 

It is now time to show a prompt, so we can ensure the user intended to stop all the processes. To do this, we use the Read-Host cmdlet. This code is shown here (the prompt itself can be seen in the previous image):

$rtnPrompt = Read-Host -Prompt `
  " 
   would like to kill $procfile processes? 
   <y / n>
  "

Now we need to evaluate the user’s response. To do this, we use the switch statement, which is similar to the Select case command from VBScript. The switch is used to determine what was handed to the Read-Host cmdlet. This value was stored in the $rtnPrompt variable. If it is equal to y, we print in green the processes that will be deleted, and then we call the Stop-Process cmdlet to stop each process. If the variable is equal to n, the message is printed in yellow to say that nothing will be stopped. If an invalid response is typed, the message is displayed in red that a y or n response was expected:

switch($rtnPrompt) 
{
 "y"     { 
          Write-Host -BackgroundColor green "$procfile processes will be killed..." 
          stop-process -name $(Get-Content $procFile) -ErrorAction continue 
         }
 "n"     { 
          Write-Host -BackgroundColor yellow "$procfile processes will not be killed" 
         }
 default { 
           Write-Host -BackgroundColor red "Response y or n expected. exiting..." ;
           exit
         }
} #end switch

Here is what the display looks like when processes will be killed:

Image of what is displayed when processes will be killed

 

Well, JB, hopefully this script will alleviate some of your hair loss problems. If not, consult your general practitioner. Script you tomorrow.

Ed Wilson and Craig Liebendorfer, Scripting Guys