Script to Join a Computer to the Domain

by Jeremy Saunders on November 28, 2009

This script will join a computer to a domain. You can either specify the parameters as command line arguments, or look them up in an ini file.

If an OU is not specified, the value is set to NULL, which means that the computer object will be placed in the OU/Container that is set as the Domain default within Active Directory, which is typically the Computers container.

It also checks to see if the computer object already exists in AD. If it does, it will join to the object in its existing location.

IMPORTANT: Refer to the %SystemRoot%\Debug\NetSetup.LOG file to help fault find any issues with the domain joining process.

Syntax of command line, if specifying arguments:

cscript JoinDomain.vbs “[domain]” “[username]” “[password]” “[MachineAccountOU]”

Example of command line, if specifying arguments:

cscript JoinDomain.vbs “mydomain.com” “build” “password” “OU=Citrix,OU=Servers,DC=myDomain,DC=com”

Example of the contents of the JoinDomain.ini file:

[Identification]
JoinDomain = mydomain.com
DomainAdmin = build
DomainAdminPassword = “password”
MachineObjectOU = “OU=New,OU=Servers,DC=myDomain,DC=com”


‘ This script will join a computer to a domain. You can either specify the parameters as
‘ command line arguments, or look them up in an ini file.
‘ If an OU is not specified, the value is set to NULL, which means that the computer
‘ object will be placed in the OU/Container that is set as the Domain default within
‘ Active Directory.
‘ It also checks to see if the computer object already exists in AD. If it does, it will
‘ join to the object in its existing location.

‘ IMPORTANT: Refer to the %SystemRoot%\Debug\NetSetup.LOG file to help fault find any
‘ issues with the domain joining process.

‘ Release 1.2 by Jeremy@jhouseconsulting.com on 5th March 2010.
‘ Written by Jeremy@jhouseconsulting.com on 13th November 2009.

‘ Syntax of command line, if specifying arguments:
‘ cscript JoinDomain.vbs “” “” “” “

‘ Example of command line, if specifying arguments:
‘ cscript JoinDomain.vbs “mydomain.com” “build” “password” “OU=Citrix,OU=Servers,DC=myDomain,DC=com”

‘ Example of the contents of the JoinDomain.ini file:

‘ [Identification]
‘ JoinDomain = mydomain.com
‘ DomainAdmin = build
‘ DomainAdminPassword = “password”
‘ MachineObjectOU = “OU=New,OU=Servers,DC=myDomain,DC=com”

Option Explicit

Const JOIN_DOMAIN = 1
Const ACCT_CREATE = 2
Const ACCT_DELETE = 4
Const WIN9X_UPGRADE = 16
Const DOMAIN_JOIN_IF_JOINED = 32
Const JOIN_UNSECURE = 64
Const MACHINE_PASSWORD_PASSED = 128
Const DEFERRED_SPN_SET = 256
Const INSTALL_INVOCATION = 262144

Dim wshShell, objFSO, sScriptFullName, sScriptPath, blnUseArgs, strDomain, strUser
Dim strPassword, strOU, objNetwork, strComputer, strExistingLocation, objComputer
Dim intReturn, strSystemDrive, striniFileLocation, striniFile, strErrorDescription
Dim blnDebug

blnDebug = False

Set wshShell = CreateObject(“wscript.shell”)
Set objFSO = CreateObject(“Scripting.FileSystemObject”)
sScriptFullName = WScript.ScriptFullName
sScriptPath = Left(sScriptFullName, InStrRev(sScriptFullName, “\”))
strSystemDrive = WshShell.ExpandEnvironmentStrings(“%SystemDrive%”)
striniFileLocation =strSystemDrive & “\wininst\”
striniFile = striniFileLocation & “JoinDomain.ini”
If NOT objFSO.FileExists(striniFile) Then
striniFile = sScriptPath & “JoinDomain.ini”
End If

