The VBScript Network and Systems Administrator's Cafe:

Networking

Jan 5 2009   2:03AM GMT

Retrieve environment variable values from a remote system with WMI



Posted by: Jerry Lees
WMI, Environment Variables, Win32_Environment, VBScript, Windows Management Interface, System Administration, Remote management, PATH variable

Back in October I shared with you a way to retrieve environment variables with a script titled Using Environment variables inside a VBScript script. The script worked like a champ and got me through several tight binds in gathering information, hopefully it has for you as well. However, it has one flaw… it doesn’t work on a remote system! In fact, it only works on the system that the script is running on.

So, I had to recently go back to the drawing board and create a script and series of functions that would work remotely so that I could wrap it in a function to gather information from a bunch of servers. I also Learned a thing or two in the process!

First, The script uses the Win32_environment classes in WMI and this class returns ALL envirnment variables for ALL users. That threw me for a loop when I saw multiple PATH environment variables– some that were different. Second, The search is case sensitive without using the SQL % wildcards (I didn’t need them, so implementing that is left up to you the reader.)

I have the three functions I wrote, that are really variations of one another below. Just add them to your script and call them with the appropriate values and you should be in business!

Function RemoteAllEnvironmentVariables(ServerName)
     ‘Lists all environment variables on the remote system
    
Dim objWMIService, colItems, objItem
 
     RemoteAllEnvironmentVariables = “”
     Set objWMIService = GetObject(”winmgmts:\\” & ServerName & “\root\cimv2″)
     Set colItems = objWMIService.ExecQuery(”Select * from Win32_Environment”)
     For Each objItem in colItems
         RemoteAllEnvironmentVariables = RemoteAllEnvironmentVariables & objitem.name & “: ” & objItem.VariableValue & VbCrLf
     Next
End Function

Function RemoteAllEnvironmentVariablesVariations(ServerName, VariableName)
     ‘Lists all environment variables on the remote system, along with every case variation
     Dim objWMIService, colItems, objItem
 
     RemoteAllEnvironmentVariablesVariations = “”
     Set objWMIService = GetObject(”winmgmts:\\” & ServerName & “\root\cimv2″)
     Set colItems = objWMIService.ExecQuery(”Select * from Win32_Environment”)
     For Each objItem in colItems
         If UCase objItem.name) = UCase(VariableName) Then
         RemoteAllEnvironmentVariablesVariations = RemoteAllEnvironmentVariablesVariations & objitem.name & “: ” & objItem.VariableValue & VbCrLf
         End If
     Next
End Function

 
Function RemoteEnvironmentVariable(ServerName, VariableName)
     ’Lists all environment variables on the remote system, exactly as you typed it in the function call.
     Dim objWMIService, colItems, objItem
 
     RemoteEnvironmentVariable = “”
     Set objWMIService = GetObject(”winmgmts:\\” & ServerName & “\root\cimv2″)
     Set colItems = objWMIService.ExecQuery(”Select * from Win32_Environment Where Name = ‘” & VariableName & “‘”)
     For Each objItem in colItems
         RemoteEnvironmentVariable = objItem.VariableValue
     Next
End Function

Sep 4 2008   4:01PM GMT

Pinging a remote computer from another remote computer using the WMI Win32_PingStatus class in VBScript



Posted by: Jerry Lees
Networking, monitoring, Development, VBScript, Functions

I recently began working on trying to figure out ways to troubleshoot real problems with a VBScript and give me some diagnostic information about the current state of the environment. As I build this script I plan on sharing pieces of it bit by bit with you, my readers. I also wanted to get back to writing some WMI scripts that will help you all do your jobs more efficiently. Lastly, I wanted to begin building a “toolbox” script that you could use to write your own scripts. These are the goals I’m tracking toward in my next series of posts that contain VBScript code. Now onto this script…

The first piece of troubleshooting a problem, in my opinion, is ensuring that a communication path exists between two systems. Duh! However, simply pinging the systems individually from your desktop isn’t a good test… it only tests the your computer can communicate with the two systems, not that they can communicate with each other!

