The scripts are used to update existing and create new user accounts based on the data in the CSV file. To execute the scripts, create a scheduled task configured for the Domain object type and add a managed domain to the Activity Scope of the task.
CSV File Sample:
sn,givenName,sAMAccountName,description,physicalDeliveryOfficeName,AccountPassword,manager
Robertson,William,wrobertson,Sales Manager at New York Office,New York,secret,Stephen Jones
John,Susan,sjohn,Senior Controller at LA Central,LA Central,,James Borwn
Smith,Elizabeth,esmith,---TERMINATED---,TERM,Z0eArjoQe
Script 1: Create new and update existing users
The script imports user accounts from a CSV file. Existing accounts are updated based on the data in the CSV file and non-existing ones are created in Active Directory. Existing users are identified by the property specified in the $userIdProperty variable.
Parameters:
- $csvFilePath - Specifies a path to the CSV file that will be imported.
- $userIdColumn - Specifies the name of the column that contains the property for identifying existing users.
- $userIdProperty - Specifies the LDAP name of the property for identifying existing users (e.g. sAMAccountName, employeeID).
- $accountPasswordColumn - Specifies the name of the column that contains account passwords.
- $customColumnNames - Maps column headers with LDAP names of the corresponding user account properties. If mapping is not specified for a column header, the header specified in the file will be used as the property LDAP name.
- $aDObjectProperties - Specifies the list of headers of the columns that contain references to other AD objects, such as, Manager, Secretary or Assistant. Objects can be referenced in the columns by their:
- Distinguished Name
- Full name (cn attribute)
- Display name
Import-Module Adaxes
$csvFilePath = "\\SERVER\share\ImportUsers.csv" # TODO: modify me
$userIdColumn = "EmployeeName" # TODO: modify me
$userIdProperty = "sAMAccountName" # TODO: modify me
$accountPasswordColumn = "AccountPassword" # TODO: modify me
$customColumnNames = @{
"JobTitle" = "title";
"FirstName" = "givenName";
} # TODO: modify me
$aDObjectProperties = @("Manager", "Secretary") # TODO: modify me
$domainName = $Context.GetObjectDomain("%distinguishedName%")
$importedUsers = Import-Csv -Path $csvFilePath
foreach ($userFromCSV in $importedUsers)
{
$userObject = @{}
$accountPassword = $NULL
$propertiesToClear = @()
foreach ($property in $userFromCSV.PSObject.Properties)
{
$columnName = $property.Name
$value = $property.Value
if ($columnName -ieq $accountPasswordColumn -and !([System.String]::IsNullOrEmpty($value)))
{
$accountPassword = ConvertTo-SecureString -AsPlainText $value -Force
continue
}
elseif ($columnName -ieq $accountPasswordColumn -and [System.String]::IsNullOrEmpty($value))
{
continue
}
if ($customColumnNames.ContainsKey($columnName))
{
$propertyName = $customColumnNames[$columnName]
}
else
{
$propertyName = $columnName
}
if ([System.String]::IsNullOrEmpty($value))
{
$propertiesToClear += $propertyName
continue
}
# Parse special columns
if ($columnName -ieq $userIdColumn)
{
$propertyName = $userIdProperty
}
elseif ($aDObjectProperties -icontains $columnName)
{
$aDObject = Get-AdmObject -Filter {(Name -eq $value) -or (DisplayName -eq $value) -or (distinguishedName -eq $value)} `
-AdaxesService localhost -ErrorAction SilentlyContinue -Server $domainName
if ($aDObject -is [System.Array])
{
$Context.LogMessage("Found more than one object with identity '$value'.", "Warning")
continue
}
if ($aDObject -eq $NULL)
{
$Context.LogMessage("Could not locate object with identity '$value'.", "Warning")
continue
}
$value = $aDObject.DistinguishedName
}
if ($value -ieq "True" -or $value -ieq "False")
{
$value = [System.Boolean]::Parse($value)
}
$userObject.Add($propertyName, $value)
}
# Check whether the user exists
$valueForSearch = $userObject.$userIdProperty
$userExists = Get-AdmUser -LdapFilter "($userIdProperty=$valueForSearch)" `
-AdaxesService localhost -ErrorAction SilentlyContinue -Server $domainName
if ($userExists -eq $NULL)
{
# Build user name
$displayName = $userObject.GivenName + " " + $userObject.SN
$parameters = @{
"Path" = "%distinguishedName%"
"Name" = $displayName;
"Server" = $domainName;
"AdaxesService" = "localhost"
"Enabled" = $True
"OtherAttributes" = $userObject
"ErrorAction" = "Stop"
}
if (!([System.String]::IsNullOrEmpty($accountPassword)))
{
$parameters.Add("AccountPassword", $accountPassword)
}
# Create a new user account
try
{
New-AdmUser @parameters
}
catch
{
$Context.LogMessage("An error occurred when creating user '$displayName'. Error: " + $_.Exception.Message, "Warning")
}
continue
}
if ($userExists -is [System.Array])
{
$Context.LogMessage("Found more than one user with value '$valueForSearch' in property '$userIdProperty'", "Warning")
continue
}
# If user exists, update account
$displayName = $userExists.Name
try
{
Set-AdmUser -Identity $userExists.DistinguishedName -Replace $userObject `
-AdaxesService localhost -Server $domainName -ErrorAction Stop
}
catch
{
$Context.LogMessage("An error occurred when updating user '$displayName'. Error: " + $_.Exception.Message, "Warning")
}
if ($propertiesToClear.Length -ne 0)
{
try
{
Set-AdmUser -Identity $userExists.DistinguishedName -Clear $propertiesToClear `
-AdaxesService localhost -Server $domainName -ErrorAction Stop
}
catch
{
$Context.LogMessage("An error occurred when updating user '$displayName'. Error: " + $_.Exception.Message, "Warning")
}
}
if ([System.String]::IsNullOrEmpty($accountPassword))
{
continue
}
try
{
Set-AdmAccountPassword -Identity $userExists.DistinguishedName -NewPassword $accountPassword `
-Reset -Server $domainName -AdaxesService localhost -ErrorAction Stop
}
catch
{
$Context.LogMessage("An error occurred when updating the password for user '$displayName'. Error: " + $_.Exception.Message, "Warning")
}
}
Script 2: Only update existing users
The script imports user accounts from a CSV file. Existing accounts are updated based on the data in the CSV file and are identified by the property specified in the $userIdProperty variable. The script also sends an email notification containing users that were not found or if there were more than one user found with a specific identity.
Parameters:
- $csvFilePath - Specifies a path to the CSV file that will be imported.
- $userIdColumn - Specifies the name of the column that contains the property for identifying existing users.
- $userIdProperty - Specifies the LDAP name of the property for identifying existing users (e.g. sAMAccountName, employeeID).
- $accountPasswordColumn - Specifies the name of the column that contains account passwords.
- $customColumnNames - Maps column headers with LDAP names of the corresponding user account properties. If mapping is not specified for a column header, the header specified in the file will be used as the property LDAP name.
- $ignoreUnspecifiedColumns - If set to True, only the columns specified in the $customColumnNames variable will be imported. If set to False, columns from the mapping will be imported accordingly, while for the rest the column headers will be considered property schema names.
- $aDObjectProperties - Specifies the list of headers of the columns that contain references to other AD objects, such as, Manager, Secretary or Assistant. Objects can be referenced in the columns by their:
- Distinguished Name
- Full name (cn attribute)
- Display name
- $skipEmptyColumnNames - Specifies CSV file column headers. The corresponding AD properties will not be cleared by the script if the columns are empty.
- $to - Specifies the email notification recipient.
- $subject - Specifies the email notification subject.
- $reportHeader - Specifies the report header.
- $reportFooter - Specifies the report header.
Import-Module Adaxes
$csvFilePath = "\\SERVER\share\ImportUsers.csv" # TODO: modify me
$userIdColumn = "EmployeeName" # TODO: modify me
$userIdProperty = "employeeId" # TODO: modify me
$accountPasswordColumn = "AccountPassword" # TODO: modify me
$customColumnNames = @{
"JobTitle" = "title";
"FirstName" = "givenName";
} # TODO: modify me
$ignoreUnspecifiedColumns = $False # TODO: modify me
$aDObjectProperties = @("Manager", "Secretary") # TODO: modify me
$skipEmptyColumnNames = @("MyColumn") # TODO: modify me
# E-mail settings
$to = "recipient@domain.com" # TODO: modify me
$subject = "Import report" # TODO: modify me
$reportHeader = "<h2>Import report</h2>"
$reportFooter = "<hr /><p><i>Please do not reply to this e-mail, it has been sent to you for notification purposes only.</i></p>" # TODO: modify me
$domainName = $Context.GetObjectDomain("%distinguishedName%")
$importedUsers = Import-Csv -Path $csvFilePath
$moreThanOneUserFound = New-Object "System.Text.StringBuilder"
$userNotFound = New-Object "System.Text.StringBuilder"
foreach ($userFromCSV in $importedUsers)
{
$userObject = @{}
$accountPassword = $NULL
$propertiesToClear = @()
foreach ($property in $userFromCSV.PSObject.Properties)
{
$columnName = $property.Name
$value = $property.Value
if ($columnName -ieq $accountPasswordColumn -and !([System.String]::IsNullOrEmpty($value)))
{
$accountPassword = ConvertTo-SecureString -AsPlainText $value -Force
continue
}
elseif ($columnName -ieq $accountPasswordColumn -and [System.String]::IsNullOrEmpty($value))
{
continue
}
if ($customColumnNames.ContainsKey($columnName))
{
$propertyName = $customColumnNames[$columnName]
}
elseif ($columnName -ieq $userIdColumn)
{
$propertyName = $userIdProperty
}
elseif ($ignoreUnspecifiedColumns)
{
continue
}
else
{
$propertyName = $columnName
}
if ([System.String]::IsNullOrEmpty($value))
{
if ($skipEmptyColumnNames -contains $columnName)
{
continue
}
$propertiesToClear += $propertyName
continue
}
# Parse special columns
if ($aDObjectProperties -icontains $columnName)
{
$aDObject = Get-AdmObject -Filter {(Name -eq $value) -or (DisplayName -eq $value) -or (distinguishedName -eq $value)} `
-AdaxesService localhost -ErrorAction SilentlyContinue -Server $domainName
if ($aDObject -is [System.Array])
{
$Context.LogMessage("Found more than one object with identity '$value'.", "Warning")
continue
}
if ($aDObject -eq $NULL)
{
$Context.LogMessage("Could not locate object with identity '$value'.", "Warning")
continue
}
$value = $aDObject.DistinguishedName
}
if ($value -ieq "True" -or $value -ieq "False")
{
$value = [System.Boolean]::Parse($value)
}
$userObject.Add($propertyName, $value)
}
# Check whether the user exists
$valueForSearch = $userObject.$userIdProperty
$userExists = Get-AdmUser -LdapFilter "($userIdProperty=$valueForSearch)" `
-AdaxesService localhost -ErrorAction SilentlyContinue -Server $domainName
if ($NULL -eq $userExists)
{
$userNotFound.Append("<li>$valueForSearch</li>")
continue
}
if ($userExists -is [System.Array])
{
$moreThanOneUserFound.Append("<li>$valueForSearch</li>")
continue
}
# If user exists, update account
$displayName = $userExists.Name
try
{
Set-AdmUser -Identity $userExists.DistinguishedName -Replace $userObject `
-AdaxesService localhost -Server $domainName -ErrorAction Stop
}
catch
{
$Context.LogMessage("An error occurred when updating user '$displayName'. Error: " + $_.Exception.Message, "Warning")
}
if ($propertiesToClear.Length -ne 0)
{
try
{
Set-AdmUser -Identity $userExists.DistinguishedName -Clear $propertiesToClear `
-AdaxesService localhost -Server $domainName -ErrorAction Stop
}
catch
{
$Context.LogMessage("An error occurred when updating user '$displayName'. Error: " + $_.Exception.Message, "Warning")
}
}
if ([System.String]::IsNullOrEmpty($accountPassword))
{
continue
}
try
{
Set-AdmAccountPassword -Identity $userExists.DistinguishedName -NewPassword $accountPassword `
-Reset -Server $domainName -AdaxesService localhost -ErrorAction Stop
}
catch
{
$Context.LogMessage("An error occurred when updating the password for user '$displayName'. Error: " + $_.Exception.Message, "Warning")
}
}
if ($moreThanOneUserFound.Length -eq 0 -and $userNotFound.Length -eq 0)
{
return
}
# Build report
$html = New-Object "System.Text.StringBuilder"
$html.Append($reportHeader)
if ($userNotFound.Length -ne 0)
{
$html.Append("<b>The following users were not found in Active Directory:</b>")
$html.Append("<ol>")
$html.Append($userNotFound.ToString())
$html.Append("</ol>")
}
if ($moreThanOneUserFound.Length -ne 0)
{
$html.Append("<b>Found more than one user with the following value of the $userIdProperty property:</b>")
$html.Append("<ol>")
$html.Append($moreThanOneUserFound.ToString())
$html.Append("</ol>")
}
# Send report
$Context.SendMail($to, $subject, $NULL, $html.ToString())
Script 3: Only create new users
The script imports new user accounts from a CSV file. Each user will get a randomly generated password. The script also sends an email notification containing users with a specific identity that already exist.
Parameters:
- $csvFilePath - Specifies a path to the CSV file that will be imported.
- $userIdColumn - Specifies the name of the column that contains the property for identifying existing users.
- $userIdProperty - Specifies the LDAP name of the property for identifying existing users (e.g. sAMAccountName, employeeID).
- $accountPasswordColumn - Specifies the name of the column that contains account passwords.
- $customColumnNames - Maps column headers with LDAP names of the corresponding user account properties. If mapping is not specified for a column header, the header specified in the file will be used as the property LDAP name;
- $aDObjectProperties - Specifies the list of headers of the columns that contain references to other AD objects, such as, Manager, Secretary or Assistant. Objects can be referenced in the columns by their:
- Distinguished Name
- Full name (cn attribute)
- Display name
- $ouDN - Specifies the distinguished name (DN) of the OU where new users will be created. For information on how to get the DN of a directory object, see Get the DN of an Active Directory object.
- $to - Specifies the email notification recipient.
- $subject - Specifies the email notification subject.
- $reportHeader - Specifies the report header.
- $reportFooter - Specifies the report header.
Import-Module Adaxes
$csvFilePath = "\\SERVER\share\ImportUsers.csv" # TODO: modify me
$userIdColumn = "EmployeeName" # TODO: modify me
$userIdProperty = "sAMAccountName" # TODO: modify me
$accountPasswordColumn = "AccountPassword" # TODO: modify me
$customColumnNames = @{
"JobTitle" = "title";
"FirstName" = "givenName";
} # TODO: modify me
$aDObjectProperties = @("Manager", "Secretary") # TODO: modify me
$ouDN = "CN=Users,DC=domain,DC=com" # TODO: modify me
# E-mail settings
$to = "recipient@domain.com" # TODO: modify me
$subject = "Import report" # TODO: modify me
$reportHeader = "<h2>Import report</h2>"
$reportFooter = "<hr /><p><i>Please do not reply to this e-mail, it has been sent to you for notification purposes only.</i></p>" # TODO: modify me
$domainName = $Context.GetObjectDomain($ouDN)
$importedUsers = Import-Csv -Path $csvFilePath
$rootDSE = $Context.BindToObject("Adaxes://RootDSE")
$userFound = New-Object "System.Text.StringBuilder"
foreach ($userFromCSV in $importedUsers)
{
$userObject = @{}
$accountPassword = $NULL
foreach ($property in $userFromCSV.PSObject.Properties)
{
$columnName = $property.Name
$value = $property.Value
if ($columnName -ieq $accountPasswordColumn -and !([System.String]::IsNullOrEmpty($value)))
{
$accountPassword = ConvertTo-SecureString -AsPlainText $value -Force
continue
}
elseif ($columnName -ieq $accountPasswordColumn -and [System.String]::IsNullOrEmpty($value))
{
continue
}
if ($customColumnNames.ContainsKey($columnName))
{
$propertyName = $customColumnNames[$columnName]
}
else
{
$propertyName = $columnName
}
if ([System.String]::IsNullOrEmpty($value))
{
continue
}
# Parse special columns
if ($columnName -ieq $userIdColumn)
{
$propertyName = $userIdProperty
}
elseif ($aDObjectProperties -icontains $columnName)
{
$aDObject = Get-AdmObject -Filter {(Name -eq $value) -or (DisplayName -eq $value) -or (distinguishedName -eq $value)} `
-AdaxesService localhost -ErrorAction SilentlyContinue -Server $domainName
if ($aDObject -is [System.Array])
{
$Context.LogMessage("Found more than one object with identity '$value'.", "Warning")
continue
}
if ($aDObject -eq $NULL)
{
$Context.LogMessage("Could not locate object with identity '$value'.", "Warning")
continue
}
$value = $aDObject.DistinguishedName
}
if ($value -ieq "True" -or $value -ieq "False")
{
$value = [System.Boolean]::Parse($value)
}
$userObject.Add($propertyName, $value)
}
# Check whether the user exists
$valueForSearch = $userObject.$userIdProperty
$userExists = Get-AdmUser -LdapFilter "($userIdProperty=$valueForSearch)" `
-AdaxesService localhost -ErrorAction SilentlyContinue -Server $domainName
if ($NULL -eq $userExists)
{
# Build user name
$displayName = $userObject.GivenName + " " + $userObject.SN
$parameters = @{
"Path" = $ouDN
"Name" = $displayName;
"Server" = $domainName;
"AdaxesService" = "localhost"
"Enabled" = $True
"OtherAttributes" = $userObject
"ErrorAction" = "Stop"
}
if (!([System.String]::IsNullOrEmpty($accountPassword)))
{
$parameters.Add("AccountPassword", $accountPassword)
}
# Create a new user account
try
{
New-AdmUser @parameters
}
catch
{
$Context.LogMessage("An error occurred when creating user '$displayName'. Error: " + $_.Exception.Message, "Warning")
}
}
else
{
$userFound.Append("<li>$valueForSearch</li>")
}
}
if ($userFound.Length -eq 0)
{
return
}
# Build report
$html = New-Object "System.Text.StringBuilder"
$html.Append($reportHeader)
$html.Append("<b>The following users were found in Active Directory:</b>")
$html.Append("<ol>")
$html.Append($userFound.ToString())
$html.Append("</ol>")
$html.Append($reportFooter)
$Context.SendMail($to, $subject, $NULL, $html.ToString())
I built the task as described in (https://www.adaxes.com/tutorials_ActiveDirectoryManagement_ScheduleImportOfUsersFromCSV.htm).
And as an action the script is deposited.
Unfortunately no user will import
CSV file as described (with my data).
sn,givenName,sAMAccountName,description,physicalDeliveryOfficeName,AccountPassword,manager
Robertson,William,wrobertson,Sales Manager at New York Office,New York,secret,Stephen Jones
Hello Christian,
Could you, please, provide a screenshot of the Scheduled Task you created including the Activity Scope? You can send it to support@adaxes.com.
Does the Scheduled Task produce any error messages when executing the script? If so, please, provide us with screenshots. You can check it by viewing the Activity History of the task:https://www.adaxes.com/help/?ManageScheduledTasks.ViewActivityHistory.html.
If you made any modifications to the script, please, provide us with the updated script in TXT format.
Could you please support me on this error.
Thank you.
Dario
Could you, please, post here or send us (support[at]adaxes.com) the script you are using in TXT format including all your modifications?
Also, provide us with a screenshot of the Scheduled Task that executes the script. Please, make sure that the screenshot includes the Activity Scope section.
Unfortunately, we did not receive any information from Dario. For troubleshooting purposes, please, provide the same data as was requested above.
Thank you for the provided details. The issue occurs because of the modifications you made in the script. For us to correct it, please, specify what exactly all your modifications are intended for and what the desired behavior is. Live examples will be very helpful.
CSV Contains:
Company, Employee_ID, Location, First_Name, Middle_Name, Last_Name, Job_title, Role,Supervisor
2000, 12345, 20394, Lexie, M, Smith, Care Associate, RG-20000-Campus-Matrix, 137250
Based on the csv:
The sAMAAccountName should be the last name and employee ID
$sAMAccountName= ($LastName + $EmpID)
Manager: Lookup based on the Supervisor field which is the Employee ID for the Manager
$MgrID="Supervisor"
$Manager=Get-ADUser -LDAPFilter "(EmployeeID=$MgrID)" -Properties distinguishedName
Users Full Name should be the concatenated first and last name:
$userIdColumn=$($FirstName + " " + $LastName)
All of the other fields are to go in as they are:
"Company"= "company"
"Employee_ID" = "employeeID";
"Location" = "Office";
"First_Name" = "GivenName";
"Middle_Name" = "MI";
"Last_Name" = "Surname"
"Job_Title" = "title";
"Role" = "Department";
Email Settings:
$to = Should Lookup the Managers email address for each imported user based on the result of the manager lookup.
Thank you for specifying. For us to update the script according to your needs, please, specify what should be done if a manager with the specified employee ID is not found. Should the user be created with an empty Manager property? Should notifications about existing users be sent to a different email? Any additional details and live examples of the desired behavior will be much appreciated.
What if not only the manager does not exist, but also the sAMAccountName is already taken? Should a corresponding email be sent to ServcieDesk@domain.com?
Thank you for the confirmation. Please, find the updated script below.
I modified what you sent as follows:
Changed the Path to the CSV, Changed the $to and added the following:
$customColumnNames = @{
"Company"= "company"
"Employee_ID" = "employeeID";
"Location" = "Office";
"First_Name" = "GivenName";
"Middle_Name" = "middleName";
"Last_Name" = "sn"
"Job_Title" = "title";
"Role" = "Department";
"Supervisor" = "$mgrid";
$aDObjectProperties = @("Manager = Supervisor", "Secretary")
$ouDN = info was changed.
CSV Content
Company,Employee_ID,Location,First_Name,Middle_Name,Last_Name,Job_Title,Role,Supervisor
20000,128,20127,Lexie,r,Test,Test Associate,rg-20000-Campus-CaretrckrMatrix,135743
20000,133,20423,Madeline,C,Test,Resident Test Associate,rg-20000-Campus-RCACaretrackerAL,135743
20000,136,20415,Irene,M,Test,Test Services Asst,rg-20000-Campus-SmartlinxOnly,135743
When the script is run the log says completed. The users are NOT created and the execution log says:
"An error occurred when creating user 'Irene Test'. Error: Parameter must be a non empty string. Parameter name: name"
We opened a support ticket to help you with the script. An email was sent to the address of your account.
Hello Jay,
The current version of the script not only updates the users, but also creates new ones. Also, it attempts to update all the properties present in the CSV file. However, the script can be updated to work exactly as you need. Still on 15k users it can take quite long.It totally depends on your requirements. If you have a CSV file with user data that is frequently updated, using such a script should work just fine to keep your user data up to date in Active Directory.
>So this script as is just needs the headings of the columns to be the same as the attribute name or map them in the script. Correct?
Yes, that is correct.
>Also we will need a check added to only update the accounts where information changed.
There is no need to add the check. Adaxes does not update properties to the same values. If all the properties are the same (nothing has changed), no updates will be performed.
$csvFilePath = "\\ServerName\Scripts\Output\testVcpiExport.csv" # TODO: modify me
$userIdColumn = "Name" # TODO: modify me
$userIdProperty = "employeeID" # TODO: modify me
$accountPasswordColumn = "AccountPassword" # TODO: modify me
$customColumnNames = @{
"JobTitle" = "title";
"FirstName" = "givenName";
"SamAccountName" = "SamAccountName";
"Departmentnumber" = "Departmentnumber";
"enabled" = "enabled";
"department" = "department";
"description" = "description";
"office" = "office";
"emailaddress" = "emailaddress";
"extensionAttribute2" = "extensionAttribute2";
CSV with one record:
Name,SamAccountName,Departmentnumber,enabled,empid,department,description,title,office,emailaddress,extensionAttribute2,whenChanged
"Test, user",tuser1,322507,FALSE,96587,North Michigan,"#322507, Office, test job,Cook,322507,,Jobtestcode,5/31/2021 20:31
I receive the following error:
Exception calling "Add" with "2" argument(s): "Item has already been added. Key in dictionary: 'employeeId' Key being added: 'employeeid'" Stack trace: at <ScriptBlock>, <No file>: line 97
Here are the changes i have made:
$csvFilePath = "\\server\Scripts\Output\testImport.csv" # TODO: modify me
$userIdColumn = "Name" # TODO: modify me
$userIdProperty = "employeeID" # TODO: modify me
$accountPasswordColumn = "AccountPassword" # TODO: modify me
$customColumnNames = @{
"title" = "title";
"SamAccountName" = "SamAccountName";
"Departmentnumber" = "Departmentnumber";
"enabled" = "enabled";
"department" = "department";
"description" = "description";
"office" = "office";
"emailaddress" = "emailaddress";
"extensionAttribute2" = "extensionAttribute2";
Import file content:
Name,SamAccountName,Departmentnumber,enabled,empid,department,description,title,office,emailaddress,extensionAttribute2,whenChanged
"user, test",test1,322507,FALSE,99613, Michigan,TestAccountuser,Cook,322507,,TestRoleOnly,5/31/2021 20:31
Error:
Exception calling "Add" with "2" argument(s): "Item has already been added. Key in dictionary: 'employeeid' Key being added: 'employeeID'" Stack trace: at <ScriptBlock>, <No file>: line 97
ScriptModifications:
$csvFilePath = "\\server\testImport.csv" # TODO: modify me
$userIdColumn = "cn" # TODO: modify me
$userIdProperty = "employeeid" # TODO: modify me
$accountPasswordColumn = "AccountPassword" # TODO: modify me
$customColumnNames = @{
"title" = "title";
"Departmentnumber" = "departmentNumber";
"department" = "department";
"description" = "description";
"office" = "physicalDeliveryOfficeName";
"emailaddress" = "mail";
"extensionAttribute2" = "extensionAttribute2";
Test file:
cn,SamAccountName,Departmentnumber,enabled,empid,department,description,title,office,emailaddress,extensionAttribute2,AccountPassword,whenChanged
Joe Test,jtest,322507,TRUE,987654321,North Michigan,OfficeLocation,Cook,322507,,TestRole,,5/31/2021 20:31
To get notifications on the import attempts performed via the script, you can specify your email address in the $to variable.
Most probably, the changes are not performed because the Joe Test user account was not found in your domain. The thing is that the value for user search is obtained from the column whose name is specified in the $userIdColumn variable. In your case, it is the cn column which contains full name but not an employee ID whose attribute name is specified to perform the search by (the value of the $userIdProperty variable). At the same time, the empid column name does not match any attribute LDAP name and is not listed in the $customClumnNames variable. That will cause an error during the script execution. If the empid column contains the employee IDs the user search should be performed by, you can change the $userIdColumn variable value to empid to remedy the issue.
Also, the whenChanged attribute specified in your CSV file is System Only. It means the attribute can be set/updated only by Active Directory and attempts to update manually (e.g. via the script) will cause errors. Thus, you should remove the attribute column from the file.
For your information, as the title, Departmentnumber, department, description, and extensionAttribute2 column name match the names of the corresponding attributes, there is no need to list them in the $customColumnNames variable. In case of the file you are importing, the variable can be like the following:
I'm working with Script 2 - I what to update the attribute employeeNumber. I made a list with one line, but I get the Error the User not found.
$csvFilePath = "\\Server\csv\Update_User.csv" # TODO: modify me
$userIdColumn = "sAMAccountName" # TODO: modify me
$userIdProperty = "employeeNumber" # TODO: modify me
$accountPasswordColumn = "AccountPassword" # TODO: modify me
$customColumnNames = @{
"sAMAccountName" = "sAMAccountName";
"employeeNumber" = "employeeNumber";
} # TODO: modify me
$aDObjectProperties = @("employeeNumber") # TODO: modify me
sAMAccountName,employeeNumber,
Peter.Muster,AB52
The thing is that you specifies the column and the property for identifying user account incorrectly. The sAMAccountName column contains the value of the sAMAccountName property, not that of the employeeNumber property. Also, as the employeeNumber is not of DN syntax and you have no such properties in the CSV file, the $aDObjectProperties should be set to an empty array. Finally, your script should be exactly as below.
Yes, it is possible using a custom command and a parameter. In this case, the corresponding line in the script will look as below, where param-filePath is the name of the parameter used to specify the path to the CSV file.
The parameter can be of Edit box type and users will have to manually enter the path. Unfortunately, there is no parameter that would allow you to browse the file system to select a file. However, thank you for the suggestion. We forwarded it to the corresponding department for consideration.
<h2>Paycom Import Report</h2>
" # Specifies the report header. $reportFooter = "<hr />
<p><em>Please do not reply to this e-mail, it has been sent to you for notification purposes only.</em></p>
" # Specifies the report header. $domainName = $Context.GetObjectDomain("%distinguishedName%") $importedUsers = Import-Csv -Path $csvFilePath $moreThanOneUserFound = New-Object "System.Text.StringBuilder" $userNotFound = New-Object "System.Text.StringBuilder" foreach ($userFromCSV in $importedUsers) { $userObject = @{} $accountPassword = $NULL $propertiesToClear = @() foreach ($property in $userFromCSV.PSObject.Properties) { $columnName = $property.Name $value = $property.Value if ($columnName -ieq $accountPasswordColumn -and !([System.String]::IsNullOrEmpty($value))) { $accountPassword = ConvertTo-SecureString -AsPlainText $value -Force continue } elseif ($columnName -ieq $accountPasswordColumn -and [System.String]::IsNullOrEmpty($value)) { continue } if ($customColumnNames.ContainsKey($columnName)) { $propertyName = $customColumnNames[$columnName] } else { $propertyName = $columnName } if ([System.String]::IsNullOrEmpty($value)) { $propertiesToClear += $propertyName continue } # Parse special columns if ($columnName -ieq $userIdColumn) { $propertyName = $userIdProperty } elseif ($aDObjectProperties -icontains $columnName) { $aDObject = Get-AdmObject -Filter {(Name -eq $value) -or (DisplayName -eq $value) -or (distinguishedName -eq $value)} ` -AdaxesService localhost -ErrorAction SilentlyContinue -Server $domainName if ($aDObject -is [System.Array]) { $Context.LogMessage("Found more than one object with identity '$value'.", "Warning") continue } if ($aDObject -eq $NULL) { $Context.LogMessage("Could not locate object with identity '$value'.", "Warning") continue } $value = $aDObject.DistinguishedName } if ($value -ieq "True" -or $value -ieq "False") { $value = [System.Boolean]::Parse($value) } $userObject.Add($propertyName, $value) } # Check whether the user exists $valueForSearch = $userObject.$userIdProperty $userExists = Get-AdmUser -LdapFilter "($userIdProperty=$valueForSearch)" ` -AdaxesService localhost -ErrorAction SilentlyContinue -Server $domainName if ($NULL -eq $userExists) { $userNotFound.Append("
<ul>
<li>$valueForSearch</li>
</ul>
") continue } if ($userExists -is [System.Array]) { $moreThanOneUserFound.Append("
<ul>
<li>$valueForSearch</li>
</ul>
") continue } # If user exists, update account $displayName = $userExists.Name try { Set-AdmUser -Identity $userExists.DistinguishedName -Replace $userObject ` -AdaxesService localhost -Server $domainName -ErrorAction Stop } catch { $Context.LogMessage("An error occurred when updating user '$displayName'. Error: " + $_.Exception.Message, "Warning") } if ($propertiesToClear.Length -ne 0) { try { Set-AdmUser -Identity $userExists.DistinguishedName -Clear $propertiesToClear ` -AdaxesService localhost -Server $domainName -ErrorAction Stop } catch { $Context.LogMessage("An error occurred when updating user '$displayName'. Error: " + $_.Exception.Message, "Warning") } } if ([System.String]::IsNullOrEmpty($accountPassword)) { continue } try { Set-AdmAccountPassword -Identity $userExists.DistinguishedName -NewPassword $accountPassword ` -Reset -Server $domainName -AdaxesService localhost -ErrorAction Stop } catch { $Context.LogMessage("An error occurred when updating the password for user '$displayName'. Error: " + $_.Exception.Message, "Warning") } } if ($moreThanOneUserFound.Length -eq 0 -and $userNotFound.Length -eq 0) { return } # Build report $html = New-Object "System.Text.StringBuilder" $html.Append($reportHeader) if ($userNotFound.Length -ne 0) { $html.Append("<strong>The following users were not found in Active Directory:</strong>") $html.Append("
<ol>") $html.Append($userNotFound.ToString()) $html.Append("</ol>
") } if ($moreThanOneUserFound.Length -ne 0) { $html.Append("<strong>Found more than one user with the following value of the $userIdProperty property:</strong>") $html.Append("
<ol>") $html.Append($moreThanOneUserFound.ToString()) $html.Append("</ol>
") } # Send report $Context.SendMail($to, $subject, $NULL, $html.ToString())
What exactly do you mean by cannot get it to find all the users to update? Does the script update some users but not all? Do you face any errors? If so, please, send us (support@adaxes.com) screenshots. Also, please, send us a sample CSV file you are using. Any additional details will be much appreciated.
To achieve the desired behavior, you can create scheduled task configured for the Organizational Unit object type and specify only the required OU in the Activity Scope. Make sure to select the The Organizational Unit object checkbox only.
I updated the Script to Create User only, and when I ran the Script, it generated the following error:
The term 'Import-Module' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. Stack trace: at <ScriptBlock>, <No file>: line 1
I did not modify the Import-Module Line, and I have other Scripts running with this same Import Module call that does not error out.
Most probably, there is some unprintable character in the line. You can try to just remove it from the script. Starting with PowerShell 3.0 required modules are imported automatically.
I was getting the Script 2: Only update existing users to work. Thank you for that.
Can you help me on how can I use it to only update one user and not a bulk? This is for when I create a new user, and the "sAMAccountName" match a entry from the csv file it will update the attributes.
/Thomas
There is no easy way to just update this script to meet your needs. The thing is that you need a totally reverse logic and thus the script will be totally different.
I was able to find a workaround for the problem, I just added some lines. So instead of running the loop on all users in the csv file I only got it to run on my current user.
So, what i did was make some new variable:
$CurrentUser = "%username%"
$folder = "E:\csvfilefromHR" # Location of file
$csvfile = "CSVfilename" #Name of file
$csvfiles = Get-ChildItem -Path $folder -File | Where-Object {$_.Extension -like ".csv" -and $_.Name -like "$csvfile*"} | Sort-Object -Property LastWriteTime -Descending | select -First 1 | select fullname # Selecting the newest CSV file
$importedUsersNofilter = Import-Csv -path $csvfiles.FullName -Encoding UTF8 # Import the whole CSV file.
importedUsers = $importedUsersNofilter| Where-Object {$_.user_name -eq $CurrentUser} # Import only the line with current user.
Then I use the rest of the script to update the users.
Hope this can help other also.
/Thomas