Change the script to export Groups and nested objects differently - powershell

I created a similiar script like that:
$Groups = Get-QADGroup
$Result = #()
$Groups | ForEach-Object {
$Group = $_
$Members = Get-QADGroupMember $Group -Indirect | ? objectClass -eq "user"
$Obj = '' | Select-Object -Property Name, Members
$Obj.Name = $Group.Name
$Obj.Members = ($Members | % {$_.SamAccountName + "_" + 'Test'})
$Result += $Obj
}
$Result | Export-Csv -Path C:\Temp\groups.csv -NoTypeInformation -Encoding Unicode -Delimiter ";"
The output looks something like this (example data):
"Name";"Members"
"RootGroup01";"Subuser01_Test";"Subuser02_Test";"Subuser03_Test"
"RootGroup02";"Subuser02_Test"
"RootGroup03";"Subuser01_Test";"Subuser02_Test";"Subuser04_Test";
Is it possible to change the script, that I get something like this?:
"RootGroup01";"RootGroup02";"RootGroup03"
"Subuser01_Test";"Subuser02_Test";"Subuser01_Test"
"Subuser02_Test";;"Subuser02_Test"
"Subuser03_Test";;"Subuser04_Test"
The group names should be the header and the belonging users are in the right column. If there is no user, the column cell just stays empty.

You can write such function to transpose your data:
function Transpose-Data{
param(
[String[]]$Names,
[Object[][]]$Data
)
for($i = 0;; ++$i){
$Props = [ordered]#{}
for($j = 0; $j -lt $Data.Length; ++$j){
if($i -lt $Data[$j].Length){
$Props.Add($Names[$j], $Data[$j][$i])
}
}
if(!$Props.get_Count()){
break
}
[PSCustomObject]$Props
}
}
Then you invoke it in the following way:
$Groups = #(Get-QADGroup)
$Members = #(
$Groups | ForEach-Object {
,#(
Get-QADGroupMember $_ -Indirect |
? objectClass -eq user |
% {$_.SamAccountName + "_" + 'Test'}
)
}
)
Transpose-Data $Groups.Name $Members |
Export-Csv -Path C:\Temp\groups.csv -NoTypeInformation -Encoding Unicode -Delimiter ";"

Related

Local users and their groups

I want to get a similar report as in the following thread for a bunch of computers retrieved from the AD.
$adsi = [ADSI]"WinNT://$($WKS.name)"
$adsi.Children | where { $_.SchemaClassName -eq 'user' } | Foreach-Object {
$groups = $_.Groups() | Foreach-Object { $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null) }
$_ | Select-Object #{ n = 'UserName'; e = { $_.Name } }, #{ n = 'Groups'; e = { $groups -join ',' } } | | Export-Csv -Path "\\..\KontaLokalne.csv" -NoClobber -Append -Encoding UTF8 -Delimiter ";" -NoTypeInformation
}
I want to get an additional information about each account listed - is the account enabled or not.
Additionally, I would like to send the output to the file in the format: computer name; account name; member of the groups.
Could You help me?
To check whether a user account is enabled or not using ADSI, you will have to test if the ADS_UF_ACCOUNTDISABLE bit in the .UserFlags property is set or not.
To do this, you need to bitwise and the value of the UserFlags with the value of ADS_UF_ACCOUNTDISABLE (2):
$adsi = [ADSI]"WinNT://$($WKS.name)"
$result = $adsi.Children | Where-Object { $_.SchemaClassName -eq 'user' } | ForEach-Object {
$groups = $_.Groups() | Foreach-Object { $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null) }
$_ | Select-Object #{Name = 'UserName'; Expression = { $_.Name } },
#{Name = 'Enabled'; Expression = { ($_.UserFlags.Value -band 2) -eq 0} },
#{Name = 'Groups'; Expression = { $groups -join ',' } }
}
# now you can export the resulting collection
# do you really want to use -Append here?
$result | Export-Csv -Path "\\..\KontaLokalne.csv" -NoClobber -Append -Encoding UTF8 -Delimiter ";" -NoTypeInformation
See ADS_USER_FLAG_ENUM

Powershell - cheking var is giving me the right results but Export-CSV gives numbers

