Value not storing on a variable - powershell

I am trying to store the value of a function value with add-member on it on my $GroupStorage variable but it does not store on the variable? Anyone knows how to do it? My goal is to add it force to my $storageHolder
$NestedGroupUsers = Get-ADUsers_cachedV2 -GroupName $nestedmember.distinguishedName
$GroupStorage = $NestedGroupUsers | Add-Member -NotePropertyName MainParentGroup -NotePropertyValue $ADgroupname.name -Force
$resultHOlder += $GroupStorage
==============================================================================================
This is my whole code. This code is Getting all the users from nested Group.
function Get-CachedADUSER($AduserCached) {
# $AduserCached = $resultHOlder
$cachedResults = Get-Variable -Scope Global -Name $AduserCached -ErrorAction SilentlyContinue
if ($null -ne $cachedResults) {
$existing = write-host "Check: i found existing"
return $cachedResults.value , $existing
}
else {
$searching = write-host "Check: Searching"
$results = get-aduser $AduserCached -properties * #enabled, displayname, EmployeeNumber, LastLogonDate, PasswordLastSet
Set-CachedADUSER -setAduserCached $AduserCached -value $results
return $results.value , $searching
}
}
Function Set-CachedADUSER($setAduserCached, $value) {
Set-Variable -Scope Global -Name $setAduserCached -Value $value
return $value
}
function Get-ADUsers_cachedV2 {
param (
[Parameter(ValuefromPipeline = $true, mandatory = $true)][String] $GroupName
)
[int]$circular = $null
# result holder
$resultHolder = #()
$table = $null
$nestedmembers = $null
$adgroupname = $null
$GroupStorage = #()
$NestedGroupUsers = #()
# get members of the group and member of
$ADGroupname = get-adgroup $groupname -properties memberof, members
# $ADGroupname = Get-CachedGroupMembership -GroupName $groupName -properties memberof, members
# list all members as list (no headers) and save to var
$memberof = $adgroupname | select -expand memberof
if ($adgroupname) {
if ($circular) {
$nestedMembers = Get-ADGroupMember -Identity $GroupName -recursive
$circular = $null
}
else {
$nestedMembers = Get-ADGroupMember -Identity $GroupName | sort objectclass -Descending
# if get adgroupmember returns nothing, it uses the members for ordinary getADGroup
if (!($nestedmembers)) {
$unknown = $ADGroupname | select -expand members
if ($unknown) {
$nestedmembers = #()
foreach ($member in $unknown) {
$nestedmembers += get-adobject $member #-ErrorAction SilentlyContinue
}
}
}
}
# loops through each member
ForEach ($nestedmember in $nestedmembers) {
# creates the properties into a custom object.
$Props = #{
Type = $nestedmember.objectclass;
Name = $nestedmember.name;
DisplayName = "";
ParentGroup = $ADgroupname.name;
Enabled = "";
EmployeeNumber = "";
LastLogonDate = "";
PasswordLastSet = "";
}
# if member object is a user
if ($nestedmember.objectclass -eq "user") {
# saves all the properties in the table.
$nestedADMember = Get-CachedADUSER -AduserCached $nestedmember.Name -properties * #enabled, displayname, EmployeeNumber, LastLogonDate, PasswordLastSet
$table = new-object psobject -property $props
$table.enabled = $nestedadmember.enabled
$table.name = $nestedadmember.samaccountname
$table.displayname = $nestedadmember.displayname
$table.EmployeeNumber = $nestedadmember.EmployeeNumber
$table.LastLogonDate = $nestedadmember.LastLogonDate
$table.PasswordLastSet = $nestedadmember.passwordLastSet
#save all in 1 storage
$resultHOlder += $table #| select type, name, displayname, parentgroup, enabled, EmployeeNumber, LastLogonDate, PasswordLastSet
}
# if member object is group
elseif ($nestedmember.objectclass -eq "group") {
$table = new-object psobject -Property $props
# if circular, meaning the groups member of list contains one of its members.
# e.g. if group 2 is a member of group 1 and group 1 is a member of grou 2
if ($memberof -contains $nestedmember.distinguishedname) {
$table.comment = "Circular membership"
$circular = 1
}
$NestedGroupUsers = Get-ADUsers_cachedV2 -GroupName $nestedmember.distinguishedName
$GroupStorage = $NestedGroupUsers | Add-Member -NotePropertyName MainParentGroup -NotePropertyValue $ADgroupname.name -Force
$resultHOlder += $NestedGroupUsers
}
else {
if ($nestedmember) {
$table = new-object psobject -property $props
$resultHolder += $table #| select type, name, displayname, parentgroup, enabled, EmployeeNumber, LastLogonDate, PasswordLastSet
}
}
}
}
return $resultHOlder
}
function Get-NestedGroupUsers_cachedV2 {
param (
[Parameter(Mandatory = $true)][String]$FileName,
[Parameter(Mandatory = $true)][String]$searchFilePath
)
$storageHolder = #()
$groupList = Get-Content $searchFilePath
$groupList | ForEach-Object {
$allusers = Get-ADUsers_cachedV2 -GroupName $_
$storageHolder += $allusers
}
$storageHolder | Export-Csv -Path "C:\Users\***\***\$FileName.csv" -NoTypeInformation #-Force
}

