Updating users with different descriptions in AD - powershell

I have a .csv file with a couple of users and each user has a different description. I'm trying to create a script to update the users' description with what is in the .csv file. I have searched but have been unable to find a script that does what I need it to do. Can someone take a look at my script please? I am erroring at:
Unexpected token 'in' in expression or statement. At line:6 char:35
Unexpected token 'in' in expression or statement. At line:6 char:38
ipmo ac*
$file = c:\user_file.csv
$user = $_.samaccountname
$desc = $_.description
Import-csv $file | Foreach ($user in $file) {
#(Set-aduser -identity $($file.user) -description $($file.desc))
}
Any help would be appreciated since I have been trying to do this for a week now and I'm sure it's something easy?

I would instead do something like this.
ipmo ac*
$file = "c:\user_file.csv"
Import-csv $file | ForEach-Object{
Set-aduser -identity $_.samaccountname -description $_.description
}
This is assuming you have your CSV with columns called samaccountname and description.
Not sure what you were trying to do with $user and $desc so those are just omitted. Guessing they would have actually been null since $_ is meant to be used inside a pipeline.
The ForEach you were using is not meant to have pipeline input. The way you have it usually stands on its own. So we switched it to the ForEach-Object version that allows pipeline input.

Related

PowerShell Array w/ Filter ~ ParameterBindingException

I am trying to make a list of users and compare their SamAccount Names to Active Directory and to filter which user AD accounts are disabled.
I receive the error message below when I execute the script.
I do the following:
$Names = #("Shannon.Hoffman","Kameron.Mack","Ashleigh.Reeves","Diego.Colon","Mayra Ortega","Mark.Dunn")
Get-ADUser -Filter {(Enabled -eq "False") -and (SAMAccountName -like $Names)}
I recieve this error message:
Get-ADUser : Cannot convert 'System.Object[]' to the type 'Microsoft.ActiveDirectory.Management.ADUser' required by parameter 'Identity'. Specified method is not supported.
I also get an error saying ParameterBindingException
I am relatively new to PowerShell. Can you please help me understand what I am doing wrong?
Many Thanks!
I would really suggest that you learn PowerShell before trying to do useful things. Things can go badly very quickly.
For one thing, you are filtering using the entire list instead of per user, so you would need to use a loop. Something like the below could do what you require:
$Names = #("username1","username2")
Foreach ($Name in $Names){
$User = Get-ADUser -Identity $Name
if ($User.Enabled){
#user is enabled, add to your list
}
}
Heres some extra reading:
Foreach
Pipeline
PS AD

How to extract field content in powershell

History: I'm making a Powershell script in order to create user from a defined table containing list of users and put them in a defined OrganizationalUnit.
Problem: At the end of the script, I'd like to have a report in order to list whether or not there is one or many user account disabled amoung newly created account
In my script, I have to input a password for each user, but I may enter a password that won't meet the password policy defined in Active Directory; in this case, the account will be created but disabled.
To proceed, I tried :
dsquery user "ou=sp,dc=mydomain,dc=local" -disabled
and it print me this :
"CN=user1,OU=SP,DC=mydomain,DC=local"
"CN=user2,OU=SP,DC=mydomain,DC=local"
"CN=user3,OU=SP,DC=mydomain,DC=local"
My goal : I'd like to extract in a variable the values in "CN" field in order to compare them to the inital user table in my script.
dsquery user "dc=mydomain,dc=local" -disabled | where-object {$_.CN -ne $null}
or
dsquery user "dc=mydomain,dc=local" -disabled | where-object {$_.Common-Name -ne $null}
But it didn't help (doesn't work). How can I proceed please?
It's not tested - just "from my mind"
$csvData = Import-Csv 'UserList.csv' -Delimiter ';' -Encoding UTF8
$userList = dsquery user "ou=sp,dc=mydomain,dc=local" -disabled
$listOfDisabledAccounts = #()
foreach ($user in $userList)
{
if ($csvData.Name -contains (($user -split ',')[0] -replace 'CN=',''))
{
$listOfDisabledAccounts += $csvData.Name
}
}
$listOfDisabledAccounts
dsquery is not a PowerShell cmdlet, but an executable. This means that it is not going to return PowerShell objects to the pipeline. Kongstead's method works off of the knowing that it returns string output. By manipulating the string using split and replace you can get the output into something usable for your purposes. The other two methods to get this information would be to use the the AD module (from RSAT on desktop OSs) and ADSI methods from .Net. Both of these would return data that would be directly usable.
The AD cmdlets would be the easiest. To get all the disabled accounts would look something like this:
Search-ADAccount -AccountDisabled -SearchBase "dc=mydomain,dc=local"
The following example uses PowerShell's match function to parse the CN field, similar to the answer from Kongsted. It should help you achieve what you are looking for, if using AD cmdlets is not an option.
#This is the output from your current query, from the question, it appears to be an array.
$output = ("CN=user1,OU=SP,DC=mydomain,DC=local","CN=user2,OU=SP,DC=mydomain,DC=local","CN=user3,OU=SP,DC=mydomain,DC=local")
$disabledAccs = #()
foreach ($line in $output) {
#match everything after CN= up to the next comma
if([string]$line -match "CN=([^,]*)"){
$disabledAccs += , $Matches[1]
}
}

