In this tutorial, we’ll look at how to add a server to an Active Directory domain using PowerShell.
As we’ve already mentioned in previous articles on this blog, PowerShell can really save a lot of time when adding and configuring servers, client devices, services and applications. It can also be used to make scripts so that you can automate repetitive tasks.
As a result, we’re going to show you how to add a machine to a domain using PowerShell. We’ll also look at how to change its name on the domain too. So, you’re getting two for the price of one!
How to Add a Server to a Domain Using PowerShell
Before you get started…
- To be registered with an organisation on the Jotelulu platform and to have logged in.
- A Servers subscription on the platform.
- A defined naming policy.
Part 1 – Changing the Name of the Server
When you install a Windows server or computer, it will initially be given a random name that will probably be very difficult to remember and won’t have anything to do with its main function within the business.
# Rename-Computer -NewName <Server_Name>
- <Server_Name> is the name you intend to give to the server.
For example, this might look something like this:
# Rename-Computer -NewName SW22DHCPSERVER01

Part 2 – Adding the Server to an AD DS Domain Using PowerShell
# Add-Computer <Domain>
- <Domain> is the domain that you want to add the server to.
# Add-Computer jotelulu.com
Once you’ve done this, you’ll need to restart the server again.

Congratulations! Your server has now been joined to your Active Directory domain!
Summary
Thanks for choosing Jotelulu!

You can use PowerShell ISE console to attach a device to a domain. This can be useful to people who prefer to use code or more likely to be for the Windows Server Core operating system.
PowerShell Code
Variables
- $domain = “domain.local” = Domain name that you are want to attach your device to
- $username = “domainaccountname” = Username of a Domain account
Once you are happy that you have all the correct variables in place, go ahead and run the code.
Domain Attached
This will go through the stages of renaming the device and attaching it to the Domain that you entered the details for. When it has completed fully, reboot the device and you will now find that it is attached to the Domain successfully.
What happens if the device is already named as desired?
If the device is already named correctly, you can skip the renaming portion of the script and proceed directly to the steps that attach the device to the domain.
Can this script be used on any version of Windows?
This script is primarily intended for Windows operating systems that support PowerShell and can be joined to a domain, such as Windows Server editions and Professional editions of Windows desktop operating systems.
Glossary
- PowerShell ISE (Integrated Scripting Environment): A host application for Windows PowerShell that enables users to write, run, and debug scripts in a graphical interface.
- Domain: A network of computers that share a common directory database and security policies. In this context, it usually refers to an Active Directory domain.
- Administrator Privileges: Elevated permissions required to perform tasks that affect system settings or other users.
- Script: A set of commands saved in a file that can be executed by a scripting engine, such as PowerShell.
- Credential: In computing, a credential is typically a username and password used to authenticate and authorize a user to perform actions on a system.
- SecureString: A type in PowerShell used to store sensitive information, like passwords, in a more secure manner.
- Rename-Computer: A PowerShell cmdlet used to change the name of a computer.
- Add-Computer: A PowerShell cmdlet used to add a computer to a domain or workgroup.
- Restart: A process of rebooting a computer system to apply changes and complete certain operations.

