My Corporate DNS Server was lying to me, often.

I was trying to copy some files to a group tonormaldnsoperation a computers.  What I’d do is check if the computer is alive first, by doing a network ping.  If the computer answered the Ping, then the computer was alive, so I would then copy files to it.

It mostly worked, except when it didn’t.  Here is the clue which lead me to the answer:

C:\>ping alfred

Pinging ALFRED [192.168.1.5] with 32 bytes of data:
Reply from 192.168.1.5: bytes=32 time<1ms TTL=128

C:\>ping powergirl

Pinging POWERGIRL [192.168.1.5] with 32 bytes of data:
Reply from 192.168.1.5: bytes=32 time<1ms TTL=128

C:\>

The DNS server was returning the same IP address for two different computers.  As POWERGIRL was powered on, it answered the Ping request for ALFRED.  When I tried to copy to ALFRED, it failed as the file copy was trying to verify that ALFRED was at 192.168.1.5, and it wasn’t.

The cause?  The DNS server was retaining IP addresses for 24 hours.  Sometimes a computer’s IP will change more often than that.  So the DNS server ended up with 2 or more DNS computer records with the same IP.
The fix?  Tell the DNS server to only retain DNS records for 2 hours.  (for the more technically minded, we adjusted the Time To Live value).

How I originally detected the DNS server was lying to me?
I pinged the computer (ALFRED) to get it’s IP address (192.168.1.5).
I then asked IP address 192.168.1.5 what it’s computer name was.  In the example above, it was actually POWERGIRL.

The code to do that is in the Reachable function, below:

Continue reading

Some great free scripting tools.

PrimalScript_box Sapien make, what I think is the best script editor available.  It’s called PrimalScript.  Not cheap, but it was the only way I know to step though a PowerShell script.  That’s changed with PowerShell 2, with it’s ISE.  But I’m still sticking with PrimalScript.

Sapien make a number of free tools available, and since I believe they preserve a wider audience, see below.


Continue reading

The WMI Overflow Error with GetObject

VBscript_bookThat’s what I thought at least.  Consider this snippet of code from the Delete computers from SMS VBscript:

Set objResource = GetObject( "WinMgmts:\\" & strSMSServer & _ 
                  "\root\SMS\site_" & strSMSSiteCode & _
                  ":SMS_R_System.ResourceID=" & cint(intResourceID))

This statement would fail about 50% of the time.  The error code was
Err.Number: 6
Err.Description: Overflow

Google was not my friend.  It was down to debugging the code line by line.  Now I’d like to say I spotted it immediately, but it took me two hours of looking over the script to finally work out what was going on.

The number of computers in our SMS database exceeds 32768, which is the limit for an integer variable.  The cint function was reporting an Overflow error as the value of intResourceID was over 32768.  Foiled by a bug in 4 year old code from Microsoft.

The answer was to change cint(intResourceID)) to  cstr(intResourceID)) .

Bookmark and Share

Deleting computers from SMS 2003 (and perhaps SCCM 2007), with a script.

Below is a script which will delete a list of computers from SMS 2003.  And quite possibly SCCM 2007 as well (not tested).  It was originally taken from the SMS 2003 Recipe Book, modified by Paul Town, and further improved by me.
The changes I made were:

  • the script will read a text file of computers to be deleted, and loop though them.
  • ping the computer to be deleted, and if it’s “pingable”, don’t delete it.
  • fixed a bug with the WMI GetObject call.

strSMSServer = "WISEFAQ2003"
strSMSSiteCode = ""

Set objFSO = CreateObject("Scripting.FileSystemObject")
If not objFSO.FileExists("C:\computer_lists\sms_deletion.txt") Then
WScript.Quit(99)
End If

Continue reading

VBscript: "Pinging" a computer.

VBscript_book If you looked at yesterday’s post, carefully I’ll admit as WordPress loves to mangle the display of <CODE>; you might have noticed that I check to see if a computer is on the network, before I try and do something to it.
The reason is simple.
Checking that a computer is on the network, is faster, than just trying to copy a file to it, and checking for a failure.  I don’t know why, but I suspect a “Ping” is faster than a file operation.
Here is some (crude) code I wrote the other day, which shows a ping in use:

