Proxyaddresses added to the multivalued attribute not appearing on seperate lines - powershell

I am using the following script to create a spreadsheet of users and proxyaddress values (matching a string) as a record prior to removing them, in the case of an emergency I want to be able to put the values back.
The script works well if there is only a single entry per user, the issue is seen when a user has more than one entry. The problem is that when I attempt to revert back to the original values, when viewed through an attribute editor the proxyaddresses are appearing all on one line instead of a separate line for each proxy address. I am not sure if the fault is on the collection script, or the script I am using to set the values. To collect the values I am running the following:
$entry = "*test.com"
$users = get-content "Testusers.txt"
$date = get-date
$mydata = #()
$domain = [system.environment]::UserDomainName
$attribute = "Proxyaddresses"
$report = "{0}_{1}_{2:HHmm_dd-MM-yyyy}.txt" -f $attribute,$domain,$date
$px = $users | Get-ADUser -Properties proxyaddresses -server $domain
foreach ($user in $px){
if ($user.proxyaddresses -like $entry){
$name = $user.samaccountname
$proxyaddresses = $user.proxyaddresses -like $entry
$mydata += New-Object PSObject -Property #{
Samaccountname = $name
Proxyaddresses = $proxyaddresses
}
}
}
$mydata | select samaccountname,#{ l = "Proxyaddresses"; e = {$_.Proxyaddresses } }| export-csv "$PWD\$report" -NoTypeInformation -Append
To return the values back to the original state I am running the following:
$csv = import-csv "Proxyaddresses_Domain_1201_05-04-2017.csv"
$domain = [system.environment]::UserDomainName
$attribute = "Proxyaddresses"
foreach ($line in $csv){
$user = $line.samaccountname
$proxyaddresses = $line.proxyaddresses
Get-aduser $User -server $domain -Properties $attribute | Set-ADUser -add
#{$attribute = $proxyaddresses} -server $domain
}
I have tried various things such as in the collection script
$proxyaddresses = $line.proxyaddresses -join ","
I have also tried the same tactic in the script used to set the values but instead of creating a new line it removes a space between the entries on the same line when viewed through an AD attribute editor.
I have also tried to change
$proxyaddresses = $user.proxyaddresses -like $entry
to the following however this did not solve the problem
$proxyaddresses = ([Microsoft.ActiveDirectory.Management.ADPropertyValueCollection]$user.proxyaddresses -like $entry
HELP!!!

When you are exporting the data, change your select statement from this
select samaccountname,#{ l = "Proxyaddresses"; e = {$_.Proxyaddresses } }
to this
select samaccountname,#{Name="Proxyaddresses";Expression={$_.proxyaddresses -join "*"}}
Which will convert the ADPropertyValueCollection to a * separated string. If you are exporting to a CSV, you don't want to use a comma as the join separator as it will mess up the CSV. I've used a * in the example, as exchange uses colons and semi colons already.
Then when you re-import it, just make sure to convert the * seperated string back into a string array, and use -replace instead of -add
Set-ADUser -replace #{$attribute = $proxyaddresses.Split("*")} -server $domain

Related

No output to CSV using PowerShell psobject in Active Directory

I have this portion of code here that has worked in the past in multiple AD environments, however after testing within a new AD environment, I am getting no output to CSV or any errors being thrown. The size of the CSV file is always zero.
if (![string]::IsNullOrEmpty($searchbase))
{
$ADComputers = get-adcomputer -searchBase $searchbase -filter * -properties * -ResultPageSize $resultpagesize
}
else
{
$ADComputers=Get-ADComputer -Filter * -Properties * -ResultPageSize $resultpagesize
}
$data = #()
foreach ($computer in $ADComputers) {
$computer.member| foreach-object {$members += $_}
$computer.memberof | foreach-object {$memberof += $_}
$memstr = ($members -join ";")
$memstr2 = ($memberof -join ";")
$ADcomp = Get-ADComputer $computer -properties logonCount, ManagedBy | select-object logonCount, ManagedBy
$row = New-Object -TypeName psobject -Property #{
PrincipalID = $script:ctr;
logonCount=$ADcomp.logonCount;
ManagedBy=$ADcomp.ManagedBy;
}
$data += $row
$script:ctr++
}
$data | Export-Csv "ADComputers.csv" -NoTypeInformation
I'm not sure exactly where to go from here because I have tested multiple different options, so any help would be greatly appreciated!
The only reason you get no output is that $ADComputers has no elements. This may be related to a value in the variable $searchbase that does not exist or simply has no computer accounts in it.
But here are some general recommendations:
you do:
if (![string]::IsNullOrEmpty($searchbase))
you could also do:
If ($searchbase)
In principle if you have different scenarios to cover and so the parameter may change take a look at splatting.
Then you query all computers with all available properties but later in the loop you query the specific computer again which is not necessary. Also you should avoid adding elements to an array by using +=, this causes to rebuild the array each time which is slow.
Furthermore $computer.memberof is already an array holding the information but you pipe it to foreach and build a new array holding the identical information only to join it later to a string.
If this is not part of function I don't know why you raise the scope of the variable $ctr from local to script think this is not necessary.
Putting this all together you could do:
#Define HashTable for splatting
$parametersHt = #{
filer='*'
properties='*'
resultsetpagesize=$resultpagesize
}
#If searchbase is specified add parameter to splatting HashTable
If ($searchbase){
$parametersHt.add('Searchbase',$searchbase)
}
#Get computers
$ADComputers = get-adcomputer #parametersHt
#Set Counter
$ctr = 0
$data = #(
foreach ($computer in $ADComputers){
$ctr++
[PSCustomObject]#{
PrincipalId = $ctr #Really the counter here - not $computer.samaccountname?
logonCount=$computer.logonCount
manageddBy=$computer.ManagedBy
memberof=($computer.memberof -join ";") #added this, but in your code sample you don't return this value, if not needed remove. btw. a computer can be memberof a group but it can't have members
}
}
)
$data | Export-Csv -path ".\ADComputers.csv" -NoTypeInformation

