Assignment operator prevents concatenation - powershell

I have AD groups named xxx16up, yyy16up, zzz16up. What I'm trying to do is if:
AD user is grade level 16 and up
AD user is not yet a member of said group
the script will add the AD user to the corresponding group based on company codes xxx, yyy, zzz.
$list = Import-CSV "C:\update12Apr2018.csv"
foreach ($company in $list) {
$myList = ( Get-ADGroup "$($company.comp)16up" ).DistinguishedName
if ( ([INT]$_.level -ge 16) -and (Get-ADUser -LDAPFilter "(!(memberof=$myList))" )) {
Add-ADGroupMember -Identity "$($company.comp)16up" -Members $company.samAccountName
}
}
The part highlighted does not work within the code. But if I take it out and run it by itself it has no problems. It produces the corresponding group of either xxx16up, yyy16up, or zzz16up.
Within the code, it gave below error:
Get-ADGroup : Cannot find an object with identity: '16up' under: 'DC=ACME,DC=com'. At line:1 char:33
+ ... ch ($company in $list) { ( Get-ADGroup "$($company.comp)16up" ).Disti ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (16up:ADGroup) [Get-ADGroup], ADIdentityNotFoundException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,Microsoft.ActiveDirectory.Manag
ement.Commands.GetADGroup
I was able to narrow down the problem to when there is an assignment operation and that is when it acts as if the concatenation failed.

ForEach ($company in $list) {
$groupName = $company.comp + '16up'
$myList = ( Get-ADGroup $groupName ).DistinguishedName
see the sleight of hand? ;-)

Related

Check and Update multiple attributes of AD users

I am trying to do an update to Active Directory from a CSV.
I want to check each value to see if the AD and CSV values match.
If the AD value and CSV values don't match, then I want to update the AD value.
finally I want to create a log of the values changed, which would eventually be exported to a CSV report.
Now there is about 30 values I want to check.
I could do an if statement for each value, but that seems like the hard way to do it.
I am try to use a function, but I cant seem to get it working.
I am getting errors like:
set-ADUser : replace
At line:94 char:9
+ set-ADUser -identity $ADUser -replace #{$ADValue = $DIAccount ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (JDoe:ADUser) [Set-ADUser], ADInvalidOperationException
+ FullyQualifiedErrorId : ActiveDirectoryServer:0,Microsoft.ActiveDirectory.Management.Commands.SetADUser
set-ADUser : The specified directory service attribute or value does not exist
Parameter name: Surname
At line:94 char:9
+ set-ADUser -identity $ADUser -replace #{$ADValue = $DIAccount ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (JDoe:ADUser) [Set-ADUser], ArgumentException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:System.ArgumentException,Microsoft.ActiveDirectory.Management.Commands.SetADUser
Any suggestions would be welcome
Code I am using:
Function AD-Check ($ADValue, $ADUser, $ADAccount, $UpdateAccount)
{
If ($ADAccount -ne $UpdateAccount)
{
set-ADUser -identity $ADUser -replace #{$ADValue = $UpdateAccount}
$Change = "Updated"
}
Else
{
$Change = "No Change"
}
Return $Change
}
$Import = get-content C:\temp\ADUpdates.csv
Foreach ($user in $Import)
{
$Account = get-aduser $User.Samaccountname -Properties *
#First Name Check
$Test = AD-Check "GivenName" $Account.samaccountname $Account.givenname $user.givenname
$ChangeGivenName = $Test
#Initials Check
$Test = AD-Check "Initials" $Account.samaccountname $Account.Initials $user.Initials
$ChangeInitials = $Test
#Last Name Check
$Test = AD-Check "Surname" $Account.samaccountname $Account.SurnameSurname $user.Surname
$ChangeSurname = $Test
}
Reply to Theo, cant seem to add this any other way...
Thanks Theo, it seems to make sense, but getting an error.
Select-Object : Cannot convert System.Collections.Specialized.OrderedDictionary+OrderedDictionaryKeyValueCollection to one of the following types {System.String,
System.Management.Automation.ScriptBlock}.
changed the following to get all properties for testing and it works.
$Account = Get-ADUser -Filter "SamAccountName -eq '$sam'" -ErrorAction SilentlyContinue -Properties $propsToCheck
Left the following and it kicks the error
$oldProperties = $Account | Select-Object $propsToCheck
Using the following just for testing:
$propertiesMap = [ordered]#{
SamAccountName = 'sAMAccountName'
mail = 'mail'
GivenName = 'givenName'
Initials = 'initials'
Surname = 'sn'
Office = 'physicalDeliveryOfficeName'
MobilePhone = 'mobile'
DistinguishedName = 'DistinguishedName'
}
Starting of with a WARNING:
Replacing user attributes is not something to be taken lightly and you
need to check any code that does that on a set of testusers first.
Keep the -WhatIf switch to the Set-ADUser cmdlet so you
can first run this without causing any problems to the AD.
Only once you are satisfied all goes according to plan, remove the -WhatIf switch.
Please carefully read all inline comments in the code.
In your code you use an input CSV file, apparently with properties and values to be checked/updated, but instead of using Import-Csv, you do a Get-Content on it, so you'll end up with just lines of text, not an array of parsed properties and values..
Next, as Mathias already commented, you need to use the LDAP attribute names when using either the -Add, -Remove, -Replace, or -Clear parameters of the Set-ADUser cmdlet.
To do what you intend to do, I would first create a hashtable to map the PowerShell attribute names to their LDAP equivalents.
To see which property name maps to what LDAP name, you can use the table here
# create a Hashtable to map the properties you want checked/updated
# the Keys are the PowerShell property names as they should appear in the CSV
# the Values are the LDAP AD attribute names in correct casing.
$propertiesMap = [ordered]#{
SamAccountName = 'sAMAccountName'
GivenName = 'givenName'
Initials = 'initials'
Surname = 'sn'
Office = 'physicalDeliveryOfficeName'
Organization = 'o'
MobilePhone = 'mobile'
# etcetera
}
# for convenience, store the properties in a string array
$propsToCheck = $propertiesMap.Keys | ForEach-Object { $_.ToString() }
# import your CSV file that has all the properties you need checked/updated
$Import = Import-Csv -Path 'C:\temp\ADUpdates.csv'
# loop through all items in the CSV and collect the outputted old and new values in variable $result
$result = foreach ($user in $Import) {
$sam = $user.SamAccountName
# try and find the user by its SamAccountName and retrieve the properties you really want (not ALL)
$Account = Get-ADUser -Filter "SamAccountName -eq '$sam'" -ErrorAction SilentlyContinue -Properties $propsToCheck
if (!$Account) {
Write-Warning "A user with SamAccountName '$sam' does not exist"
continue # skip this one and proceed with the next user from the CSV
}
# keep an object with the current account properties for later logging
$oldProperties = $Account | Select-Object $propsToCheck
# test all the properties and create a Hashtable for the ones that need changing
$replaceHash = #{}
foreach ($prop in $propsToCheck) {
if ($Account.$prop -ne $user.$prop) {
$ldapAttribute = $propertiesMap[$prop] # get the LDAP name from the $propertiesMap Hash
# If any of the properties have a null or empty value Set-ADUser will return an error.
if (![string]::IsNullOrWhiteSpace($($user.$prop))) {
$replaceHash[$ldapAttribute] = $user.$prop
}
else {
Write-Warning "Cannot use '-Replace' with empty value for property '$prop'"
}
}
}
if ($replaceHash.Count -eq 0) {
Write-Host "User '$sam' does not need updating"
continue # skip this one and proceed with the next user from the CSV
}
# try and do the replacements
try {
##########################################################################################################
# for safety, I have added a `-WhatIf` switch, so this wll only show what would happen if the cmdlet runs.
# No real action is performed when using '-WhatIf'
# Obviously, there won't be any difference between the 'OLD_' and 'NEW_' values then
##########################################################################################################
$Account | Set-ADUser -Replace $replaceHash -WhatIf
# refresh the account data
$Account = Get-ADUser -Identity $Account.DistinguishedName -Properties $propsToCheck
$newProperties = $Account | Select-Object $propsToCheck
# create a Hashtable with the old and new values for log output
$changes = [ordered]#{}
foreach ($prop in $propsToCheck) {
$changes["OLD_$property"] = $oldProperties.$prop
$changes["NEW_$property"] = $newProperties.$prop
}
# output this as object to be collected in variable $result
[PsCustomObject]$changes
}
catch {
Write-Warning "Error changing properties on user '$sam':`r`n$($_.Exception.Message)"
}
}
# save the result as CSV file so you can open with Excel
$result | Export-Csv -Path 'C:\temp\ADUpdates_Result.csv' -UseCulture -NoTypeInformation