what I want is that the $report_groups val gives me in Export-CSV the output that i get in Terminal. But i cant figure it why does he gives me Numbers.
$get_AD_Groups = Get-ADGroup -Filter '*' | Select-Object Name
$report_groups = New-Object -TypeName System.Collections.ArrayList
foreach ($item in $get_AD_Groups) {
$get_users = $item.Name | Get-ADGroupMember | Select-Object Name
$disabled_user = 0
foreach ($user in $get_users) {
$status = $user.Name | Get-ADUser -ErrorAction SilentlyContinue
if(($status.ObjectClass -eq 'user') -and ($status.Enabled -ne 'True')) {
$disabled_user++
}
}
if ($get_users.Count -eq $disabled_user) {
$report_groups.Add($item.Name)
}
}
$report_groups | Export-Csv -Path "..\report.csv" -NoTypeInformation -Force -Delimiter ";"
Now when i run $report_groups in Terminal i get the list of the AD Group BUT as soon i do the Export-CSV this is what i get:
So thanks again to Lee_Dailey for helping me on this.
Changes done.
$report_groups = #()
if ($get_users.Count -eq $disabled_user) {
$fill = [PSCustomObject]#{
AD_GROUP = $item.Name
}
$report_groups += $fill
}

Expanding System.Object[] for Export to CSV

Hello again and sorry!
To keep it really short. What am i doing wrong?
Im attempting to export a list of users filtered by using a customobject to a CSV and it outputs it into the same block. Is there no way to change this? I only ask because, all the other pages ive looked at it keeps telling me to use -join, to join them as strings which does the exact same thing. Is it not possible to output it as multiple rows for each user?
$GPMem = Get-ADGroupMember -Identity security.group | Select-Object -ExpandProperty Name
[array]$TPpl = $GPMem | Where-Object {$_ -like "T*"}
[array]$RPpl = $GPMem | Where-Object {$_ -like "r*"}
[array]$CPpl = $GPMem | Where-Object {$_ -like "c*"}
[pscustomobject]#{
TPeople = (#($TPpl) |Out-String).Trim()
TPCount = $TPpl.Count
RPeople = (#($RPpl) |Out-String).ToString()
RPCount = $TPpl.Count
CPeople = $CPpl
CPCount = $TPpl.Count
} | Export-Csv -Path C:\Users\abraham\Desktop\csv.csv -NoTypeInformation -Force
here is how to insert a ; OR newline into the values of a column ... [grin]
$ThingList = #('One Thing', 'Two Thing', 'Three Thing')
$ThingList -join '; '
'=' * 20
$ThingList -join [System.Environment]::NewLine
output ...
One Thing; Two Thing; Three Thing
====================
One Thing
Two Thing
Three Thing
create 3 more arrays for the count (each array will be exported to a column), then find the array with the most count and generate a psobject for each line.
[array]$TPpl = #("T1" ,"T2", "T3")
[array]$TPpl_count = #($TPpl.Count)
[array]$RPpl = #("R1" ,"R2", "R3", "R4")
[array]$RPpl_count = #($RPpl.Count)
[array]$CPpl = #("C1" ,"C2", "C3", "C4","C5")
[array]$CPpl_count = #($CPpl.Count)
$leng = [array]$TPpl.Count,$RPpl.Count,$CPpl.Count
$max = ($leng | measure -Maximum).Maximum
$csv = for($i=0;$i -lt $max;$i++){
New-Object -TypeName psobject -Property #{
"TPeople" = $(if ($TPpl[$i]) { $TPpl[$i]})
"TPCount" = $(if ($TPpl_count[$i]) { $TPpl_count[$i]})
"RPeople" = $(if ($RPpl[$i]) { $RPpl[$i]})
"RPCount" = $(if ($RPpl_count[$i]) { $RPpl_count[$i]})
"CPeople" = $(if ($CPpl[$i]) { $CPpl[$i]})
"CPCount" = $(if ($CPpl_count[$i]) { $CPpl_count[$i]})
}
}
$csv | Export-Csv C:\Temp\test.csv -NoTypeInformation
result:
your final code should be:
$GPMem = Get-ADGroupMember -Identity security.group | Select-Object -ExpandProperty Name
[array]$TPpl = $GPMem | Where-Object {$_ -like "T*"}
[array]$RPpl = $GPMem | Where-Object {$_ -like "r*"}
[array]$CPpl = $GPMem | Where-Object {$_ -like "c*"}
[array]$TPpl_count = #($TPpl.Count)
[array]$RPpl_count = #($RPpl.Count)
[array]$CPpl_count = #($CPpl.Count)
$leng = [array]$TPpl.Count,$RPpl.Count,$CPpl.Count
$max = ($leng | measure -Maximum).Maximum
$csv = for($i=0;$i -lt $max;$i++){
New-Object -TypeName psobject -Property #{
"TPeople" = $(if ($TPpl[$i]) { $TPpl[$i]})
"TPCount" = $(if ($TPpl_count[$i]) { $TPpl_count[$i]})
"RPeople" = $(if ($RPpl[$i]) { $RPpl[$i]})
"RPCount" = $(if ($RPpl_count[$i]) { $RPpl_count[$i]})
"CPeople" = $(if ($CPpl[$i]) { $CPpl[$i]})
"CPCount" = $(if ($CPpl_count[$i]) { $CPpl_count[$i]})
}
}
$csv | Export-Csv C:\Temp\test.csv -NoTypeInformation