This script simply uses our friend WMI to make a call a remote computer requesting that computer ping another computer. Simple enough, but invaluable because how many times have you had to login to a remote computer to check if it can connect to a system? Now you don’t have to… you can do it from a script!

The script uses the Win32_PingStatus class in WMI. Essentially, it will only work on Windows XP and newer (Sorry, Windows 2000 and older doesn’t support the WMI class we need.) and the user executing the script will likely need to be an administrator on the system that is being called (but not necessarily being pinged). For further information on this class you can reference the Win32_PingStatus documentation.

Now lets get to the script!

 ‘Use a remote computer to ping another remote computer
Option Explicit
 
‘Change the SourceServer and RemoteServer Strings below to servernames or IP addresses for you.
wscript.Echo RemotePing(”SourceServer”, “RemoteServer”)
wscript.Echo “Done!”

Function RemotePing( SourceComputer, DestinationComputer)

 Dim strComputer1, strComputer2
 Dim objWMIService, colItems, objItem

 strComputer1 = SourceComputer
 strComputer2 = DestinationComputer

 On Error Resume Next
  ’ error control block
  Set objWMIService = GetObject(”winmgmts:{impersonationLevel=impersonate}//” & strComputer1 & “\root\cimv2″)
  Set colItems = objWMIService.ExecQuery (”Select * from Win32_PingStatus ” & “Where Address = ‘” & strComputer2 & “‘”)
  For Each objItem in colItems
      If objItem.StatusCode = 0 Then
          RemotePing = strComputer1& “: Reply received from ” & strComputer2 & ” in ” & objItem.ResponseTime & ” ms.”         
      Else
       RemotePing = “Error pinging ” & strComputer2 & ” from ” & strComputer1 & “. The status code returned was :” & objItem.StatusCode
      End If
  Next
 On Error GoTo 0
End function

As always, this code works perfectly. However, sometimes the formatting of the blog breaks the code if you copy and paste it into your editor. So, if you’d like to not type or troubleshoot any syntax errors due to the copy and paste problems– I’ve provided the code for download, plus example output files  from my final tests for you. You’ll find the code and other files available for download from my website’s (www.websystemsadministration.com) File Depot under the ITKE Blog Scripts category. Enjoy and happy scripting!


Jul 18 2008   3:46PM GMT

Useful site: Tons of free books online… did I mention free?



Posted by: Jerry Lees
Networking, routers, Documentation, Development, Developer documentation, Exchange, web sites, online books, online resources

I like free stuff. Who doesn’t? And with the price of technology books you can imagine I was amazed when I found a pretty cool site recently, Scribd, that allows you to upload electronic documents. They then add this document to the database they have and make it search-able. Plus, you can search the database for specific subjects or words.

Not only are regular people uploading books and documents, but there are publisher’s uploading books. Sometimes they are just excerpts, but sometimes they are entire books as well like:

ASP Programming for the Absolute Beginner
Beginning ASP NET 3 5 in C Sharp 2008 From Novice to Professional
MSPress Exam 70-284 Implementing and managing Exchange server 2003

There’s even a CCIE Study Guide and my personal favorite the VBScript Complete Reference !

 And Many Many more… so stroll on over there and see what you can find!

Enjoy!


Jun 13 2008   2:18PM GMT

How to find a lost router password for most routers



Posted by: Jerry Lees
Networking, Security, routers, password, default passwords, lost password, factory default

In this installment, I thought I’d take a quick break from VBScript and give you a little networking information I stumbled upon.

Recently, at my current job site we had a situation where the client didn’t know the router password because a series of network administrators had left and the password was simply “lost in the shuffle”. Of course, you all know this is not a good situation to be in if you need to preform network maintenance or want to upgrade a portion of the network somehow.

Of course the only thing we could hope for was that the previous network administrators had NOT been security minded and left the router passwords blank, or that there had not been a console password configured… so started off with trying to figure out what the factory default passwords were for the particular router we were working with at the moment. In our search I found a really awesome resource, that will be invaluable if this ever happens to you here. This site has all the major player’s factory default router passwords in a database, simply select your manufacturer and click find password. Where you are then presented with the known factory default router passwords for specific models from the manufacturer! Awesomeness!

Well, as luck would have it, the last guy didn’t follow standard security practices and this site had the default router password we needed. We were able to get in and get the job done– and change the password when we were done. Plus, after such a scare, the client is sure to not let this happen again. :-)