Get Distribution List muliple Owners in exchange

i need a power shell cmd or script which will give me the list of all the Distributions list along with the OWNERS of that like managed by.
But , if there are multiple users inside managedby attribute then I am getting System.Object[].
My question are :
1- how can we get multiple users for managedby attribute ?
2- how can we add employeeid and samaccountname for managedby users ?
3 - if there is no managed by user then it display "NO MANAGED BY USER"
4- I want to get mail groups not hidden.
script :
$DGroups=Get-DistributionGroup -resultsize unlimited
$mastertable=#()
ForEach($Group in $DGroups){
$table=[pscustomobject][ordered]#{
Name = $group.name
"Managed By" = $group.managedby.name
"DistinguishedName" = $group.DistinguishedName
}
$Mastertable += $table
}
$Mastertable | export-csv C:\tmp\managedby.csv -NoTypeInformation
My output :
"Name","Managed By","DistinguishedName"
"IT research","System.Object[]","CN=IT research,OU=TEST,DC=contoso,DC=com"
"Test Mail Group 1","User01","CN=\Test Mail Group 1,OU=Test,OU=COMPANY,DC=contoso,DC=com"
"Test Mail Group 2",,"CN=\Test Mail Group 2,OU=Test,OU=COMPANY,DC=contoso,DC=com"
My desired output :
"Name","Managed By","DistinguishedName","OWNERSAMACCOUNTNAME","OWNEREMPLOYEEID"
"IT research","User01;User02","CN=IT research,OU=TEST,DC=contoso,DC=com","tst124;tst125","242333;344232"
"Test Mail Group 1","User01","CN=\Test Mail Group 1,OU=Test,OU=COMPANY,DC=contoso,DC=com","tst124","242333"
"Test Mail Group 2","NO MANAGED BY USER","CN=\Test Mail Group 2,OU=Test,OU=COMPANY,DC=contoso,DC=com"
LAST UPDATE :
[PS] C:\Windows\system32>$group.ManagedBy
OrgHierarchyToIgnore :
IsDeleted : False
Rdn : CN=John T
Parent : contoso.com/COMPANY/IT
Depth : 5
DistinguishedName : CN=John T,OU=IT,DC=contoso,DC=com
IsRelativeDn : False
DomainId : contoso.com
PartitionGuid : 59ce2f71-eaa2-4ddf-a4fa-f25069d0b324
PartitionFQDN : contoso.com
ObjectGuid : 62d578e8-b69c-45bc-967a-e530d72792e1
Name : John T
[PS] C:\Windows\system32>$group.ManagedBy | ForEach-Object { $_ | Get-ADUser -Properties EmployeeId }
Get-ADUser : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties
do not match any of the parameters that take pipeline input.
At line:1 char:42
+ $group.ManagedBy | ForEach-Object { $_ | Get-ADUser -Properties EmployeeId }
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (contoso.com/COMPANY/IT/John T:PSObject) [Get-ADUser], ParameterBindingException
+ FullyQualifiedErrorId : InputObjectNotBound,Microsoft.ActiveDirectory.Management.Commands.GetADUser
It is my understanding the ManagedBy attribute stores the DistinguishedName(s) of one or more users (or none at all).
I haven't tested this myself, but you could try:
$DGroups = Get-DistributionGroup -ResultSize Unlimited
$mastertable = foreach($group in $DGroups) {
# initialize a PsCustomObject
$data = [PsCustomObject]#{
Name = $group.Name
DistinguishedName = $group.DistinguishedName
ManagedBy = 'NOT MANAGED'
OwnerSamAccountName = $null
OwnerEmployeeId = $null
}
if ($group.ManagedBy) {
$managedBy = $group.ManagedBy | ForEach-Object { Get-ADUser -Identity $_.DistinguishedName -Properties EmployeeId }
$data.ManagedBy = $managedBy.Name -join ';'
$data.OwnerSamAccountName = $managedBy.SamAccountName -join ';'
$data.OwnerEmployeeId = $managedBy.EmployeeId -join ';'
}
# output this data to be collected in $mastertable
$data
}
$mastertable | Export-Csv 'C:\tmp\managedby.csv' -NoTypeInformation