Find users with a certain parameter, display the groups they belong to and count how many

I am trying to get a number of how many people with specific titles are in specific groups.
What my approach is:
I am looking for users with specific titles.
I am looping over those users and looking for their groups they are in
Then I am looping over each group and trying to add .csv entry when there is a new one for that specific title, if group is listed, I am trying to just increment the counter.
I think that my approach is slow - every time I export and import .csv file, but I am sure there is a way to work on a imported file.
Also I have strange error: when importing test.csv I have like 10 entries instead of one. How to fix that?
My code:
clear
$Roles = Get-Content 'C:\Users\DWodzinski-admin\Documents\Titles.txt'
$Users = #()
Foreach ($Item in $Roles){
$Users += Get-ADUser -Filter {title -like $Item} -properties title, SamAccountName | Select SamAccountName, title
}
Foreach ($User in $Users){
$AdGroups = Get-ADPrincipalGroupMembership $User.SamAccountName | Select Name
foreach ($thing in $AdGroups) {
$name = $thing.name
$csv = Import-Csv "C:\Users\DWodzinski-admin\Documents\test.csv"
foreach($i in $csv){
if($i.Group -eq $name -and $i.Title -eq $User.title) {
$i.Count += 1
Export-CSV "C:\Users\DWodzinski-admin\Documents\test.csv" -NoTypeInformation
} else {
$NewCsvEntry = #{
Title = $User.title
Group = $name
Count = 0
}
[PSCustomObject]$NewCsvEntry | Export-CSV "C:\Users\DWodzinski-admin\Documents\test.csv" -NoTypeInformation -Append
}
$i
}
}
$csv | Export-CSV "C:\Users\DWodzinski-admin\Documents\test.csv" -NoTypeInformation -Append
}
i changed it so that it only imports your csv once, at the start, and exports (overwrites) it at the end. maybe it also fixes your issue with the 10 entries, try it out.
clear
$csv = Import-Csv "C:\Users\DWodzinski-admin\Documents\test.csv"
$Roles = Get-Content 'C:\Users\DWodzinski-admin\Documents\Titles.txt'
$Users = #()
Foreach ($Item in $Roles) {
$Users += Get-ADUser -Filter { title -like $Item } -properties title, SamAccountName | Select SamAccountName, title
}
Foreach ($User in $Users) {
$AdGroups = Get-ADPrincipalGroupMembership $User.SamAccountName | Select Name
foreach ($thing in $AdGroups) {
$name = $thing.name
foreach ($i in $csv) {
if ($i.Group -eq $name -and $i.Title -eq $User.title) {
$i.Count += 1
}
else {
$newCsvEntry = [PSCustomObject]#{
Title = $User.title
Group = $name
Count = 0
}
$csv += $newCsvEntry
}
$i
}
}
}
$csv | Export-CSV "C:\Users\DWodzinski-admin\Documents\test.csv" -NoTypeInformation -Force
If anyone want to know how I did it, I created ArrayList with CustomObjects:
clear
$Roles = Get-Content 'C:\Users\DWodzinski-admin\Documents\Titles.txt'
$Users = #()
$List = New-Object System.Collections.ArrayList
$Object = [PSCustomObject]#{
Name = 'Pierwszy';
Title = 'Czarny';
Count = 0;
}
$List.add($Object)
Foreach ($Item in $Roles){
$Users += Get-ADUser -Filter {title -like $Item} -properties title, SamAccountName | Select SamAccountName, title
}
Foreach ($User in $Users){
$AdGroups = Get-ADPrincipalGroupMembership $User.SamAccountName | Select Name
foreach($Group in $AdGroups){
if($List | Where Name -eq $Group.name | Where Title -eq $User.title){
$temp = $List | Where Name -eq $Group.name | Where Title -eq $User.title
$temp.Count += 1
} else {
$Object = [PSCustomObject]#{
Name = $Group.Name;
Title = $User.title;
Count = 1;
}
$List.add($Object)
}
}
}
$FilePathLocation = "C:\Users\DWodzinski-admin\Documents\test.csv"
$List | Export-Csv -Path $FilePathLocation -NoTypeInformation