Now, we got lucky (and so did the client after years of service from the router with default passwords), but what if you need to get into a router and the password has been set to something other than default? Well, this situation is a bit harder– but not impossible. You need to see if you can get onto the console of the router, most major manufacturers have a mechanism for you to plug directly into a router with a serial cable and change settings. Hopefully, this will NOT have a console password– if it does try the defaults, just in case.

Once in, get a dump or output of the configuration. Then you will need to follow the manufacturers method to change the password. Should the console connection not have enough security to change the passwords– you may have to set the router to factory defaults. Be sure if you do this you have the configuration completely and you are prepared to rebuild it. I would not recommend you do this unless you have either done this before or you have 24/7/365 support and have the support folks on the phone while you do it.

Here is my recommendation (and I’ll probably get many security folks commenting differently) , but assuming the router is in a secured place, (a hall closet or the CEO’s office does not count) and locked away so only authorized people can get to it, I almost always leave no password on the console for cases just like this one I’ve mentioned.

Hopefully this helps someone out there and good luck!


Apr 17 2008   8:52PM GMT

Creating text files using the Scripting.FileSystemObject with VBScript



Posted by: Jerry Lees
VBScript, FSO, Functions, Scripting.FileSystemObject, File System Object, Log files

Well, I didn’t expect the cat to get out of the bag quite so quickly! (Congratulations go out to Stoinov for getting the correct answer I was thinking of so very quickly!) So while he’s been sleeping during his night, which seems to be my day… I thought I’d throw together a quick “Write a text file” script together for you all. (A little trivia for you all in the United States, that I found hard to believe when I learned it… VBScript, and VB for that matter, is in English regardless of where you are in the world. If you’re on a Japanese system writing VBScript, your using the same language as us folks in the United States. Talk about portable code!)

Back to the matter at hand, this script doesn’t do anything terribly spectacular– by itself. All it does is opens (or creates) a text file named what you call it where you specify. The heart of the script is the WriteTextFile () function, which accepts two pieces of data; a full path to a file name and the data you want to write. That’s it! But—- this function will let you write logs, CSV (Comma Separated Value) files or any other form of text file from any type of script for which you choose to use it!

A quick little note on the access method I hard coded into the script. You  will notice three constants used ForReading, ForWriting, and ForAppending these are there so you could change the mode easily without having to go to the documentation for the OpenTextFile Method of the Scripting.FileSystemObject and figure out what numbers to use to change the access method. you simply just need to change the access method from ForReading on the OpenTextFile line of the script to accomplish this task. An excerpt of the Microsoft documentation for the values and descriptions are listed below, for your reference.

Constant Value Description
ForReading 1 Open a file for reading only. You can’t write to this file.
ForWriting 2 Open a file for writing.
ForAppending 8 Open a file and write to the end of the file.

Notice it has a ForAppending attribute? If you wanted to … say log a series of collected values over a number of calls to the script you would have to change the access method to appending, however, keep in mind that ForAppending assumes the file already exists and you will receive an error if it doesn’t.

So, here is the script to write a file…

Option Explicit
Dim Error

Error = WriteTextFile (”c:\test.txt”, “I created a text file with VBScript!”)
If Error = 0 Then
    WScript.Echo “File Written Correctly.”
Else
    WScript.Echo”Error number ” & Error & ” occurred.”
End If

Function WriteTextFile (OutputFile, Data)
    Dim wrtlog, fso
 
    ’these are constants for the OpenTextFile method’s file access modes
    Const ForReading = 1, ForWriting = 2, ForAppending = 8
  
    On Error Resume Next
    Set fso = CreateObject(”Scripting.FileSystemObject”)
    Set wrtlog = fso.OpenTextFile (OutputFile, ForWriting , true)

    wrtlog.WriteLine(Data)
    WriteTextFile = Err.Number ‘You can use Err.Description here to debug.
End Function

That’s it. Small, but a VERY powerful tool to add to your tool belt in scripting.

