How to pass an input file to a powershell script which makes changes to AD attributes:
-
Donnerstag, 5. Juli 2012 09:37
I am using the below script to make changes to a mail attribute in AD. At the moment, the script takes input from a ldap query. I would like to change it to an input file containing email addresses. In the below script, I am not using get-mailbox command let to disable email address policies on mailboxes because it wont work for those mailboxes which have aliases in an incorrect format. Please assist.
$strFilter = "(&( msexchhomeservername=/o=Messaging/ou=Exchange Administrative Group (FYDIBOHF23SPDLT)/cn=Configuration/cn=Servers/cn=Exchangeserver1))"
$objDomain = New-Object System.DirectoryServices.DirectoryEntry
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.SearchRoot = $objDomain
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchScope = "Subtree"$colResults = $objSearcher.FindAll()
foreach ($objResult in $colResults)
{
$objItem = $objResult.GetDirectoryEntry()
$objitem.putex(1,"msexchpoliciesincluded",$null)
$objitem.setInfo()
}
Alle Antworten
-
Donnerstag, 5. Juli 2012 14:29Moderator
If you already have a file, you can read the file in using either get-content or import-csv depending on format of the input file. Once you have data from file into a variable, you can use your foreach loop with little modification where objitem will be replaced with data from input file.
Bhargav Shukla | PFE : Messaging | Exchange Server TechCenter | Microsoft Exchange Team Blog | My Threads | My Blog