CSV var as expression is empty, shown as {}

I got a small issue. I have a CSV with some names. I needed to get the email addresses of those users, so I created a small script that will find users with that firstname and lastname in AD.
After that, I wanted to export it to a new CSV file, but keep the phone-numbers from the first CSV file so its also available in the new CSV export.
That last part don't seem to work. In the output that expression is shown as {}.
Can someone help me?
$csv = import-csv -path C:\users\da6\desktop\UsersZonderEmail.csv
$output = #()
foreach ($i in $csv) {
$givenname = $i.Voornaam
$lastname = $i.Achternaam
$number = $i.IpPhone
$output += try {Get-ADUser -Filter {givenname -eq $givenname -and surname -eq $lastname} | select Name, UserPrincipalName, #{ name="ipphone"; expression=$number}} catch {}
}
Basically what is wrong with your code is that you forgot the opening bracket { in the expression oart of the calculated property.
Also note that -Filter should be a string, not a scriptblock.
Lastly, adding to an array with += is a bad habit, as the entire array needs to be rebuilt in memory on every addition.
Better let PowerShell collect the values from the loop:
$csv = Import-Csv -Path 'C:\users\da6\desktop\UsersZonderEmail.csv'
$output = foreach ($item in $csv) {
Get-ADUser -Filter "GivenName -eq '$($item.Voornaam)' -and Surname -eq '$($item.Achternaam)'" -Properties EmailAddress |
Select-Object Name, UserPrincipalName, #{ Name="ipphone"; Expression = {$item.IpPhone}}, EmailAddress
}
# output to new CSV file
$output | Export-Csv -Path 'C:\users\da6\desktop\UsersMetEmail.csv' -NoTypeInformation

Get-AdUser no acepting variable

im trying to pull out all the information regarding my domain admin adminsitrators
#set domains we are going to query
$domains = 'mydomainname.com'
#first here i bring the sam accounts names
Foreach ($domain in $domains)
{
$OUTPUT =Get-AdGroupMember -identity “Domain Admins” -recursive -server $domain |
Select-Object -Property samAccountName|
Select samAccountName;
$Outputs +=$OUTPUT;
$OUTPUT |Export-CSV "C:\File\$($domain).csv" -NoTypeInformation ;
}
$OUTPUT #this print the sam accounts
#here is the problem
Foreach ($user in $OUTPUT)
{
$Users2 =Get-ADUser -Filter "SamAccountName -like '$OUTPUT'" -Properties *
$USER3 +=$Users2;
$Users2 |Export-CSV "C:\File\$($domain)Userpop.csv" -NoTypeInformation ;
}
I think this is a problem with your filter. Try changing that line as follows:
Get-ADUser -Filter " SamAccountName -like `"$($user.samaccountname)`" " -Properties *
It can't be $OUTPUT as that's an array. Your loop variable is $user which is an object so you need the .samaccountname property. The filter needs a string with the -like matching a quoted string, so you need `" to pass the quote through to the final string.
Your CSV output of $user2 may not be what you expect either as each object is output to the same file. Perhaps you mean to have a -Append or write them to different files?
You'll probably want to reset $user3 as well. Perhaps add $user3 = #() before that loop.
You should always try to avoid adding to arrays with $array += $something, because that means the entire array gets rebuild in memory, costing time and resources.
Also, I would advise using more descriptive variable names, so the code will still be understandable after some time.
Then, because you are getting info from different domains, it is important to store the domain name in the first loop together with the samaccount names, so you can use these as -Server parameter in the second loop on Get-ADUser
Try
#set domains we are going to query
$domains = #('mydomainname.com') # since there is only one domain listed, use #() to force it into an array
$domainsAndAdmins = foreach ($domain in $domains) {
# store the SamAccountNames for this domain as objects in an array
$admins = Get-AdGroupMember -Identity 'Domain Admins' -Recursive -Server $domain |
Select-Object -Property SamAccountName
# export this to csv file
$outFile = 'C:\File\{0}.csv' -f $domain
$admins | Export-Csv $outFile -NoTypeInformation
# output an object with both the domain and the array of SamAccountNames
# this will be captured in variable $domainsAndAdmins
[PsCustomObject]#{Domain = $domain; Admins = $admins.SamAccountName }
}
# output on screen
$domainsAndAdmins | Format-Table -AutoSize
# will result in something like
#
# Domain Admins
# ------ ------
# mydomainname.com {jdoe, jbloggs, mpimentel}
# myseconddomainname.com {jdoe, mpimentel}
# next get ALL (?) properties from the users we found
$domainsAndAdmins | ForEach-Object {
$domain = $_.Domain
$result = foreach ($user in $_.Admins) {
Get-ADUser -Filter "SamAccountName -like '$user'" -Server $domain -Properties * -ErrorAction SilentlyContinue
}
$outFile = 'C:\File\{0}_Userpop.csv' -f $domain
$result | Export-Csv $outFile -NoTypeInformation
}

Disable users from valid list

I've got a list of valid users provided by HR. The formatting was not cool, so I managed to get a new file like I wanted: one column, on each line the samaccountname (1st letter of firstname and name).
My file looks like this:
bgates
sjobs
bmarley
epresley
etc.
I'd like to disable users who are NOT in this list. I guess I have to deal with some if stuff, but I don't know how to.
#HariHaran, i have tried this:
#this part works fine
$list = Import-Csv .\listadnames2.csv -Delimiter ";"
$lol =
ForEach ($user in $list)
{
$user.prenom[0] + $user.nom
}
$lol | Out-File .\samaccountnames.csv
$validusers = Import-Csv .\samaccountnames.csv
$fullusers = Get-ADUser -Filter * -SearchBase "OU=USERS,DC=domain,DC=com" -ResultPageSize 0 -Prop samaccountname | Select samaccountname
foreach ($u in $validusers)
if ($u -match $fullusers) {continue} else
{
Set-ADUser -Identity $($._) -Enabled $false -whatif
}
The users list (samaccountnames.csv) you create in $lol is not a CSV file, but simply a text file with all constructed usernames each on a separate line.
Therefore you should read the file using
$validusers = Get-Content .\samaccountnames.csv instead of $validusers = Import-Csv .\samaccountnames.csv.
Then you'll have an array of samaccountnames to work with.
Next, I wonder why you use -ResultPageSize 0.. The default setting is 256 objects per page, so I can only imaging you could need this value to be higher than this default, not less.
(see the docs)
Taken from the part where you read the samaccountnames file, I think this will do the job:
$validusers = Get-Content .\samaccountnames.csv
# property 'SamAccountName' is returned by default as are
# 'DistinguishedName', 'Enabled', 'GivenName', 'Name', 'ObjectClass', 'ObjectGUID', 'SID', 'Surname' and 'UserPrincipalName'
# get the user objects from AD and loop through them to see if they need to be set disabled
Get-ADUser -Filter * -SearchBase "OU=USERS,DC=domain,DC=com" | ForEach-Object {
# the $_ automatic variable now holds an AD user object
# or use if($_.SamAccountName -notin $validusers). Only for PowerShell version 3.0 and up
if ($validusers -notcontains $_.SamAccountName) {
$_ | Set-ADUser -Enabled $false -WhatIf
}
}

Output department and direct reports

I am trying to create an "initial" text file that will hold a script run of all users + department + direct reports. My next step after making this file is to create another file the same way but compare it to the original to see if the department for the users ever changed. (not sure yet how to compare the department value just yet)
My current issue is that the department, even though the process is identical to another program I have made in the past, won't print it. Furthermore, when it prints my direct reports it prints only the first one with the whole extension of CN=..., OU=... etc.
I want it to print this way:
username | Department(extensionAttribute14) | Direct Reports (as a single string)
we38432 | IT-Security | cm03456: 04555a: ....etc
My original script used this code for department:
$deps = Get-Aduser -filter {name -like *} -Properties name, extensionAttribute14 | Select name, extensionAttribute14 | Export-CSV $listing -notypeinformation
and this worked. I tried the {name -like *} but that gave me errors in my current program. I know the Export-CSV makes it work but I can't use this format anymore.
for the direct reports my original was this:
foreach ($ID in $directReports){
if ($ID -ne $Null){
$directreports = get-aduser $ID
$directreports.name | Out-File $output -Append
}
This code printed line by line the direct reports but I want them all listed in the same excel cell when I send it there.
I have printed a listing of all the members in the past using ":" and it worked but it is not the case with the direct reports listing. I just get errors when I use this format from my other program:
foreach ($member in $empty.members){
$string = $member.substring(3,$member.indexof(",")-3)
$members = $members + ":" + $string
}
I hope someone can help me with my two issues.
Import-Module ActiveDirectory
$documentOld = "C:\Temp\Old_Supervisor_list_mo_yyyy.txt"
Clear-Content $documentOld
$Header = `
"User ID" <#+ "|" + `
"Department" + "|" + `
"Direct Reports"#>
$Header | Out-File $documentOld -Append
$Users = Get-AdUser -Filter * -Properties name, Enabled, Manager, extensionAttribute14 | Select Enabled, name, Manager, extensionAttribute14
foreach ($user in $Users){
if ($user.enabled –eq $true) {
$name = $user.name
$directReports = Get-ADUser -Identity $name -Properties directreports | Select -ExpandProperty directreports
$department = $user.extensionAttribute14
foreach ($ID in $directReports){
if ($ID -ne $Null){
$directreports = get-aduser $ID
# $string = $directreports + ":"
}#end if $ID
}#end foreach $ID
$listing = `
$name + "|" + $deparment + "|" + $directreports#$string
$listing | Out-File $documentOld -Append
}# end if
}# end foreach $user
Let see if we can make this a little easier and efficient.
Import-Module ActiveDirectory
$documentOld = "C:\Temp\Old_Supervisor_list_mo_yyyy.txt"
$Users = Get-AdUser -Filter * -Properties name,Enabled,Manager,extensionAttribute14 | Where-Object{$_.Enabled}
$Users | ForEach-Object{
$props = #{
Name = $_.Name
Department = $_.extensionAttribute14
DirectReports = ($_.Manager | Where-Object{$_} | ForEach-Object{Get-Aduser $_ | Select-object -ExpandProperty Name}) -join ":"
}
New-Object -TypeName psobject -Property $props
} | Select-Object Name,Department,DirectReports | Export-CSV -Delimiter "|" -NoTypeInformation -Path $documentOld
First we get all the users from your directory with Get-AdUser -Filter * taking all the properties outside the norm that we want. Since you just wanted accounts that are enabled we filter those out now with Where-Object{$_.Enabled}.
The fun part is creating the custom object array ( which is necessary for input for Export-CSV). Create a small hashtable called $props where we set the properties by their friendly names. The special one being DirectReports where we take all the users manager DN's ( Assuming they have one where is what Where-Object{$_} does by filtering out nulls/empty strings.) and use Get-Aduser to get there names. Since you could have more than one manager an array is most likely returned we use -join to ensure only a single string is given for the DirectReports property. That property collection is created for every user and it is then used to create a New-Object which is sent to the output stream.
The Select-Object that follows is just to ensure the order of columns in the CSV that is created. No need for making a CSV file with lots of Out-Files when Export-CSV and -Delimiter "|" will do the hard work for you.