Likely your $GroupStorage variable is coming out empty?
Add -PassThru to the Add-Member command which will send the modified object down the pipe to $GroupStorage. Add-Member does not return any objects without that switch.
$GroupStorage = $NestedGroupUsers | Add-Member -NotePropertyName MainParentGroup -NotePropertyValue $ADgroupname.name -PassThru

Related

Remove duplicate items in object but not all of it

How can I remove duplicates before exporting to a csv?
foreach ($group in $ADGroups) {
$ADResult += [PSCustomObject]#{
ADGroup = $group.name
ADuser = $user.name
}
#Remove-ADGroupMember -Identity $Group.DistinguishedName -Members $UserInfo.DistinguishedName -Confirm:$false
$group = $null
}
In the above bit of code the result comes out like
aduser | adgroup
x | a
x | s
x | v
The aduser is the same for each group. How can I post the user once
so it comes out like the following without the duplicate user?
aduser | adgroup
x | a
| s
| v
This will create the output as you requested. You'll lose the ability to sort and filter if you plan to work with the output data in Excel but it's your choice.
#Users Group Membership
$ADGroups = Get-ADGroup -Filter *
$groupMembership = foreach ($group in $ADGroups) {
$members = Get-ADGroupMember -Identity $group | Where-Object { $_.objectClass -eq 'user' }
foreach ($member in $members) {
[PSCustomObject]#{
ADuser = $member.name
ADGroup = $group.name
}
}
}
#Get Unique Users
$usersUnique = $groupMembership | Select-Object -Property ADuser -Unique | Sort-Object -Property ADuser
#Loop each Unique user and add a new NoteProperty ADuser2. This will be populated with ADuser if its the first occurrence, else blank.
$results = foreach ($user in $usersUnique) {
$firstOccurrence = $true
$userMembership = $groupMembership | Where-Object { $_.ADuser -eq $user.ADuser } | Sort-Object -Property ADGroup
foreach ($membership in $userMembership) {
if ($firstOccurrence) {
$membership | Add-Member -MemberType NoteProperty -Name ADuser2 -Value $user.ADuser -PassThru
$firstOccurrence = $false
}
else {
$membership | Add-Member -MemberType NoteProperty -Name ADuser2 -Value "" -PassThru
}
}
}
#Export to CSV
$results | Sort-Object -Property ADuser, ADGroup | Select-Object ADuser2, ADGroup | Export-Csv -Path C:\support\user-group_membership_report.csv -NoTypeInformation
I would go with something like this:
$i = 0
foreach ($group in $ADGroups) {
if($i -eq 0){
$ADResult += [PSCustomObject]#{
ADGroup = $group.name
ADuser = $user.name
}
$i = 1
}
else {
$ADResult += [PSCustomObject]#{
ADGroup = $group.name
ADuser = ""
}
}
}

I want to implement a cache storage on my powershell for quicker runtime on next run

