Solved

VBscript need help with joining workstation to domain

Posted on 2011-02-16
3
902 Views
Last Modified: 2012-05-11
Hi my company has finally upgraded from RIS to WDS and I've found that the %MACHINENAME% variable doesn't work to name a XP machine during the sysprep's mini setup phase.  I've put together a script below which automates the machine name phase during sysprep in the cmdlines section.  
Because of company policy all workstations must be prestaged so this script below in a nut shell does the following:

- Finds the DCs using the DNS address assigned by DHCP
- Pulls the GUID from BIOS
- Queries AD using GUID retrieving D/Name associated with GUID
- Chanes computer with name pulled from AD
- Joins computer to domain

The problem i'm having is when I run the script on a workstaton, it changes the computer name and joins it to the domain but when i goto log on to the workstation is says the the 'computer account is not in AD or couldnt find a DC'.  The computer account is in AD with the associated GUID.
The funny thing is, if I run the script on a workstation that's already configured with the computer name it has associated with is GUID in AD, it joins the workstation to the domain and I can log on.

I'm not sure what to do from here.  Below is my script and if someone has any pointers or an easier way, im all ears.
Option Explicit


Dim colAdapters, nic, objPing, objstatus, strDNS
Dim objWMIService, strComputer, objSystems, objItem, colComputer, objCompItem
Dim strHexID, strGUID, k, strTMP
Dim adoCommand, adoConnection, strBase, strFilter, strAttributes
Dim objRootDSE, strDNSDomain, strQuery, adoRecordset, strDN
Dim objNS, strName, strUser, strPassword, strServer
Dim arrbytGUID, strHexGUID, arrbytSID, strHexSID, strDecSID

Const ADS_SECURE_AUTHENTICATION = &H1
Const ADS_SERVER_BIND = &H200

' Specify the local computer.
strComputer = "."

' Specify credentials.
strUser = "Domain\User"
strPassword = "password"

' Specify Domain Controller.

