i want to export csv file with columns "ParentGroupName", "MemberName", "DisplayName"
At the moment it is exporting the three datas into one column.
function getGroups{
$Groups += Get-ADGroup -Filter * -SearchBase "ou=Groups,ou=DCM,ou=NTG,dc=prod,dc=main,dc=ntgov" | Select-Object -ExpandProperty samaccountname
return $Groups
}
Measure-Command{
$Groups = getGroups
write-host "Groups:" $Groups.Count
}
Measure-Command{
$date = $(get-date).ToString("dd MMM yyyy")
$global:FileName = "Active Directory Group Membership - DCM -" + $date
$stringBuilder = New-Object System.Text.StringBuilder
foreach ($GroupName in $Groups){
Get-ADGroupMember -Identity $GroupName | Sort-Object $_.SamAccountName | ForEach-Object {
$ParentGroupName = (Get-ADGroup -Identity $GroupName).SamAccountName
$MemberName = $_.SamAccountName # Member of the Group.
if ($_.ObjectClass -eq 'group') {
$DisplayName = ' - '
} elseif ($_.ObjectClass -eq 'user') {
$a = (Get-ADUser -Identity $MemberName -Properties Displayname)
$DisplayName = $a.DisplayName
}
$null = $stringBuilder.Append("$ParentGroupName, $MemberName, $DisplayName")
}
}
outputArray = $stringBuilder.ToString()
out-file C:\Users\augut\Desktop\$FileName.csv
outputArray | out-file C:\Users\augut\Desktop\$FileName.csv
}
You're making a headache for yourself by manually constructing the CSV file. This can be simplified considerably by constructing a custom object for each item found with the properties you need recorded, then stuffing those into an array and exporting that array to a CSV file.
function getGroups{
$Groups += Get-ADGroup -Filter * -SearchBase "ou=Groups,ou=DCM,ou=NTG,dc=prod,dc=main,dc=ntgov" | Select-Object -ExpandProperty samaccountname
return $Groups
}
$Groups = getGroups
write-host "Groups:" $Groups.Count
$date = $(get-date).ToString("dd MMM yyyy")
$global:FileName = "Active Directory Group Membership - DCM -" + $date
$results = #();
foreach ($GroupName in $Groups){
Get-ADGroupMember -Identity $GroupName | Sort-Object $_.SamAccountName | ForEach-Object {
$ItemProperties = #{
"ParentGroupName" = (Get-ADGroup -Identity $GroupName).SamAccountName;
"MemberName" = $_.SamAccountName
}
if ($_.ObjectClass -eq 'group') {
$ItemProperties.Add("DisplayName","-");
} elseif ($_.ObjectClass -eq 'user') {
$ItemProperties.Add("DisplayName",(Get-ADUser -Identity $MemberName -Properties DisplayName).DisplayName);
}
$MyItem = New-Object -TypeName psobject -property $ItemProperties;
$Results += $MyItem;
$ItemProperties = $null;
}
}
$results | export-csv -path "C:\Users\augut\Desktop\$FileName.csv" -NoTypeInformation
Related
I'm having issues trying to have my script read and apply the AD groups with my script. Right now, it's just posting what's in my script, but I would like to have the script read what's in my .txt file and use it with the rest of my script.
$filePath = "C:\Users\UserName\Downloads\ADGroupList.txt"
Get-Content -Path $filePath
Get-ADGroup -filter {Name -like "$filePath" } -Properties managedBy |
ForEach-Object {
$managedBy = $_.managedBy;
if ($managedBy -ne $null)
{
$manager = (get-aduser -Identity $managedBy -Properties emailAddress);
$managerName = $manager.Name;
$managerEmail = $manager.emailAddress;
}
else
{
$managerName = 'N/A';
$managerEmail = 'N/A';
}
Write-Output $_; } |
Select-Object #{n='Group Name';e={$_.Name}}, #{n='Managed By Name';e={$managerName}}, #{n='Managed By Email';e={$managerEmail}}
Export-Csv -Path "C:\Users\UserName\Documents\ADGroupManagerList.csv"
The easiest way is to loop over the group names you have in the ADGroupList.txt file (assuming this is a list of group names, each on a separate line)
$filePath = "C:\Users\UserName\Downloads\ADGroupList.txt"
# just loop over the group names you have in the text file and capture the output
$result = Get-Content -Path $filePath | ForEach-Object {
$group = Get-ADGroup -Filter "Name -like '$_'" -Properties managedBy
# create an object pre filled in when no manager was found
$obj = [PsCustomObject]#{
'Group Name' = $group.Name
'Managed By Name' = 'N/A'
'Managed By Email' = 'N/A'
}
# test if the ManagedBy is populated
if (-not [string]::IsNullOrWhiteSpace($group.ManagedBy)) {
# try to use the DN in property ManagedBy to find the manager
try {
$manager = Get-ADUser -Identity $group.ManagedBy -Properties EmailAddress -ErrorAction Stop
$obj.'Managed By Name' = $manager.Name
$obj.'Managed By Email' = $manager.EmailAddress
}
catch {
Write-Warning "No user found for '$($group.ManagedBy)'.. Please check AD."
}
}
# output the object so it gets collected in variable $result
$obj
}
# write the file
$result | Export-Csv -Path "C:\Users\UserName\Documents\ADGroupManagerList.csv" -NoTypeInformation
For workaround you can use this powershell script to get the mangedBy of groups.
Get-ADGroup -filter * -Properties managedBy |
ForEach-Object {
$managedBy = $_.managedBy;
if ($managedBy -ne $null)
{
$manager = (get-aduser -Identity $managedBy -Properties emailAddress);
$managerName = $manager.Name;
$managerEmail = $manager.emailAddress;
}
else
{
$managerName = 'N/A';
$managerEmail = 'N/A';
}
Write-Output $_; } |
Select-Object #{n='Group Name';e={$_.Name}}, #{n='Managed By Name';e={$managerName}}, #{n='Managed By Email';e={$managerEmail}}
I did some PowerShell script to find inactive users in AD that are 90 days old looping through all DCs to also get LastLogon attribute. I also need some extra attributes that only ADUser can bring out. I've got an error when running my script with the piping in the $users = Search-ADAccount line.
Import-Module ActiveDirectory
function Get-ADUsersLastLogon() {
$dcs = Get-ADDomainController -Filter {Name -like "*"}
$OUs = #()
$OU += "ou=Users-A,ou=Users,ou=Items,dc=mydc,dc=com"
$OU += "ou=Users-B,ou=Users,ou=Items,dc=mydc,dc=com"
$time = 0
$exportFilePath = "c:\tmp\lastLogon-test $(get-date -f dd-MM-yyyy).csv"
$columns = "name;username;whencreated;whenchanged;DNname;datetime"
#InactiveTest
$InactiveFilter = #{
UsersOnly = $true
AccountInactive = $true
TimeSpan = New-Timespan -Days 90
}
#EndInactiveTest
Out-File -FilePath $exportFilePath -Force -InputObject $columns
foreach ($OU in $OUs) {
$users = Search-ADAccount #InactiveFilter |
Get-ADUser -Filter * -SearchBase $OUs -Property displayName, whenCreated, whenChanged
foreach ($user in $users) {
foreach($dc in $dcs) {
$hostname = $dc.HostName
$currentUser = Get-ADUser $user.SamAccountName |
Get-ADObject -Server $hostname -Properties lastLogon
if ($currentUser.LastLogon -gt $time) {
$time = $currentUser.LastLogon
}
}
$dt = [DateTime]::FromFileTime($time)
$row = $user.displayName + ";" + $user.SamAccountName + ";" +
$user.whenCreated + ";" + $user.whenChanged + ";" +
$user.distinguishedName + ";" + $dt
Out-File -FilePath $exportFilePath -Append -NoClobber -InputObject $row
$time = 0
}
}
}
Get-ADUsersLastLogon
I think iterating through DC's and OU's and then collecting only the inactive users last logon dates could best be done using a Hashtable object as intermediate storage.
This helps avoiding duplicate entries and gives the opportunity to compare the LastLogonDate properties.
For the final output, it uses one single cmdlet called Export-Csv.
Below my (untested) code:
function Get-ADUsersLastLogon {
# get your ad domain
$DomainName = (Get-ADDomain).DNSRoot
# get all DC hostnames as string array
$DCs = Get-ADDomainController -Filter * -Server $DomainName | Select-Object -ExpandProperty Hostname
# create an array of OU distinghuished names used as SearchBase
$OUs = "OU=Users-A,OU=Users,OU=Items,DC=mydc,DC=com", "OU=Users-B,OU=Users,OU=Items,DC=mydc,DC=com"
$exportFilePath = "c:\tmp\lastLogon-test $(Get-Date -Format dd-MM-yyyy).csv"
$InactiveFilter = #{
UsersOnly = $true
AccountInactive = $true
TimeSpan = New-Timespan -Days 90
}
# use a lookup Hashtable to eliminate duplicates and collect only the latest logon dates
$lookup = #{}
# loop through the list of dc's
foreach ($dc in $DCs) {
# loop through the list of OU's
foreach ($ou in $OUs) {
$users = Search-ADAccount #InactiveFilter -SearchBase $ou -Server $dc
foreach($user in $users) {
# get the properties we want from the AD User.
# using the PowerShell property names, we get the dates already converted into DateTime objects.
$usr = Get-ADUser -Identity $user.DistinguishedName -Server $dc -Properties DisplayName, Created, Modified, LastLogonDate |
Select-Object #{Name = 'Name'; Expression = {$_.DisplayName}},
SamAccountName,
#{Name = 'WhenCreated'; Expression = {$_.Created}},
#{Name = 'WhenChanged'; Expression = {$_.Modified}},
#{Name = 'DistinguishedName'; Expression = {$_.DistinguishedName}},
#{Name = 'LastLogon'; Expression = {$_.LastLogonDate}}
if ($usr) {
if ($lookup.ContainsKey($($user.DistinguishedName))) {
# we have collected this user before
$lastLogon = $lookup[$($user.DistinguishedName)].LastLogon
if ($lastLogon) {
if (($usr.LastLogon) -and $lastLogon -lt $usr.LastLogon) {
# only store this new instance if the $user.LastLogon property is of a later date
$lookup[$($user.DistinguishedName)] = $usr
}
}
}
else {
# this is a new user, so add the object to the HashTable
$lookup[$($user.DistinguishedName)] = $usr
}
}
else {
# should never happen..
Write-Warning "User $($user.SamAccountName) not found."
}
}
}
}
# export the objects contained in the $lookup Hashtable as CSV
($output = foreach ($key in $lookup.Keys) {
$lookup.$key
}) | Export-Csv -Path $exportFilePath -NoTypeInformation -Delimiter ';' -Encoding UTF8 -Force
}
Hope that helps
#voilier Sorry, I don't understand how it works for you. Pasted your code and Get-ADUser cmdlet expects filter value. If you use get-help get-aduser -full you will see that searchbase parameter can only be used with Filter or LDAPFilter parameters. More than that neither of them accept pipeline input. Identity parameter accepts pipeline input by value only. so you need to use the distinguishedname property from Search-ADAccount #InactiveFilter for example distinguishedname and pass it to filter
$users = Search-ADAccount #InactiveFilter | %{Get-ADUser -filter {distinguishedname -eq $_.distinguishedname} -SearchBase $OU -Property displayName, whenCreated, whenChanged}
I replaced your $users=... part with the code above and now I see no errors and CSV file created successfully.
Replace your foreach $ou in $ous with this and check the csv file. it works on my computer
Foreach ($ou in $ous){
$users = (Search-ADAccount #InactiveFilter | %{Get-ADUser -filter {distinguishedname -eq $_.distinguishedname} -SearchBase $OU -Property displayName, whenCreated, whenChanged})
foreach ($user in $users) {
foreach($dc in $dcs) {
$hostname = $dc.Name
$last_logon_time=((Get-ADUser $user.SamAccountName | Get-ADObject -Server "$hostname" -Properties lastLogon) |?{$_.lastlogon -gt $time}) | select -ExpandProperty lastlogon
}
$dt = [DateTime]::FromFileTime("$last_logon_time")
$row = $user.displayName + ";" + $user.SamAccountName + ";" +
$user.whenCreated + ";" + $user.whenChanged + ";" +
$user.distinguishedName + ";" + $dt
Out-File -FilePath $exportFilePath -Append -NoClobber -InputObject $row
$last_logon_time = 0
}
}
I hope it helps you
I need help finding users/groups that fall under multiple domains in my organization. As I have it right now it only looks through the main domain. I would want it to search for users/groups in all of my organizations domains.
This is what I have:
$Users = #()
$Groups = #()
$list = Get-Content C:\temp\ADGroups.txt
Foreach ($o in $list){
$ObjectClass = (Get-ADObject -Filter {SamAccountName -eq $o}).ObjectClass
If ($ObjectClass -eq "User")
{
$U = Get-ADUser -Properties * -Identity $o
$User = "" | Select FullUserName, LoginID, Description
$User.FullUserName = $U.DisplayName
$User.LoginID = $U.SamAccountName
$User.Description = $U.description
$Users += $User
}
Else
{
If ($ObjectClass -eq "Group")
{
$G = Get-ADGroup -Properties * -Identity $o
$GM = Get-ADGroupMember -Identity $G.name -Recursive | Get-ADUser -Properties *
Foreach ($gmember in $GM)
{
$Group = "" | Select GroupName, GroupDescription, GroupMemberName, GroupMemberLoginID, GroupMemberDesc
$Group.GroupName = $G.Name
$Group.GroupDescription = $G.Description
$Group.GroupMemberName = $gmember.Name
$Group.GroupMemberLoginID = $gmember.SamAccountName
$Group.GroupMemberDesc = $gmember.Description
$Groups += $Group
}
}
}
}
>> $Users | Export-Csv C:\temp\PCMUsers.csv -NoTypeInformation
>> $Groups | Export-Csv C:\temp\PCMGroups.csv -NoTypeInformation
Going off of TheIncorrigible1 comment, here is some code to accompany which may be useful.
$Domains = (Get-ADForest).Domains.ForEach{(Get-ADDomain $_).PDCEmulator}
$Users = #()
$Groups = #()
$list = Get-Content C:\temp\ADGroups.txt
ForEach ($dom in $Domains) {
Foreach ($o in $list){
$ObjectClass = (Get-ADObject -Filter {SamAccountName -eq $o}).ObjectClass
#Gets the users in that directory according to the ObjectClass rules
Get-ADUser -Identity $ObjectClass -Server $dom -Properties *
#....
}
}
#....
#....
Note: I don't have the AD-Module installed so I couldn't test it. let me know if it fails
I have a script from a previously answered question, but don't have enough reputation to comment. I tried to run that script and came across this error message:
Export-CSV : Cannot append CSV content to the following file: C:\users.csv. The appended object does not have a property that corresponds to the following column: User;Group. To continue with mismatched properties, add the -Force parameter, and then retry the command.
How can I debug this script to resolve this issue?
Function Get-ADGroupsRecursive{
Param([String[]]$Groups)
Begin{
$Results = #()
}
Process{
ForEach($Group in $Groups){
$Results+=$Group
ForEach($Object in (Get-ADGroupMember $Group|?{$_.objectClass -eq "Group"})){
$Results += Get-ADGroupsRecursive $Object
}
}
}
End{
$Results | Select -Unique
}}
import-module activedirectory
$users = get-aduser -Filter {Name -Like "*"} -Searchbase "OU=Sample Accounts,DC=domain,DC=com" -Properties MemberOf | Where-Object { $_.Enabled -eq 'True' }
$targetFile = "C:\users.csv"
rm $targetFile
Add-Content $targetFile "User;Group"
foreach ($user in $users)
{
$Groups = $User.MemberOf
$Groups += $Groups | %{Get-ADGroupsRecursive $_}
$Groups | %{New-Object PSObject -Property #{User=$User;Group=$_}}|Export-CSV $targetfile -notype -append
}
try this function
function Get-InChainGroups
{
param (
[parameter(mandatory = $true)]
$user,
$domain)
$user1 = (get-aduser -filter { name -eq $user } -server $domain).distinguishedname
Write-verbose "checking $user"
$ldap = "(&(objectcategory=group)(groupType:1.2.840.113556.1.4.803:=2147483648)(member:1.2.840.113556.1.4.1941:=$user1))"
try { Get-ADobject -LDAPFilter $ldap -server $domain | select #{ n = 'Identity'; e = { $user } }, Name, #{ n = 'DN'; e = { $_.distinguishedname } } | ft -a }
catch { "Exception occurred" }
}
i'm trying to retrieve all groups, userID and names from AD and export this to CSV file with three columns, one for ParentGroupNames, then DisplayName, then memberName. The below works accept for DisplayName which seems to repeat one name for all groups.
function getGroups{
$Groups += Get-ADGroup -Filter * -SearchBase "ou=Groups,ou=DCM,ou=NTG,dc=prod,dc=main,dc=ntgov" | Select-Object -ExpandProperty samaccountname
return $Groups
}
$Groups = getGroups
write-host "Groups:" $Groups.Count
$date = $(get-date).ToString("dd MMM yyyy")
$global:FileName = "Active Directory Group Membership - DCM -" + $date
$results = #();
foreach ($GroupName in $Groups){
Get-ADGroupMember -Identity $GroupName | Sort-Object $_.SamAccountName |
ForEach-Object {
$ItemProperties = #{
"ParentGroupName" = (Get-ADGroup -Identity $GroupName).SamAccountName;
"MemberName" = $_.SamAccountName
}
if ($_.ObjectClass -eq 'group') {
$ItemProperties.Add("DisplayName","-");
} elseif ($_.ObjectClass -eq 'user') {
$ItemProperties.Add("DisplayName",(Get-ADUser -Identity $MemberName -Properties DisplayName).DisplayName);
}
$MyItem = New-Object -TypeName psobject -property $ItemProperties;
$Results += $MyItem;
$ItemProperties = $null;
}
}
$results | export-csv -path "C:
There an error in your code, change $MemberName to $ItemProperties.MemberName here's fixed code:
function getGroups{
$Groups += Get-ADGroup -Filter * -SearchBase "ou=Groups,ou=DCM,ou=NTG,dc=prod,dc=main,dc=ntgov" | Select-Object -ExpandProperty samaccountname
return $Groups
}
$Groups = getGroups
write-host "Groups:" $Groups.Count
$date = $(get-date).ToString("dd MMM yyyy")
$global:FileName = "Active Directory Group Membership - DCM -" + $date
$results = #();
foreach ($GroupName in $Groups){
Get-ADGroupMember -Identity $GroupName | Sort-Object $_.SamAccountName |
ForEach-Object {
$ItemProperties = #{
"ParentGroupName" = (Get-ADGroup -Identity $GroupName).SamAccountName;
"MemberName" = $_.SamAccountName
}
if ($_.ObjectClass -eq 'group') {
$ItemProperties.Add("DisplayName","-");
} elseif ($_.ObjectClass -eq 'user') {
$ItemProperties.Add("DisplayName",(Get-ADUser -Identity $ItemProperties.MemberName -Properties DisplayName).DisplayName);
}
$MyItem = New-Object -TypeName psobject -property $ItemProperties;
$Results += $MyItem;
$ItemProperties = $null;
}
}
$results | export-csv -path "C:\1"