Prerequisites
- Administrator Account: Ensure you have the necessary credentials with permissions to join the computer to the domain.
- Domain Information: Know the domain name you want to join.
- Network Connectivity: Ensure the computer is connected to the network where the domain is accessible.
Steps
- Open PowerShell as Administrator:
- Press
Win + Xand select “Windows PowerShell (Admin)” or search for “PowerShell” in the Start menu, right-click, and select “Run as administrator”.
2. Set Execution Policy (if required):
- If PowerShell scripts are restricted, you may need to set the execution policy. Run the following command:
3. Rename Computer (Optional):
- If you want to rename the computer before joining the domain, use the following command:
Rename-Computer -NewName "NewComputerName" -Restart- Replace
"NewComputerName"with your desired computer name. - The computer will restart. Reopen PowerShell as an administrator after the restart.
4. Join the Domain:
- Use the
Add-Computercmdlet to join the domain. The basic syntax is:
- Replace
"YourDomainName"with the actual domain name. - Replace
YourDomain\YourUsernamewith a domain user account that has permission to join the computer to the domain.
5. Provide Domain Credentials:
- After running the
Add-Computercommand, a prompt will appear asking for the password of the domain account specified. - Enter the password and press
Enter.
6. Restart the Computer:
- To apply the changes, restart the computer by using the following command:
7. Verify Domain Join (Optional):
- After the computer restarts, log in with a domain account to verify the computer has joined the domain.
- You can also verify this by running:
- The output should display your domain name.
Example Command
Here is an example with placeholder values:
Note
- Ensure the time and date on the computer are synchronized with the domain controller, as time discrepancies can prevent domain joining.
- If any issues arise, check network connectivity, DNS settings, and the availability of the domain controller.
This was the result of a colloboration between me (with programming skills, but not in PowerShell!) and ChatGPT. It blows my mind away, what can be done with ChatGPT – this is what work IS supposed to be! Quick, without researching every single line. Human and machine in perfect colloboration:
# PowerShell script to get A and AAAA records for a list of domains, with debug output
# Define the path to the domain list and output CSV file
$domainListPath = "C:\your\path\domains.txt"
$outputCsvPath = ".\domain_records.csv"
# Read the list of domains from the file
$domains = Get-Content $domainListPath
# Prepare an array to hold the results
$results = @()
# Loop through each domain and query its A and AAAA records
foreach ($domain in $domains) { Write-Host "Processing domain: $domain" # Initialize the record object $record = New-Object PSObject -Property @{ Domain = $domain ARecord = $null AAAARecord = $null WARecord = $null WAAAARecord = $null } Write-Host " Performing nslookup..." # Perform nslookup for A and AAAA records $nslookupResults = nslookup $domain $nslookupResults = $nslookupResults | Select-Object -Skip 2 # Extract A and AAAA records foreach ($line in $nslookupResults) { Write-Host "Debug output" Write-Host $line if ($line -match "(\d+\.\d+\.\d+\.\d+)") { $address = $matches[1] Write-Host " Found A record: $address" $record.ARecord = $address } elseif ($line -match "([a-fA-F0-9:]+:[a-fA-F0-9:]+)") { $address = $matches[1] Write-Host " Found AAAA record: $address" $record.AAAARecord = $address }
<# if ($line -match "Address: (.*)") { $address = $matches[1] # Determine if the address is IPv4 (A record) or IPv6 (AAAA record) if ($address -match "\d+\.\d+\.\d+\.\d+") { Write-Host " Found A record: $address" $record.ARecord = $address } elseif ($address -match "([a-fA-F0-9:]+:[a-fA-F0-9:]+)") { Write-Host " Found AAAA record: $address" $record.AAAARecord = $address } } #> } Write-Host " Performing www nslookup..." # Perform nslookup for A and AAAA records $nslookupResults = nslookup www.$domain $nslookupResults = $nslookupResults | Select-Object -Skip 2 # Extract A and AAAA records foreach ($line in $nslookupResults) { Write-Host "Debug output" Write-Host $line if ($line -match "(\d+\.\d+\.\d+\.\d+)") { $address = $matches[1] Write-Host " Found A record: $address" $record.WARecord = $address } elseif ($line -match "([a-fA-F0-9:]+:[a-fA-F0-9:]+)") { $address = $matches[1] Write-Host " Found AAAA record: $address" $record.WAAAARecord = $address }
<# if ($line -match "Address: (.*)") { $address = $matches[1] # Determine if the address is IPv4 (A record) or IPv6 (AAAA record) if ($address -match "\d+\.\d+\.\d+\.\d+") { Write-Host " Found A record: $address" $record.ARecord = $address } elseif ($address -match "([a-fA-F0-9:]+:[a-fA-F0-9:]+)") { Write-Host " Found AAAA record: $address" $record.AAAARecord = $address } } #> } # Add the record to the results array $results += $record
}
Write-Host "Exporting results to CSV..."
# Export the results to a CSV file
$results | Export-Csv -NoTypeInformation -Path $outputCsvPath
Write-Host "Script completed. Check $outputCsvPath for output."
# End of scriptbe sure to adjust the path in the line $domainListPath = “C:\your\path\domains.txt”.
The script can be saved as a .ps1 file, and then executed in the Windows PowerShell.
domains.txt looks like this, for example – simply one domain on each line:
7vi.de
7voice.de
airtaxi.toThe output looks like this:

