Solved

VBscript need help with joining workstation to domain

Posted on 2011-02-16
3
905 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
ID: 34912849
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
ID: 34938864
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
ID: 34938906
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

U.S. Department of Agriculture and Acronis Access

With the new era of mobile computing, smartphones and tablets, wireless communications and cloud services, the USDA sought to take advantage of a mobilized workforce and the blurring lines between personal and corporate computing resources.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This script will sweep a range of IP addresses (class c only, 255.255.255.0) and report to a log the version of office installed. What it does: 1.)      Creates log file in the directory the script is run from (if it doesn't already exist) 2.)      Sweep…
For both online and offline retail, the cross-channel business is the most recent pattern in the B2C trade space.
This Micro Tutorial hows how you can integrate  Mac OSX to a Windows Active Directory Domain. Apple has made it easy to allow users to bind their macs to a windows domain with relative ease. The following video show how to bind OSX Mavericks to …
Two types of users will appreciate AOMEI Backupper Pro: 1 - Those with PCIe drives (and haven't found cloning software that works on them). 2 - Those who want a fast clone of their boot drive (no re-boots needed) and it can clone your drive wh…

809 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