set-aduser , update several extensionattribute variables plus other attributes at once in powershell script

So I have a basic script that works when values are hardcoded. I need some help getting it to work when values are dynamic from a file:
Here is the basic script:
set-ADUser -Identity test.hsi -replace #{extensionAttribute4="LoadedFromInterface";extensionAttribute5="2";extensionAttribute6="2"} -Manager jim.james
What I want to do is read from a file using Import-CSV, loading the important columns into variables, checking for null/empty condition and then re-setting the variables if they were null. Ultimately doing the same as above but with variables that got loaded from the file. extentionAttribute5 and extensionAttribute6 would both be values from the file (sometimes null) and manager would also be a variable that is assigned from file.
Import-CSV C:\Users\user1\Documents\WTKtoAD\WTKtoAD.csv | %{$SAM = $_.SamAccountName;If ($_.PhoneTypeMobile -eq $Null) {$PhoneMobile = "NotProvided"} Else {$PhoneMobile = $_.PhoneTypeMobile};If ($_.PhoneTypeHome -eq $Null) {$PhoneHome = "NotProvided"} Else {$PhoneHome = $_.PhoneTypeHome}} | set-ADUser -Identity $SAM -Add #{extensionAttribute4="LoadedFromKronos";extensionAttribute5=$PhoneHome;extensionAttribute6=$PhoneMobile} -Manager $_.Manager
When I run the script I get the following error in Powershell ISE (x86) 'Run As Admnistrator'.
PS C:\Users\user1> Import-CSV C:\Users\user1\Documents\WTKtoAD\WTKtoAD.csv | %{$SAM = $_.SamAccountName;If ($_.PhoneTypeMobile -eq $Null) {$PhoneMobile = "NotProvided"} Else {$PhoneMobile = $_.PhoneTypeMobile};If ($_.PhoneTypeHome -eq $Null) {$PhoneHome = "NotProvided"} Else {$PhoneHome = $_.PhoneTypeHome}} | set-ADUser -Identity $SAM -Add #{extensionAttribute4="LoadedFromKronos";extensionAttribute5=$PhoneHome;extensionAttribute6=$PhoneMobile} -Manager $_.Manager
Set-ADUser : Cannot validate argument on parameter 'Identity'. The argument is null. Provide a valid value for the argument, and then try running the command again.
At line:1 char:318
+ ... User -Identity $SAM -Add #{extensionAttribute4="LoadedFromKronos";extensionAttri ...
+ ~~~~
+ CategoryInfo : InvalidData: (:) [Set-ADUser], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.SetADUser
The file looks like this:
> SamAccountName,PhoneTypeMobile,PhoneTypeHome,Manager
> test.hsi,333-234-3433,'',bob.henst
The reason for the error is because you have put the Set-ADUser in the wrong place (AFTER the ForEach-Object).
You can hardly tell from your code because you are putting everything on the same line which makes it very hard to read. My advice is to give it some air. That way, mistakes are far easier to spot.
As for the code. I didn't test because I don't have AD available right now but i think this will work better:
# this is the content of the WTKtoAD.csv file
# SamAccountName,PhoneTypeMobile,PhoneTypeHome,Manager
# test.hsi,333-234-3433,'',bob.henst
Import-CSV C:\Users\user1\Documents\WTKtoAD\WTKtoAD.csv |
ForEach-Object {
$SAM = $_.SamAccountName
if ([string]::IsNullOrEmpty($_.PhoneTypeMobile)) { $PhoneMobile = "NotProvided" } else { $PhoneMobile = $_.PhoneTypeMobile }
if ([string]::IsNullOrEmpty($_.PhoneTypeHome)) { $PhoneHome = "NotProvided" } else { $PhoneHome = $_.PhoneTypeHome }
if ([string]::IsNullOrEmpty($_.Manager)) { $Manager = $null } else { $Manager = $_.Manager }
$props = #{
extensionAttribute4 = "LoadedFromKronos"
extensionAttribute5 = $PhoneHome
extensionAttribute6 = $PhoneMobile
}
Set-ADUser -Identity $SAM -Replace $props -Manager $Manager
}
As you can see, i have also put in a small test for the Manager. If in the CSV this is an empty string, it will now Clear the manager property for the user.

