I have made this script to set/change the location attribute of computers in a specific OU.
My variable is ok but when I execute, it is not taking it line by line.
How can I solve this.
Import-module ActiveDirectory
$computers= Get-ADcomputer -Filter * -searchbase "OU=XX,OU=XXX,OU=WXXX,DC=TGE,DC=XX,DC=XX" | ForEach-Object {$_.Name}
Set-ADcomputer -identity "$computers" -Location "buildingA"
Your $Computers is an [Array] Object which means it has a set of objects inside
The Set-ADComputer command cannot process all the array at once, to process each one of them you need to use the 'Foreach' method for example:
Foreach ($Computer in $Computers)
{
Set-ADcomputer -identity $computer -Location "buildingA"
}
Another Approach is add the foreach after the pipe, like this:
Get-ADcomputer -Filter * -searchbase "OU=XX,OU=XXX,OU=WXXX,DC=TGE,DC=XX,DC=XX" | ForEach-Object {Set-ADComputer -identity $_ -Location "buildingA"}
Try piping the output of Get-ADcomputer into Set-ADcomputer:
Get-ADcomputer -Filter * -searchbase "OU=XX,OU=XXX,OU=WXXX,DC=TGE" | Set-ADcomputer -Location "buildingA"
Related
Been a while since I posted, but i've hit a road-block which an annoying issue
I have a need to scan all of the companies domains for user accounts based on full name, as is FIRST LAST
The same code works fine when running a get-aduser -identity -server domain.name, but using
Get-aduser -filter -server doesn't work inside a For loop, and I'm not sure why!
Here's the code:
$AllDomains = (Get-ADForest).domains
Function Check-ADUser {
Param(
$FullName,
$ADList
)
$ADUserArray = #()
ForEach ($SubDomain in $ADList) {
write-host "Checking for $FullName on $SubDomain ..."
$UserADDomain = Get-ADUser -Server $SubDomain -Filter {(Name -eq $Fullname)} -properties * -ErrorAction SilentlyContinue | Select #{n="DomainName"; e={($_.CanonicalName -split '/')[0]}} `
| Select-Object DomainName -ExpandProperty DomainName
} #ForEach $Domain
The results return black
Here's the code that work fine:
$AllDomains = (Get-ADForest).domains
Function Check-ADUser {
Param(
$FullName,
$ADList
)
$ADUserArray = #()
ForEach ($SubDomain in $ADList) {
write-host "Checking for $FullName on $SubDomain ..."
$UserADDomain = Get-ADUser -Server $SubDomain -Identity $userName -properties * -ErrorAction SilentlyContinue | Select #{n="DomainName"; e={($_.CanonicalName -split '/')[0]}} `
| Select-Object DomainName -ExpandProperty DomainName
} #ForEach $Domain
The function is called via a for loop against each user as such
$Users = #"
Rocky Balboa
Bruce Willis
Gene Simmons
Liz Phair
Steven Segal
"# | ForEach {$_.Split([String[]]"`r`n",[StringSplitOPtions]::None)}
$outarray = #()
ForEach ($user in $Users) {
$aa = Check-ADUser -FullName $User -ADList $AllDomains
}
The only real difference in the code within the function, is the use the -filter instead of -identity on the get-aduser cmdlet
What's odd, is that if I run the code outside of the for loop, it works! I'm thinking it's a Powershell gotcha! any help appreciated :-)
Owen
Use the filter statement like this,
If you are interested in performance, limit the properties to canonicalName instead of *.
After reading the last part of the docs, I think removing the ( ) within curly braces should resolve your issue as well.
$UserADDomain = Get-ADUser -Server $SubDomain -Filter "Name -eq '$Fullname'" -properties * -ErrorAction SilentlyContinue | Select #{n="DomainName"; e={($_.CanonicalName -split '/')[0]}}
if ($null -ne $UserADDomain) {
return $UserADDomain
}
See Microsoft docs on Filter
Excerpt:
Note: For String parameter type, PowerShell will cast the filter query to a string while processing the command. When using a string variable as a value in the filter component, make sure that it complies with the PowerShell Quoting Rules. For example, if the filter expression is double-quoted, the variable should be enclosed using single quotation marks: Get-ADUser -Filter "Name -like '$UserName'". On the contrary, if curly braces are used to enclose the filter, the variable should not be quoted at all: Get-ADUser -Filter "Name -like '$UserName'".
I am putting together a script that will check all of my web servers certificates so that I can monitor when they are set to expire. When the script goes to execute the Invoke-Command I am getting this error:
Here is my code:
Import-Module WebAdministration
$results = #()
$ou = 'OU=test,OU=test,OU=Servers,DC=contoso,DC=com'
$subtree = Get-ADOrganizationalUnit -SearchBase $ou -SearchScope Subtree -filter * | Select-Object -ExpandProperty DistinguishedName
ForEach($dn in $subtree){
$servers = Get-ADComputer -Filter * -SearchBase $dn | select Name
$results += $servers
}#ForEach($dn in $subtree)
$scriptBlock = [scriptblock]::Create({
Import-Module WebAdministration; Get-ChildItem -Path IIS:SSLBindings | ForEach-Object -Process `
{
If($_.Sites){
$certificate = Get-ChildItem -Path CERT:LocalMachine/My |
Where-Object -Property Thumbprint -EQ -Value $_.Thumbprint
[PSCustomObject]#{
Sites = $_.Sites.Value
CertificateDNSNameList = $certificate.DnsNameList
CertificateNotAfter = $certificate.NotAfter
}#[PSCustomObject]
}#If($_.Sites)
}#Import-Module
})#ScriptBlock
ForEach($server in $results){
Invoke-Command -ComputerName $server -ScriptBlock $scriptBlock | Select Sites,CertificateDNSNameList,CertificateNotAfter,PSComputerName #ScriptBlock
}#ForEach($server in $results)
Now, If I take the following line out of the loop and replace $server with an actual server name, I get the results I am looking for:
Invoke-Command -ComputerName ServerName -ScriptBlock $scriptBlock | Select Sites,CertificateDNSNameList,CertificateNotAfter,PSComputerName
Any ideas what I am doing wrong?
Your Results-Array is not an array of string, it is an array of object. Each object have the attribute name. Change your last ForEach-Loop into this and your script will work:
ForEach($server in $results){
Invoke-Command -ComputerName $server.name -ScriptBlock $scriptBlock | Select Sites,CertificateDNSNameList,CertificateNotAfter,PSComputerName #ScriptBlock
}#ForEach($server in $results)
It looks to me like "select Name" is returning an object rather than a string. Try changing the line that fetches the servers to this:
$servers = Get-ADComputer -Filter * -SearchBase $dn | select -ExpandProperty Name
Domain→OU=Client Computers→OU=Location
Each computers has an extensionAttribute1 value.
I need to get each computer's extensionAttribute1 and export to a CSV file.
I ran below code, but was unable to get it right. Tried few variation with no success.
I ran this first (no error here):
$Computers = Get-ADComputer -Filter * -SearchBase "OU=Location,OU=Client Computers,DC=ABC,DC=ABC1" -Properties *
Then I ran this:
foreach ($Computer in $Computers) {
Get-ADComputer $Computer -Filter * -Properties extensionAttribute5 |
Export-Csv C:\computer_users.csv
}
and got the following error:
Get-ADComputer : A positional parameter cannot be found that accepts
argument
I tried with parenthesis, commas, single quotes, double quotes, … just can't figure it out.
Get-ADComputer $Computer -Filter * ...
is the same as
Get-ADComputer -Identity $Computer -Filter * ...
If you take a look at the documentation you'll see that the parameters -Identity and -Filter are mutually exclusive. Besides, you don't need the loop and the second Get-ADComputer call anyway. Simply select the properties you want from your first Get-ADComputer call and pipe the result to Export-Csv:
$ou = 'OU=Location,OU=Client Computers,DC=ABC,DC=ABC1'
Get-ADComputer -Filter * -SearchBase $ou -Properties extensionAttribute1 |
Select-Object Name, extensionAttribute1, ... |
Export-Csv 'C:\computer_users.csv' -NoType
I have the following script - it works except for the departmentNumber. Any ideas?
# Import AD Module
Import-Module ActiveDirectory
# Import CSV into variable $users
$users = Import-Csv -Path C:\users.csv
# Loop through CSV file and update users if they exist
foreach ($user in $users) {
Get-ADUser -Filter "SamAccountName -eq '$($user.samaccountname)'" - Properties * |
Set-ADUser -EmailAddress $($user.EmailAddress) -Title $($user.Title) -Office $($user.Office) -OfficePhone $($user.OfficePhone) -departmentNumber $($user.departmentNumber) }
EDIT:
I tried the following using the "-Add" operator:
Import-Module ActiveDirectory
$users = Import-Csv -Path C:\users.csv
foreach ($user in $users) {
Get-ADUser -Filter "SamAccountName -eq '$($user.samaccountname)'" -Properties * |
Set-ADUser -Add #{departmentNumber = "$($user.departmentNumber)"}
}
And the following, using the "-Replace" operator:
Import-Module ActiveDirectory
$users = Import-Csv -Path C:\users.csv
foreach ($user in $users) {
Get-ADUser -Filter "SamAccountName -eq '$($user.samaccountname)'" -Properties * |
Set-ADUser -Replace #{departmentNumber = "$($user.departmentNumber)"}
}
Still no luck - do I have the syntax messed up?
I'm taking a quick look at the help for Set-ADUser: https://technet.microsoft.com/en-us/library/ee617215.aspx
I see a parameter for -Department, but not one for -DepartmentNumber
Will it work within your company's structure to just use -Department ?
For a custom attribute, you should be able to use the -Add parameter
-Add #{otherTelephone='555-222-1111', '555-222-3333'; otherMobile='555-222-9999' }
In order to use -Add or -Replace, you'll need to use a hashtable as your input instead of a string.
Here's a quick set of commands I used to convert a string into a single item hashtable:
$DeptNo = 'test'
$hash = #{}
$hash.Add('DepartmentNumber',$DeptNo)
$hash
Output from $hash:
Name Value
---- -----
DepartmentNumber test
I think you'll then be able to use -Add $hash to get it to do what you want.
Here is my code that got it working:
Set-ADUser -Identity $samName -Add #{'departmentNumber'="$UserDept"}
It is important to note you can only use -Add if nothing is there
otherwise use -Replace
$UserDept was a number but the quotes make it a string
and the attribute must have single quotes around it.
I'm writing a script to take one GroupOfNames object and create a second group with the first groups members. It seems like it would be a very simple piece of code:
$obj = Get-ADObject -Server "$server" -SearchBase $SearchBase -Filter "name -eq '$GroupName'" -Properties Member
New-ADObject -Server "$server" -Path $SearchBase -Type 'GroupOfNames' -name "$NewGroupName" -OtherAttributes #{'Member'= ($($obj.Member))}
When I run this the $obj gets created and I can display both the GroupOfNames information, as well as the list of members. But when it calls the New-ADObject cmdlet, I get the following error:
New-ADObject : Unable to contact the server. This may be because this server does not exist, it is currently down, or it does not have the Active Directory Web Services running.
I've tried multiple variations of the code and all fail with similar errors.
Interestingly, if I loop through the list of members and add them to the group one at a time, it works, but it just takes way too long (an hour+ vs seconds).
Try this, it casts the results of your first query, ADPropertyValueCollection, to a string array(untested!):
$obj = Get-ADObject -Server "$server" -SearchBase $SearchBase
-Filter "name -eq '$GroupName'" -Properties Member
$m = [string[]]$obj.Member
New-ADObject -Server "$server" -Path $SearchBase -Type 'GroupOfNames'
-name "$NewGroupName" -OtherAttributes #{'Member'= $m}
After some trial and error, I found that I could reliably add about 6000 members at a time. Here's the basic flow:
(Get-ADObject -Server "$server" -SearchBase $SearchBase -Filter { name -eq "$GroupName" } -Properties Member).Member | %{
$SubList += [string] $_
if($SubList.count -ge 6000) {
Set-ADObject -Server "$server" -Identity $NewGroup -Add #{'Member'= ($SubList)}
$SubList = #()
}
}
if($SubList.count -gt 0) {
Set-ADObject -Server "$server" -Identity $NewGroup -Add #{'Member'= ($SubList)}
}
Thank you #Raf for the push in the right direction.