Solved

VBscript need help with joining workstation to domain

Posted on 2011-02-16
3
906 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

Migrating Your Company's PCs

To keep pace with competitors, businesses must keep employees productive, and that means providing them with the latest technology. This document provides the tips and tricks you need to help you migrate an outdated PC fleet to new desktops, laptops, and tablets.

Question has a verified solution.

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

Can I legally transfer my OEM version of Windows to another PC?  (AKA - Can I put a new systemboard in my OEM PC?) Few of us are both IT and legal experts but we all have our own views of Microsoft's licensing rules and how they apply.  There are…
Over the years I have built up my own little library of code snippets that I refer to when programming or writing a script.  Many of these have come from the web or adaptations from snippets I find on the Web.  Periodically I add to them when I come…
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…
A short tutorial showing how to set up an email signature in Outlook on the Web (previously known as OWA). For free email signatures designs, visit https://www.mail-signatures.com/articles/signature-templates/?sts=6651 If you want to manage em…

789 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