I am a powershell beginner and self learner. I finally made my script to get AD Users from NestedGroup. I now want to make a cache for them to make a quicker result when I run the script on the second time. I am totally lost on what I am doing and I want to ask for some approach from professionals here. Thank you for guidance.
Here is my code.
function Get-CachedGroupMembership($groupname){
$groupName = "cached_$($groupName)"
$cachedResults = Get-Variable -Scope Global -Name $groupName -ErrorAction SilentlyContinue
if($null -ne $cachedResults){
"found cached result"
$existing = write-host "Check: i found existing"
return $cachedResults, $existing
}
else{
$searching = write-host "Check: Searching"
$results = get-adgroup $groupname -properties memberof, members
Set-CachedGroupMembership -groupName $groupName -value $results
return $searching
}
}
Function Set-CachedGroupMembership($groupName,$value){
Set-Variable -Scope Global -Name $groupName -Value $value
return $value
}
function Get-ADUsers_cached {
param (
[Parameter(ValuefromPipeline = $true, mandatory = $true)][String] $GroupName
)
[int]$circular = $null
# result holder
$resultHolder = #()
$table = $null
$nestedmembers = $null
$adgroupname = $null
# get members of the group and member of
# $ADGroupname = get-adgroup $groupname -properties memberof, members
$ADGroupname = Get-CachedGroupMembership -GroupName $groupName
# list all members as list (no headers) and save to var
$memberof = $adgroupname | select -expand memberof
if ($adgroupname) {
if ($circular) {
$nestedMembers = Get-ADGroupMember -Identity $GroupName -recursive
$circular = $null
}
else {
$nestedMembers = Get-ADGroupMember -Identity $GroupName | sort objectclass -Descending
# if get adgroupmember returns nothing, it uses the members for ordinary getADGroup
if (!($nestedmembers)) {
$unknown = $ADGroupname |select -expand members
if ($unknown) {
$nestedmembers = #()
foreach ($member in $unknown) {
$nestedmembers += get-adobject $member
}
}
}
}
# loops through each member
ForEach($nestedmember in $nestedmembers){
# creates the properties into a custom object.
$Props = #{
Type = $nestedmember.objectclass;
Name = $nestedmember.name;
DisplayName = "";
ParentGroup = $ADgroupname.name;
Enabled = "";
Nesting = $nesting;
DN = $nestedmember.distinguishedname;
Comment = ""
EmployeeNumber = "";
LastLogonDate = "";
PasswordLastSet = "";
}
# if member object is a user
if ($nestedmember.objectclass -eq "user") {
# saves all the properties in the table.
$nestedADMember = get-aduser $nestedmember.Name -properties enabled, displayname, EmployeeNumber, LastLogonDate, PasswordLastSet
$table = new-object psobject -property $props
$table.enabled = $nestedadmember.enabled
$table.name = $nestedadmember.samaccountname
$table.displayname = $nestedadmember.displayname
$table.EmployeeNumber = $nestedadmember.EmployeeNumber
$table.LastLogonDate = $nestedadmember.LastLogonDate
$table.PasswordLastSet = $nestedadmember.PasswordLastSet
#save all in 1 storage
$resultHOlder += $table | select type, name, displayname, parentgroup, nesting, enabled, dn, comment , EmployeeNumber, LastLogonDate, PasswordLastSet
}
# if member object is group
elseif ($nestedmember.objectclass -eq "group") {
$table = new-object psobject -Property $props
# if circular, meaning the groups member of list contains one of its members.
# e.g. if group 2 is a member of group 1 and group 1 is a member of grou 2
if ($memberof -contains $nestedmember.distinguishedname) {
$table.comment = "Circular membership"
$circular = 1
}
# for circular output
#$table | select type, name, displayname, parentgroup, nesting, enabled, dn, comment
#calling function itself
$resultHOlder += Get-ADUsers_cached -GroupName $nestedmember.distinguishedName
}
else {
if ($nestedmember) {
$table = new-object psobject -property $props
$resultHolder += $table | select type, name, displayname, parentgroup, nesting, enabled, dn, comment, EmployeeNumber, LastLogonDate, PasswordLastSet
}
}
}
}
return $resultHOlder
}
function Get-NestedGroupUsers_cached {
param (
[Parameter(Mandatory = $true)][String]$FileName,
[Parameter(Mandatory = $true)][String]$searchFileURL
)
$storageHolder = #()
$groupList = Get-Content $searchFileURL
$groupList | ForEach-Object {
$allusers = Get-ADUsers_cached -GroupName $_
$storageHolder += $allusers
}
$storageHolder | select ParentGroup, Name, EmployeeNumber, Enabled, LastLogonDate, PasswordLastSet |Export-Csv -Path "C:\Users\***\Desktop\$FileName.csv" -NoTypeInformation -Force
}
You can make use of a global or module scoped variable to store the info. Then, check for the presence of the variable on second execution and pull from that, if present.
For instance, your query of AD Groups would be a good one to cache.
I would make two functions to make this easier:
function Get-CachedGroupMembership($groupname){
$groupName = "cached_$($groupName)"
$cachedResults = Get-Variable -Scope Global -Name $groupName -ErrorAction SilentlyContinue
if($null -ne $cachedResults){
"found cached result"
return $cachedResults
}
else{
"need to cache"
$results = get-adgroup $groupname -properties memberof, members
Set-CachedGroupMembership -groupName $groupName -value $results
}
}
Then to cache the results, I'd use this function too.
Function Set-CachedGroupMembership($groupName,$value){
Set-Variable -Scope Global -Name $groupName -Value $value
return $value
}
Finally, replace the call to $ADGroupname = get-adgroup $groupname -properties memberof, members with a call to Get-CachedGroupMembership -GroupName $groupName.
If you really want to persist the cache, you could even write results out to JSON and modify these functions to retrieve them, but then you could have an issue with stale results. So, you should always leave a way to force an update to the cache, for instance you could modify these functions to add a -Force switch to update your cached value.
With a little copy and paste, you could modify these functions into Get-CachedADUser as well, and have your entire script caching results.