Set objWMIService = GetObject("winmgmts:" _
      & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colAdapters = objWMIService.ExecQuery _
      ("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")
For Each nic In colAdapters
              if Not IsNull(nic.DNSServerSearchOrder) Then
                  Set objPing = GetObject("winmgmts:{impersonationLevel=impersonate}")._
                    ExecQuery("select * from Win32_PingStatus where address = '"_
                       & nic.DNSServerSearchOrder(0) & "'")
                  For Each objStatus in objPing
                        If IsNull(objStatus.StatusCode) Or objStatus.StatusCode = 0 Then
                        strServer = nic.DNSServerSearchOrder(0)
                        Else
                              strServer = nic.DNSServerSearchOrder(1)
                        End If
                  Next
            End If
Next

'get the local netbootGUID in format: {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Set colComputer = objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystemProduct")
For Each objCompItem In colComputer
  strGUID = "{" & objCompItem.UUID & "}"
Next

' Convert hex string to escaped hex format.
strHexGUID = DisplayGUIDToEscapedHex(strGUID)
strGUID = strHexGUID

' Determine DNS domain name. Use server binding and alternate
' credentials. The value of strDNSDomain can also be hard coded.
Set objNS = GetObject("LDAP:")
Set objRootDSE = objNS.OpenDSObject("LDAP://" & strServer & "/RootDSE", _
     strUser, strPassword, _
     ADS_SERVER_BIND Or ADS_SECURE_AUTHENTICATION)
strDNSDomain = "DC=Domain,DC=com,DC=au"

'objRootDSE.Get("defaultNamingContext")

' Create the ADO Connection object.
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Properties("User ID") = strUser
adoConnection.Properties("Password") = strPassword
adoConnection.Properties("Encrypt Password") = True
adoConnection.Properties("ADSI Flag") = ADS_SERVER_BIND _
     Or ADS_SECURE_AUTHENTICATION
adoConnection.Open "Active Directory Provider"
Set adoCommand = CreateObject("ADODB.Command")
adoCommand.ActiveConnection = adoConnection

strBase = "<LDAP://" & strServer & "/" & strDNSDomain & ">"

' Filter on computer object with netbootGUID equal to local GUID.
strFilter = "(&(objectCategory=computer)" _
    & "(netbootGUID=" & strGUID & "))"

' Comma delimited list of attribute values to retrieve.
strAttributes = "distinguishedName,sAMAccountName"

' Construct the LDAP syntax query.
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False

' Run the query.
Set adoRecordset = adoCommand.Execute

' Enumerate the resulting recordset.
Do Until adoRecordset.EOF
    ' Retrieve values.
    strDN = adoRecordset.Fields("distinguishedName").Value
    strName = adoRecordset.Fields("sAMAccountName").Value
    ' Remove trailing "$" character.
    strName = Left(strName, Len(strName) - 1)
    adoRecordset.MoveNext
Loop

' Clean up.
adoRecordset.Close
adoConnection.Close

' Rename Computer and Join Domain
Const JOIN_DOMAIN = 1
Const ACCT_CREATE = 2
 
Dim sCmpName
Dim sUser, sPassword, sDomain, sOU

sUser = "User"
sPassword = "password"
sDomain = "Domain"
 
Dim oWMI, oCmp, oOS, sReturn
 
Set oWMI = GetObject("winmgmts:\\.\root\cimv2")
For Each oCmp in oWMI.InstancesOf("Win32_ComputerSystem")
  sReturn = oCmp.Rename(strName)
  sReturn = oCmp.JoinDomainOrWorkgroup(sDomain, sPassword, _
    sDomain & "\" & sUser,, JOIN_DOMAIN+ACCT_CREATE)
Next

 Function DisplayGUIDToEscapedHex(ByVal strGUID)
    ' Function to convert GUID value from display string to
    ' escaped hex format (every byte escaped with a backslash).

    Dim TempGUID

    TempGUID = Replace(strGUID, "{", "")
    TempGUID = Replace(TempGUID, "}", "")
    TempGUID = Replace(TempGUID, "-", "")
    DisplayGUIDToEscapedHex = "\" & Mid(TempGUID, 7, 2) _
          & "\" & Mid(TempGUID, 5, 2) _
       & "\" & Mid(TempGUID, 3, 2) _
       & "\" & Mid(TempGUID, 1, 2) _
       & "\" & Mid(TempGUID, 11, 2) _
       & "\" & Mid(TempGUID, 9, 2) _
       & "\" & Mid(TempGUID, 15, 2) _
       & "\" & Mid(TempGUID, 13, 2) _
       & "\" & Mid(TempGUID, 17, 2) _
       & "\" & Mid(TempGUID, 19, 2) _
       & "\" & Mid(TempGUID, 21, 2) _
       & "\" & Mid(TempGUID, 23, 2) _
       & "\" & Mid(TempGUID, 25, 2) _
       & "\" & Mid(TempGUID, 27, 2) _
       & "\" & Mid(TempGUID, 29, 2) _
       & "\" & Mid(TempGUID, 31, 2)

End Function

0
Comment
Question by:Thunder-Cat
  • 2
3 Comments
 
LVL 65

Accepted Solution

by:
RobSampson earned 500 total points
Comment Utility
I would say you're going to need a reboot between these two lines:
  sReturn = oCmp.Rename(strName)
  sReturn = oCmp.JoinDomainOrWorkgroup(sDomain, sPassword, _
    sDomain & "\" & sUser,, JOIN_DOMAIN+ACCT_CREATE)


After renaming a computer, you would need to reboot before joining the domain.  I have added a reboot command, and a text file flag to let the script know if it's running after or before a reboot.  You will need to run the same script a second time after a reboot.

Regards,

Rob.
Option Explicit

Dim colAdapters, nic, objPing, objstatus, strDNS
Dim objWMIService, strComputer, objSystems, objItem, colComputer, objCompItem
Dim strHexID, strGUID, k, strTMP
Dim adoCommand, adoConnection, strBase, strFilter, strAttributes
Dim objRootDSE, strDNSDomain, strQuery, adoRecordset, strDN
Dim objNS, strName, strUser, strPassword, strServer
Dim arrbytGUID, strHexGUID, arrbytSID, strHexSID, strDecSID
Dim objFSO, strTempFile, objFile

Const ADS_SECURE_AUTHENTICATION = &H1
Const ADS_SERVER_BIND = &H200

' Specify the local computer.
strComputer = "."

' Specify credentials.
strUser = "Domain\User"
strPassword = "password"

strTempFile = "C:\REBOOTED.TXT"

' Specify Domain Controller.

Set objWMIService = GetObject("winmgmts:" _
      & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colAdapters = objWMIService.ExecQuery _
      ("SELECT * FROM Win32_NetworkAdapterConfiguration WHERE IPEnabled = True")
For Each nic In colAdapters
              if Not IsNull(nic.DNSServerSearchOrder) Then
                  Set objPing = GetObject("winmgmts:{impersonationLevel=impersonate}")._
                    ExecQuery("select * from Win32_PingStatus where address = '"_
                       & nic.DNSServerSearchOrder(0) & "'")
                  For Each objStatus in objPing
                        If IsNull(objStatus.StatusCode) Or objStatus.StatusCode = 0 Then 
                        strServer = nic.DNSServerSearchOrder(0)
                        Else
                              strServer = nic.DNSServerSearchOrder(1)
                        End If
                  Next
            End If
Next

'get the local netbootGUID in format: {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Set colComputer = objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystemProduct")
For Each objCompItem In colComputer
  strGUID = "{" & objCompItem.UUID & "}"
Next

' Convert hex string to escaped hex format.
strHexGUID = DisplayGUIDToEscapedHex(strGUID)
strGUID = strHexGUID

' Determine DNS domain name. Use server binding and alternate
' credentials. The value of strDNSDomain can also be hard coded.
Set objNS = GetObject("LDAP:")
Set objRootDSE = objNS.OpenDSObject("LDAP://" & strServer & "/RootDSE", _
     strUser, strPassword, _
     ADS_SERVER_BIND Or ADS_SECURE_AUTHENTICATION)
strDNSDomain = "DC=Domain,DC=com,DC=au"

'objRootDSE.Get("defaultNamingContext")

' Create the ADO Connection object.
Set adoConnection = CreateObject("ADODB.Connection")
adoConnection.Provider = "ADsDSOObject"
adoConnection.Properties("User ID") = strUser
adoConnection.Properties("Password") = strPassword
adoConnection.Properties("Encrypt Password") = True
adoConnection.Properties("ADSI Flag") = ADS_SERVER_BIND _
     Or ADS_SECURE_AUTHENTICATION
adoConnection.Open "Active Directory Provider" 
Set adoCommand = CreateObject("ADODB.Command")
adoCommand.ActiveConnection = adoConnection

strBase = "<LDAP://" & strServer & "/" & strDNSDomain & ">"

' Filter on computer object with netbootGUID equal to local GUID.
strFilter = "(&(objectCategory=computer)" _
    & "(netbootGUID=" & strGUID & "))"

' Comma delimited list of attribute values to retrieve.
strAttributes = "distinguishedName,sAMAccountName"

' Construct the LDAP syntax query.
strQuery = strBase & ";" & strFilter & ";" & strAttributes & ";subtree"
adoCommand.CommandText = strQuery
adoCommand.Properties("Page Size") = 100
adoCommand.Properties("Timeout") = 30
adoCommand.Properties("Cache Results") = False

' Run the query.
Set adoRecordset = adoCommand.Execute

' Enumerate the resulting recordset.
Do Until adoRecordset.EOF
    ' Retrieve values.
    strDN = adoRecordset.Fields("distinguishedName").Value
    strName = adoRecordset.Fields("sAMAccountName").Value
    ' Remove trailing "$" character.
    strName = Left(strName, Len(strName) - 1)
    adoRecordset.MoveNext
Loop

' Clean up.
adoRecordset.Close
adoConnection.Close

' Rename Computer and Join Domain
Const JOIN_DOMAIN = 1
Const ACCT_CREATE = 2
 
Dim sCmpName
Dim sUser, sPassword, sDomain, sOU

sUser = "User"
sPassword = "password"
sDomain = "Domain"
 
Dim oWMI, oCmp, oOS, sReturn, objOSSet, objOS
 
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FileExists(strTempFile) = False Then
	Set oWMI = GetObject("winmgmts:\\.\root\cimv2")
	For Each oCmp in oWMI.InstancesOf("Win32_ComputerSystem")
		sReturn = oCmp.Rename(strName)
	Next
	Set objFile = objFSO.CreateTextFile(strTempFile, True)
	objFile.Close
    Set objOSSet = GetObject("winmgmts:{(RemoteShutdown)}//./root/cimv2").ExecQuery("select * from Win32_OperatingSystem where Primary=true")
    For Each objOS In objOSSet
		objOS.Reboot()
    Next
Else
	Set oWMI = GetObject("winmgmts:\\.\root\cimv2")
	For Each oCmp in oWMI.InstancesOf("Win32_ComputerSystem")
		sReturn = oCmp.JoinDomainOrWorkgroup(sDomain, sPassword, _
			sDomain & "\" & sUser,, JOIN_DOMAIN+ACCT_CREATE)
	Next
	objFSO.DeleteFile strTempFile, True
	MsgBox "Computer has been joined to the domain."
End If

 Function DisplayGUIDToEscapedHex(ByVal strGUID)
    ' Function to convert GUID value from display string to
    ' escaped hex format (every byte escaped with a backslash).

    Dim TempGUID

    TempGUID = Replace(strGUID, "{", "")
    TempGUID = Replace(TempGUID, "}", "")
    TempGUID = Replace(TempGUID, "-", "")
    DisplayGUIDToEscapedHex = "\" & Mid(TempGUID, 7, 2) _
          & "\" & Mid(TempGUID, 5, 2) _
       & "\" & Mid(TempGUID, 3, 2) _
       & "\" & Mid(TempGUID, 1, 2) _
       & "\" & Mid(TempGUID, 11, 2) _
       & "\" & Mid(TempGUID, 9, 2) _
       & "\" & Mid(TempGUID, 15, 2) _
       & "\" & Mid(TempGUID, 13, 2) _
       & "\" & Mid(TempGUID, 17, 2) _
       & "\" & Mid(TempGUID, 19, 2) _
       & "\" & Mid(TempGUID, 21, 2) _
       & "\" & Mid(TempGUID, 23, 2) _
       & "\" & Mid(TempGUID, 25, 2) _
       & "\" & Mid(TempGUID, 27, 2) _
       & "\" & Mid(TempGUID, 29, 2) _
       & "\" & Mid(TempGUID, 31, 2)

End Function

Open in new window

0
 

Author Comment

by:Thunder-Cat
Comment Utility
Cheers that worked.  Now Ive got to try and get the script to run in the cmdlines file.  

When I add any of the lines in the cmdlines.txt file the script still doesn't run.

"C:\Wscript.exe VBScript.vbs"
"C:\Sysprep\i386\$OEM$\wscript.exe VBscipt.vbs"
"C:\Sysprep\i386\$OEM$\VBscipt.vbs"  

U have any pointers?
0
 
LVL 65

Expert Comment

by:RobSampson
Comment Utility
Try using
wscript C:\VBScript.vbs

or
C:\Windows\System32\wscript.exe C:\VBScript.vbs

wscript is it's own executable, and the full path to the VBS needs to be specified after it.

Regards,

Rob.
0

Featured Post

Threat Intelligence Starter Resources

Integrating threat intelligence can be challenging, and not all companies are ready. These resources can help you build awareness and prepare for defense.

Join & Write a Comment

It is only natural that we all want our PCs to be in good working order, improved system performance, so that is exactly how programs are advertised to entice. They say things like:            •      PC crashes? Get registry cleaner to repair it!    …
For both online and offline retail, the cross-channel business is the most recent pattern in the B2C trade space.
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now