Continue reading

The Windows PowerShell syntax was deliberately chosen

PowerShell logo The Windows PowerShell syntax was deliberately chosen to facilitate ease of use and ease of learning.  Corporate enterprise Windows administrators are the target audience.

– Windows PowerShell Scripting Guide by Ed Wilson, Microsoft Press.

I’m teaching myself PowerShell at the moment, because:

  1. it’s the future of Windows scripting.
  2. I had 1400+ computers I needed to check for a particular file, and it looked easier with PowerShell.

Future of Windows scripting.

Back in the dark ol’ days, if you needed a script created on DOS and Windows, your choices were DOS Batch, and DOS Batch.  This changed in 1991 with KiXtart.  KiXtart was created by a Microsoft employee, to provide corporate IT types with more robust logon scripting.

Like the 9 headed Hydra, KiXtart blossomed.  And got into places where it shouldn’t have gone.  I know of one 4000+ desktop company using it for software deployments.  Erkkkk!  Imagine how much spaghetti code there would have been in that.

Then VBscript.  VBscript was trumpeted by Microsoft in 1998 as the better/new way forward.  One Windows IT Pro writer said in 2001:

VBScript, one of the most powerful and underused features in the Windows environment, provides the same powerful programming tools (e.g., variable support, structured program control, the ability to leverage COM objects) that you’ll find in full-featured development languages.

It was that very powerfulness which caused some security problems with VBscript (mis)use.  So Microsoft threw the baby out with the bath water and created PowerShell to address those security issues.  Sure there are some other advantages to PowerShell, such as speed, and that it’s going to be how you script/interact with new Microsoft products.

Those 1400+ computers?

The script worked well.  Here is the cut down version:

$windows_PCs = (Get-Content c:\temp\pc-list.txt)
foreach ($computer in $windows_PCs)
{
$file_exist_path = "\\"+ $computer + "\c$\data\fred.txt"
$file_exist_OK = (Test-Path $file_exist_path)
if ($file_exist_OK)
{
write-host $computer has the fred file
}
else
{
write-host $computer is missing the fred file
}
#endif - PowerShell does not use EndIf statements, so I put this here as a boundary.
}
#next - PowerShell doesn't have a next statement either.

Output:
CATBERT has the fred file

Bookmark and Share

VBscript to uninstall a Microsoft security patch

This is a small script I wrote many years ago to uninstall security patches.  I customise it when I need it.

In this example, I’ve customised it for MS09-032, but the principles apply to most patches.

Note that I don’t check for admin rights, I’m assuming that I’ll be using a desktop software deployment tool to run it on the user’s desktop.

' VBscript to roll back a security patch, in this case MS09-032.
‘ Dale Robinson – 2006 –> 2009

Option Explicit
On Error Resume Next

Dim bUninstallFileExists, OSSystemRoot, objWSHShell, objEnv, sMS09032Installed, sPatchCmd,sUninstallExe

Set objWSHShell = WScript.CreateObject("WScript.Shell")
Set objEnv = objWSHShell.Environment("Process")

' MS09-032 sets this registry key if it's installed.

Continue reading

Get the logged on user – code which works!

Some VBscript code which ACTUALLY works. I don’t understand some sites which share code. You go looking for VBscript code on the net to do something, and invariably IT DOES NOT WORK.

For one of two reasons:

  • it’s a code snippet, and you need to write code around it to get it to work
  • it’s a code snippet, which has been copied from somewhere else, where it did not work either.

The VBscript I’ll post in the CodeWhichWorks category will work because:

  • I use it in a production environment, so I know it works
  • I use it in a production environment, and I use this code as a memory jogger.

 

GetLoggedOnUser

Get the username, user domain & computer name of the user & computer which is running the VBscript.

Message box showing user and computer details '*********************************************************
' NAME: GetLoggedOnUser
'
' AUTHOR: Dale Robinson (WISEFAQ.COM)
' DATE  : September 2008
'
' COMMENT: Get the logged on user.
'
' Version: 1.0
'*********************************************************


Option Explicit
On Error GoTo 0

