Posts Tagged ‘active directory’

How To Seize FSMO Roles and Clean Up Failed Domain Controllers In Active Directory

Friday, December 18th, 2009

Alright, so I think at some point, every SysAdmin will have a domain controller fail.  Every SysAdmin should also know that unless you run dcpromo.exe to demote a domain controller before removing it from AD, you can have some issues.  From FSMO to DFRS, it’s just not a good situation.  Here is a summary guide on how to clean up AD after one of your Domain Controllers fail.  Also, this looks long, but it’s all very simple, just putting it into step-by-step sort of drags it out, so no worries, this should be about a 30 minute process.

USE CAUTION: Improperly using ntdsutil may result in partial or complete loss of Active Directory functionality… Don’t go exploring without doing your research.

STEP 1:

Finding Current FSMO Role Masters

First, We need to know whether that particular server was holding any of the FSMO roles.  To check this, we have a couple options, Either via the GUI(1), or via ntdsutil(2).  Personally, I prefer to do it via ntdsutil, as I always feel that there is more power in the command line.  Also, I just hate using a mouse. There are other options, but these two are all that I will cover in this post. For more you can look into “netdom” or “replmon” tools from microsoft, these are not included in windows by default, so I will overlook them for now.  (NOTE: For this, I definitely recommend ntdsutil, as in step 2, I will expect it to already be open and connected.  the GUI Method, is more for information.)

Method 1:

Open AD Users and Computers.

Right-click the name of the domain you are wanting to look at, then select Operations Masters.

FindFSMO1

From this view, you can determine the current Domain-Specific RID Master, PDC Emulator, and Infrastructure Master FSMO Roles.

Now, open AD Domains and Trusts,

Right-click the AD Domains and Trusts in the nav. pane and go to Operations Masters.  This will show you the Domain Naming Master Role.

Finally, to find the Schema Master, you will have an extra step.   You will need to register the Schmmgmt.dll library first.

Goto: Start>Run and type:

regsvr32 schmmgmt.dll

Hit Enter, you should see a success message.

Now, that should allow you to open a new console: AD Schema.  To open it, goto: Start>Run, type:

mmc

hit enter.  Now, in the management console, goto File>Add/Remove Snap-in> click Add.  Double Click Active Directory Schema and close the add/remove dialog windows.

Now, right-click the AD Schema icon and goto Operations Masters.

Method 2:

To check the FSMO Roles via the command line using ntdsutil, we will need to do the following.

Alright, let’s open up a command prompt, then type

ntdsutil

and hit enter.

at the ntdsutil prompt, you will type

roles

hit enter.

Now, you should see a screen that says “fsmo maintenance”.  type

connections

and hit enter again. Here you will connect to the server you want to become the FSMO master(localhost works, if thats what you want). So type:

connect to server <FQDN of server>

and hit enter again. now you will leave the server connections page and go back to fsmo maintenance. Type:

q

Now we should be back in fsmo maintenance, type

select operation target

Hit Enter. Then type:

list roles

Once you hit enter, it should show you the servers that hold each role.
FindFSMO2

Type “q” to get back to fsmo maintenance, but stay at this screen for the next step.

STEP 2:

Seizing FSMO Roles From Dead Server

OK, so this step is optional.  based on the results of your last step.  You only need to seize the roles if the FSMO master is no longer operational.  To do this step we will use ntdsutil.

Now, we need to seize the roles that are on our dead server.  You should know what roles your dead server holds from the last step, so only do this command for those.  Remember, I had you connect to the server that will receive the FSMO role(s).  A quick way to see the syntax for seizing is just type “?” and it will show you how to transfer/seize, it is basically:

seize <role>

as in:

seize schema master

or for transfers(only to be done if current master is still live/active)

transfer <role>

To verify the roles transferred(ignore the errors you get at first, you are guaranteed to have one since the current master is unavailable), put in

select operation target

then the same way we found the masters before:

list roles for connected server

Now, we’re almost done, we have transferred the FSMO roles(the biggest potential problem), and just need to cleanup the AD metadata and sites/services.

STEP 3:

Metadata Cleanup

For the next step, we will go back to the first ntdsutil prompt.  type “q” and hit enter until your prompt says “ntdsutil:”.  Type

metadata cleanup