What is the best way to make this script run in parallel for faster execution?

This code is to get all users from nested groups. I want it to run in a parallel for faster running time. What would be the best approach for this? I tried to do parallel on my foreach on my last function to run the whole code but I cant call the function inside the parallel. Thanks in advance for anyone who already encountered this logic.
function Get-CachedADUSER($AduserCached){
# $AduserCached = $resultHOlder
$cachedResults = Get-Variable -Scope Global -Name $AduserCached -ErrorAction SilentlyContinue
if($null -ne $cachedResults){
$existing = write-host "Check: i found existing"
return $cachedResults.value , $existing
}
else{
$searching = write-host "Check: Searching"
$results = get-aduser $AduserCached -properties enabled, displayname, EmployeeNumber, LastLogonDate, PasswordLastSet
Set-CachedADUSER -setAduserCached $AduserCached -value $results
return $results.value , $searching
}
}
Function Set-CachedADUSER($setAduserCached,$value){
Set-Variable -Scope Global -Name $setAduserCached -Value $value
return $value
}
function Get-ADUsers_cachedV2 {
param (
[Parameter(ValuefromPipeline = $true, mandatory = $true)][String] $GroupName
)
[int]$circular = $null
# result holder
$resultHolder = #()
$table = $null
$nestedmembers = $null
$adgroupname = $null
# get members of the group and member of
$ADGroupname = get-adgroup $groupname -properties memberof, members
# $ADGroupname = Get-CachedGroupMembership -GroupName $groupName -properties memberof, members
# list all members as list (no headers) and save to var
$memberof = $adgroupname | select -expand memberof
if ($adgroupname) {
if ($circular) {
$nestedMembers = Get-ADGroupMember -Identity $GroupName -recursive
$circular = $null
}
else {
$nestedMembers = Get-ADGroupMember -Identity $GroupName | sort objectclass -Descending
# if get adgroupmember returns nothing, it uses the members for ordinary getADGroup
if (!($nestedmembers)) {
$unknown = $ADGroupname |select -expand members
if ($unknown) {
$nestedmembers = #()
foreach ($member in $unknown) {
$nestedmembers += get-adobject $member #-ErrorAction SilentlyContinue
}
}
}
}
# loops through each member
ForEach($nestedmember in $nestedmembers){
# creates the properties into a custom object.
$Props = #{
Type = $nestedmember.objectclass;
Name = $nestedmember.name;
DisplayName = "";
ParentGroup = $ADgroupname.name;
# ParentGroup = $ADgroupname.name;
Enabled = "";
# Nesting = $nesting;
# DN = $nestedmember.distinguishedname;
# Comment = ""
EmployeeNumber = "";
LastLogonDate = "";
PasswordLastSet = "";
}
# if member object is a user
if ($nestedmember.objectclass -eq "user") {
# saves all the properties in the table.
$nestedADMember = Get-CachedADUSER -AduserCached $nestedmember.Name -properties enabled, displayname, EmployeeNumber, LastLogonDate, PasswordLastSet
$table = new-object psobject -property $props
$table.enabled = $nestedadmember.enabled
$table.name = $nestedadmember.samaccountname
$table.displayname = $nestedadmember.displayname
$table.EmployeeNumber = $nestedadmember.EmployeeNumber
$table.LastLogonDate = $nestedadmember.LastLogonDate
$table.PasswordLastSet = $nestedadmember.PasswordLastSet
#save all in 1 storage
$resultHOlder += $table | select type, name, displayname, parentgroup, enabled, EmployeeNumber, LastLogonDate, PasswordLastSet
}
# if member object is group
elseif ($nestedmember.objectclass -eq "group") {
$table = new-object psobject -Property $props
# if circular, meaning the groups member of list contains one of its members.
# e.g. if group 2 is a member of group 1 and group 1 is a member of grou 2
if ($memberof -contains $nestedmember.distinguishedname) {
$table.comment = "Circular membership"
$circular = 1
}
# for circular output
#$table | select type, name, displayname, parentgroup, nesting, enabled, dn, comment
#calling function itself
$resultHOlder += Get-ADUsers_cachedV2 -GroupName $nestedmember.distinguishedName
}
else {
if ($nestedmember) {
$table = new-object psobject -property $props
$resultHolder += $table | select type, name, displayname, parentgroup, enabled, EmployeeNumber, LastLogonDate, PasswordLastSet
}
}
}
}
return $resultHOlder
}
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
This is what I want to make parallel for faster execution
function Get-NestedGroupUsers_cachedV2 {
param (
[Parameter(Mandatory = $true)][String]$FileName,
[Parameter(Mandatory = $true)][String]$searchFilePath
)
$storageHolder = #()
$groupList = Get-Content $searchFilePath
$groupList | ForEach-Object {
$allusers = Get-ADUsers_cachedV2 -GroupName $_
$storageHolder += $allusers
}
$storageHolder | select ParentGroup, Name, EmployeeNumber, Enabled, LastLogonDate, PasswordLastSet |Export-Csv -Path "C:\Users\***\****\$FileName.csv" -NoTypeInformation #-Force
}