As always, this code works perfectly. However, sometimes the formatting of the blog breaks the code if you copy and paste it into your editor. So, if you’d like to not type or troubleshoot any syntax errors due to the copy and paste problems– I’ve provided the code for download, plus example output files  from my final tests for you. You’ll find the code and other files available for download from my website’s (www.websystemsadministration.com) File Depot under the ITKE Blog Scripts category. Enjoy and happy scripting!


Mar 7 2008   10:22PM GMT

Eventlog search tool — Find quick help with windows event log entries



Posted by: Jerry Lees
Networking, Security, DataCenter, Exchange, Administration tools

While not VBScript related, I found this Microsoft Eventlog and Error Message Search a few days ago as I stumbled around looking for tools that I thought network administrators would need on my site that I’ve been toying with– I had to share the tool with you as well!

 The tool itself is an awesome resource, similar to EventID.net– except it’s FREE and it comes from Microsoft themselves providing links to Microosft content about the event entry or error message.

 You can search for any combination of the following:

Microsoft Product|
Version
Message ID
Event Source
File Name
Language

When you do it takes you to a search result page that lists the available results for your specific search, each seem to have not only an example of the message, but also an explanation of what the event means…. and the best part a section entitled User Action that gives a possible solution for the problem!

 Enjoy the tip!


Mar 3 2008   9:11PM GMT

Using Set, GetObject, ExecQuery, and For Next in VBSCRIPT to use WMI objects



Posted by: Jerry Lees
Networking, SQL, Development, VBScript, VBScript Statements, Objects

In my last blog entry I explained error control via on error resume next and on error goto 0, there are other ways as well– but for now this should work to get us by.

Next well discuss the Set, GetObject, ExecQuery, and “For Each” commands in the script we worked with, these are on lines 3, 4 and 5 below.

The script was basically (line numbers included as a reference):

1. On Error Resume Next
2. 
strComputer = “.”
3. Set objWMIService = GetObject(”winmgmts:\\” & strComputer & “\root\cimv2″)
4.
Set colItems = objWMIService.ExecQuery(”Select * from Win32_PrinterDriver”,,48)
5.
For Each objItem in colItems
6. 
    Wscript.Echo “ConfigFile: ” & objItem.ConfigFile
7. 
    Wscript.Echo “DataFile: ” & objItem.DataFile
8. 
    Wscript.Echo “DriverPath: ” & objItem.DriverPath
9.
     Wscript.Echo “Name: ” & objItem.Name
10.
   Wscript.Echo “OEMUrl: ” & objItem.OEMUrl
11.
   WScript.Echo “_________________” & vbcrlf
12.
Next

The Set command basically tells cscript (or wscript) to assign the value of a variable to be the value of another or creates an object. For all intensive purposed, you can think of an object as a piece of specialized code that is already written that you can call from within your program and use as if it were your own. An object can contain many different types of values, that are referenced by names. These names are either properties (values) or methods (functions to do something and probably give you a value back).

Next, the GetObject command. this is the true heart of our WMI script. In fact, this is where almost all the magic happens! The Getobject comamnd lets us use pieces of code outside of our application as if we had written them on our own– the plus being that we don’t have to write them. In this case it is a WMI call to retrieve an object called “winmgmts:\\.\root\cimv2″.

This object is the root WMI provider that is built into the OS and the period represents the local machine, to get other machine you would specify it’s name instead– this is why we used a variable in the script. (Remember, scripts are powerful when they are reusable for the same situation at a different time, so try to use variables where ever you think a piece of information could change in the furture to allow you to reuse the script.) This WMI provider returns a WMI object that allows us to reference and use the piece of the OS that deals with WMI. Notice we SET the object to the variable objWMIService in the line?

 In the next line of code we actually USE it, again another SET command. But this time we use:
