In the code below, the userprinciplename will output strings like "LLL_John.Smith#email.com" and XXXX_Jane.Doe#email.com" but i am hoping to extract a substring from that, that being the codes before the "_" character, so LLL and XXXX.
There may be some which do not have an underscore character however and so these would need to be ignored / have the original string it would have returned.
##Check bottom of script for setting specific OU
Function Get-LastLogon {
param(
[string]$OUName
)
# Get all matching OUs on any level
$OUs = Get-ADOrganizationalUnit -Filter "Name -like '$OUName'"
$DCs = Get-ADDomainController -Filter *
# Get all users from each OU from each DC
$ADUsers = Foreach ($OU in $OUs) {
Foreach ($DC in $DCs.HostName) {
Get-ADUser -SearchBase $OU.DistinguishedName -Filter * -Properties LastLogon -server $dc |
Select-Object Name,userPrincipalName, #{n='LastLogon';e={[DateTime]::FromFileTime($_.LastLogon)}}
}
}
# return most recent LastLogon date for each user
$ADUsers |
Group Name,userPrincipalName |
Select Name,userprinciplename, #{n='LastLogon';e={$_.Group.LastLogon | sort -desc | select -First 1}}
} ## End function
##Enter the OU here
Get-LastLogon -OUName 'Clients'
##Un-comment below to export to csv
## | Export-Csv -Path 'C:\temp\UserExport.csv'
Here is what the script looks like now in full:
##Check bottom of script for setting specific OU
Function Get-LastLogon {
param(
[string]$OUName
)
# Get all matching OUs on any level
$OUs = Get-ADOrganizationalUnit -Filter "Name -like '$OUName'"
$DCs = Get-ADDomainController -Filter *
$ADUsers = foreach ($OU in $OUs) {
foreach ($dc in $DCs.HostName) {
Get-ADUser -SearchBase $OU.DistinguishedName -Filter * -Properties lastLogonTimeStamp -Server $dc |
Select-Object Name,UserPrincipalName,
#{Name = 'LastLogon';Expression = {[DateTime]::FromFileTime($_.lastLogonTimeStamp)}},
#{Name = 'UserCode'; Expression = {([regex]'^([^_]+)_.*').Match($_.UserPrincipalName).Groups[1].Value}}
}
} }
# return the most recent LastLogon date for each user
# (only the users with a code prefix in the UserPrincipalName)
$ADUsers | Where-Object { ![string]::IsNullOrWhiteSpace($_.UserCode) } |
Group-Object UserPrincipalName | ForEach-Object {
[PsCustomObject]#{
Name = $_.Group[0].Name
UserCode = $_.Group[0].UserCode
LastLogon = $_.Group.LastLogon | Sort-Object -Descending | Select-Object -First 1
}
}
## End function
$OUcustom = Read-Host -prompt 'Enter OU here or "Clients" for all'
##Enter the OU here
Get-LastLogon -OUName $OUcustom |
##export csv
Export-Csv -path "C:\temp\UserExport_$((Get-Date).ToString("ddMM_HHmm")).csv" -NoTypeInformation
".csv extracted to C:\temp"
pause
Just add another calculated property to the code you have to get the array of user objects:
$ADUsers = foreach ($OU in $OUs) {
foreach ($dc in $DCs.HostName) {
Get-ADUser -SearchBase $OU.DistinguishedName -Filter * -Properties lastLogonTimeStamp -Server $dc |
Select-Object Name,UserPrincipalName,
#{Name = 'LastLogon';Expression = {[DateTime]::FromFileTime($_.lastLogonTimeStamp)}},
#{Name = 'UserCode'; Expression = {if ($_.UserPrincipalName -like '*_*#*') {($_.UserPrincipalName -split '_')[0]} else { $null }}}
# or use regex like:
# #{Name = 'UserCode'; Expression = {([regex]'^([^_]+)_.*').Match($_.UserPrincipalName).Groups[1].Value}}
}
}
Then you can filter out the users that do have such a code:
# return the most recent LastLogon date for each user
# (only the users with a code prefix in the UserPrincipalName)
$ADUsers | Where-Object { ![string]::IsNullOrWhiteSpace($_.UserCode) } |
Group-Object UserPrincipalName | ForEach-Object {
[PsCustomObject]#{
Name = $_.Group[0].Name
UserCode = $_.Group[0].UserCode
LastLogon = $_.Group.LastLogon | Sort-Object -Descending | Select-Object -First 1
}
}
If you want to rule out all users that do not have some code followed by an underscore in their UserPrincipalName property straight away, you can use the filter parameter:
Get-ADUser -SearchBase $OU.DistinguishedName -Filter "UserPrincipalName -like '*_*#*'" -Properties lastLogonTimeStamp -Server $dc
This however will not give you the opportunity to use the collected users for some other purpose, like outputting users who do not have a code prefixed, as would be easy to do with the code above.
P.S. Did you know PowerShell also provides an attribute LastLogonDate, which is the LDAP property lastLogonTimeStamp, converted to local time.
So this was actually more simple than I realised.
I just needed to add in:
#{N='userPrincipalName';E={$_.userPrincipalName.Split("_")[0]}}
To the first and second blocks where UserPrincipleName was being selected.
Will post the full working code below for relevance.
##Check bottom of script for setting specific OU
Function Get-LastLogon {
param(
[string]$OUName
)
# Get all matching OUs on any level
$OUs = Get-ADOrganizationalUnit -Filter "Name -like '$OUName'"
$DCs = Get-ADDomainController -Filter *
# Get all users from each OU from each DC
$ADUsers = Foreach ($OU in $OUs) {
Foreach ($DC in $DCs.HostName) {
Get-ADUser -SearchBase $OU.DistinguishedName -Filter * -Properties LastLogon -server $dc |
Select-Object Name,#{N='userPrincipalName';E={$_.userPrincipalName.Split("_")[0]}}, #{n='LastLogon';e={[DateTime]::FromFileTime($_.LastLogon)}}
}
}
# return most recent LastLogon date for each user
$ADUsers |
Group Name,userPrincipalName |
Select Name,#{N='userprinciplename';E={$_.userprinciplename.Split("_")[0]}}, #{n='LastLogon';e={$_.Group.LastLogon | sort -desc | select -First 1}}
} ## End function
$OUcustom = Read-Host -prompt 'Enter OU here or "Clients" for all'
##Enter the OU here
Get-LastLogon -OUName $OUcustom |
##export csv
Export-Csv -path "C:\temp\UserExport_$((Get-Date).ToString("ddMM_HHmm")).csv" -NoTypeInformation
".csv extracted to C:\temp"
pause
Related
I have the following code, I'm just trying to export what security groups are attached to each Domain Controller.
I have so far made this, however! I cannot seem to export the computer names along side the Groups in the output! Can someone potentially help! I've been going round in circles for hours
$ou = "OU=Domain Controllers,DC=example,DC=com"
$user = Get-ADComputer -SearchBase $ou -Filter * -properties * | Select ntSecurityDescriptor, Name
$user2 = $user.ntSecurityDescriptor.Access |
select-object -expandproperty IdentityReference |
sort-object -unique
if ($user2-eq "example\user") {
#They Match
Write-Host "Oh Sugar"
$user.ntSecurityDescriptor.Access |
Select-Object -expandproperty IdentityReference |
sort-object -unique
} else {
Write-Host "Phew"
}
Update 20th August. I updated my code to loop around and show the computer name in the output.
$ou = "OU=Domain Controllers,DC=example,DC=com"
$computers = Get-ADComputer -SearchBase $ou -Filter * -properties ntSecurityDescriptor, Name
$code = foreach ($computer in $computers)
{
Get-ADComputer $computer -properties ntSecurityDescriptor
$owner = $computer.ntSecurityDescriptor.Access |
Select-Object -expandproperty IdentityReference |
sort-object -unique
$export = if ($owner-eq "example\user") {
#Problem found
$computer.Name
} else {
}
$export | Out-File 'C:\Temp\output.csv' -Append
}
I have a list of users (their CN), and I want a list of the groups they are member of.
I already have a code which almost does the trick, but it shows as follows:
User1 - group1;group2
User2 - group1;group2;group3 etc...
Also, groups are shown as distinguished name (with container etc), so very long. I only want the name.
I want to show it as follows:
User1 - group1
User1 - group2
User2 - group1, etc
The code that shows the groups the users are member of, but not in the visual way i like is below:
Import-Csv -Path .\Input_CN.csv |
ForEach-Object {
$User = Get-ADUser -filter "CN -eq '$($_.CN)'" -properties memberof
[PSCustomObject]#{
SourceCN = $_.CN
MemberOf = $User.MemberOf -join ";"
}
} | Export-Csv -Path .\Output.csv -Delimiter ";" -NoTypeInformation
.\Output.csv
I have some other code that list the groups how I want, but I am unable to list it per user. And unable to combine it with the above code.
get-aduser -filter {cn -eq "Testuser"} -properties memberof |
Select -ExpandProperty memberof |
ForEach-Object{Get-ADGroup $_} |
Select -ExpandProperty Name
Thanks in advance :)
You could combine both code pieces like this:
Import-Csv -Path .\Input_CN.csv |
ForEach-Object {
$user = Get-ADUser -Filter "CN -eq '$($_.CN)'" -Properties MemberOf, CN -ErrorAction SilentlyContinue
foreach($group in $user.MemberOf) {
[PSCustomObject]#{
SourceCN = $user.CN
MemberOf = (Get-ADGroup -Identity $group).Name
}
}
} | Export-Csv -Path .\Output.csv -Delimiter ";" -NoTypeInformation
Edit
Although I have never seen an AD user to have no group membership at all (should have at least the default Domain Users in the MemberOf property), You commented that you would like to have a test for that aswell.
Import-Csv -Path .\Input_CN.csv |
ForEach-Object {
$user = Get-ADUser -Filter "CN -eq '$($_.CN)'" -Properties MemberOf, CN -ErrorAction SilentlyContinue
if (!$user) {
Write-Warning "No user found with CN '$($_.CN)'"
# skip this one and resume with the next CN in the list
continue
}
$groups = $user.MemberOf
if (!$groups -or $groups.Count -eq 0) {
[PSCustomObject]#{
SourceCN = $user.CN
MemberOf = 'No Groups'
}
}
else {
foreach($group in $groups) {
[PSCustomObject]#{
SourceCN = $user.CN
MemberOf = (Get-ADGroup -Identity $group).Name
}
}
}
} | Export-Csv -Path .\Output.csv -Delimiter ";" -NoTypeInformation
This is a bit clunky, but you can use nested loops:
Import-Csv -Path .\Input_CN.csv | ForEach-Object {
$user = Get-ADUser -filter "CN -eq '$($_.CN)'" -properties cn, memberof
$user | ForEach-Object {
$_.MemberOf |
ForEach-Object {
[PSCustomObject]#{
SourceCN = $user.CN
MemberOf = $_.split('[=,]')[1]
}
}
}
} | Where-Object {$null -ne $_.MemberOf} |
Export-Csv -Path .\Output.csv -Delimiter ";" -NoTypeInformation
UPDATE: Updated to show only the 'CN' part of the group name and to filter any users who are not a member of any group.
All in one line could be
Get-ADUser -filter {Enabled -eq $True} -Properties Name, Created | Select-Object Name, Created, #{Name="Groups";Expression={Get-ADPrincipalGroupMembership -Identity $_.SamAccountName | Where-Object {$_.GroupCategory -Eq 'Security'} | Join-String -Property Name -Separator ", "}}
I am having issues in my thought process. I want an output of something like
'Group Name' 'Title' 'Count' and I am able to get the 'Group Name' and 'Title' Columns but I'm not sure how to count, say, all of the repeat groups in the 'sales' title. Where my code is right now, is searching the entire column to see if it finds that group name, and if it finds that column and then it move the counter by 1 (this is wrong because it my find a group name with a different title)
Any help would be greatly appreciated! Thank you
$allOffices = get-aduser -filter * -Properties physicaldeliveryofficename | Select-Object -ExpandProperty physicaldeliveryofficename #Selecting all offices
$uniOffices = $allOffices | Select-Object -Unique
$groups = $null
$global:ErrorActionPreference = 'silentlycontinue'
$finallist = #()
$count = 0
foreach ($office in $uniOffices) { # Loop through all unique offices
$peopleInOffice = $null
$peopleInOffice = get-aduser -filter * -properties office | Where-Object office -eq $office | Select-Object -ExpandProperty SamAccountName # Array of people in a certain office, selects username
foreach ($person in $peopleInOffice){
$groups = get-ADPrincipalGroupMembership $person
foreach($group in $groups) {
if(($finallist.'Group Name'-contains $group.name) -and ($finallist.'Title' -contains $office)){$count++}
$finallist+= $group| Select-Object #{N='Group Name';E={$group.name}},#{N='Title';E={($office)}},#{N='Count';E={$count}}
}
}
}
$finallist
So I started working on your problem, and I'm unsure what you're asking. Here's a greatly simplified and more efficient representation of your code:
$offices = Get-ADUser -Filter 'PhysicalDeliveryOfficeName -like "*"' -Properties PhysicalDeliveryOfficeName |
Select-Object -ExpandProperty PhysicalDeliveryOfficeName -Unique
$list = foreach ($office in $offices)
{
foreach ($person in (Get-ADUser -Filter "Office -eq '$office'" -Properties Office, MemberOf))
{
$person.MemberOf |
Get-ADGroup -Properties Name |
Select-Object -Property #(
#{
N = 'Group Name'
E = {$PSItem.Name}
}
#{
N = 'Title'
E = {$office}
}
)
}
}
At the end, you have a $list object which is an array of pscustomobject objects that you can manipulate. You can use Group-Object to determine how many groups there are with similar names using calculated properties, etc.
Using your problem statement:
how to count all of the repeat groups in the sales title
$list | Group-Object -Property Title | Select-Object -ExpandProperty Count
Looking to write a powershell script that will pull ALL AD users, their group memberships and the groups Description Field.
I have been using two scripts to accomplish this, and just manually manipulating them in excel. Any attempt to combine them has been met with error.
Import-module activedirectory
$ou ="DC=blah,DC=blah"
Get-ADGroup -Filter * -SearchBase $OU | select -expandproperty name | % {
$group= "$_"
$result += Get-ADGroupMember -identity "$_" | select #{n="Group";e={$group}},name
}
$result | export-csv 'c:\users\membership.csv' -notypeinformation
And:
Import-Module ActiveDirectory
$Groups = ForEach ($G in (Get-ADGroup -Filter * ))
{
$UN = Get-ADGroup $G -Properties Description | select name, description
New-Object PSObject -Property #{
Desc=$UN.description
Name=$UN.name
}
}
$Groups | Export-CSV C:\users\GroupDesc.csv -notypeinformation
I hope i've got this right, this will pull all users from AD and get the groups each one is a member of (including the groups description). After everything is done it puts the info into a csv.
Import-Module ActiveDirectory
$OU = "DC=blah,DC=blah"
#$allUsers = Get-ADUser -LDAPFilter "(&(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2))" # all users that are enabled
#$allUsers = Get-ADUser -Filter * # all users
$allUsers = Get-ADUser -Filter * -SearchBase $OU
$results = #()
foreach($user in $allUsers)
{
$userGroups = Get-ADPrincipalGroupMembership -Identity $user
foreach($group in $userGroups)
{
$adGroup = Get-ADGroup -Identity $group -Properties Description
$results += $adGroup | Select-Object -Property #{name='User';expression={$user.sAMAccountName}},Name,Description
}
}
$results | Export-Csv -Path 'C:\Membership.csv' -NoTypeInformation -Encoding Unicode
I have a requirement to generate a CSV report to get group members. However, I there are many child domains which contains groups starting with ADM.
I need report in the following format:
GroupName User Company LasLogon CN
ADM_AM UserOne CP1
I've found one script on internet:
Get-ADGroup -Server dc1.chd1.pd.local -Filter 'Name -like "ADM*"' |
ForEach-Object{
$hash=#{GroupName=$_.Name;Member=''}
$_ | Get-ADGroupMember -ea 0 -recurs |
ForEach-Object{
$hash.Member=$_.Name
New-Object psObject -Property $hash
}
} |
sort groupname,member
This script only gives me GroupName and UserName but not other information.
How can I generate this report?
I'm not sure what "ADM_AM, UserOne, CP1" is, but i got this much for you. I'm still new to powershell so forgive me if this is a lot of code =)
$array = #()
Foreach ($group in (Get-ADGroup -Server dc1.chd1.pd.local -Filter 'Name -like "ADM*"'))
{
$hash=#{Username ='';GroupName=$group.Name;Company='';LastLogon='';CN=''}
$members = $hash.GroupName | Get-ADGroupMember -Recursive -ErrorAction SilentlyContinue
Foreach($member in $members)
{
$properties = $member.SamAccountName | Get-ADUser -Properties SamAccountName, Company, lastLogon, CN
$hash.Username = $properties.SamAccountName
$hash.Company = $properties.Company
$hash.LastLogon = $properties.lastLogon
$hash.CN = $properties.CN
$obj = New-Object psObject -Property $hash
$array += $obj
}
}
$array | Export-Csv C:\ -NoTypeInformation
Here is what I would do, Im sure you can shorten it. You shoud specify a searchbase. Once you have the members samaccountname, you can use Get-ADUser to get whatever fields you want.
$GrpArr = #()
$Groups = get-adgroup -filter {name -like "adm*"} -searchbase "ou=Groups,dc=all,dc=ca" | select samaccountname
foreach ($group in $groups)
{
$GrpArr += $group
$members = get-adgroupmember $group | select samaccountName
foreach ($member in $members)
{
$memprops = get-aduser $member -properties company
$comp = $memprops.company
$grpArr += "$member,$comp"
}
}
$grpArr | export-csv c:\temp\Groups.csv -NoTypeInformation