-
Donnerstag, 5. Juli 2012 14:49
Get-COntent usermail.txt | ForEach-Object{ if($result=([adsisearcher]"mail=$_").FindOne()){ $user=$result.GetDirectoryEntry() $user.PutEx(1,'msexchpoliciesincluded',$null) $user.SetInfo() $result.GetDirectoryEntry() }else{ Write-host "User for mail id $_ not found!" } }¯\_(ツ)_/¯
-
Freitag, 6. Juli 2012 05:00
Thanks for the script. I think it will make the script easier if I pass the DN of each object.
$colresults = get-content c:\input.txt
foreach ($objResult in $colResults)
{
$objresult.putex(1,"msexchpoliciesincluded",$null)
$objresult.setInfo()
}but this doesnt work. It gives the below error. I am sure I am missing something clearly obvious here like GetDirectoryEntry() but not sure of the syntax. Please assist.
Method invocation failed because [System.String] doesn't contain a method named 'putex'.
Method invocation failed because [System.String] doesn't contain a method named 'setinfo'.
Feroz
-
Freitag, 6. Juli 2012 07:54
Wht do you not want to do this correctly. You are just guessing.
Th ecode I posted worcj completely. It is the only way it can be done. The file must contain lega values and you must search for the objects.
If you ha ve the DN then you can get the object directly however you cannot keep changing the question.
What is in your file? YOu posted that it was the mail address.
Get-Content usermail.txt | ForEach-Object{ if($user=([adsisearcher]"LDAP://$_")){ $user.PutEx(1,'msexchpoliciesincluded',$null) $user.SetInfo() }else{ Write-host "User for dn $_ not found!" } }
¯\_(ツ)_/¯
- Bearbeitet jrvMicrosoft Community Contributor Freitag, 6. Juli 2012 07:55
-
Montag, 9. Juli 2012 02:04
Sorry about changing the input file. I thought it would be easier if I pass the DN directly as it might reduce the processing time of the script. Also, when I try your code, it gives the following error:-
Method invocation failed because [System.DirectoryServices.DirectorySearcher] doesn't contain a method named 'PutEx'.
Feroz
-
Montag, 9. Juli 2012 02:23
What version of Acrive Directory and WIndows are you using. It works correctly on WS2008 and WS2003.
¯\_(ツ)_/¯
-
Montag, 9. Juli 2012 08:40
OS-Windows server 2008
Domain function level- Windows server 2003
Feroz
-
Montag, 9. Juli 2012 09:46
The below script works by taking DN as an input. I have tested it successfully.
Import-csv "c:\usermail.csv" |ForEach-Object {
$dn = $_.dn
$strFilter = "(&(objectCategory=User)(objectCategory=Person))"
$objSearcher = New-Object System.DirectoryServices.DirectorySearcher
$objSearcher.PageSize = 1000
$objSearcher.Filter = $strFilter
$objSearcher.SearchRoot = "LDAP://$dn"
$colProplist = "msexchpoliciesincluded"
foreach ($i in $colPropList){$objSearcher.PropertiesToLoad.Add($i)}
$Colresults = $objsearcher.FindAll()
foreach ($Objresult in $Colresults)
{
$objItem = $objResult.GetDirectoryEntry()
$objitem.putex(1,"msexchpoliciesincluded",$null)
$objitem.setInfo()
}}
Feroz
-
Montag, 9. Juli 2012 13:04
Sorry - my fault. I pasted the wrong version of the script.
Get-Content usermail.txt | ForEach-Object{ if($result=([adsi]"LDAP://$_")){ $user.PutEx(1,'msexchpoliciesincluded',$null) $user.SetInfo() }else{ Write-host "User for dn $_ not found!" } }The key is that you have to retrieve the 'DirectoryEntry' object to use the 'PutEx' method. Since you are using the DN you do not need a searcher. A DN can drectly reference reference an object in AD by add 'LDAP://' to the beginning to turn the DN into a Path.
Try it at a prompt
$dn='some full dn to a user account or other object'
[adsi]"LDAP://$dn"Most of your code is unnecessary when using a DN. A DN specifically reference a single object in AD. In your code you are uisng a DN to specifiy a serchroot. The search then is searching only one item,.
There is very little difference between using the email address and the DN. The DN eliminates one step. Here is a simple rewrite of the email example using a similar technique
Get-COntent usermail.txt | ForEach-Object{ if($result=([adsisearcher]"mail=$_").FindOne()){ $user=[adsi]$result.Path $user.PutEx(1,'msexchpoliciesincluded',$null) $user.SetInfo() $result.GetDirectoryEntry() }else{ Write-host "User for mail id $_ not found!" } }This time I used the [adsi] accellerator instead of GetDirectoryEntry. and passed it the 'Path' of the 'Found' object. 'FindOne' is all that is necessary when using a DN as a target as it can only ever return one object.
This is your code minus most of the unnecessary lines.
Import-csv "c:\usermail.csv" | ForEach-Object { $objSearcher = New-Object System.DirectoryServices.DirectorySearcher $objSearcher.SearchRoot = "LDAP://$($_.dn)" $Colresults = $objsearcher.FindAll() foreach ($Objresult in $Colresults) { $objItem = $objResult.GetDirectoryEntry() $objitem.putex(1,"msexchpoliciesincluded",$null) } }What you are trying to do is actually very simole but if you copy and attempt to convert old VBSWcritp code it devcomes significanly more complicated. VBScript (COM) has no DirectorySeacher([adsisearcher]) an copying the LDAP AD provider of ADO causes adding way too many items to the script. If you are returning thousands of items than you can add some of the lines.
Notneed to add properties in a loop when ther is opnly one property and no need adding propperties when you are going to retrieve the Directory Entry which will always have all of the properties available.
Adding $obj to the beginning of evey varailbale only makes the code harder to read. It does not add any useful information. $results is also preferable to $colResults because $results implies a collection.
¯\_(ツ)_/¯
- Bearbeitet jrvMicrosoft Community Contributor Montag, 9. Juli 2012 13:06
- Als Antwort markiert ferozkhan17 Dienstag, 10. Juli 2012 13:51
-
Dienstag, 10. Juli 2012 09:56
Thank you so much!
I am going to discard my script happily.
I believe there are some minor issues in your first two scripts. Please correct me if I am wrong. In the 1st script, there should be one variable (either $result or $user). In the 2nd script, I think we do not need " $result.GetDirectoryEntry()" as per your explanation. Also, why are we using the If loop? Is it to check if the object is valid or not? If yes, then it causes the script to give errors in case there is an invalid object because anyhow the invalid object will still go in to the rest of the code.
Feroz
-
Dienstag, 10. Juli 2012 10:25
A little modified version of your scripts. Can you please tell me how do I define the pagesize in this as I need to make changes to thousands of objects? or do I need to use the 3rd script (if I want to use page size) and define the value of the pagesize? Thanks again.
Get-Content c:\input.txt |
ForEach-Object{
$user=([adsi]"LDAP://$_")
$user.PutEx(1,'msexchpoliciesincluded',$null)
$user.SetInfo()}Get-COntent c:\input2.txt |
ForEach-Object{
$result=([adsisearcher]"mail=$_").FindOne()
$user=[adsi]$result.Path
$user.PutEx(1,'msexchpoliciesincluded',$null)
$user.SetInfo()}Feroz
-
Dienstag, 10. Juli 2012 11:46You don't need to specify the pagesize, as you are only using .findOne(). By definition, this will only return one object.
Grant Ward, a.k.a. Bigteddy
-
Dienstag, 10. Juli 2012 13:29
A little modified version of your scripts. Can you please tell me how do I define the pagesize in this as I need to make changes to thousands of objects? or do I need to use the 3rd script (if I want to use page size) and define the value of the pagesize? Thanks again.
Get-Content c:\input.txt |
ForEach-Object{
$user=([adsi]"LDAP://$_")
$user.PutEx(1,'msexchpoliciesincluded',$null)
$user.SetInfo()}Get-COntent c:\input2.txt |
ForEach-Object{
$result=([adsisearcher]"mail=$_").FindOne()
$user=[adsi]$result.Path
$user.PutEx(1,'msexchpoliciesincluded',$null)
$user.SetInfo()}
Feroz
Please spend some time studying he documentation on Active Directory. You have copied some old VBScript code or copied some PowerShell that was badly converted from VBScript. THe items you are tryng to use ar not necessary when seraching for a single item. You are searching for ONE item and returnin gone item per search. PageSize is irrelevent. PageSize is automatically set to teh maximum and only needs to be set to less if you are returnin more that teh maximum number of objects in a single find. (FindAll) . You are using FindOne.
If you have a DistinguishedName you can use that as an ADSI Path by adding "LDAP:\\". If you have a mail id or a samaccountname you must use the ADSISearcher to find the oblect. You cannot make changes using 'PutEx' on a searcher result object. You must use the objects 'Path' (adsPath) to return the full object using 'GetDirectoryEntry' or using [adsi]. Both work the same.
¯\_(ツ)_/¯
-
Dienstag, 10. Juli 2012 13:51Thanks for explaining about page size. I got the other things already via your previous post.
Feroz