hit enter. You should still be connected to a domain controller, but if you closed ntdsutil and reopened it, you will need to put in

connections

then

connect to server <servername>

then type quit back to the metadata cleanup prompt (”q”). Now, we will pick our target for cleanup. Type:

select operation target

At this point, if you only have 1 domain, or within the domain you pick, only 1 site, you can skip some steps. Your domain number, site number will be “0″(zero) if there is only one. For the sake of thoroughness, I will show you how to find the index anyway. To find the domain, type:

list domains

Now, find the domain you want to work with, and type:

select domain <number>

Now, we find the site within the domain where the domain controller used to reside.

list sites

put in the site you want:

select site <number>

To find the servers within that site, type:

list servers in site

then we will select the inactive server by typing:

select server <number>

Now, type enter “q” to quit back to metadata cleanup prompt. The final command to cleanup all metadata for that server is:

remove selected

You will receive a warning, but if you’re positive that server is down and will need rebuilt, you should be safe to hit Yes.  You should get a message saying it was removed successfully.  If you receive an error that the object could not be found, it was probably already removed from the domain controller.  Open up AD Users and Computers to verify the server is gone from the Domain Controllers OU.  Alright, we’re almost done, just another 5 minutes of work, at the most.

Step 4:

Remove The Server From Sites & Services

This will be done via the AD Sites & Services Snap-in.  Just expand the site where the server was located, and delete the object for the failed server… This step is done.

Step 5:

Remove The Server From DNS

This step depends a lot on how you have your DNS set up, I am assuming the DNS is run on a Windows server, and hopefully a DC.  It doesn’t have to be, that’s just how i prefer it.  Unfortunately, where I work, The DNS servers are separate and I have no access to them… such a pain.  Anyway, open up your DNS Management Console.  I hope you know this, but it’s:
Start>run> type “mmc”, hit enter. Goto File>Add/Remove Snap-in>hit Add>double-click DNS>Close>Close.
Now, expand the zone where the server used to be(probably Forward Lookup Zones>domain.local), and delete the A record(also called a host record) for the server. Remove the CNAME record in the _msdcs.root domain of forest zone in DNS. If you have reverse lookup zones, also remove the server from these zones. If you have anywhere else the server is referenced, or are unsure, you might want to check for these now.

You’re Done!  Now, you should be good to go.  Let me know if any of you have issues with this guide, notice anything wrong, or just have errors/questions.  I will be glad to help, and I know I have some pretty atrocious grammar/spelling at times.

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.

Java Remote Install via GPO and Permissions

Monday, June 29th, 2009

Alright, so we had some training that needed the latest Java(6u14) to work.  I extracted the .msi and pushed it out by GPO by doing the following:

Download the version you want from: http://java.com/en/download/manual.jsp

Install Java to the machine you are using.  Once done, go to

C:\documents and settings\<your username>\application data\sun\java\jre<version> folder.

In this folder, there is an msi and a file called data1.cab.  Copy this to a file share accessible by the clients.

Go to GPMC and add  a new GPO, go to Computer Settings>Software Settings>Software Installation>Right click and add new.  Put in the UNC to the msi file(the cab must be in the same directory as the msi btw).  Then set any permissions you want by going to the properties after it is added.

This is the basic way to get Java to install via GPO.  We had one issue, where the training application needed users to have admin rights to the Java folder for the training to run.  Here is what I did for that.

First, make sure you have PSExec installed on the machine you ware working on.

Run a command psexec \\<remote machine name> echo y| cacls “c:\program files\java” /g “<domain>\domain users”:f

This grants any domain users on the machine have /f(full access) to the java folder.  The echo y| is piped in because, cacls command doesnt have a switch to automatically answer y/n to confirm.  this pipes in the y after you run the command.

There is a great program out there for modifying settings in MSI files.  It’s called orca.  you can get it here. Once installed you can do a ctrl+f to find settings and change them.  Some googling may be needed to find what values things need to be set to, but this is one that I do with Java to make it not prompt users for updates constantly.

In orcca, open the jre<version> msi and go to Property table(left column) and find AutoUpdateCheck in the right side.  Change the value to 0(zero).  Then save the msi.  For more options, you can find info on sun’s website and just by looking through the msi in orca.  A lot of the options are selfexplanatory, but there is the ability to go way more in depth than I currently know how, as well.