Powershell - Getting Distribution Lists that have sender Restrictions

We have a distribution list (called "TopGroup", for example) that has sub-DLs inside it, as well as normal personal user email accounts alongside those nested DLs. For some reason, only the individual accounts are receiving any mail sent to MasterDL. Any members inside the sub-DLs do not receive anything sent to MasterDL in their inbox. then I have noticed there is restriction (to only allow specific users sending message to specific distribution groups.) on some sub-DLs.BTW I have been using Exchange Server 2013.
script regarding this? What we are looking for is a PowerShell script that can
1 - Identify all nested groups
2 - Identify on each TOP DL check for 2nd layer DL
2 - Identify 2nd layer DL Distribution Lists that have sender Restrictions and get list
3 - Report them and take output to CSV
4 - optional- notify user and manager and IT group via email
it would be output like below :
ParentGroupName SubDL1 Restriction SubDL2 Restriction .... so on
Group Group1 GroupA,GroupB Group2 GroupA,GroupB,Group
Here is my script so far :
Import-Module ActiveDirectory
$groups = Get-ADGroup -Filter "name -like '*'" -SearchBase "OU=Groups,DC=contoso,DC=com" | Select SamAccountName
Foreach ($g in $groups)
{
$member = Get-ADGroupMember $g | ?{$_.ObjectClass -eq "Group"} | Select Name,SamAccountName
foreach ($sg in $member)
{
$sgname = $sg.name
Write-Host $sgname -foregroundcolor "magenta" -backgroundcolor "yellow"
$dg = Get-DistributionGroup -Identity "$sgname"
if ($dg.AcceptMessagesOnlyFromDLMembers.count -ne 0){
Write-Host "$($dg.Name) has mail attribute set" -ForegroundColor Green
Get-DistributionGroup -ResultSize Unlimited -filter {AcceptMessagesOnlyFromDLMembers -ne $null} | select-object Name,#{Name="AcceptMessagesOnlyFromDLMembers";Expression={[string]::join(";",($_.AcceptMessagesOnlyFromDLMembers| foreach {$_.name}) )}}
}
}
elseif($dg.AcceptMessagesOnlyFromDLMembers.count -eq 0){
Write-Host "$($dg.Name) has no mail attribute set" -ForegroundColor Cyan
}
}
}
Error message :
#Test_groupA has mail attribute set Get-ADGroupMember : Cannot bind parameter 'Identity'. Cannot convert value "#{SamAccountName=test}" to type "Microsoft.ActiveDirectory.Management.ADGroup". Error: "Cannot convert the "#{SamAccountName=test}" value of type "Selected.Microsoft.ActiveDirectory.Management.ADGroup" to type "Microsoft.ActiveDirectory.Management.ADGroup"." At line:9 char:31
+ $member = Get-ADGroupMember $g | ?{$_.ObjectClass -eq "Group"} | Select Name,S ...
+ ~~
+ CategoryInfo : InvalidArgument: (:) [Get-ADGroupMember], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.ActiveDirectory.Management.Commands.GetADGroupMember
Thanks,

