Archive for the ‘Windows - Scripting’ Category

Killing Processes on Server 2000 from VBScript

Thursday, October 8th, 2009

Alright, so we have a report server that has a massive SQL database and is running Server 2000 SP4. I honestly don’t know too much about it, because we have a DBA who does pretty much 90% of the maintenance/admin work on this server and the reports have nothing to do with the programs I work with. Anyway, the reports that are run export the SQL data to Excel spreadsheets. Once the report is run, the Excel process is left running. This server is already extremely old and bogged down as is, so having over a hundred instances of Excel running on it wasn’t helping. I wrote a script to check for all processes named “excel” and see how long they have been running, then kill the ones that were running for what seem to be too long of time. I had some issues, because Server 2000 does not have all of the capabilies as 2003, obviously. This script requires that you download pskill, part of the PSTools suite from SysInternals(now Microsoft). Now, while the script requires PSKill, it is able to run on server 2000/2003/2008(and 2000/xp/vista/7), so hopefully it is still useful to someone else out there. The script is below and I tried to make sure it was well-commented to help you out. Feel free to leave any suggestions/questions below. Enjoy.


''''This script requires pskill, part of the PSTools suite from SysInternals(now Microsoft). This script is assuming pskill is in your path for cmd line(generally, c:\windows(winnt on 2000/nt)\system32\)

Option Explicit
Dim strComputer, objWMIService, colProcessList, objProcess, PDate, Days, Hrs, Min, Sec, objSWbemLocator, WshShell
strComputer = "."
Set WshShell = CreateObject("wscript.shell")
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process Where Name = 'Excel.exe'") ' Replace Excel with whatever the process is you're looking for.
Do
If colProcessList.Count = 0 Then ' This kills the script if the process we are looking for is not running.(also ties with last commented line for looping)
Exit Do
Else
For Each objProcess in colProcessList
If objProcess.CreationDate "" Then
PDate = Left(objProcess.CreationDate,14) ' pulls the date process started in format: yyyymmddhhmmss
Days = DateDiff("d",DateSerial(Left(PDate,4),Mid(PDate,5,2),Mid(PDate,7,2)),Date) ' find how many days process has been running
Hrs = Hour(Now) - Mid(PDate,9,2) ' find how many hours process was running, if started same day
Min = Minute(Now) - Mid(PDate,11,2) ' same but for minutes
Sec = Second(Now) - Mid(Pdate,13,2) ' same but for seconds
If Hrs > 6 Then ' This is where you specify how long the process has to have been running in order for it to be killed, so you don't kill active jobs. Change it from "Hrs" to "Min" or "Sec" for minutes or seconds. Change 6 to whatever number of units.(currently set to kill processes over 6 hours old)
WshShell.Run "pskill -t " & objProcess.ProcessId, 0, False
Else
If Days > 0 Then ' This is a failsafe to the previous "If". Since it only detects how many hours process was running, if started same day. This guarantees that it kills anything over a day old.
WshShell.Run "pskill -t " & objProcess.ProcessId, 0, False
End If
End If
End If
Next
WScript.Sleep 1000 ' wait before trying again
Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process Where Name = 'Excel.exe'") ' Recheck for processes ' This makes the script keep looking until there aren't any active processes. i.e. a report is being run now, we will wait until it is done to kill the process and the script.
End If
Loop

Login Script for Everyone

Monday, September 21st, 2009

UPDATED 12/23/09: The script on the bottom is the original.  I have made a few changes to log all errors and to fix a couple glitches that come up in some environments.  Changed the syntax of the addWindowsPrinterConnection command, and made it set default printer.  Here is the new script(the original post is below):


Option Explicit
Const ADS_PROPERTY_APPEND = 3 'sets the variable to Append
Const ADS_UF_NORMAL_ACCOUNT = 512
Const E_ADS_PROPERTY_NOT_FOUND = &h8000500D
CONST HKEY_LOCAL_MACHINE = &H80000002
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8

Dim WshShell : Set WshShell = CreateObject(”wscript.shell”)
Dim strContainer, strUser, i, objRootDSE, strDisplayName, ObjFSO, objInFile, objContainer, strLine, strName, objOU, objGroup, objUser, objFile, objFile2, varDomainNC, objRoot, strText, FirstLine, arrMemberOf, Group, strFirstName, strLastName, strLine2, objOU2, objNetwork, strGroup, objConnection, objCommand, objRecordSet, objErrorLog, strComputer, colItems, objWMIService, colInstalledPrinters, strComputer2
Set objOU2 = GetObject(”LDAP://CN=users,DC=domain,DC=local”)
Set objOU = GetObject(”LDAP://ou=users,ou=indianapolis,DC=domain,DC=local”)
ObjOU.Filter= Array(”user”)
Set objGroup = objOU2.Getobject(”group”, “cn=CSRs”)
Set objFSO = CreateObject(”Scripting.FileSystemObject”)
Set objNetwork = WScript.CreateObject(”Wscript.Network”)
Set objRootDSE = GetObject(”LDAP://rootDSE”)
strComputer2 = “.”
Dim CRLF
CRLF = Chr(13) & Chr(10)

‘*************(Global Scripting) this section applies to all computers no matter what group users are in.

”default lockheed banner script
Function Ask(strAction)

Dim intButton
intButton = MsgBox(strAction, _
vbQuestion + vbYesNo, _
L_Welcome_MsgBox_Title_Text )
Ask = intButton = vbYes

End Function

MsgBox “This system is the property of this Corporation, and is intended for” & CRLF & _
“the use of authorized users only. All activities of individuals using this computer” & CRLF & _
“with or without authority, or in excess of their authority, may be monitored and recorded” & CRLF & _
“by system personnel. If any such monitoring reveals evidence of criminal activity or is in” & CRLF & _
“violation of foreign or U.S. state or federal law, such evidence may be provided to law” & CRLF & _
“enforcement officials and/or used for further legal action by this Corporation and/or the” & CRLF & _
“organization’s Information Protection group. Unauthorized use of this system is prohibited” & CRLF & _
“and may result in revocation of access, disciplinary action and/or legal action. The” & CRLF & _
“company reserves the right to monitor and review user activity, files and electronic messages.” & CRLF & _
“REMINDER: Information transmitted to a foreign person on this network may be subject ” & CRLF & _
“to applicable Export Control laws. Contact your Export Coordinator for assistance.” & CRLF & _
“(This machine is not authorized for classified processing)”, _
vbOKOnly, _
“SYSTEM USE MONITORING NOTICE – IPM-003 Banner Statement”

WshShell.Run “net use s: /delete”, 0, False
WshShell.Run “Net use s: \\server\shared /persistent:yes”, 0, False

‘*************End of global scripting

”pull local computer name for loggin info.
strComputer = objNetwork.ComputerName

”pull logon id
strUser = objNetwork.UserName

”turn logon id into container name for LDAP queries

Set objConnection = CreateObject(”ADODB.Connection”)
objConnection.Open “Provider=ADsDSOObject;”
Set objCommand = CreateObject(”ADODB.Command”)
objCommand.ActiveConnection = objConnection
objCommand.CommandText = “;(&(objectCategory=User)(samAccountName=” & strUser & “));name;subtree”
Set objRecordSet = objCommand.Execute
On Error Resume Next
strUser = objRecordSet.Fields(”name”)
On Error GoTo 0
objConnection.Close
Set objRecordSet = Nothing
Set objCommand = Nothing
Set objConnection = Nothing
strUser = Replace(strUser, “,”, “\,”)

‘’set user to have LDAP queries run
ON ERROR RESUME NEXT
Set objUser = GetObject(”LDAP://cn=” & strUser & “,ou=users,ou=indianapolis,dc=domain,dc=local”)
If Err.Number = 0 Then

”\/\/\/\/\/\/Determine Group memberships. PLEASE NOTE: group names must be in UPPER case and the “Left(strGroup, X)”
‘ X must be the number of characters in the group name.
‘\/\/\/\/\/\/\/

arrMemberOf = objUser.GetEx(”memberOf”)

If Err.Number <> E_ADS_PROPERTY_NOT_FOUND Then
For Each Group in arrMemberOf
strGroup = UCase(Group)
strGroup = Right(strGroup, Len(strGroup) – 3)
If Left(strGroup, 2) = “IT” Then
‘*****IT group scripting

‘’set Z:IT drive
WshShell.Run “net use z: /delete”, 0, False
WshShell.Run “Net use z: \\server\it /persistent:yes”, 0, False

”Prepare to set printers
Set objWMIService = GetObject(”winmgmts:\\” & strComputer & “\root\cimv2″)

”This prevents script from stopping when mapping network printers on the server where they
”are shared from
ON ERROR RESUME NEXT

”Add Printers

objNetwork.AddWindowsPrinterConnection “\\server\Xerox WorkCentre 5675 PS”
objNetwork.SetDefaultPrinter “\\server\Xerox WorkCentre 5675 PS”

‘*****End of IT
Else
If Left(strGroup, 4) = “CSRS” Then
‘*****CSR group scripting

‘*****End of CSR
Else
If Left(strGroup, 10) = “MANAGEMENT” Then
‘*****Management group scripting – NOTE: all managers are members of “Team Leads” group

‘*****End of Management
Else
If Left(strGroup, 7) = “Quality” Then
‘*****Quality scripting – NOTE: all quality are members of “TeamLeads” group

‘*****End of Quality
Else
If Left(strGroup, 10) = “TEAMLEADS” Then
‘*****Team Lead scripting

”Prepare to set printers
Set objWMIService = GetObject(”winmgmts:\\” & strComputer & “\root\cimv2″)

”This prevents script from stopping when mapping network printers on the server
”where they are shared from
ON ERROR RESUME NEXT

”Add Printers
objNetwork.AddWindowsPrinterConnection “\\server\Xerox WorkCentre 5675 PS”

‘*****End of Team Lead
End If
End If
End If
End If
End If
Next
Else
‘*****Create Error Log if groups could not be determined

Set objErrorLog = objFSO.OpenTextFile(”\\server\errors\signonerrors.txt”, ForAppending, True)
objErrorLog.WriteLine strUser & ” on ” & strComputer & ” could not be found in Active Directory on ” & Date
objErrorLog.WriteLine “The error code is ” & Err.Number
Err.Clear
End If
Else
‘*****Create Error Log for all other errors
Set objErrorLog = objFSO.OpenTextFile(”\\server\errors\signonerrors.txt”, ForAppending, True)
objErrorLog.WriteLine strUser & ” on ” & strComputer & ” had the following error: ” & Err.Number & ” on ” & Date
Err.Clear
End If

ORIGINAL POST: We have a new program in with a new domain. On our other networks, there are seperate logon scripts for pretty much every security group and they all call other scripts. With this network, i wanted to keep things simple, so this script connects to AD and checks their group membership before running the apropriate commands for each group. This particular network does not have any shares yet, and isn’t very complex, but here is the base of it. Let me know if you want to know how to add anything more to it.

Option Explicit
Const ADS_PROPERTY_APPEND = 3 'sets the variable to Append
Const ADS_UF_NORMAL_ACCOUNT = 512
Const E_ADS_PROPERTY_NOT_FOUND = &h8000500D
CONST HKEY_LOCAL_MACHINE = &H80000002
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8

Dim WshShell : Set WshShell = CreateObject(”wscript.shell”)
Dim strContainer, strUser, i, objRootDSE, strDisplayName, ObjFSO, objInFile, objContainer, strLine, strName, objOU, objGroup, objUser, objFile, objFile2, varDomainNC, objRoot, strText, FirstLine, arrMemberOf, Group, strFirstName, strLastName, strLine2, objOU2, objNetwork, strGroup, objConnection, objCommand, objRecordSet, objErrorLog, strComputer, colItems, objWMIService, colInstalledPrinters, strComputer2
Set objOU2 = GetObject(”LDAP://CN=users,DC=arra,DC=local”)
Set objOU = GetObject(”LDAP://OU=arra-users,DC=arra,DC=local”)
ObjOU.Filter= Array(”user”)
Set objGroup = objOU2.Getobject(”group”, “cn=CSRs”)
Set objFSO = CreateObject(”Scripting.FileSystemObject”)
Set objNetwork = WScript.CreateObject(”Wscript.Network”)
Set objRootDSE = GetObject(”LDAP://rootDSE”)
strComputer2 = “.”
Dim CRLF
CRLF = Chr(13) & Chr(10)

‘*************(Global Scripting) this section applies to all computers no matter what group users are in.

”default lockheed banner script
Function Ask(strAction)

Dim intButton
intButton = MsgBox(strAction, _
vbQuestion + vbYesNo, _
L_Welcome_MsgBox_Title_Text )
Ask = intButton = vbYes

End Function

MsgBox “This system is the property of this Corporation, and is intended for” & CRLF & _
“the use of authorized users only. All activities of individuals using this computer” & CRLF & _
“with or without authority, or in excess of their authority, may be monitored and recorded” & CRLF & _
“by system personnel. If any such monitoring reveals evidence of criminal activity or is in” & CRLF & _
“violation of foreign or U.S. state or federal law, such evidence may be provided to law” & CRLF & _
“enforcement officials and/or used for further legal action by this Corporation and/or the” & CRLF & _
“organization’s Information Protection group. Unauthorized use of this system is prohibited” & CRLF & _
“and may result in revocation of access, disciplinary action and/or legal action. The” & CRLF & _
“company reserves the right to monitor and review user activity, files and electronic messages.” & CRLF & _
“REMINDER: Information transmitted to a foreign person on this network may be subject ” & CRLF & _
“to applicable Export Control laws. Contact your Export Coordinator for assistance.” & CRLF & _
“(This machine is not authorized for classified processing)”, _
vbOKOnly, _
“SYSTEM USE MONITORING NOTICE – IPM-003 Banner Statement”

‘*************End of global scripting

”pull local computer name for loggin info.
strComputer = objNetwork.ComputerName

”pull logon id
strUser = objNetwork.UserName

”turn logon id into container name for LDAP queries

Set objConnection = CreateObject(”ADODB.Connection”)
objConnection.Open “Provider=ADsDSOObject;”
Set objCommand = CreateObject(”ADODB.Command”)
objCommand.ActiveConnection = objConnection
objCommand.CommandText = “;(&(objectCategory=User)(samAccountName=” & strUser & “));name;subtree”
Set objRecordSet = objCommand.Execute
On Error Resume Next
strUser = objRecordSet.Fields(”name”)
On Error GoTo 0
objConnection.Close
Set objRecordSet = Nothing
Set objCommand = Nothing
Set objConnection = Nothing

‘’set user to have LDAP queries run
Set objUser = GetObject(”LDAP://cn=” & strUser & “,ou=arra-users,dc=arra,dc=local”)

”\/\/\/\/\/\/Determine Group memberships. PLEASE NOTE: group names must be in UPPER case and the “Left(strGroup, X)”
‘ X must be the number of characters in the group name.
‘\/\/\/\/\/\/\/

arrMemberOf = objUser.GetEx(”memberOf”)

If Err.Number E_ADS_PROPERTY_NOT_FOUND Then
For Each Group in arrMemberOf
strGroup = UCase(Group)
strGroup = Right(strGroup, Len(strGroup) – 3)
If Left(strGroup, 2) = “IT” Then
‘*****IT group scripting

‘’set Z:IT drive
WshShell.Run “net use z: /delete”, 0, False
WshShell.Run “Net use z: \\indarradc04\it”, 0, False

”Prepare to set printers
Set objWMIService = GetObject(”winmgmts:\\” & strComputer & “\root\cimv2″)

”This prevents script from stopping when mapping network printers on the server where they
”are shared from
ON ERROR RESUME NEXT

”Add Printers
objNetwork.AddWindowsPrinterConnection(”\\indarradc03\Xerox WorkCentre 5675 PS”)

‘*****End of IT
Else
If Left(strGroup, 4) = “CSRS” Then
‘*****CSR group scripting

‘*****End of CSR
Else
If Left(strGroup, 10) = “MANAGEMENT” Then
‘*****Management group scripting – NOTE: all managers are members of “Team Leads” group

‘*****End of Management
Else
If Left(strGroup, 10) = “TEAM LEADS” Then
‘*****Team Lead scripting

”Prepare to set printers
Set objWMIService = GetObject(”winmgmts:\\” & strComputer & “\root\cimv2″)

”This prevents script from stopping when mapping network printers on the server
”where they are shared from
ON ERROR RESUME NEXT

”Add Printers
objNetwork.AddWindowsPrinterConnection(”\\indarradc03\Xerox WorkCentre 5675 PS”)

‘*****End of Team Lead
End If
End If
End If
End If
Next
Else
‘*****Create Error Log if groups could not be determined

Set objErrorLog = objFSO.OpenTextFile(”\\indarradc04\errors\signonerrors.txt”, ForAppending, True)
objErrorLog.WriteLine strUser & ” on ” & strComputer & ” could not be found in Active Directory on ” & Date
Err.Clear
End If

Again, let me know if you need help modifying/adding anything for your own use.

**UPDATE(9/25)**

Changed the
WshShell.Exec(”net use…”)
lines to
WshShell.Run “net use…”, 0, False

This allows us(and does it already) to set any outside commands or scripts(in this case mapping drives, but can call bat files or whatever) to run invisibly(the 0), and “False” says to continue with the rest of the script immediately, True would mean to wait for the outside command to complete before continuing. This site has the details.

Run Method(Windows Script Host)

Bulk Add of Users to Active Directory – vbscript

Monday, September 21st, 2009

This script is fairly basic. We have a temporary(7-12 month) program coming in and they need their own domain. They won’t have exchange or really need AD for anything except authentication and GPOs. This was made for server 2008, but everything works on 2000/2003. We got a list of 85 names for user accounts in a text file, so this is how i used them for input. anyway, here it is:

Option Explicit
Const ADS_PROPERTY_APPEND = 3 'sets the variable to Append
Const ADS_UF_NORMAL_ACCOUNT = 512
Const ForReading = 1
Dim strcontainer, strUser, i, objRootDSE, strDisplayName, ObjFSO, objInFile, objContainer, strLine, strName, objOU, objGroup, objUser, objFile, objFile2, varDomainNC, objRoot, strText, FirstLine, strFirstName, strLastName, strLine2, objOU2
Set objOU2 = GetObject("LDAP://CN=users,DC=arra,DC=local")
Set objOU = GetObject("LDAP://OU=arra-users,DC=arra,DC=local")
Set objGroup = objOU2.Getobject("group", "cn=CSRs")
strContainer = "ou=Arra-Users"
Set objFSO = CreateObject("Scripting.FileSystemObject")

'***********************************************
'* Connect to a container *
'***********************************************
Set objRootDSE = GetObject("LDAP://rootDSE")
If strContainer = "" Then
Set objContainer = GetObject("LDAP://" & _
objRootDSE.Get("defaultNamingContext"))
Else
Set objContainer = GetObject("LDAP://" & strContainer & "," & _
objRootDSE.Get("defaultNamingContext"))
End If
'***********************************************
'* End connect to a container *
'***********************************************

Set objInFile = objFSO.OpenTextFile("C:\Users\webbc\Desktop\Users.txt", ForReading)
Do until objInFile.AtEndOfStream
strLine2 = objInFile.ReadLine
FirstLine = 0

strText = Replace(strLine2, " ", "§§")
Dim arrText : arrText = Split(strText, "§§")

For Each strLine In arrText
If FirstLine 1 Then
FirstLine = FirstLine + 1
strLine = Replace(strLine, "§§", "")
strFirstName = strLine
Else
strLine = Replace(strLine, "§§", "")
strLastName = strLine
End If
Next

strUser = Left(strFirstName, 1) & strLastName
strDisplayName = strFirstName & " " & strLastName

Set objUser = objContainer.Create("User", "cn =" & strDisplayName)
objUser.Put "displayName", strDisplayName
objUser.Put "description", strLastName & ", " & strFirstName
objUser.Put "sAMAccountName", strUser
objUser.Put "givenName", strFirstName
objUser.Put "sn", strLastName
objUser.Put "userPrincipalName", strUser & "@arra.local"
objUser.Put "Homedrive", "h"
objUser.Put "scriptPath", "login.bat"
objUser.Put "HomeDirectory", "\\indarradc03\Home\" & strUser
objUser.SetInfo

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.CreateFolder("\\indarradc03\Home" & "\" & strUser)

objUser.AccountDisabled = FALSE
objUser.Put "pwdLastSet", 0

'* edit the password to suit

objUser.SetPassword("NewPassword1")
objUser.SetInfo

objGroup.PutEx ADS_PROPERTY_APPEND, "member", Array("cn=" & strDisplayName & ",OU=arra-users,dc=arra,dc=local")
objGroup.SetInfo
Loop

Let me know if you have any questions.

VBScript to find a file (virtually) anywhere in the domain.

Wednesday, August 5th, 2009

Alright, I haven’t posted in a while, but I also haven’t had any new issues develop that I felt would be helpful or insightful to any of you out there. But today, I did have to write a script to find out if a file had been copied from the directory it was supposed to be in to any other place in the domain. At first, I thought they were crazy, but I turned to my good friend VBScript and got the job done. There are several pieces to this script, each very useful in it’s own right. First, it connects to the domain controller and finds out what domain you are in(handy if you work on several domains and don’t want to fiddle to make it work different places), then it makes a .txt file with every computer account in the domain on a line. The next step is pinging each of the machines listed to see if they are are available. Then, it connects and scans the C drive (via c$) for the file name recursively scans hidden folders and files as well. Then, it finds any shared folders on the system(say a server, where shares are not on C:) and scans them recursively. It reports if the file was found on the system or not and if it was, the exact location on the machine. Anyway, let me know if you have any questions on how to get this working for different scenarios or need to just make certain snippets work.

***Updated 8/7/09 with revisions to make script shorter, more efficient and work better with regular expression/pattern searching***

''Script to find all machines in AD, search C drive of all machines for a pattern in the filename, then search any shared folders for the file and reports
'' whether it was found and whether the machines are reachable by ping.
'' Side Note -- Can not scan shares on Windows 2000 or older, it will simply skip those shares. It will still scan C drive on Windows 2000, not NT

Option Explicit
CONST HKEY_LOCAL_MACHINE = &H80000002
Const ForReading = 1
Const ForWriting = 2
Const ForAppending = 8
Dim strResultsFile, strServerName, strErrorNumber, strErrorDescription
Dim strAge, strLatestFile, strClientName, strDNSDomain
Dim strBase, strFilter, strAttributes, strQuery
Dim objWMIService, objLocator, objResultsFile, objRootDSE, objCommand, objConnection
Dim objRecordSet
Dim strSearchName
Dim objNetwork : Set objNetwork = CreateObject("WScript.Network")
Dim strFileName : strFileName = "computers.txt"
Dim objFSO : Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim WshShell : Set WshShell = CreateObject("wscript.shell")
Dim i
Dim ii
Dim objFile, objCurrentFile, objTempList, objFS, objList, strCurrentFile2, objLogFile1, objLogFile2
Dim strComputer()
Dim strRet

'Here, you can put in the Regulare Expression pattern to use when searching.
Dim objRegEx : Set objRegEx = CreateObject("VBScript.RegExp")
objRegEx.Global = True
objRegEx.IgnoreCase = True
objRegEx.Pattern = ".*pip_dvalles.*"

Dim IsFound
Dim strReply, png, strPing
Dim strList, objShare, strShare
Dim strShares()
Dim strDate, strTime, strHour, strMinute, strSeconds, Now, NowStart, ConnectTime
NowStart = Now
strResultsFile = "computers.txt"
strDate = CStr(Year(Date) * 10000 + Month(Date) * 100 + Day(Date))
strTime = Time
strHour = Hour (strTime)
strMinute = Minute (strTime)
strSeconds = Second (strTime)
Dim strFound, strNotFound
strFound = "C:\Found.txt"
strNotFound = "C:\NotFound.txt"

Set objLogFile1 = objFSO.OpenTextFile(strNotFound, ForAppending, True)
Set objLogFile2 = objFSO.OpenTextFile(strFound, ForAppending, True)

'Check for the presence of the Computer.txt file in the same folder as the script
If Not objFSO.FileExists(strFileName) Then

Set objResultsFile = objFsO.OpenTextFile (strResultsFile, ForWriting, True)
' Start getting a list of all servers from AD
' Determine DNS domain name from RootDSE object.
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("DefaultNamingContext")
'Start the ADO connection
Set objCommand = CreateObject("ADODB.Command")
Set objConnection = CreateObject("ADODB.Connection")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
objCommand.ActiveConnection = objConnection

'Set the ADO connection query strings
strBase = ""
strFilter = "(objectCategory=computer)"
strAttributes = "distinguishedName,objectCategory,name"

'Create the Query
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
objCommand.CommandText = strQuery
objCommand.Properties("Page Size") = 100
objCommand.Properties("Timeout") = 30
objCommand.Properties("Cache Results") = False
Set objRecordSet = objCommand.Execute

objRecordSet.MoveFirst

'Find all computers in the domain
While Not objRecordset.EOF
ON ERROR RESUME NEXT
strServerName = objRecordset.Fields("name")
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strServerName & "\root\cimv2")
strErrorNumber = Err.Number
strErrorDescription = Err.Description

objResultsFile.WriteLine strServerName

'NEXT!
objRecordSet.MoveNext

Wend
objResultsFile.Close
WScript.Echo "All computer accounts in " & strDNSDOMAIN & " have been found." & vbCrLf & "Click OK to scan for file: " & objSearchFile
Set objFile = objFSO.OpenTextFile(strFileName, ForReading)
Else
Set objFile = objFSO.OpenTextFile(strFileName, ForReading)
End if

'start parsing through computer.txt
Do Until objFile.AtEndOfStream
isFound = FALSE
Redim Preserve strComputer(i)
strComputer(i) = objFile.ReadLine

'Ping Computers to make sure that they are reachable.
Set png = WshShell.exec("ping -n 1 " & strComputer(i))
Do Until png.Status = 1 : WScript.Sleep 10 : Loop
strPing = png.StdOut.ReadAll

'NOTE: The string being looked for in the Instr is case sensitive.
'Do not change the case of any character which appears on the
'same line as a Case InStr. AS this will result in a failure.
Select Case True
Case InStr(strPing, "Request timed out") > 1
strReply = "Request timed out"
Case InStr(strPing, "could not find host") > 1
strReply = "Host not reachable"
Case InStr(strPing, "Reply from") > 1
strReply = "Ping Successful"
End Select

' Connects to the operating system's file system
ON ERROR RESUME NEXT
Set objFS = GetObject("WinNT://" & strComputer(i) & "/LanmanServer,FileService")
objList = ""

' Loops through each share and checks for file
For Each objShare In objFS
strShare = LCase(objShare.name)
Set objTempList = WshShell.Exec("cmd /c dir /a/s/b \\" & strComputer(i) & "\" & strShare)
Do Until objTempList.StdOut.AtEndOfStream
objCurrentFile = objTempList.StdOut.ReadLine
If objRegEx.Test(objFSO.GetBaseName(objCurrentFile)) Then
strCurrentFile2 = objfSO.GetBaseName(objCurrentFile)
objLogFile2.WriteLine Now & " - The file " & objSearchFile & " was found on " & strComputer(i) & " at " & objCurrentFile
isFound = True
Else
If isFound = False Then
isFound = False
Else
isFound = True
End If
End If
Loop
objList = LCase(objShare.name) & vbCrLf & objList
Next

'Check for file on remote PC
Set objTempList = WshShell.Exec("cmd /c dir /a/s/b \\" & strComputer(i) & "c$")
Do Until objTempList.StdOut.AtEndOfStream
objCurrentFile = objTempList.StdOut.ReadLine
If objRegEx.Test(objFSO.GetBaseName(objCurrentFile)) Then
strCurrentFile2 = objfSO.GetBaseName(objCurrentFile)
objLogFile2.WriteLine Now & " - The file " & objSearchFile & " was found on " & strComputer(i) & " at " & objCurrentFile
isFound = True
Else
If isFound = False Then
isFound = False
Else
isFound = True
End If
End If
Loop

'Write to Not Found Log, if not found.
If isFound = False Then
objLogFile1.WriteLine Now & "No File matching the pattern (" & objRegEx.Pattern & ") was found on " & strComputer(i)
End If
Loop
objLogFile1.Close
objLogFile2.Close
WScript.Echo "Done scanning, LogFiles are located at:" & vbCrLf & strFound & vbCrLf & strNotFound & vbCrLf & "Click OK to finish"

Hope this helps someone out there.

How to Modify Registry Settings via Batch File(or DOS promt) OR Making WSUS work

Wednesday, June 24th, 2009

The need for this came about recently at my new job.  The place has no patch management software in place and is incredibly far behind and failing compliance in their security audits.  I threw in a WSUS server, thinking it would be fairly easy since I had done it before in new environments without ever having a hitch.  Well, let me tell you, this was no picnic.  There were previously 4 seperate WSUS servers for different OUs… Stupid.  Anyway, it took me some time to remove the GPOs and remnants of the ols SUS servers.  They hadn’t been used in over 4 years and none of the current staff knew they ever existed anyway.

I cleaned everything up(or so I thought), and installed WSUS clean on our utility server(running Server 03).  synchronized with Microsoft and approved all critical updates.  I put in a GPO on the domain linked to the OUs containing anything that wasn’t a server, since I wasn’t up for going through checking server updates and they don’t have a test environment.  (There are well over 100 servers here, I don’t want to patch them all with a faulty patch and lose my job in less than a month)… Aanyway, only about 20/500 PCs joined, I tried everything from PSEXECing gpupdate /force, remotely installing the newest windows update client, and a couple other things.  nothing was working.  I went over the Group Policies dozens of times.  Why wasn’t it working?  I still have yet to figure it out, but I do have a workaround.

The settings for the clients that I wanted were as follows:

WSUS Server http://wsus:8530

Download and install every thrusday at 11pm

The registry keys for these settings are at:

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate

and

HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU

This is what I put in the .bat file:


reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate /v WUServer /t reg_sz /d "http://wsus:8350" /f
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate /v WUStatusServer /t reg_sz /d "http://wsus:8350" /f
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU /v UseWUServer /t reg_dword /d 1 /f
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU /v AUOptions /t reg_dword /d 4 /f
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU /v NoAutoUpdate /t reg_dword /d 0 /f
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU /v ScheduledInstallDay /t reg_dword /d 5 /f
reg add HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU /v ScheduledInstallTime /t reg_dword /d 23 /f

I set the script to run at Computer startup via GPO, and voila, They are all joining.  Now I need to figure out the cause of all my pain.  Here are a couple more resources that may help with other questions.  Leave a comment if you have any questions and I’ll do my best to answer it.

MS-DOS “REG” command help

Automatic Updates Registry Values

VBScript/GPO to Change Network Speed/Duplex settings

Thursday, June 4th, 2009

OK, so I have a project where there is a system in place to monitor user desktops and it is getting a 1 second lag.  I Can’t give much more detail than that, but the manufacturers of the software recommended setting the network speed of all servers/clients in the environment to 100M/Full.  This is only affecting a portion of our network and all of our equipment is GB/Full.  There are 80 users and 4 servers that need these changes made.  I needed a way to automate this switch to those particular machines, so I turned to VBscript and GPO.

Here is the script I used:


Option Explicit
Const HKEY_LOCAL_MACHINE = &H80000002
Const ForReading = 1

CheckAllNICS

Sub CheckAllNICS
Dim objFSO : Set objFSO = WScript.CreateObject(”Scripting.FileSystemObject”)
Dim InputFile, ArrayFile, i
InputFile=”localhost”

ArrayFile = Split(Trimws(InputFile),vbcrlf)

For i = 0 To UBound(Arrayfile)
If IsOnline(Arrayfile(i)) Then
IdentifyNIC(Arrayfile(i))
Else
WScript.Echo ArrayFile(i) & “,OFFLINE”
End If
Next
End Sub

Sub IdentifyNIC(strComputer)
Dim objReg
Dim blnNicFound
Dim strKeyPath,arrSubKeys,subkey,strValue
On Error Resume Next
blnNicFound = True
Set objReg = GetObject(”winmgmts:{impersonationLevel=impersonate}!\\” & strComputer & “\root\default:StdRegProv”)
If Err Then
WScript.Echo strComputer & “,ERROR READING REGISTRY”
Exit Sub
Else
strKeyPath = “System\Currentcontrolset\Control\Class\{4D36E972-E325-11CE-BFC1-08002be10318}”
objReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys

For Each subkey In arrSubKeys

objReg.GetStringvalue HKEY_LOCAL_MACHINE, strKeyPath & “\” & subkey,”DriverDesc”, strValue
Select Case strValue
Case “3Com EtherLink XL 10/100 PCI TX NIC (3C905B-TX)”
WScript.Echo “** CHECK DUPLEX SETTING MANUALLY **”
Exit Sub
Case “Broadcom NetXtreme 57xx Gigabit Controller”, “Broadcom NetXtreme Gigabit Ethernet”
CheckDuplexValue strKeyPath & “\” & subkey, “RequestedMediaType”, strComputer, strValue
Set strIntel = “false”
Exit Sub
Case “Broadcom NetXtreme Gigabit Ethernet”
CheckDuplexValue strKeyPath & “\” & subkey, “RequestedMediaType”, strComputer, strValue
Set strIntelA = “false”
Exit Sub
Case “HP NC7781 Gigabit Server Adapter
WScript.Echo “** CHECK DUPLEX SETTING MANUALLY **”
Exit Sub
Case “HP NC7782 Gigabit Server Adapter
WScript.Echo “** CHECK DUPLEX SETTING MANUALLY **”
Exit Sub
Case “Intel(R) 82540EM Based Network Connection”, “Intel(R) PRO/100 VE Network Connection”, “Intel(R) 82566DM-2 Gigabit Network Connection”, “Intel(R) PRO/100 VM Network Connection”, “Intel(R) PRO/1000 EB Network Connection with I/O Acceleration”, “Intel(R) PRO/1000 MT Network Connection”
CheckDuplexValue strKeyPath & “\” & subkey, “SpeedDuplex”, strComputer, strValue
Set strIntel = “true”
Exit Sub
Case “Marvell Yukon 88E8055 PCI-E Gigabit Ethernet Controller”
CheckDuplexValue strKeyPath & “\” & subkey, “ConnectionType_A”, strComputer, strValue
Exit Sub
Case “NVIDIA nForce Networking Controller”
CheckDuplexValue strKeyPath & “\” & subkey, “ForceSpeedDpx”, strComputer, strValue
Exit Sub
Case “Realtek RTL8139C+ Fast Ethernet NIC”
WScript.Echo “** CHECK DUPLEX SETTING MANUALLY **”
Exit Sub
Case Else
blnNicFound = False
End Select
Next

If Not blnNICFound Then
WScript.Echo “Unknown NIC on ” & strComputer
End If

End If
End Sub

‘ON INTEL 4 = 100/FULL, ALL OTHERS 6 = 100/FULL, 0 = AUTO FOR EVERY KNOWN NIC

Sub CheckDuplexValue (strDuplexSettingKeyPath,strDuplexSettingSubKey,strComputer,NICType)
Dim strValue
Dim objReg : Set objReg = GetObject(”winmgmts:{impersonationLevel=impersonate}!\\” & strComputer & “\root\default:StdRegProv”)
objReg.GetStringValue HKEY_LOCAL_MACHINE, strDuplexSettingKeyPath, strDuplexSettingSubKey, strValue
If strValue <> 6 Then
objReg.SetStringValue HKEY_LOCAL_MACHINE, strDuplexSettingKeyPath, strDuplexSettingSubKey, “6″
objReg.GetStringValue HKEY_LOCAL_MACHINE, strDuplexSettingKeyPath, strDuplexSettingSubKey, strValue
‘WScript.Echo strComputer & “,” & NICType & “,” & strDuplexSettingSubKey & “,” & strValue
End If
If strIntel = “true” Then
objReg.SetStringValue HKEY_LOCAL_MACHINE, strDuplexSettingKeyPath, strDuplexSettingSubKey, “4″
objReg.GetStringValue HKEY_LOCAL_MACHINE, strDuplexSettingKeyPath, strDuplexSettingSubKey, strValue
‘WScript.Echo strComputer & “,” & NICType & “,” & strDuplexSettingSubKey & “,” & strValue
End If

End Sub

Private Function trimWS(sTxt)
Dim oRE : Set oRE = New RegExp
oRE.Pattern = “(^\s+)|(\s+$)”
oRE.Global = True
trimWS = oRE.Replace( sTxt, “” )
End Function

Function IsOnline(PCName)
Dim objItem
Dim objPing : Set objPing = GetObject(”winmgmts:{impersonationLevel=impersonate}”)._
ExecQuery(”select * from Win32_PingStatus where address = ‘” & PCName & “‘”)

For Each objItem in objPing
If IsNull(objItem.ReplySize) Then
IsOnline = False
Else
IsOnline = True
End If
Next

End Function

So, basically, you need to find the key

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002bE10318}001

This is for any NIC on Windows XP.

The Line “DriverDesc” is the Driver name, it much match one of the names in the script above(I left the settings for all the various, to help ease the pain a bit).  Most Drivers will either have a DWORD for “RequestedMediaType”(Broadcom) or “SpeedDuplex”(Intel).  You will have to test to find for others, refer to the script if it helps.  The Registry values to set all cards to auto is “0″(zero), for ALL NICs.  to set to 100/Full, its 6(broadcom) or 4(intel).  adjust the script to meet your needs.

Then, I first tried to call the script from the user’s normal logon file: a batch script.  this would have worked, except users need admin rights to run vbscripts.  Since this is a high security environment, that was not an option.  So I linked a GPO to the OU for the computers I needed the settings changed on.  The GPO was:

Computer Configuration>Windows Settings>Scripts>Startup.  Simply put the path to the script and have the users reboot their machines.  When the machines come up, all pcs will be at the correct speed.

Leave a comment if you have any questions.  I would be glad to go more in depth about how the script works, if anyone cares to know.