My question is how I split content prompted from a command line in powershell
I want to find all the OU's path on my server, so I can use them later on..
get-aduser -Filter * | Select DistinguishedName | findstr "OU="
OUTPUT
CN=Username1,OU=firma1,DC=bc,DC=local
CN=Username2,OU=firma2,DC=ad,DC=local
and I want only
OU=firma1,DC=bc,DC=local
OU=firma2,DC=ad,DC=local
This should work:
Get-ADUser -Filter * |
Where-Object { $_.DistinguishedName.IndexOf('OU=') -gt 0 } |
ForEach-Object { $_.DistinguishedName.Substring($_.DistinguishedName.IndexOf('OU=')) }
This code filters out any objects that aren't in an OU, which includes those which are in the Users built-in container, like CN=Administrator,CN=Users,DC=bc,DC=local. You could also handle those users with an if statement in the ForEach-Object.
How about using the .NET String.Split method directly
Get-ADUser -Properties DistinguishedName | ForEach-Object {
$_.DistinguishedName.Split(",", 2)[1]
}
This splits the DistinguishedName into two parts at the comma (i.e. everything before the first comma and everything after) and returns the second part only (array index [1]).
I would probably add a Sort-Object and a Select-Object -Unique to the end of that.
Worth a read: Get-ADOrganizationalUnit, maybe that is what you are actually are looking for?
This approach is similar, with the PowerShell-native -split operator:
$DNs = Get-ADUser -Properties DistinguishedName | Select -ExpandProperty DistinguishedName
$DNs -split ',',2 | where { $_.StartsWith("OU=") }
Related
Import-Module ActiveDirectory
Get-ADComputer -Filter {enabled -eq $true} -properties *|select Name,
| Out-File -FilePath c:\Powershell.txt
I am trying to export a list to txt file and have it display a list of all the computers on my domain by name and the OU or group it is assigned to. i am able to retrieve the name with this, but would like to ad a OU Colum.
Since the DistinguishedName value contains the OU RDN, we can extract it with a bit of string splitting magic:
Get-ADUser -Filter * |Select Name,#{Name='OU';Expression={$_.DistinguishedName -split '(?<!\\),' |Select -Index 1}}
This will give us only the RDN (ie. OU=Company Users), if you want the full DN of the OU, do:
Get-ADUser -Filter * |Select Name,#{Name='OU';Expression={$_.DistinguishedName -split '(?<!\\),',2 |Select -Skip 1}}
The pattern (?<!\\), will match any , in the DN only if not preceded by \ - this is to avoid splitting on escaped ,'s, like in CN=LastName\, FirstName,OU=Users,...
Honestly, I would derive the OU from the DistinguishedName value. It will be quicker than running additional ActiveDirectory module PowerShell commands. You can then output the OU value using Select-Object's calculated properties. I would also recommend outputting to CSV (using Export-Csv) since that format is easily readable by PowerShell and other file editing tools.
Get-ADComputer -Filter 'Enabled -eq $true' |
Select-Object Name,#{n='OU';e={$_.DistinguishedName -creplace '^.*?,(?=[A-Z]{2}=.*)'}} |
Export-Csv -Path c:\Computers.csv
Note that the CSV export will have a header row and values will be delimited by comma. If you prefer a different delimiter, you can use the -Delimiter parameter or your PowerShell session's default list separator with the -UseCulture switch.
-creplace is a case-sensitive version of -replace operator.
^.*?,(?=[A-Z]{2}=.*) is regex syntax for matching the text to replace. ^ denotes the start of the string. .*?, matches a few characters as possible until a , is matched. But since a CN value can contain , characters, we only want to stop matching when it precedes OU= or DC=. This is why we have positive lookahead (?=[A-Z]{2}=.*). [A-Z]{2} matches exactly two capital letters followed by =.
This what I do, it is a bit slower than the other examples provided but it will prevent any timeout on the Get-ADcomputer cmdlet. I'm also using CanonicalName to have an absolute path of the OU because OUs can have the same name and Canonical is easier to read than Distinguished.
$OUs = Get-ADOrganizationalUnit -Filter * -Properties CanonicalName
$Result = foreach($OU in $OUs)
{
$hash = #{
Filter = 'Enabled -eq $true'
SearchScope = 'OneLevel'
SearchBase = $OU.DistinguishedName
}
foreach($computer in Get-ADComputer #hash)
{
[pscustomobject]#{
ComputerName = $computer.Name
OU = $OU.CanonicalName
}
}
}
Good Morning Guys,
I write this script to export multiple users in multiple groups in a CSV file.
In addition to not exporting anything, I cannot insert a column in the CSV where the user's appatenency group is specified. Just the one with the name "vpn-*", like vpn-users
Powershell Version 4.0
$Data = $UserData = #()
$GroupName = Get-ADGroup -Filter {name -like "VPN-*"} -Properties Name | Select-Object Name
Foreach ($group in $GroupName)
{
$UserData = Get-ADGroupMember -Identity {$group}
Where objectClass -eq 'user' |
Get-ADUser -Properties Name, UserPrincipalName, description, Enabled |
Select-Object Name, UserPrincipalName, description, Enabled
}
$UserData | export-csv "c:\members2.csv"
I see a number of issues with the posted code. Some are mere preferences, but others look like they would affect the outcome.
-Properties Name isn't needed in the initial Get-ADGroup command. The Name property is returned by default.
Respectful to #Theo's comment re: -ExpandProperty, however, I prefer not to use that unnecessarily. You don't even need the first Select-Object command, just reference the property and it will unroll and return a string array. Property unrolling is supported as of PowerShell Version 3.
Your argument to the -Filter parameter should be a string. I myself have a hard time breaking the habit of wrapping those queries in script blocks {...}, however, there are some specifics of the AD cmdlets, and using a string is a best practice. Basically, the argument takes a string type, if you give it a script block it will convert it to a string and that process may not always work as desired.
It's better to store your AD properties in an array you can cite multiple times. Normally you would've only needed to add 'Description' but considering you were also using it in a later Select-Object command it makes more sense to add all the desired properties to an array.
Personally, I prefer not to use simplified syntax. I don't know what the community's opinion is on that but I rewrote using my preference.
You were also missing |' before the Where-Object command.
And, yes you would have to move the Export-Csv inside the loop to output data per loop iteration. Using the -Append parameter to avoid overwriting it on every iteration.
Untested Example:
$ADProps = 'Name', 'UserPrincipalName', 'description', 'Enabled'
$GroupName = (Get-ADGroup -Filter "name -like 'VPN-*'" ).Name
Foreach ( $Group in $GroupName )
{
$UserData =
Get-ADGroupMember -Identity $Group |
Where-Object{ $_.objectclass -eq 'user' } |
Get-ADUser -Properties $ADProps |
Select-Object ($ADProps += #{Name = 'Group'; Expression = { $Group }})
$UserData | export-csv "c:\members2.csv" -NoTypeInformation -Append
}
I am trying to send a user name (SamAccountName) down the PowerShell Pipeline to find a computer based on the Description property in Active Directory:
The Description property is always "something-UserName"
I know I don't need to send the variable down the pipeline and can simply express it in the filter but I have s specific use case where I need to do this.
This is what I have tried:
"bloggsJ" | %{Get-ADComputer -server domain.com -Filter * -Properties Description | ?{$_.Description -eq "something-$_"}} | select Name
This produces nothing even though there is a computer with a description property of "Something-bloggsJ" on that domain.
Any advice please.
Instead of using the -eq operator, I would use -like.
Something like this:
"bloggsJ", "IanB" | ForEach-Object {
$name = $_
Get-ADComputer -Filter * -Properties Description |
Where-Object {$_.Description -like "*-$name"}
} | Select-Object Name
Inside the ForEach-Object loop, the $_ automatic variable is one of the usernames. Inside the Where-Object clause, this $_ variable represents one ADComputer object, so in order to have the username to create the -like string, you need to capture that name before entering the Where-Object clause.
I believe you are missing the underscore for $_ variable:
"ivan" | ForEach-Object -Process { Get-ADComputer -Filter * -properties description | Where-Object -Property description -eq "something-$_"}
this one is working ...
I am trying to create a script to take care of a repetitive task I have. Basically I need to get the person's ID that manages a particular folder.
My first script tells me the various security groups assigned to a specified folder. The second script takes a specified AD group and tells me who manages it. Ideally I want to just run the script, input my folder name and have it tell me who manages the various AD groups assigned. I can then go and do the rest. But I am having an issue with the output of the first script. I have it so it displays in the console correctly, but I cannot figure out how to get those results into the filter in the second script.
Script one:
$FN = Read-Host -Prompt "Please enter Folder name"
$ADG = (Get-Acl $FN).Access |
Select IdentityReference |
Where-Object IdentityReference -like '*SL*'
foreach ($ACL in $ADG) {
$Group.Fullname + ($ACL.IdentityReference.Value.Split('\'))[1] | Out-String
}
Script two:
Get-ADGroup -Filter {Name -like "use output here"} -Properties managedby |
Select managedby
I would be most appreciative of any assistance. ESPECIALLY if I am barking up the wrong PowerShell command! My first foray into using multiple queries in a script.
It's not quite clear to me what the $Group.Fullname + (...)[1] | Out-String is supposed to do, but assuming that you want to run the second command for each identity reference from your first command you could do something like this:
Get-Acl $FN |
Select-Object -Expand Access |
Select-Object -Expand IdentityReference |
Where-Object { $_.Value -like '*SL*' } |
ForEach-Object {
$name = $_.Value.Split('\', 2)[-1]
Get-ADGroup -Filter "Name -like '*${name}*'" -Property ManagedBy
} |
Select-Object -Expand ManagedBy |
Get-ADUser
I have a list of names taken from Oracle that Im trying to find the SamAccountName for. The file is a CSV and some names are "last, first" or "last, first middle initial" and some have three or four names like "alpha bravo charlie delta". The names in the list are likely not the same as listed in AD. Trying to figure out how to sort through this to find AD accounts. The code I currently have is not producing any results.
Import-Module ActiveDirectory
Import-Csv "\\server\users\folder\Oracle_HR.csv"
ForEach-Object{
Get-ADUser -Filter { Name -like "'$($_.name)'"} -Properties Name |
Select-Object Name,SamAccountName |
Export-CSV "\\server\users\folder\Oracle_ADs.csv" -NoTypeInformation
}
The answers by Gabriel Luci and Mathias R. Jessen give good advice on "fuzzy" filtering of AD users.[1]
However, your primary problem is that your ForEach-Object call is not receiving pipeline input, because you haven't connected it to output from the Import-Csv call.
Simply join the two commands with |:
Import-Csv "\\server\users\folder\Oracle_HR.csv" | ForEach-Object { # ...
Secondarily, your -Filter argument { Name -like "'$($_.name)'"} mistakenly applies two layers of quoting and is missing wildcard characters, given that -like compares against the entire field, yet you want substring matching.
Since it's better to avoid the use of script blocks ({ ... }) as -Filter arguments, use a string:
"Name -like `"*$($_.name)*`"" # Note the enclosing '*' to match substrings
Note that I've used embedded " quoting (escaped as `") rather than ' quoting, so as not to break the filter with names that contain ', such as O'Malley.
That said, if, as your question suggests, the names in your CSV data aren't direct substrings of the AD users' .Name property values, the above filter will not be enough, and even the ANR (Ambiguous Name Resolution) technique shown in the linked answers may not be enough.
Thirdly, your Export-Csv call is misplaced: because it is inside the ForEach-Object script block, the same output file gets overwritten in every iteration.
Restructure your command as follows:
Import-Csv ... | ForEach-Object { ... } | Export-Csv ...
Optional reading: ForEach-Object behavior when not providing pipeline input:
The associated script block is executed once.
$_, the automatic variable that contains the current input object, is $null.
[1] Note that the search term in the LDAP filter may need escaping ; per this article, the characters * ( ) \ NUL require escaping and must be escaped as \<hh>, where <hh> is the two-digit hex representation of the char's ASCII code (e.g., * must be escaped as \2A):
$escapedName = -join $(foreach ($c in [char[]] $_.name) { if ('*', '\', '(', ')', "`0" -contains $c) { '\' + ([int] $c).ToString('X2') } else { $c } })
Get-ADUser -LDAPFilter "(anr=$escapedName)"
With $_.name containing string "James* (Jimmy) Smith\Smyth`0", $escapedName would evaluate to literal James\2A \28Jimmy\29 Smith\5CSmyth\00
Keep in mind that the property names in PowerShell are not named the same as the attributes in AD. The Name property corresponds to both the name and cn attributes in AD (both attributes are always the same).
There is also DisplayName (displayName in AD), GivenName (givenName), and Surname (sn). You could try matching against the DisplayName:
Get-ADUser -Filter "DisplayName -eq '$($_.name)'"
If none of those properties match your data exactly, you will have some trouble. No one thing you do will probably work for every account. Hopefully this is just a one-time job and you can work through them in pieces (try one thing, take out the ones that work, and try something different on the rest).
One thing you can try is using AD's Ambiguous Name Resolution (ANR), which will match a search string against several different attributes and even match a first and last name against givenName and sn. That might work with some in your list. You would use it like this:
Get-ADUser -LDAPFilter "(anr=$($_.name))"
If none of that works, you'll have to split the names (for example, by spaces: $_.name.Split(" ")) and try to match pieces of it to different attributes. You'll have to look at your data and see what works.
One approach is to use the Ambiguous Name Resolution feature in Active Directory.
It'll do fuzzy matching against multiple attributes, like the displayName, Name and mail attributes (among others), so it's pretty good for this exact kind of scenario where you don't necessarily know the order or the names or the full name up front:
Get-ADUser -LDAPFilter "(&(anr=$($_.name)))"
I recommend using LDAPFilter and Ambiguous Name Resolution (anr) with Get-ADUser. The algorithm looks up several name fields in different orders to find matches:
Get-ADUser -LDAPFilter "(anr=John Doe)"
Or modifying your code:
Get-ADUser -LDAPFilter "(anr=$($_.name))"
You could try something like the following:
Import-Module ActiveDirectory
$allUsers = Get-Content "\\server\users\folder\Oracle_HR.csv"
$users = #()
ForEach($obj in $allUsers){
$user = Get-ADUser -Filter { GivenName -like $obj} -Properties Name, samAccountName
if(!$user){
$user = Get-ADUser -Filter { SurName -like $obj} -Properties Name, samAccountName
}
if(!$user){
$user = Get-ADUser -Filter { Name -like $obj} -Properties Name, samAccountName
}
if(!$user){
Write-Host "User $obj could not be found" -ForegroundColor Red
}else{
$users += $user
}
}
$users | Select-Object Name,SamAccountName | Export-CSV "\\server\users\folder\Oracle_ADs.csv" -NoTypeInformation
You might need to split the values also like:
Import-Module ActiveDirectory
$allUsers = Get-Content "\\server\users\folder\Oracle_HR.csv"
$users = #()
ForEach($obj in $allUsers){
$objSplit = $obj.Split(",")
foreach($split in $objSplit){
$user = Get-ADUser -Filter { GivenName -like $split} -Properties Name, samAccountName
if(!$user){
$user = Get-ADUser -Filter { SurName -like $split} -Properties Name, samAccountName
}
if(!$user){
$user = Get-ADUser -Filter { Name -like $split} -Properties Name, samAccountName
}
if(!$user){
Write-Host "User $split could not be found" -ForegroundColor Red
}else{
if($users.samAccountName -notcontains $user.SamAccountName){
$users += $user
}
}
}
}
$users | Select-Object Name,SamAccountName | Export-CSV "\\server\users\folder\Oracle_ADs.csv" -NoTypeInformation