A VBScript Wake on LAN Project
Saturday, November 29th, 2008I was working at home one weekend recently, performing some scheduled server maintenance. We have mostly HP servers where I work, and they have this nice feature built into them called Remote Insight. It’s a card that’s plugged into the motherboard of the server. This card has an ethernet port on it. You can connect to the RI card over this ethernet port and use it as a sort of virtual KVM. It’s a fantastic feature, letting you control a server remotely, shutting down or restarting if you need to, and, since it’s essentially attached to the console, you can even get into the BIOS should the need arise.
That is, when it works.
The RI cards are pretty reliable, but every once in a while they’ll disconnect you and make you wait a 30 minute timout period before it resets the connection. Not a big deal if you’re in the building, but a much bigger problem if you’re offsite, as I was this particular weekend.
Anyway, I had to shut down a server briefly, and that server’s RI card decided that right then would be a good time to drop its connection. I had to drive in to work on a Sunday just so I could press the power button on the server. I was good and annoyed, let me tell you.
The next work day, I decided to give myself a backup method of turning on a server. My tool of choice? A wonderful piece of technology called Wake on LAN. I use a tiny application called WOL.EXE for this. Open a command prompt, type “wol 112233445566″ (that last part being a MAC address) and WOL.EXE sends out what’s called the magic packet to wake up the computer (or server) with the correct MAC address. This would have suited my needs perfectly, if only I’d had the MAC address of the server in question.
Hmm, I feel some scripting coming on.
Let’s not limit this to servers. Let’s cover all the computers in an entire domain, ok? Ok.
The first thing to do is gather all the computer names from your Active Directory domain. I found the perfect script over at Microsoft’s Script Center Repository. Their website doesn’t support direct hyperlinking, so I can’t link to the script. I’ll just give it to you here:
On Error Resume Next
Const ADS_SCOPE_SUBTREE = 2
Set objConnection = CreateObject(”ADODB.Connection”)
Set objCommand = CreateObject(”ADODB.Command”)
objConnection.Provider = “ADsDSOObject”
objConnection.Open “Active Directory Provider”
Set objCommand.ActiveConnection = objConnectionobjCommand.Properties(”Page Size”) = 1000
objCommand.Properties(”Searchscope”) = ADS_SCOPE_SUBTREEobjCommand.CommandText = _
“SELECT Name FROM ‘LDAP://dc=fabrikam,dc=com’ WHERE objectCategory=’computer’”
Set objRecordSet = objCommand.ExecuteobjRecordSet.MoveFirst
Do Until objRecordSet.EOF
Wscript.Echo objRecordSet.Fields(”Name”).Value
objRecordSet.MoveNext
Loop
Quick side note: The script references an example AD domain as ‘LDAP://dc=fabrikam,dc=com’. The AD domain where I work is actually a subdomain of our public domain name, so I have to add to the DC path above. Like so: ‘LDAP://dc=subdomain,dc=fabrikam,dc=com’. Note how I added a third DC section. That’s how you can reference a subdomain name in an LDAP path.
The script as-is will output the information it gathers to the console, but I wanted to capture it in a text file. The easiest way to do this without modifying the script is to run the script from within Microsoft’s Scriptomatic tool, with Scriptomatic set to display the results in a text file. Boom, nice and easy. I use Scriptomatic a lot this way.
Paste the script into Scriptomatic, change the LDAP path in the script to your own AD domain, and click Run. After a second or two you’ll see a text file pop open with a list of all the computers and servers in your domain. Save this text file somewhere safe. I saved mine with the name workstations.txt.
Now we need to fetch all the MAC addresses of the computers listed in that text file we just saved. We’ll use another script to do that, using the text file we just saved as the input for the script.
Here’s the script:
‘—– Let’s Dim our variables —————————————————————-
Dim strComputer, objFSO
‘—– Set some constants used for manipulating text files————————————-
Const ForReading = 1
Const ForAppending = 8‘—– Let’s open the list of workstations we grabbed from Active Directory ——————-
Set objFSO = CreateObject(”Scripting.FileSystemObject”)
Set objFile = objFSO.OpenTextFile(”C:\scripts\Fetch MAC Addresses\workstations.txt”, ForReading)‘—– We want to loop through the text file line by line, grabbing MAC addresses as we go —
Do Until objFile.AtEndOfStream
strComputer = objFile.ReadLine‘—– Let’s see if we can ping the workstation ———————————————–
Set WshShell = CreateObject(”WScript.Shell”)
PINGFlag = Not CBool(WshShell.run(”ping -n 2 -w 250 ” & strComputer,0,True))‘—– If we can ping the workstation, grab the MAC address and save it in a text file ——–
If PINGFlag = True Then
wScript.Echo strComputer & ” pings”
Dim objShell,objExec
Set objShell=CreateObject(”wscript.shell”)
strCommand=”nbtstat -a ” & strComputer
Set objExec=objShell.Exec(strCommand)
Do While objExec.StdOut.AtEndOfStreamTrue
strLine=objExec.StdOut.ReadLine
If InStr(strLine,”MAC Address”) Then
arrFields = Split(strLine, ” “)
strMAC1 = arrFields(7)
strMACAddress = Replace(strMAC1, “-”, “”)
strCompEntry = strComputer & “,” & strMACAddress
Set objFile2 = objFSO.OpenTextFile(”C:\scripts\Fetch MAC Addresses\MAC_Addresses.txt”, ForAppending)
objFile2.WriteLine strCompEntry
objFile2.close
End If
Loop
Else‘—– If we can’t ping the workstation, let’s log that so we can get the MAC address later —-
Set objFile3 = objFSO.OpenTextFile(”C:\scripts\Fetch MAC Addresses\cannot_ping.txt”, ForAppending)
objFile3.WriteLine strComputer
objFile3.closeEnd If
Loop
The script reads the first workstation name, sees if the workstation responds to ping, runs the nbtstat command against the workstation, grabs the MAC address by monitoring the stdout of the nbtstat command, then saves the workstation name and MAC address (sans hyphens) to a second text file. Also, if the workstation does not respond to ping, it saves that workstation name to a third text file. We can use this third text file at a later date as the input file of this same script so that, over time, we can gather all the MAC addresses in our domain.
There you have it, all the MAC addresses in your domain. For myself, I now have all the information I need to wake up any workstation or server on my domain, but let’s not stop here. Let’s make it easy to use the MAC addresses we just gathered.
Here’s a script that prompts you for a workstation name, searches for the MAC address in the second text file, then automatically sends the WOL packet to wake up the workstation.
‘—– Let’s dim our variables ————————————————
dim fname, objFSO, objFile‘—– This opens an input box into which we’ll enter our workstation name —-
fname=InputBox(”Which computer do you want to wake up?”)
fname = UCase(fname)‘—– Some tracking integers ————————————————-
i = 0
y = 0Const ForReading = 1
‘—– Open the text file of MAC addresses and read the ———————–
‘—– entire thing into memory at once —————————————Set objFSO = CreateObject(”Scripting.FileSystemObject”)
Set objFile = objFSO.OpenTextFile_
(”C:\scripts\Fetch MAC Addresses\Copy of MAC_Addresses.txt”, ForReading)
strFile = objFile.ReadAll
objFile.Close‘—– Split the file into an array, using the comma delimiter —————-
arrFields = Split(strFile, “,”)
‘—– When we find a match we’ll increment Y by 1, but ———————–
‘—– we want the script to keep looping until otherwise ———————Do While y=0
‘—– Whatever array field has the workstation name, the MAC address ———
‘—– will be in the next field ———————————————-strPC=arrFields(i)
strMAC=arrFields(i+1)‘—– Let’s see if we have a match between the workstation name taken ——–
‘—– from the text file and the input box ———————————–If strPC = fname Then
‘—– If we do, let’s grab the MAC address and send the WOL signal ———–
Dim objShell,objExec
Set objShell=CreateObject(”wscript.shell”)
strCommand=”C:\scripts\wol.exe ” & strMAC
Set objExec=objShell.Exec(strCommand)
‘—– Let’s get a visual confirmation that we sent the WOL signal ————wscript.echo “Wake on lan command sent to MAC address ” & strMAC
‘—– Since we found a match, let’s increment Y ——————————
y=1
End If‘—– If we didn’t find a match, let’s look at the next workstation name —–
‘—– which will always be two array segments away —————————i=i+2
‘—– The loop will terminate here once Y=1, otherwise it’ll keep going ——
Loop
And there you have it. I hope you find this helpful.