Hey, Scripting Guy! Quick-Hits Friday: The Scripting Guys Respond to a Bunch of Questions (01/09/09)
How Can I Tell the Status of Services on a Computer?
Hey, Scripting Guy! I’m wondering if you can help me before I tear all my hair out. I’m trying to write a script using WMI that checks for a few core services such as antivirus, remote desktop software, and the like. The intention is to bolt this information onto another one of your (brilliant little) scripts I use to e-mail this information if certain things aren’t installed.
I’ve found a really convoluted script somewhere on the Internet that enumerates all services along with service users and a count of services at the end, but this is really overkill. I just want an “If exist” type script for a handful of services, which we can then run on all our PCs!
The Scripting Guide talks about listing the status of services, and probably is the kind of script you were railing against. People sometimes make a big deal about Windows PowerShell “one liners,” but you can certainly use a more compact syntax within VBScript as well. The thing is, no one ever did. I actually came up with this type of syntax when I was writing the Microsoft Press book, Microsoft Windows Scripting with WMI: Self-Paced Learning Guide. I also used it quite a bit when I was writing scripts for the Windows Vista Resource Kit (First Edition). In that book, I was interested in printing out the user name and the computer name. Because the script might be run remotely, I could not use any of the properties from the WshShell object. You can also use something such as this VBScript to solve your problem:
Dim aryServices(3) aryServices(0) = "bits" aryServices(1) = "lmhosts" aryServices(2) = "LanmanServer" aryServices(3) = "LanmanWorkstation" For Each Service In aryServices WScript.Echo Service + ":" wscript.echo vbTab + GetObject("winmgmts:win32_Service.name='" + Service + "'").State Next
How Do I Run a Script?
Hey, Scripting Guy! Please don’t make fun of me, but I am new to the script thing. I found your scripts when searching for “remove account unknown.” I copied the script text to a text file and don’t know what to do with it. Ashamedly yours.
We love new scripters who want to learn. Welcome! Here is a link to help you with the first steps of scripting. A quick summary of the steps required to get your script running may be in order. Basically what you do is this:
Open Notepad. Copy the text of the script to Notepad.
Save the file with a .vbs extension.
Open the Command Prompt window, and then type cscript and then the path to the script, including the file name.
Et voila! Like magic, the script will run. As with anything initially mysterious, running a script seems so simple after you’ve done it a few times.
If it is a Windows PowerShell script, you need to follow these steps instead.
Download and install Windows PowerShell.
Open Notepad. Copy the text of the script to Notepad.
Save the file with a .ps1 extension.
Open Windows PowerShell.
Type this command inside the Windows PowerShell prompt: Set-ExecutionPolicy remotesigned. Note: In Windows Vista, you must start Windows PowerShell with administrator rights to execute this command.
Type the path to the script, including the file name.
Et voila! Like magic, the script will run. But wait, there’s more: Here’s the link for the Windows PowerShell hub.
Be sure you download Windows PowerShell 1.0. The 2.0 version is still in beta. By the way, perhaps you are wondering how to tell the difference between Windows PowerShell code and VBScript code? Well, Windows PowerShell code will look like the code following this paragraph, which is taken from the “Hey, Scripting Guy!” article, How Can I Kill Processes? There are two things that are a dead giveaway that you are looking at Windows PowerShell code: All the variables begin with a dollar sign; also, the command name Get-Process has a dash in it. In VBScript code, we do not use dollar signs for variable names, and the commands do not have dashes in them. Here’s the Windows PowerShell sample:
$mem = 0 $procFile = "c:\FSO\annoyingProcesses.txt" Get-process -name (Get-Content $procFile) -ErrorAction continue |
Now let’s look at a little bit of VBScript code. The big clue that you are loooking at VBScript code is the use of the word Set. We do not use Set in Windows PowerShell. Also notice the absence of dollar signs for the variable names. Here’s the VBScript sample:
Set objExcel = CreateObject("Excel.Application") objExcel.Visible = True objExcel.DisplayAlerts = FALSE
Hope this helps!
How Can I Send Information with an SMTP E-Mail Script?
Hey, Scripting Guy! I wrote a script that looks at the creation dates of all files in a certain directory. If the files were created less than an hour from the current time, the script returns those file names. The script will need to send the information in an SMTP e-mail. I reviewed the link that explains how to send SMTP e-mail with a general string message; however; I am not sure how to get all the information from my previous script into a single property for the SMTP e-mail script. Can you please help?
We have some more examples of SMTP e-mail scripts in the Community-Submitted Scripts Repository. There are also a couple of scripts in the Script Repository that might help. Basically what you need to do is concatenate your file names and information into a single variable that you will use for the e-mail text. Suppose you have the following:
myFileName = "myfile.txt" myFileDate = "filedate" myFileSize = "fileSize" MyText = MyText & VbCrLf & MyFileName + vbTab + MyFileDate + vbTab + MyFileSize WScript.Echo myText
Note that we use the ampersand (&) character to concatenate our output. “Concatenate” is a fancy word that simply means to glue things together. One thing to keep in mind about concatenation is that it is “super glue”—it sticks things together without any spaces in between them. So if you want a space, you need to include one. I used vbTab, which is an intrinsic constant that means you want a tab worth of space between things. You could also have used ” ” to include a single space. This technique is covered in the Microsoft Press book, Microsoft VBScript Step By Step.
If we have an array of files, we need to loop through the array. We still use the same type of technique, but will add a For…Next loop. There are a couple of things to point out. To create the array, I am using the Array function. To find out how far to go using the For…Next construction, I use the UBound function. When you are using For…Next, it automatically increments the value of the counter variable (i, in this example). Here is the DemoConcatenateOutputFromArray.vbs :
AryFileName = Array("myfile.txt", "myNextFile.txt", "afile.txt") AryFileDate = Array("filedate", "myNextFileDate", "adate") AryFileSize = Array("fileSize", "myNextFileSize", "asize") For i = 0 To UBound(AryFileName) MyText = MyText & VbCrLf & AryFileName(i) + vbTab + AryFileDate(i) + vbTab + AryFileSize(i) Next WScript.Echo myText
Troubleshooting a Script That Monitors Folders and Subfolders
Hey, Scripting Guy! I’m new, self-taught scripter, so I apologize upfront if my code doesn’t look so great. I would really appreciate if you can help me with what is probably a relatively simple task. I am trying to run a script that will monitor a folder and its subfolders for file creation, deletion, and modification, and then log everything in a file. In my code, everything works, but I get incomplete results. For example, if am monitoring a folder with 5 files in it and I select and delete four of them at the same time, the script will only report 2 or 3 fiels. Or if I add a file and then delete a file, nothing is reported. What’s going on?
WMI is a lot of things, but it is also not a lot of other things. WMI is not a replacement for Filemon. It is not designed for long-term monitoring. It is a high impact performance hit on your system. What is it really good for? WMI is good for short-term monitoring. For instance, I have a script that will copy a 4 GB file, and then I intend to zip it up and send it by e-mail. Now there are a couple of things going on here. If I write the code and use wscript.sleep, how long do I pause the script? Well, I can do testing to see how long it takes to copy a 4 GB file, and then add 10 percent to it. But what if the network is really slow today? Also, how long does it take to zip the 4 GB file? These are both great occasions to use a quick WMI script. Here is a link to a script that talks about monitoring. So how would the script go?
I start the WMI event monitor to watch for a new instance of a cim_datafile.
Then I start the file copy.
When the event fires, the new file has been copied to the directory.
Now I start the .zip process, and save the .zip file to the same folder I am monitoring.
When the event fires, that means the .zip process is done.
Now I can exit the event monitor script.
Now I can send the e-mail using a technique similar to these scripts.
By the way, when doing event monitoring in production, never use less than 30 seconds or so. In most cases I bump it up to a couple of minutes. All the scripts on the Script Center use something like this: WITHIN 5 or WITHIN 10. This is saying monitor for an event every 5 seconds or every 10 seconds, depending on the particular script. This makes for a good demonstration, but if you watch the WMI process with Task Manager during the script execution, you will see a pretty good processor spike every 5 or 10 seconds. Clearly not the kind of impact you want on a production server. This is covered really well in the Microsoft Press book, Microsoft Windows Scripting with WMI: Self-Paced Learning Guide.
Hope this helps. We will see you next week. Until then, have a safe weekend.
Ed Wilson and Craig Liebendorfer, Scripting Guys