Active Directory PowerShell Filter

I'm having issues with a script in powershell using AD Module.
I know the general rule of thumb as to how AD commands like to receive its queries so I've wrote this script to (what I thought) would fall inline with those guidelines.
$CSV=Import-Csv "c:\temp\deleteduserlist.csv"
foreach ($entry in $CSV)
{
$filter = "{SamAccountName -like ""$($entry.username)""}"
Get-ADObject -filter $filter
}
I basically need to be able to query and restore any of the users that have been deleted however it fails with:
Error Message: 'syntax error' at position: '1'
At first I was sending through the filter with single quotations like so:
{SamAccountName -like 'xxx'"}
However I have fixed this now.
One thing that puzzles me is that I can literally show the results of $filter, copy them to Get-ADObject -Filter (paste) manually and it works. Therefore I cannot understand why Powershell does not like it..
Whole Error:
Get-ADObject : Error parsing query: '{SamAccountName -like "xxxx"}'
Error M essage: 'syntax error' at position: '1'. At
C:\temp\GetDeleted.ps1:5 char:14
+ Get-ADObject <<<< -filter $filter
+ CategoryInfo : ParserError: (:) [Get-ADObject], ADFilterParsing Exception
+ FullyQualifiedErrorId : Error parsing query: '{SamAccountName -like "xxx "}' Error Message: 'syntax error' at position: '1'.,Microsoft.ActiveD irectory.Management.Commands.GetADObject
One way to do it is this
$CSV=Import-Csv "c:\temp\deleteduserlist.csv"
foreach ($entry in $CSV) {
## Set username to entry from csv file
$directory_username = $entry.username
## Build search filter before using it, interested in username and deleted objects
$directory_filter = {(SamAccountName -like $directory_username) -and (Deleted -eq $true)}
## Search for ADObject based on filter and deleted objects explicitely included in the search
$directory_found_object = Get-ADObject -Filter $directory_filter -IncludeDeletedObjects -Properties sAMAccountName, Deleted
foreach ($directory_object in $directory_found_object) {
### Execute required action on each found $directory_object
### Perhaps pipe $directory_object | Restore-ADObject with appropriate attribute values for restore
}
}
$directory_filter can be of course modified to fit your needs better. However one challenge you will be facing still is to decide which of the found objects for given sAMAccountName should be restored. This is because any given objects can be in deleted state multiple times. Perhaps one way to solve for that is to restore object with latest WhenCreated attribute value.
Also I'm not sure what motivation you have to build filter beforehand. It might be useful in case you built in on the fly for different attribute values but it seems not to be the case in your example. So for simplicity it can be also removed and included directly in Get-ADObject call like this
$directory_found_object = Get-ADObject -Filter {(SamAccountName -like $directory_username) -and (Deleted -eq $true)} -IncludeDeletedObjects -Properties sAMAccountName, Deleted

AD Update from CSV file without SamAccountName

My goal is to use a CSV file exported by HR without the correct headings to update our AD Users&Computers. Ultimately I would like to update: Department, Description/Job Title, Office, Location, Manager.
I'm not asking you to do this for me, just point me in the right direction and id be really grateful.
Also you will notice there is no SamAccountName, this is by design, because users have the same name so we have had to use the first 2 initials of some users first name followed by the last name.
import-module ActiveDirectory
Import-CSV $data | ForEach-Object {
$Name;expression={($_.'First Name'+' '+$_.'Last Name')}
$displayName;expression={$_.'First Name'+' '+$_.'Last Name'}
$givenName;expression={$_.'First Name'}
$surName;expression={$_.'Last Name'}
$description;expression={$_.'Job Name'}
$office;expression={$_.'Location Name'}
$department;expression={$_.'Department Name'}
$title;expression={$_.'Job Name'}
$manager;expression={$_.'Manager Name'}
}
foreach ($user in $data){
Get-ADUser -Filter "displayName -eq '$($user.$Name)'" | Set-ADUser -Replace #{title = “$($user.$title)”}
}
One of the errors I am getting
The term 'expression=' is not recognized as the name of a cmdlet, function, script file, or operable program.
Your code for the most part is unmanageable. It is easier to redo it in order to
point [you] in the right direction
You over complicated things by trying to rename your values of each row. While you can do that you don't really need to. FWIW you were throwing in syntax from calculated properties.
Import-Module ActiveDirectory
# Path to the CSV file
$filePath = "C:\scripts\ADIntegrationData.csv"
# Import the users
Import-CSV $filePath | ForEach-Object {
# Try and find a matching user
$displayName = "{0} {1}" -f $_.'First Name', $_.'Last Name'
Get-ADUser Get-ADUser -Filter "displayName -eq '$displayName'" | Set-ADUser -Title $_.'Job Name' -WhatIf
}
In the case of Set-ADUser you only have to use the -Add, -Remove and -Replace if the property you want to change is already present. -Title is already support so in that case we use it! Always consult the documentation so check the link for Set-ADUser and look at the attributes that are natively available to change.
You will see the -f formatting operator used here. It is a simple way to work with building complicated strings.
Notice the -WhatIf which will help you test your code before making changes to AD that might be wrong.

PowerShell Pipeline Script Block inside Hashtable

Hopefully a PowerShell noob question, but how do I access the current pipeline object inside a script block which is also within a hashtable?
Here is what I'm trying to do in its entirety:
Get-ADGroupMember "Group Name" |
Where {$_.objectClass -eq "user"} |
Get-ADUser -properties extensionAttribute1 |
Where {$_.extensionAttribute1 -ne ($_.UserPrincipalName -replace "#ADdomain.com", "#GAdomain.com")} |
Set-ADUser -replace #{extensionAttribute1=&{$_.UserPrincipalName -replace "#ADdomain.com", "#GAdomain.com"}}
I have everything working except for that last line, where the new extensionAttribute1 should be generated from the current users UserPrincipalName, replacing the domain. Running this code results in an error:
+ Set-ADUser <<<< -replace #{ExtensionAttribute1=&{$_.UserPrincipalName -replace "#ADdomain.com", "#GAdomain.com"}}
+ CategoryInfo : InvalidOperation: (CN=Bar\, Fo...ADdomain,DC=com:ADUser) [Set-ADUser], ADInvalidOperationException
+ FullyQualifiedErrorId : replace,Microsoft.ActiveDirectory.Management.Commands.SetADUser
Replacing the code inside the script block with a string works ok (below), so it seems like some sort of access issue to the current pipeline object. Does $_ not work in this case?
Set-ADUser -replace #{extensionAttribute1=&{"foobar"}}
The short answer seems to be using a foreach in your pipeline, as such:
Get-ADGroupMember "Group Name" |
Where {$_.objectClass -eq "user"} |
Get-ADUser -properties extensionAttribute1 |
Where {$_.extensionAttribute1 -ne ($_.UserPrincipalName -replace "#ADdomain.com", "#GAdomain.com")} |
foreach-objct {Set-ADUser $_ -replace #{extensionAttribute1=&{$_.UserPrincipalName -replace "#ADdomain.com", "#GAdomain.com"}}}
As for why, I'm pretty sure it's because Set-ADUser only accepts one object, whether it's one ADUser or one collection of ADUsers. Since $_ represents this, the way you had it was causing Set-ADUser to see $_ as the one object you were providing in the pipeline - the group of users (instead of each individual user).
Note: The following is speculation! If I'm wrong please correct me!
Regarding Set-ADUser taking one or more objects... here's my guess. If you look at the Input Types of Set-ADUser, it gives the types of None or Microsoft.ActiveDirectory.Management.ADUser. But as you have seen, you can also pass along a collection of ADUser objects and Set-ADUser will accept that as well. From my understanding of that cmdlet, when you call it you can run the same Set command on all objects in that collection. For instance, you could do as you mentioned (assuming $users contains everything in the pipeline up until then):
$users | Set-ADUser -replace #{extensionAttribute1=&{"foobar"}}
My guess is that under the hood, Set-ADUser is accepting $users as the single parameter value (by setting the ValueFromPipeline attribute to true in the code) and applying the parameters you provided to each object therein. Since the iteration of the collection is happening within the cmdlet's code (which is no longer in PowerShell, it's the compiled .Net code), the $_ would have no use here in terms of representing each object.
I'm not sure the mechanics of why the pipeline lets you run Get-ADUser in a pseudo-foreach fashion since they have the same input types (you called that in a similar manner without using foreach) but based on the evidence, I have to assume it's under the hood. If anyone has further insights, I'm definitely curious to know. I may be totally off base!