How to list AD group membership for AD users using input list?

I'm fairly new PS user... Looking for some assistance with a powershell script to obtain list of security groups user is member of.
To describe what I need:
I have input list (txt file) with many users (samaccountnames). Every name is on a new line.
I need the script to search these names in AD - whole forest, not just one single domain
output should look like "samaccountname" and list of groups this account is member of in one line, so I can sort it in excel
This is the script I have:
$users = Get-Content C:\users.txt
ForEach ($User in $users) {
$getmembership = Get-ADUser $User.Users -Properties MemberOf | Select -ExpandProperty memberof
$getmembership | Out-File -Append c:\membership.txt
}
but it throws me an error:
Get-ADUser : Cannot validate argument on parameter 'Identity'. The argument is null. Supply a non-null argument and try the command again.
At line:4 char:28
+ $getmembership = Get-ADUser <<<< $User.Users -Properties MemberOf | Select -ExpandProperty memberof
+ CategoryInfo : InvalidData: (:) [Get-ADUser], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.ActiveDirectory.Management.Commands.GetADUser
Anyway, this script wouldn't search the whole forest.
Sample input list:
username1
username2
username3
username4... etc
Sample output list
username1;group1;group2;group3
username2;group1;group2;group3;group4... etc or something similar
Any help would be greatly appreciated.
First: As it currently stands, the $User variable does not have a .Users property. In your code, $User simply represents one line (the "current" line in the foreach loop) from the text file.
$getmembership = Get-ADUser $User -Properties MemberOf | Select -ExpandProperty memberof
Secondly, I do not believe you can query an entire forest with one command. You will have to break it down into smaller chunks:
Query forest for list of domains
Call Get-ADUser for each domain (you may have to specify alternate credentials via the -Credential parameter
Thirdly, to get a list of groups that a user is a member of:
$User = Get-ADUser -Identity trevor -Properties *;
$GroupMembership = ($user.memberof | % { (Get-ADGroup $_).Name; }) -join ';';
# Result:
Orchestrator Users Group;ConfigMgr Administrators;Service Manager Admins;Domain Admins;Schema Admins
Fourthly: To get the final, desired string format, simply add the $User.Name, a semicolon, and the $GroupMembership string together:
$User.SamAccountName + ';' + $GroupMembership;
Get-ADPrincipalGroupMembership username | select name
Got it from another answer but the script works magic. :)
Or add "sort name" to list alphabetically
Get-ADPrincipalGroupMembership username | select name | sort name
Everything in one line:
get-aduser -filter * -Properties memberof | select name, #{ l="GroupMembership"; e={$_.memberof -join ";" } } | export-csv membership.csv
The below code will return username group membership using the samaccountname. You can modify it to get input from a file or change the query to get accounts with non expiring passwords etc
$location = "c:\temp\Peace2.txt"
$users = (get-aduser -filter *).samaccountname
$le = $users.length
for($i = 0; $i -lt $le; $i++){
$output = (get-aduser $users[$i] | Get-ADPrincipalGroupMembership).name
$users[$i] + " " + $output
$z = $users[$i] + " " + $output
add-content $location $z
}
Sample Output:
Administrator Domain Users Administrators Schema Admins Enterprise Admins Domain Admins Group Policy Creator Owners
Guest Domain Guests Guests
krbtgt Domain Users Denied RODC Password Replication Group
Redacted Domain Users CompanyUsers Production
Redacted Domain Users CompanyUsers Production
Redacted Domain Users CompanyUsers Production