Did ChatGPT do this on it’s own?
No it did not – but it provided enough syntax and “how-to” for me, to be able to fix the problems quickly. In the comments you can see it’s original code, which took the NS server which I use.
This is an example of how to massively up your productivity and do new things, which you were not able to do before – because the time/output tradeoff would not allow you to.
This is an example of how to run checks and things you need, by spinning up your own scripts quickly.
(If I would have really wanted to do this in the old days, I would probably have used Ruby or Python, and written this on a Linux machine. My desktop happens to be – still – a Windows machine, so this is the convenient get it up quickly option here.)
In the modern IT landscape, ensuring a computer joins the appropriate domain is more than a convenience—it’s an essential step toward consolidating control, simplifying access, and maintaining network security. This PowerShell script is designed to streamline the process of adding a computer to a domain.
Background
The Script
#Requires -Version 5.1
<#
.SYNOPSIS Joins a computer to a domain.
.DESCRIPTION Joins a computer to a domain.
.EXAMPLE -DomainName "Domain.com" -UserName "DomainMyDomainUser" -Password "Somepass1" Joins a computer to a "Domain.com" domain and restarts the computer. Don't expect a success result in Ninja as the computer will reboot before the script can return a result.
.EXAMPLE -DomainName "Domain.com" -UserName "DomainMyDomainUser" -Password "Somepass1" -NoRestart Joins a computer to a "Domain.com" domain and does not restart the computer.
.EXAMPLE PS C:> Join-Domain.ps1 -DomainName "domain.com" -UserName "DomainMyDomainUser" -Password "Somepass1" -NoRestart Joins a computer to a "Domain.com" domain and does not restart the computer.
.EXAMPLE -DomainName "Domain.com" -UserName "DomainMyDomainUser" -Password "Somepass1" -Server "192.168.0.1" Not recommended if the computer this script is running on does not have one of the Domain Controllers set as its DNS server. Joins a computer to a "Domain.com" domain, talks to the domain with the IP address of "192.168.0.1", and restarts the computer.
.OUTPUTS String[]
.NOTES Minimum OS Architecture Supported: Windows 10, Windows Server 2016 Release Notes: Initial Release
By using this script, you indicate your acceptance of the following legal terms as well as our Terms of Use at https://www.ninjaone.com/terms-of-use. Ownership Rights: NinjaOne owns and will continue to own all right, title, and interest in and to the script (including the copyright). NinjaOne is giving you a limited license to use the script in accordance with these legal terms. Use Limitation: You may only use the script for your legitimate personal or internal business purposes, and you may not share the script with another party. Republication Prohibition: Under no circumstances are you permitted to re-publish the script in any script library or website belonging to or under the control of any other software provider. Warranty Disclaimer: The script is provided “as is” and “as available”, without warranty of any kind. NinjaOne makes no promise or guarantee that the script will be free from defects or that it will meet your specific needs or expectations. Assumption of Risk: Your use of the script is at your own risk. You acknowledge that there are certain inherent risks in using the script, and you understand and assume each of those risks. Waiver and Release: You will not hold NinjaOne responsible for any adverse or unintended consequences resulting from your use of the script, and you waive any legal or equitable rights or remedies you may have against NinjaOne relating to your use of the script. EULA: If you are a NinjaOne customer, your use of the script is subject to the End User License Agreement applicable to you (EULA).
.COMPONENT ManageUsers
#>
[CmdletBinding()]
param ( # Domain Name to join computer to [Parameter(Mandatory = $true)] [String] $DomainName, # Use a Domain UserName to join this computer to a domain, this requires the Password parameter to be used as well [Parameter(Mandatory = $true)] [String] $UserName, # Use a Domain Password to join this computer from a domain [Parameter(Mandatory = $true)] $Password, # Used only when computer can't locate a domain controler via DNS or you wish to connect to a specific DC [Parameter()] $Server, # Do not restart computer after joining to a domain [Switch] $NoRestart
)
begin { function Join-ComputerToDomainPS2 { param ( [String] $DomainName, [PSCredential] $Credential, $Restart, $Server ) if ($Credential) { # Use supplied Credentials if ($Server) { Add-Computer -DomainName $DomainName -Credential $Credential -Server $Server -Force -Confirm:$false -PassThru } else { Add-Computer -DomainName $DomainName -Credential $Credential -Force -Confirm:$false -PassThru } } else { # No Credentials supplied, use current user Add-Computer -DomainName $DomainName -Force -Confirm:$false -PassThru } } Write-Output "Starting Join Domain" # Convert username and password into a credential object $JoinCred = [PSCredential]::new($UserName, $(ConvertTo-SecureString -String $Password -AsPlainText -Force))
}
process { Write-Output "Joining computer($env:COMPUTERNAME) to domain $DomainName" $script:JoinResult = $false try { $JoinResult = if ($NoRestart) { # Do not restart after joining if ($PSVersionTable.PSVersion.Major -eq 2) { if ($Server) { (Join-ComputerToDomainPS2 -DomainName $DomainName -Credential $Credential -Server $Server).HasSucceeded } else { (Join-ComputerToDomainPS2 -DomainName $DomainName -Credential $Credential).HasSucceeded } } else { if ($Server) { (Add-Computer -DomainName $DomainName -Credential $JoinCred -Server $Server -Force -Confirm:$false -PassThru).HasSucceeded } else { (Add-Computer -DomainName $DomainName -Credential $JoinCred -Force -Confirm:$false -PassThru).HasSucceeded } } } else { # Restart after joining if ($PSVersionTable.PSVersion.Major -eq 2) { if ($Server) { (Join-ComputerToDomainPS2 -DomainName $DomainName -Credential $Credential -Server $Server).HasSucceeded } else { (Join-ComputerToDomainPS2 -DomainName $DomainName -Credential $Credential).HasSucceeded } } else { if ($Server) { (Add-Computer -DomainName $DomainName -Credential $JoinCred -Restart -Server $Server -Force -Confirm:$false -PassThru).HasSucceeded } else { (Add-Computer -DomainName $DomainName -Credential $JoinCred -Restart -Force -Confirm:$false -PassThru).HasSucceeded } } } } catch { Write-Error "Failed to Join Domain: $DomainName" } if ($NoRestart -and $JoinResult) { Write-Output "Joined computer($env:COMPUTERNAME) to Domain: $DomainName and not restarting computer" } elseif ($JoinResult) { Write-Output "Joined computer($env:COMPUTERNAME) to Domain: $DomainName and restarting computer" if ($PSVersionTable.PSVersion.Major -eq 2) { shutdown.exe -r -t 60 } } else { Write-Output "Failed to Join computer($env:COMPUTERNAME) to Domain: $DomainName" # Clean up credentials so that they don't leak outside this script $JoinCred = $null exit 1 }
}
end { # Clean up credentials so that they don't leak outside this script $JoinCred = $null Write-Output "Completed Join Domain"
}Access 300+ scripts in the NinjaOne Dojo
Detailed Breakdown
- Parameters: These are inputs the user provides, including DomainName, UserName, Password, and Server. A switch parameter called NoRestart allows users to decide if they want the computer to restart after joining the domain.
- Begin Block: This section initializes the script. It defines a function Join-ComputerToDomainPS2 and converts the provided username and password into a secure credential object, ready for use in the joining process.
- Process Block: The central logic resides here. Depending on the provided parameters, the script will join the computer to the domain with or without a restart. It uses two primary PowerShell commands: Add-Computer and a user-defined function. If any errors arise during this process, they’re caught and reported.
- End Block: This finalizes the script, cleaning up any credentials used during its execution.
Potential Use Cases
Case Study: Imagine an MSP handling IT for several small businesses. They’ve just deployed 50 new machines and need them all on the company’s domain by the start of business the next day. Using the script, the MSP quickly feeds in the required details for all machines. Within minutes, every computer is set up, without the need for manual configurations or time-consuming setups.
Comparisons
Traditional methods of joining a computer to a domain involve manual steps through the Windows interface or using legacy scripts. These methods can be time-consuming, error-prone, and don’t scale well for large deployments. Our PowerShell approach is more efficient, less error-prone, and scales to handle multiple machines.
FAQs
- Can this script handle bulk additions of computers to a domain?
Yes, with proper looping logic in place, you can process multiple computers. - What happens if the domain details provided are incorrect?
The script will throw an error indicating the domain join failure.
Implications
Incorrectly joining domains or exposing credentials can be detrimental to IT security. If a computer joins the wrong domain, it might access unauthorized resources or become exposed to security risks.
Recommendations
- Always validate domain details before execution.
- Protect and regularly rotate domain credentials.
- Test the script in a controlled environment before deploying.
Final thoughts
In an age where automation reigns supreme, tools like this script, combined with platforms like NinjaOne, can enhance efficiency, security, and manageability. NinjaOne, in particular, offers robust monitoring and management features, ensuring that once computers are added to the domain, they remain compliant, secure, and optimized for performance.
- Updated on November 17, 2023
- Powershell, Windows Server
Which AD forest and domain functional level are you running in the organization? Are you on the latest version? In this article, you will learn how to check the forest and domain functional level.
Table of contents
- Sign in to the Domain Controller.
- Start Server Manager.
- Click on Tools > Active Directory Domains and Trusts.

- Right-click the domain and click on Properties.

- In the General tab, the Domain functional level and Forest functional level appear.

Check forest functional level with PowerShell
Find the AD forest functional level with PowerShell.
PS C:\> Get-ADForest | fl Name, ForestMode
Name : exoip.local
ForestMode : Windows2016ForestCheck domain functional level with PowerShell
Find the AD domain functional level with PowerShell.
PS C:\> Get-ADDomain | fl Name, DomainMode
Name : exoip
DomainMode : Windows2016DomainGet forest and domain functional level with PowerShell script
An excellent way to get the AD forest and domain functional level is to run the Get-ADInfo.ps1 PowerShell script.
The script will show the Active Directory forest and functional level and more information about your Active Directory.
C:\scripts\.\Get-ADInfo.ps1This is how it looks.
Active Directory Info
Computers = 5
Workstions = 1
Servers = 4
Users = 74
Groups = 88
Active Directory Forest Name = exoip.local
Active Directory Forest Mode = Windows2016Forest
Active Directory Domain Mode = Windows2016Domain
Active Directory Schema Version is 88 which corresponds to Windows Server 2019/Windows Server 2022
FSMO Role Owners
Schema Master = DC01-2019.exoip.local
Domain Naming Master = DC01-2019.exoip.local
RID Master = DC01-2019.exoip.local
PDC Emulator = DC01-2019.exoip.local
Infrastructure Master = DC01-2019.exoip.localConclusion
You learned how to check forest and domain functional level. You can get the forest and domain functional level with the GUI or PowerShell. I recommend using the Get-ADInfo.ps1 PowerShell script because this will show you more AD information.