If WScript.Arguments.Count < 3 Then blnUseArgs = False Else blnUseArgs = True strDomain = WScript.Arguments(0) strUser = WScript.Arguments(1) strPassword = WScript.Arguments(2) If WScript.Arguments.Count = 4 Then strOU = WScript.Arguments(3) End If End If If NOT blnUseArgs Then If objFSO.FileExists(striniFile) Then strDomain = GetINIString("Identification", "JoinDomain", "", striniFile) strDomain = Replace(strDomain,"""","") strUser = GetINIString("Identification", "DomainAdmin", "", striniFile) strUser = Replace(strUser,"""","") strPassword = GetINIString("Identification", "DomainAdminPassword", "", striniFile) strPassword = Replace(strPassword,"""","") strOU = GetINIString("Identification", "MachineObjectOU", "", striniFile) strOU = Replace(strOU,"""","") If blnDebug Then wscript.echo "Domain: " & strDomain & vbcrlf & _ "User: " & strUser & vbcrlf & _ "Password: " & strPassword & vbcrlf & _ "OU: " & strOU End If End If End If If strDomain <> “” AND strUser <> “” AND strPassword <> “” Then

If strOU = “” Then
strOU = NULL
End If

Set objNetwork = CreateObject(“WScript.Network”)
strComputer = objNetwork.ComputerName

strExistingLocation = getHostOU(strComputer,strDomain,strUser,strPassword)
If strExistingLocation <> “” Then
strOU = strExistingLocation
End If

Set objComputer = GetObject(“winmgmts:{impersonationLevel=Impersonate}!\\” & _
strComputer & “\root\cimv2:Win32_ComputerSystem.Name='” & strComputer & “‘”)

wscript.echo “Attempting to join the ” & chr(34) & strDomain & chr(34) & ” Domain.”
If NOT IsNULL(strOU) Then
wscript.echo “The Computer Object will be placed in the following OU:” & vbcrlf & _
chr(34) & strOU & chr(34)
End If

intReturn = objComputer.JoinDomainOrWorkGroup(strDomain, strPassword, strDomain & “\” & strUser, _
strOU, JOIN_DOMAIN + ACCT_CREATE)

Select Case intReturn
Case 0
strErrorDescription = “Successfully added the computer to the ” & chr(34) & strDomain & chr(34) & ” Domain.”
Case 5
strErrorDescription = “Access is denied”
Case 87
strErrorDescription = “The parameter is incorrect”
Case 110
strErrorDescription = “The system cannot open the specified object”
Case 1323
strErrorDescription = “Unable to update the password”
Case 1326
strErrorDescription = “Logon failure: unknown username or bad password”
Case 1355
strErrorDescription = “The specified domain either does not exist or could not be contacted”
Case 2224
strErrorDescription = “The account already exists”
Case 2691
strErrorDescription = “The machine is already joined to the domain”
Case 2692
strErrorDescription = “The machine is not currently joined to a domain”
End Select
wscript.echo strErrorDescription

End If

Set wshShell = Nothing
Set objFSO = Nothing
Set objNetwork = Nothing
Set objComputer = Nothing

wscript.quit(0)

Function GetINIString(Section, KeyName, Default, FileName)
Dim INIContents, PosSection, PosEndSection, sContents, Value, Found

‘Get contents of the INI file As a string
INIContents = GetFile(FileName)

‘Find section
PosSection = InStr(1, INIContents, “[” & Section & “]”, vbTextCompare)
If PosSection>0 Then

‘Section exists. Find end of section
PosEndSection = InStr(PosSection, INIContents, vbCrLf & “[“)
‘?Is this last section?
If PosEndSection = 0 Then PosEndSection = Len(INIContents)+1

‘Separate section contents
sContents = Mid(INIContents, PosSection, PosEndSection – PosSection)

If InStr(1, sContents, vbCrLf & KeyName & “=”, vbTextCompare)>0 Then
Found = True
‘Separate value of a key.
Value = SeparateField(sContents, vbCrLf & KeyName & “=”, vbCrLf)
ElseIf InStr(1, sContents, vbCrLf & KeyName & ” =”, vbTextCompare)>0 Then
Found = True
‘Separate value of a key.
Value = SeparateField(sContents, vbCrLf & KeyName & ” =”, vbCrLf)
End If
End If

If isempty(Found) Then Value = Default
GetINIString = Trim(Value)
End Function

‘Separates one field between sStart And sEnd
Function SeparateField(ByVal sFrom, ByVal sStart, ByVal sEnd)
Dim PosB: PosB = InStr(1, sFrom, sStart, 1)
If PosB > 0 Then
PosB = PosB + Len(sStart)
Dim PosE: PosE = InStr(PosB, sFrom, sEnd, 1)
If PosE = 0 Then PosE = InStr(PosB, sFrom, vbCrLf, 1)
If PosE = 0 Then PosE = Len(sFrom) + 1
SeparateField = Mid(sFrom, PosB, PosE – PosB)
End If
End Function

Function GetFile(ByVal FileName)
Dim FS: Set FS = CreateObject(“Scripting.FileSystemObject”)
‘Go To windows folder If full path Not specified.
If InStr(FileName, “:\”) = 0 And Left (FileName,2)<>“\\” Then
FileName = FS.GetSpecialFolder(0) & “\” & FileName
End If
On Error Resume Next

GetFile = FS.OpenTextFile(FileName).ReadAll
Set FS = Nothing
End Function

Function getHostOU(hostname,strDomain,strUser,strPassword)

Dim arrDefaultNamingContext
Dim item
Dim strDefaultNamingContext
Dim strADsPath
Dim strBase
Dim strFilter
Dim strAttributes
Dim strScope
Dim strCommandText
Dim objADOConnection
Dim objADOCommand
Dim objADORecordset
Dim hostDN, hostOU

‘ ADS Authentication constants that can be used.
Const ADS_SECURE_AUTHENTICATION = &H1
Const ADS_USE_ENCRYPTION = &H2
Const ADS_USE_SSL = &H2
Const ADS_USE_SIGNING = &H40
Const ADS_USE_SEALING = &H80
Const ADS_USE_DELEGATION = &H100
Const ADS_SERVER_BIND = &H200

‘ First, need to set the correct Default Naming Context
‘ arrDefaultNamingContext = Split(strDomain,”.”)
‘ For Each item in arrDefaultNamingContext
‘ If strDefaultNamingContext = “” Then
‘ strDefaultNamingContext = “DC=” & item
‘ Else
‘ strDefaultNamingContext = strDefaultNamingContext & “,DC=” & item
‘ End If
‘ Next
strDefaultNamingContext = strDomain
strADsPath = “LDAP://” & strDefaultNamingContext
strBase = “<" & strADsPath & ">”

‘ Specify the LDAP filter
strFilter = “(&(objectClass=computer)(cn=” & UCase(hostname) & “))”
strAttributes = “cn,distinguishedName,ADsPath”
‘ Specify the scope (base, onelevel, subtree)
strScope = “subtree”

strCommandText = strBase & “;” & strFilter & “;” & strAttributes & “;” & strScope

‘ Create ADO connection using the ADSI OLE DB provider
Set objADOConnection = CreateObject(“ADODB.Connection”)
Set objADOCommand = CreateObject(“ADODB.Command”)
objADOConnection.Provider = “ADsDSOObject”
objADOConnection.Properties(“User ID”) = strDomain & “\” & strUser
objADOConnection.Properties(“Password”) = strPassword
objADOConnection.Properties(“Encrypt Password”) = True
objADOConnection.Properties(“ADSI Flag”) = ADS_SERVER_BIND Or ADS_SECURE_AUTHENTICATION
objADOConnection.open “Active Directory Provider”
objADOCommand.activeconnection = objADOConnection
objADOCommand.CommandText = strCommandText
objADOCommand.Properties(“Page Size”) = 2000
objADOCommand.Properties(“Sort On”) = “cn”

On Error Resume Next
Set objADORecordset = objADOCommand.Execute
If Err.Number = 0 Then
While Not objADORecordset.EOF
hostDN = objADORecordset.Fields(“distinguishedName”)
objADORecordset.MoveNext
Wend
objADOConnection.Close

If Len(hostDN) > 0 Then
hostOU = Right(hostDN, (Len(hostDN) – InStr(hostDN, “,”)))
Else
hostOU =””
End If

If Len(hostOU) > 0 Then
getHostOU = hostOU
Else
getHostOU = “”
End If
Else
wscript.echo “Cannot connect to the Active Directory Provider to check for the existence of the Computer Object.”
getHostOU = “”
End If
On Error Goto 0
Err.Clear

Set objADOConnection = Nothing
Set objADOCommand = Nothing
Set objADORecordset = Nothing
End Function

Jeremy Saunders

Jeremy Saunders

Technical Architect | DevOps Evangelist | Software Developer | Microsoft, NVIDIA, Citrix and Desktop Virtualisation (VDI) Specialist/Expert | Rapper | Improvisor | Comedian | Property Investor | Kayaking enthusiast at J House Consulting
Jeremy Saunders is the Problem Terminator. He is a highly respected IT Professional with over 35 years’ experience in the industry. Using his exceptional design and problem solving skills with precise methodologies applied at both technical and business levels he is always focused on achieving the best business outcomes. He worked as an independent consultant until September 2017, when he took up a full time role at BHP, one of the largest and most innovative global mining companies. With a diverse skill set, high ethical standards, and attention to detail, coupled with a friendly nature and great sense of humour, Jeremy aligns to industry and vendor best practices, which puts him amongst the leaders of his field. He is intensely passionate about solving technology problems for his organisation, their customers and the tech community, to improve the user experience, reliability and operational support. Views and IP shared on this site belong to Jeremy.
Jeremy Saunders
Jeremy Saunders

Previous post:

Next post: