export-ADData

Overview

export-ADData is a flexible PowerShell toolkit for exporting and importing Active Directory accounts. Easily convert AD data to CSV and back, with advanced import features for cross-domain migration, OU reorganization, granular mapping, and robust validation. Ideal for admins managing AD at scale.

📢 Stay Updated!

Want to know when this project is updated?
Subscribe to the commit feed (no login required):
RSS
Paste the above link into your favorite RSS reader to get notified of new commits!


Typical Workflow and Usage Scenarios

The basic usage is to export Active Directory objects by specifying the domain root or OU you wish to target. You are free to edit the exported CSV files—removing unwanted entries or making modifications—before using them as input for the import process. To assign passwords to users, add a “Password” column to the User CSV (this column is not present in the original export) and enter the desired passwords in plain text. Note that setting a password is required to properly restore the “Enabled” status of user accounts during import.

Note:
You can also perform a mass registration from scratch by first preparing CSV templates—simply export data from any sample Active Directory environment to generate the CSV structure, then edit these files as needed. The name of the source domain does not matter, as the importer (import-ADData.ps1) can convert and map the objects to your new domain automatically.
HOWTO_prepare_CSV_data.md will be a help.

There are four major strategies for combining export and import:

  1. Export specifying “DC=domain,DC=local” and import to “DC=domain,DC=local”
    This is like backup and restore of AD users/groups. Note, however, that properties automatically generated by AD, such as GUID and SID, will have different values from the export source.

  2. Export specifying “DC=olddomain,DC=local” and import to “DC=newdomain,DC=local”
    Allocate the users/groups onto a new domain basis, translating the domain naming, respecting hierarchies.

  3. Export specifying “DC=domain,DC=local” and import to “OU=osaka,DC=domain,DC=local”
    Whole migration from the domain basis to a new specific OU, along with all intermediate OUs the users/groups depend on. In this case, users under CN=Users container are created just under OU=osaka because it is impossible to create Users container nor OU=Users under the OU. Specifying “newdomain” is also a viable choice, which is like a move to a different floor of a different building.

  4. Export specifying “OU=sales,DC=domain,DC=local” and import to “DC=domain,DC=local” with -TrimOU sales
    Useful for flattening part of the OU hierarchy. By exporting from a specific OU and importing to the domain root with -TrimOU, you can migrate only the objects under that OU directly to the root (or another OU), effectively removing their original OU nesting.

More advanced use is possible. For example, if you export from “OU=sales,DC=domain,DC=local”, and import into “OU=marketing,DC=domain,DC=local” with -TrimOU "sales" option, you can effectively move objects from the “sales” OU to the “marketing” OU in a two-step process—without manually editing every DN in the exported CSV data.

See HOWTO_prepare_CSV_data.md for a step-by-step guide on preparing CSV files for import/export.


Scripts Included

1. export-ADData.ps1

Overview

Exports users, groups, and computers from Active Directory to CSV files using a specified domain or OU as the starting point.

Key Features

Parameters

Parameter Alias Required Description
-DNPath -p Yes* Base of the Domain hierarchy from which you want to retrieve objects. DistinguishedName form.
-DNPrefix -d Yes* Alternative to -DNPath. Dotted format (e.g., unit.domain.local).
-DCDepth   No Depth of DC components in -DNPrefix (default: 2).
-OutPath -o No Folder path for output CSVs. Dialog prompts if omitted.
-Computer -comp No Export Computers only. Users and Groups are not processed.
-ExcludeSystemObject -nosys No Exclude system accounts from export.

* Either -DNPath or -DNPrefix is required. They are mutually exclusive.

Usage Examples

# Export AD Users and Groups from the Domain root to CSV files in "C:\ADExport", excluding system objects
.\export-ADData.ps1 -DNPath "DC=mydomain,DC=local" -OutPath "C:\ADExport" -ExcludeSystemObject

# Export AD Users and Groups, specifying a specific hierarchy base.
.\export-ADData.ps1 -DNPath "OU=unit,DC=mydomain,DC=local" -OutPath "C:\ADExport"

# Export AD Computers from the domain root, making the script prompt for output folder via dialog
.\export-ADData.ps1 -DNPath "DC=mydomain,DC=local" -Computer

2. import-ADData.ps1

Overview

Imports AD users, groups, and computers from CSV files, supporting domain migration, OU reorganization, and advanced mapping features. Automatically creates missing OUs and can handle a wide range of migration scenarios.

Key Features

Parameters

Parameter Alias Required Description
-DNPath -p Yes* Target base DN for import (e.g., DC=newdomain,DC=local or OU=sales,DC=newdomain,DC=local). The base DN object (OU or domain root) must already exist; this script does NOT create the base OU.
-DNPrefix -d Yes* Alternative to -DNPath. Dotted format (e.g., unit.domain.local).
-DCDepth   No Depth of DC components in -DNPrefix (default: 2).
-User -u No Import mode for users. Implied if -UserFile specified.
-UserFile -uf No Path to user CSV file. Dialog prompts if omitted and -User is set.
-Group -g No Import mode for groups. Implied if -GroupFile specified.
-GroupFile -gf No Path to group CSV file. Dialog prompts if omitted and -Group is set.
-Computer -c No Import mode for computers. Implied if -ComputerFile specified.
-ComputerFile -cf No Path to computer CSV file. Dialog prompts if omitted and -Computer is set.
-FixGroup   No Operates in a post-import fixup mode for existing groups. Run after user and group imports. This sets ManagedBy references that require prior import of users/groups. See note below.
-NoClassCheck   No By default, this script checks that all records in the input file have an ObjectClass matching the selected import mode (user, group, or computer). This switch disables the ObjectClass column check, allowing you to import files that are missing the column or contain mixed/incorrect types. Filename-based mode checks are always performed. Only use this if you know what you are doing.
-IncludeSystemObject   No Import critical system users/groups (normally dangerous).
-NewUPNSuffix   No New suffix for UserPrincipalName. Defaults to value derived from -DNPath.
-NoProtectNewOU   No Newly created OUs will not be protected from accidental deletion.
-TrimOU   No Remove one or more rightmost (nearest the domain root) OUs from source DNs before import.
-NoDefaultContainer   No Place users/groups/computers with no OU or in “Default” container, i.e., CN=Users or CN=Computers, directly under the domain root.
-NoForceDefaultContainer   No Import objects as their DN dictates: if the DN is directly under the domain root, import as is; if under default container e.g., CN=Users,DC=..., import as is. Mutually exclusive with -NoDefaultContainer.

*Either -DNPath or -DNPrefix is required. They are mutually exclusive.


Note about -FixGroup mode

-FixGroup enables a special post-import operation to set the ManagedBy property on groups, using the same GroupFile as in the import step. This is necessary because ManagedBy typically references user objects, which must already exist in the target AD. This mode does not create or remove any groups or users—it only updates the ManagedBy property for existing groups, mapping references according to the -DNPath, and advanced options (such as -TrimOU, -NoDefaultContainer, etc.).


Advanced Options

-TrimOU

Allows you to remove one or more OUs from the end (domain-root side) of the DistinguishedName of objects to be imported. The argument must be a comma-separated list of OU names (without the OU= prefix).

-TrimOU "deeper,sales"

This example trims OU=sales first, then OU=deeper, from the rightmost OUs (nearest the domain root) of each DN path, if present.

Rules:

Examples:

Exported DN -TrimOU Argument Resulting Path After Trim Explanation
OU=deeper,OU=sales,DC=domain,DC=local sales OU=deeper,DC=domain,DC=local Match (rightmost OU is “sales”), only “sales” trimmed
OU=deeper,OU=sales,DC=domain,DC=local deeper [ unchanged ] No match (rightmost OU is “sales”, not “deeper”)
OU=deeper,OU=sales,DC=domain,DC=local deeper,sales DC=domain,DC=local Match (rightmost sequence is “deeper,sales”), both OUs trimmed
OU=foo,OU=bar,OU=deeper,OU=sales,DC=domain,DC=local deeper,sales OU=foo,OU=bar,DC=domain,DC=local Match (rightmost sequence), both OUs trimmed
OU=foo,OU=bar,OU=deeper,OU=sales,DC=domain,DC=local bar,deeper [ unchanged ] No match (rightmost OUs are “deeper,sales”)

-NoDefaultContainer and -NoForceDefaultContainer

By default, users, groups, and computers that would otherwise be created directly under the domain root are placed in the domain’s “Default” container (CN=Users,DC=... for users and groups, CN=Computers for computers).
If you specify -NoDefaultContainer, such objects are instead created directly under the domain root (DC=...).
If you specify -NoForceDefaultContainer, objects are imported exactly as their DN dictates:

This behavior also applies in cases where the resulting DN path ends up directly under the domain root, such as when all OUs are removed from an object’s original DN by the -TrimOU option.

Precautions:


Password Handling, Account Enablement, and ChangePasswordAtLogon

To set a password for users during import, add a "Password" column to your User CSV (this column is not present in the original export) and enter the desired password in plain text.

Password is required to Enable an account during import.
If the password is absent for a user, the account will be created but remain disabled.

Controlling the “User must change password at next logon” flag

You have two options to control the “User must change password at next logon” (ChangePasswordAtLogon) setting for users to be imported:

Golden rule:
The "ChangePasswordAtLogon" column, if present and non-blank, takes precedence over the userAccountControl bit.

Summary Table:

ChangePasswordAtLogon (column) Password Set Action
TRUE/YES/1 Yes Set-ADUser -ChangePasswordAtLogon $true
FALSE/NO/0 Yes Set-ADUser -ChangePasswordAtLogon $false
TRUE/YES/1 No Warn, do not set
FALSE/NO/0 No Set-ADUser -ChangePasswordAtLogon $false (this is allowed)
blank/missing Yes userAccountControl bit 0x80000 → set flag if present
blank/missing No userAccountControl bit 0x80000 → warn, do not set

ManagedBy Property: Mapping and Container Handling

When importing or registering the ManagedBy property, especially with advanced options or when targeting default containers, the destination OU or container for the referenced object may not match your expectations due to mapping rules and option interactions (such as -TrimOU or -NoDefaultContainer).
A common issue is that the Distinguished Name (DN) in the ManagedBy field of the source CSV may not correspond to the DN of any imported user or group in the target AD. For example, if a computer object is imported into OU=sales,DC=domain,DC=local, but its ManagedBy value in the source CSV is directly on the domain-root (DC=domain,DC=local). The registration will fail unless a user with that exact DN exists in the destination AD.

Note: It is also impossible to register ManagedBy if it refers to a Contact object, which is currently out of scope for this script.

If you encounter unexpected placements or registration failures, review your DN mapping and advanced parameters.
You may need to adjust specific CSV records (for example, update the ManagedBy DN to match the actual imported user’s DN), or hand register the ManagedBy property after import to achieve the intended outcome.


GroupCategory and GroupScope handling in Group Imports

These properties are normally sourced from the groupType column. However, recalculating the hexadecimal integer for groupType can be cumbersome when modifications are required.
To simplify this process, you may leave groupType blank or prefix its value with a hash (“#”). In these cases, the script will use the string columns GroupCategory and GroupScope instead.


Usage Examples

# Import AD Groups from CSV to a new domain, excluding system objects
.\import-ADData.ps1 -DNPath "DC=newdomain,DC=local" -GroupFile ".\Groups_olddomain_local.csv"

# Import AD Users from CSV to an OU on a domain, using a file dialog
.\import-ADData.ps1 -DNPath "OU=osaka,DC=newdomain,DC=local" -User
# NOTE: You must create the **base** OU "osaka" in the destination AD before running the import, if it does not already exist.

# Import AD Computers from CSV
.\import-ADData.ps1 -DNPath "DC=domain,DC=local" -ComputerFile "C:\Exp\Computers_olddomain_local.csv"

# Import users, trimming two rightmost OUs and placing directly under domain root (not in CN=Users)
.\import-ADData.ps1 -DNPath "DC=domain,DC=local" -UserFile "Users_deeper_sales_domain_local.csv" -TrimOU "deeper,sales" -NoDefaultContainer

# Import users, preserving DN structure (Users container or domain root) as-is
.\import-ADData.ps1 -DNPath "DC=domain,DC=local" -UserFile "Users.csv" -NoForceDefaultContainer
Registering ManagedBy for Groups after User/Group Import

To set the ManagedBy property for groups after importing users and groups, run the following sequence. Be sure to use the same -DNPath and advanced options (such as -TrimOU, -NoDefaultContainer, etc.) for all runs to ensure DN mapping is consistent.

# Import groups
.\import-ADData.ps1 -DNPath "DC=newdomain,DC=local" -GroupFile ".\Groups_olddomain_local.csv"

# Import users
.\import-ADData.ps1 -DNPath "DC=newdomain,DC=local" -UserFile ".\Users_olddomain_local.csv"

# Register ManagedBy for groups using FixGroup mode
.\import-ADData.ps1 -DNPath "DC=newdomain,DC=local" -FixGroup -GroupFile ".\Groups_olddomain_local.csv"

Best Practices and Safety Tips


3. compare-ADCSV.ps1

Overview

Compares two CSV exports of AD users, groups or computers, helping you verify changes, migrations, or synchronization.

Key Features

Parameters

Parameter Alias Required Description
-OldFile -o Yes Old CSV file (source)
-NewFile -n Yes New CSV file (destination)
-OutFile   No Output CSV file for results
-IncludeEqual   No Include entries with no detected difference

Usage Examples

# Compare two user CSVs and output differences to a file
.\compare-ADCSV.ps1 -OldFile "oldusers.csv" -NewFile "newusers.csv" -OutFile "diff.csv"

# Compare groups, show all entries (including identical)
.\compare-ADCSV.ps1 -OldFile "oldgroups.csv" -NewFile "newgroups.csv" -IncludeEqual

4. check-ADUserPassword.ps1

Overview

Checks whether a user’s password is set as expected by querying AD.

Key Features

Parameters

Parameter Alias Required Description
-UserName -u Yes Username to validate
-Password -p Yes Password in plain text (prompted if omitted)
-Domain -d No AD Domain to query (dot or DN format; uses preset if omitted)

Usage Example

# Check if the user's password is correct
.\check-ADUserPassword.ps1 -UserName "jdoe" -Password "password123"

Logging

import-ADData.ps1 maintains a detailed log of all operations and errors. The log file is saved as import-ADData.log in the script directory.


License

This project is licensed under the MIT License - see the LICENSE file for details.


Contributing

Contributions are welcome! Please feel free to submit a Pull Request.


Author

Tatsuya Nonogaki