… objWMIService.ExecQuery(”Select * from Win32_PrinterDriver”….

The execQuery method is a part of the WMI classes Microsoft has written, and we are simply calling it to preform work. In this case, we are constructing a call to pull back all the printer drivers. The part in the quotes works exactly like a simple SQL statement would operate. Essentially in english it works like– Select all values from Table containing the printer driver information. This “table” contains lots of information on the printer drivers, I’ve only chosen to show a few items from the table, you can get more information here.

After this command completes, colItems will contain a collection of objects that each have properties named the same as the columns in the table. We use the For Each command on line 5 to loop through each member of a collection one at a time and do something with the data (or to the data). The Next command on line 12 loops back to the beginning as long as there is another object after the one currently being used in the collection.

That’s it! It’s pretty easy stuff, once you get the concepts down. Remember, The WMI object is used to execute a query against the WMI database on the system. This query returns a collection of objects containing data for the query you built.

The actual data returned (and names of methods and properties used to get the data) depends on the query you specified. More on that next time!


Feb 29 2008   2:45AM GMT

Finding HP Printers using PCL6 Drivers with WMI



Posted by: Jerry Lees
Networking, Development, VBScript, Printers, Windows Management Interface, Error control, Printer Administration

Recently, at my work we had a situation where users were reporting the printer was not printing their documents and/or it was printing very slowly. After digging into the problem, I found:

1. the documents were spooling just fine to the printer

2. the documents were not hanging in the printer

3. Sometimes there were documents printing correctly when the user printed

4. on occasion the documents “didn’t print”

Of course, the nearest printer doing it was on the floor below me… I hate stairs. ;-) After digging into it, wasting a ton of paper– and burning untold amounts of Mountain Dew and Dorito calories; I found that the print jobs were always producing printouts! Sometimes it was the document I printed and sometimes it was a single page with the following message in the documents place:

error:

Subsystem:  KERNELError:  IllegalStreamHeaderOperator:  0×0

Position: 0

 The operator and position line held various values, but was always the same first 3 lines. What I found after extensive digging was that this issue was a PCL6 error message. Some people were saying it was a network error and others were saying it was a server print driver error– Don’t they always say it’s one of these, regardless of the problem?

Those who were saying it was a network error were advising that I pulled out a sniffer, like wireshark because packets were being corrupted. I didn’t think this was good advice. First, pulling a sniffer out to troubleshoot printing was like pulling a blowtorch out to light a campfire… sure it will work, but it’s a lot of extra work! Also, I knew that Microsoft printing is done like most things Microsoft– over TCP ports 138,139, and 445 (I believe)– most importantly TCP, since TCP has error correction built in via a checksum.

The others who were saying it was a server issue were recommending that I upgrade ALL the printer drivers on the server. This was quite an undertaking since there were 40 or so printers on the server of various models– most of them made by HP. Knowing HP, the drivers were bundled together into one package and upgrading the drivers for one printer would likely change a bunch of printers. To much risk! 

I did find a few needles in the google hay stack, that were saying the problem was typical for PCL6 and to simply switch the driver back to PCL5. Since both driver types were installed when I installed the printer drivers (always a good idea) I thought I’d give it a shot. Tah Dah! It worked like a charm, with no changes in the documents printer that I could see.

Now that I had one printer fixed, but had to point and clickety click to find the other’s using PCL6 drivers. To much work! So I wrote a quick script to get the bulk of the printer drivers that were being used by the print server so I could focus on the ones needing changing.

Here is the script source, copy it to a .vbs and either; run it from the print server as is or change the second line between the quotes from a period to the name of the print server: (Note: I recommend you run this from the command line with cscript scriptname so you don’t get bombarded by popups)

On Error Resume Next

strComputer = “.”
Set objWMIService = GetObject(”winmgmts:\\” & strComputer & “\root\cimv2″)
Set colItems = objWMIService.ExecQuery(”Select * from Win32_PrinterDriver”,,48)
For Each objItem in colItems
    Wscript.Echo “ConfigFile: ” & objItem.ConfigFile
    Wscript.Echo “DataFile: ” & objItem.DataFile
    Wscript.Echo “DriverPath: ” & objItem.DriverPath
    Wscript.Echo “Name: ” & objItem.Name
    Wscript.Echo “OEMUrl: ” & objItem.OEMUrl
    WScript.Echo “_________________” & vbcrlf
Next

That’s the end of the script! You’ll want to look at the “Name:” lines for the string PCL6. Not all drivers have PCL6 in the name, but a good majority do so it should save you some time!

Take a bit of that time to leave me a comment letting me know if this was helpful!

 Good luck!