Dim bGotUserDetails
Dim sUserName, sUserDomain, sDisplay_ComputerName

Call fn_GetLoggedOnUser(sUserName,sUserDomain,sDisplay_ComputerName, bGotUserDetails)

If bGotUserDetails Then
MsgBox "Username: " + sUserName + VbCrLf + "Domain: " + sUserDomain + VbCrLf + "Computer Name: " + sDisplay_ComputerName,,"User details"
End If

WScript.Quit

Function fn_GetLoggedOnUser(fnsUserName,fnsUserDomain,fnsComputerName, boolresult)
' get some common computer / user details.
Dim objNet, objWSHShell, objEnv
On Error Resume Next
'get the username and domain
Set objNet = CreateObject("WScript.NetWork")

If Err.Number <> 0 Then
boolresult = False
Else
boolresult = True
End If

   fnsUserName = objNet.UserName
fnsUserDomain = objNet.UserDomain

'get the computer name
Set objWSHShell = WScript.CreateObject("WScript.Shell")

   If Err.Number <> 0 Then
boolresult = False
End If

   Set objEnv = objWSHShell.Environment("Process")

If Err.Number <> 0 Then
boolresult = False
End If

fnsComputerName = objEnv("COMPUTERNAME")
Set objNet = Nothing
Set objWSHShell = Nothing
Set objEnv = Nothing
On Error GoTo 0
End Function

You can download a zipped copy of GetLoggedOnUser.vbs here.

Bookmark and Share

Customers like to (re)use the methods of the support team …

Link to Officer and Sergeants Powerpoint Slidedeck I was doing some code cutting the other day for a customer.

Indirectly.

I had sent a DOS batch file to Customer A, in response for an urgent fix request.  The DOS batch file enables Customer A to use a particular web application.

The Help Desk send me an email, "Customer B have this VBscript file which doesn’t work."

Customer A shared the DOS batch file Customer B, who thought they’d have a stab at re-writing it into VBscript.

VBscript file received from Customer B:

Set objWSHShell = WScript.CreateObject("WScript.Shell")
objWSHShell.Run ("dosomething.exe /commandlineparameters", 3, True)
objWSHShell.Run ("dosomething2.exe /commandlineparameters", 3, True)

Now there’s a few problems with this file:

  • no checking to see if dosomething.exe exists.
  • no checking to see if dosomething.exe & dosomething2.exe return an error.

Here’s my ruggerised, ready for deployment version:

Option Explicit
On Error GoTo 0Dim objWSHShell, objFSO
Dim sDoSomethingParameters, sDoSomethingFilePathName, sDoSomethingCommandString
Dim boolFileExists, boolResult
Dim intDoSomethingResult
Const intWindowStyleHideAndActivate = 0
sDoSomethingFilePathName = "C:\doer\DoSomething.exe"
boolResult = False
intDoSomethingResult = 555
Set objWSHShell = WScript.CreateObject("WScript.Shell")
Call fn_CheckIfFileExists(sDoSomethingFilePathName, boolFileExists)

If Not boolFileExists Then
   ' exit with File Does Not Exist
   WScript.Quit (2318)
End If

sDoSomethingParameters = " -q -a qwerty"
sDoSomethingCommandString = sDoSomethingFilePathName + sDoSomethingParameters

intDoSomethingResult = objWSHShell.Run (sDoSomethingCommandString, intWindowStyleHideAndActivate, True)

If intDoSomethingResult <> 0 Then
   ' execution of DoSomething and parameters failed.
   WScript.Quit (1708)
End If

' if we're gotten here, it's worked, and we can exit the script!
Wscript.quit (0)

~~~~~~~

Function fn_CheckIfFileExists(fnFilePathName, boolResult)
On Error Resume Next
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.GetFile(fnFilePathName)
On Error GoTo 0
If objFSO.FileExists(fnFilePathName) Then
   boolResult = True
Else
   boolResult = False
End If

Set objFSO = Nothing
Set objFile = Nothing

End Function

I’m reminded of the maxim:
Customers like to (re)use the methods of the support team, but they don’t really understand them.

If you click on the picture, you’ll get to view the powerpoint file, where I saw the original maxim.

Bookmark and Share