PowerShell: Get all groups a member belongs to, include group type

I have a script that gives me all members of a group with certain desired information. I want this same format but for all groups that a specified username belongs to. I want information about each group, such as group type (ie security, distribution list). How would I do this? I want a different row for each group, with information about each group in the columns.
Add-PSSnapin Quest.ActiveRoles.ADManagement
$myCol = #()
ForEach ($Group in (Get-QADGroup "CN=research,OU=Security,OU=Groups,DC=xxx,DC=com" -GroupType Security))
{
ForEach ($Member in (Get-QADGroupMember $Group -SizeLimit 0))
{
$myObj = "" | Select Group, Type, Member, Email, Username, Department
$myObj.Group = $Group.Name
$myObj.Type = $Group.groupType
$myObj.Member = $Member.Name
$myObj.Email = $Member.Email
$myObj.Department = $Member.Department
$myObj.Username = $Member.sAMAccountName
$myCol += $myObj
}
}
$myCol | Export-Csv -Path "C:\Users\sdevito\Desktop\test.csv" -NoTypeInformation
or. there is this code that i found that does something similar, but each group is in the same row, different column. i cannot figure out how to edit this code to make each group on a new row.
$alist = "Name`tAccountName`tDescription`tEmailAddress`tLastLogonDate`tManager`tTitle`tDepartment`tCompany`twhenCreated`tAcctEnabled`tGroups`n"
$userlist = Get-ADUser sdevito -Properties * | Select-Object -Property Name,SamAccountName,Description,EmailAddress,LastLogonDate,Manager,Title,Department,Company,whenCreated,Enabled,MemberOf | Sort-Object -Property Name
$userlist | ForEach-Object {
$grps = $_.MemberOf | Get-ADGroup | ForEach-Object {$_.Name} | Sort-Object
$arec = $_.Name,$_.SamAccountName,$_.Description,$_.EmailAddress,$_LastLogonDate,$_.Manager,$_.Title,$_.Department,$_.Company,$_.whenCreated,$_.Enabled
$aline = ($arec -join "`t") + "`t" + ($grps -join "`t") + "`n"
$alist += $aline
}
$alist | Out-File C:\Users\sdevito\Desktop\testt.csv
How about something like:
#Requires -Version 3.0
Add-PSSnapin Quest.ActiveRoles.ADManagement
function Get-UsersGroups {
[cmdletbinding()]
param (
[Parameter(Position=0,Mandatory)][string]$Identity,
[Parameter(Position=1)][ValidateSet('all','nested','normal')][string]$MemberType
)
$user = Get-QADUser -Identity $Identity
switch ( $MemberType ) {
'all' { $groups = $user.AllMemberOf }
'nested' { $groups = $user.NestedMemberOf }
default { $groups = $user.MemberOf }
}
foreach ( $group in $groups ) {
$groupinfo = Get-QADGroup -Identity $group
$props = [ordered]#{
Group = $groupinfo.Name
Type = $groupinfo.GroupType
Member = $user.Name
Email = $user.Email
Department = $user.Department
Username = $user.sAMAccountName
}
$obj = New-Object -TypeName PSObject -Property $props
$obj
}
}
Get-UsersGroups -Identity bob | Export-Csv -Path "C:\Users\sdevito\Desktop\test.csv" -NoTypeInformation