How to use <New-Object -TypeName psobject -Property> to gather info on 2 foreach

I need to aggregate the results of 2 foreach so I can run a nice report - this is the script:
$users = Get-ADGroupMember -Identity 'TESTGRoup'
$result1 = ForEach ($user in $users){
New-Object -TypeName psobject -Property #{
User = $user
CN = $User.SamAccountName
Domain = $user.name
Name = $user.SID
}
}
$Result4 = Get-ADGroupMember 'TESTGRoup' |
Where-Object {$_.objectClass -eq 'User'} |
Get-AdUser |
ForEach {
Get-MsolUser -UserPrincipalName $_.UserPrincipalName | Select UserprincipalName, Blockcredential
$result7 = New-Object -TypeName psobject -Property #{
User1 = $Result4.UserPrincipalName
CN1 = $Result4.BlockCredential
}
}
The end result is all the users joined up on a single line and not on a table.
Sorry for the code format - not sure how to present it better.
Thanks
If I understand your question correctly, the below code will generate objects with the aggregated data you need on a single object per user:
#requires -Version 3
$results = foreach ($user in Get-ADGroupMember -Identity 'TESTGRoup')
{
$user | ? objectClass -eq User | Get-ADUser | % {
$msol = Get-MsolUser -UserPrincipalName $PSItem.UserPrincipalName
[pscustomobject]#{
'User' = $user
'CN' = $user.SamAccountName
'Domain' = $user.Name
'Name' = $user.SID
'User1' = $msol.UserPrincipalName
'CN1' = $msol.BlockCredential
}
}
}

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