While scripting a bulk user migration for a client last quarter, I hit one of those issues that wastes an hour before you realize what happened. Half the Get-ADUser calls were failing intermittently, and the error messages were vague enough to send you in three wrong directions. Turned out the problem was how we were specifying the Active Directory server parameter — mixing FQDN and NetBIOS names across scripts that were running from different network segments. Once I sorted that out, I figured it was worth writing down everything I know about specifying the Active Directory server parameter correctly, because this trips people up more than it should.
Notes Before We Get Into It
A few things to keep in mind as you read through this:
- This post focuses on the
-Serverparameter as used across the Active Directory PowerShell module — cmdlets likeGet-ADUser,Get-ADGroup,Set-ADUser,New-ADObject, and so on. The parameter behaves consistently across most of these cmdlets. - I’m assuming you already have the AD module installed. If not, check out our post on PowerShell Module Management: Install, Import, and Update for the install steps.
- Everything here applies to Windows Server 2016 through 2025. The behavior hasn’t changed meaningfully across those versions.
- I won’t be covering LDAP connection strings or third-party AD tools. This is strictly about the native PowerShell
-Serverparameter.
What the -Server Parameter Actually Accepts
The -Server parameter on AD cmdlets tells PowerShell which Active Directory Domain Services (AD DS) instance to connect to. It also works with Active Directory Lightweight Domain Services (AD LDS) and Active Directory snapshot instances, which is useful for recovery scenarios.
There are two categories of values you can pass in: domain name values and directory server values. The distinction matters more than most people think.
Domain Name Values
When you pass a domain name, PowerShell doesn’t connect to a specific domain controller. Instead, it uses the DC locator process to find an available controller in that domain. You have two options here:
Fully Qualified Domain Name (FQDN) — This is the DNS name of the domain. For example:
Get-ADUser -Filter * -Server "corp.contoso.com"
NetBIOS name — The short, flat name of the domain. For example:
Get-ADUser -Filter * -Server "CONTOSO"
Both of these tell PowerShell “find me a domain controller in this domain and run the query there.” The difference is in how the name gets resolved, and that’s where things start to diverge in practice.
Directory Server Values
When you pass a directory server value, you’re pointing PowerShell at a specific domain controller. No DC locator, no automatic selection. You get three options:
Fully qualified directory server name:
Get-ADUser -Filter * -Server "dc01.corp.contoso.com"
NetBIOS server name:
Get-ADUser -Filter * -Server "DC01"
Fully qualified directory server name with port:
Get-ADUser -Filter * -Server "dc01.corp.contoso.com:389"
That last one — specifying the port — is particularly useful when you need to query an AD LDS instance running on a non-standard port, or when you want to hit the global catalog on port 3268.
FQDN vs NetBIOS: When Each One Wins
Here’s where I’ll take a position: default to FQDN unless you have a specific reason not to. I’ve seen too many support tickets that trace back to NetBIOS resolution failures in environments where WINS is decommissioned or where network segmentation blocks NetBIOS traffic.
Why FQDN Is Usually the Better Choice
FQDN resolution relies on DNS, which is the backbone of Active Directory anyway. If DNS is broken, you have bigger problems than your PowerShell scripts. FQDN works reliably across subnets, across sites, and across forests (assuming proper DNS delegation or conditional forwarding). It’s explicit, predictable, and easy to troubleshoot.
When a client’s environment spans multiple AD sites — and most of the environments we manage at SSE do — FQDN resolution combined with AD site awareness ensures the DC locator picks a controller in the right site. NetBIOS doesn’t give you that same level of determinism.
When NetBIOS Still Makes Sense
That said, NetBIOS isn’t dead, and there are situations where it’s the pragmatic choice. Some legacy applications hardcode NetBIOS domain names. If you’re writing scripts that need to match identities across systems that use the DOMAIN\username format, working with the NetBIOS name keeps things consistent. We had a financial services client running a mix of modern and legacy line-of-business apps where every service account reference used NetBIOS format. Rewriting all of those to use UPN format would have been a six-month project with no business value.
NetBIOS names are also shorter to type interactively, which is fine for one-off commands in an admin session. It’s the automation scenarios where you want to be deliberate about using FQDN.
How the Default Value Gets Resolved
If you don’t specify the -Server parameter at all, PowerShell doesn’t just give up. It walks through a fallback chain, and understanding this chain will save you debugging time. The resolution order is:
- Pipeline input — If you pipe an AD object into a cmdlet, PowerShell uses the server value embedded in that object. Every AD object returned by the module carries metadata about which DC it was retrieved from.
- AD provider drive — If you’re running the command from within the
AD:PSDrive (the Active Directory PowerShell provider), it uses the server associated with that drive. - Local computer’s domain — As a last resort, it uses the domain of the computer running PowerShell.
This fallback chain is actually pretty well designed. But it catches people off guard in one specific scenario: running scripts from a management workstation that’s joined to a different domain than the one you’re targeting. I’ve seen this come up at least a dozen times during client engagements where the admin team uses a dedicated management forest.
A Quick Example of Fallback Behavior
Say you’re on a workstation joined to mgmt.contoso.com, and you run:
Get-ADUser jsmith
With no -Server parameter, this queries a DC in mgmt.contoso.com. If jsmith lives in corp.contoso.com, you’ll get nothing back — or worse, you’ll get a different jsmith from the wrong domain. The fix is simple:
Get-ADUser jsmith -Server "corp.contoso.com"
Simple, but easy to forget at 2 AM during a migration window.
Targeting the Global Catalog
One pattern that comes up a lot in multi-domain forests is querying the global catalog. The global catalog is a partial replica of all objects across every domain in the forest, accessible on port 3268 (or 3269 for LDAPS).
You can query it by specifying the port explicitly:
Get-ADUser -Filter {mail -eq "[email protected]"} -Server "dc01.corp.contoso.com:3268"
Or if you just want the global catalog in your current domain, you can use the port alone with the domain name:
Get-ADUser -Filter {mail -eq "[email protected]"} -Server "corp.contoso.com:3268"
This is incredibly useful when you need to search for a user but don’t know which child domain they’re in. We deployed a self-service password reset tool for a client with four child domains, and the lookup service used global catalog queries so users didn’t have to know their domain — they just typed their email address.
One caveat: the global catalog only contains a subset of attributes for objects outside the local domain. If you need an attribute that isn’t in the partial attribute set, the GC query will return the object but the attribute will be empty. You’ll need to follow up with a targeted query against the object’s home domain. The Microsoft documentation has the full list of attributes replicated to the global catalog.
Multi-Domain and Cross-Forest Scenarios
This is where server parameter choices really start to matter. In a single-domain environment, you can get away with sloppy habits. Once you add child domains, resource forests, or trust relationships, being explicit about which server you’re targeting becomes non-negotiable.
Child Domains
In a forest with a root domain and child domains — say contoso.com as root, na.contoso.com and eu.contoso.com as children — every cmdlet call needs to specify which domain you’re after:
# Query the NA domain
Get-ADGroup -Filter {Name -like "Sales*"} -Server "na.contoso.com"
# Query the EU domain
Get-ADGroup -Filter {Name -like "Sales*"} -Server "eu.contoso.com"
Using the NetBIOS names (NA and EU) would also work here, but in my experience, short generic names like that are more prone to conflicts with other naming systems — DNS suffixes, legacy WINS entries, workgroup names. FQDN avoids the ambiguity.
Cross-Forest Trusts
If you have a trust relationship with another forest, you can query it the same way — provided the trust allows it and DNS resolution works end to end:
Get-ADUser -Filter {Department -eq "Engineering"} -Server "partner.fabrikam.com"
For this to work, your machine needs to resolve partner.fabrikam.com via DNS. That usually means conditional forwarders are configured. If DNS resolution fails, the cmdlet fails, and the error message will say something about not being able to contact the server — not that DNS is the problem. Keep that in mind when troubleshooting.
vSphere Identity Sources: A Related Use Case
The FQDN-vs-NetBIOS decision isn’t limited to PowerShell. If you manage VMware environments, you’ll see the same pattern when adding an Active Directory identity source to vCenter. The configuration asks for:
- Domain Name: the FQDN of the domain
- Domain Alias: the NetBIOS name
- Primary Server URL: in
ldap://hostname:portorldaps://hostname:portformat
We had a client whose vCenter was intermittently failing AD authentication. The domain alias field had the wrong NetBIOS name — someone had typed the child domain’s name instead of the parent. The FQDN was correct, so LDAP binds worked, but token generation used the alias and broke group lookups. Fixing the alias field immediately resolved the issue. Details on the VMware documentation site cover the identity source setup in depth, and I recommend cross-referencing their guidance if you’re configuring this for a Linux VPS or vCenter appliance.
Practical Troubleshooting Guide
When something goes wrong with AD cmdlets and you suspect the server parameter is involved, here’s the sequence I follow. This is basically the playbook we use during client onboarding when we’re testing AD connectivity from management hosts.
Step 1: Verify DNS Resolution
# For FQDN
Resolve-DnsName corp.contoso.com
# For a specific DC
Resolve-DnsName dc01.corp.contoso.com
If this fails, the AD cmdlet will also fail. Fix DNS first.
Step 2: Verify DC Connectivity
Test-NetConnection dc01.corp.contoso.com -Port 389
Port 389 is standard LDAP. Use 636 for LDAPS, 3268 for global catalog, 3269 for global catalog over SSL.
Step 3: Check DC Locator Results
nltest /dsgetdc:corp.contoso.com
This shows which DC the locator selects. If it’s picking a DC in a remote site, you might have AD Sites and Services misconfigured. That’s a whole separate conversation, but it’s good to know where to look.
Step 4: Test with Explicit Server
# Broad — let DC locator choose
Get-ADUser jsmith -Server "corp.contoso.com"
# Specific — bypass DC locator
Get-ADUser jsmith -Server "dc01.corp.contoso.com"
If the specific DC works but the domain name doesn’t, the issue is likely DC locator or DNS SRV records. If neither works, it’s a connectivity or permissions issue.
Step 5: Verify NetBIOS Resolution (If Using NetBIOS)
nbtstat -a DC01
If you’re relying on NetBIOS names and this command fails, that’s your answer. Either configure WINS, ensure NetBIOS over TCP/IP is enabled on the relevant interfaces, or — better yet — switch to FQDN.
Script Patterns That Avoid Problems
After dealing with enough multi-domain environments, I’ve settled on a few patterns that prevent server parameter issues from happening in the first place.
Store the Server Value in a Variable
$TargetDomain = "corp.contoso.com"
$TargetDC = "dc01.corp.contoso.com"
# Use domain name when you want automatic DC selection
Get-ADUser -Filter * -SearchBase "OU=Sales,DC=corp,DC=contoso,DC=com" -Server $TargetDomain
# Use specific DC when you need consistency across multiple operations
$user = Get-ADUser jsmith -Server $TargetDC
Set-ADUser $user -Department "Marketing" -Server $TargetDC
That second pattern — using the same specific DC for a read-then-write operation — avoids replication latency issues. If you read from DC01 and write to DC02, there’s a window where your change hasn’t replicated and subsequent reads from DC01 won’t reflect it.
Leverage Pipeline Server Binding
Remember that AD objects carry their source server metadata. When you pipe objects between cmdlets, the downstream cmdlet automatically targets the same DC:
Get-ADUser -Filter {City -eq "Chicago"} -Server "na.contoso.com" |
Set-ADUser -City "Dallas"
In this case, Set-ADUser doesn’t need an explicit -Server parameter because it inherits the value from the piped objects. This is the first fallback method in the resolution order, and it’s both convenient and reliable.
Multi-Domain Script Template
For scripts that touch multiple domains, define your targets upfront:
$Domains = @{
NA = "na.contoso.com"
EU = "eu.contoso.com"
AP = "ap.contoso.com"
}
foreach ($region in $Domains.Keys) {
$users = Get-ADUser -Filter {Enabled -eq $true} -Server $Domains[$region]
Write-Output "$region : $($users.Count) active users"
}
This makes the server targeting obvious and auditable. Anyone reviewing the script can immediately see which domains are in scope.
Common Mistakes and How to Fix Them
These are the issues I see most often across client environments. If you’re troubleshooting an AD PowerShell problem, check these first.
Mixing FQDN and NetBIOS in the Same Script
Don’t do this:
# Inconsistent — avoid
$user = Get-ADUser jsmith -Server "CONTOSO"
Set-ADUser $user -Title "Manager" -Server "corp.contoso.com"
The Get-ADUser call might hit DC01 via NetBIOS resolution, while Set-ADUser might hit DC03 via DNS. Now you’re reading from one DC and writing to another. Pick one format and stick with it across the script.
Forgetting -Server in a Scheduled Task
Scripts that run fine interactively often break when scheduled. Why? Because the scheduled task runs under a service account that might be in a different domain, or on a server where the AD provider drive isn’t loaded. Always specify -Server explicitly in scheduled scripts. Never rely on the fallback chain in automation.
Using NetBIOS After WINS Decommission
One of our long-term accounts ran into this after a network modernization project. They decommissioned WINS as part of a cleanup initiative, and within a week, three scheduled PowerShell scripts that used NetBIOS domain names started failing every night. The admin who wrote the scripts had left the company two years prior. Nobody knew the scripts existed until the monitoring alerts fired.
This is why I’m opinionated about FQDN. NetBIOS resolution depends on infrastructure (WINS, broadcast, LMHOSTS) that organizations are actively removing. FQDN depends on DNS, which isn’t going anywhere.
Not Specifying Port for AD LDS
AD LDS instances run on custom ports. If you’re managing an AD LDS instance and use just the server name without the port, the cmdlet connects to the default AD DS instance on port 389 — not your AD LDS instance. Always include the port:
Get-ADObject -Filter * -Server "appserver01.corp.contoso.com:50000"
Security Considerations
The server parameter choice also has security implications worth mentioning. In environments where we’ve helped clients tighten their AD security posture — often after working through a ransomware incident analysis — we pay attention to how admin scripts connect to domain controllers.
Using a specific DC over LDAPS (port 636) ensures your queries are encrypted:
Get-ADUser jsmith -Server "dc01.corp.contoso.com:636"
This matters when running scripts from networks where traffic might traverse untrusted segments. It also matters for compliance — the NIST Cybersecurity Framework has guidance on protecting authentication traffic, and encrypting LDAP queries is part of that picture.
Additionally, targeting a specific DC rather than using domain-name-based resolution gives you more control over which controller processes sensitive queries. In segmented environments, your privileged access workstations should be configured to talk to specific hardened DCs, not whichever one the locator picks.
Quick Reference Table
| Value Format | Example | What It Targets | Resolution Method |
|---|---|---|---|
| Domain FQDN | corp.contoso.com |
Any DC in domain | DNS + DC Locator |
| Domain NetBIOS | CONTOSO |
Any DC in domain | NetBIOS + DC Locator |
| Server FQDN | dc01.corp.contoso.com |
Specific DC | DNS |
| Server NetBIOS | DC01 |
Specific DC | NetBIOS |
| Server FQDN + Port | dc01.corp.contoso.com:3268 |
Specific DC + service | DNS |
The Practical Takeaway
Use FQDN. Be explicit about your -Server parameter in any script that’s going to run unattended. Use the same DC for read-then-write sequences. And if you’re in a multi-domain environment, define your targets at the top of the script so anyone can see what’s in scope at a glance.
If you’re dealing with a messy multi-domain environment and need help getting your AD management scripts reliable, reach out to us. We’ve done this cleanup work across enough client environments to know where the landmines are.


