Results from Powershell to Comma Separated String - powershell

I have the below script that I run, how can I get the output to be placed into a comma separated string?
Get-ADGroup -filter * -properties GroupCategory | ft objectguid, samaccountname
Current Output
objectguid samaccountname
---------- --------------
f5b71a40-9405-4874-b9b0-b35e45346f63 WinRMRemoteWMIUsers__
95a99aa1-a771-4f86-bdce-7a6a3f00057a Administrators
6a6ad877-180c-462b-9672-bfba20200cda Users
038b03cf-1171-4546-b0af-a7654823e289 Guests
ed3995ae-6f77-492f-bcb5-bc197fa24996 Print Operators
b1f8301a-78e1-47ab-9e51-8e55525acadf Backup Operators
3d23c4c0-71d9-4e08-a8ee-a9692a6ed61f Replicator
d86e5619-5893-41b7-b3a8-eda4c2725562 Remote Desktop Users
473592e4-71c8-458f-b7fc-b474809933ff Network Configuration Operators
c433a049-f9e5-404a-9940-5cf1f8ce4d82 Performance Monitor Users
1ce2daf3-5d97-4493-9ec1-c84a49326113 Performance Log Users
24b06a4c-f32b-4081-a002-6f1851f98256 Distributed COM Users
Desired Output
f5b71a40-9405-4874-b9b0-b35e45346f63,WinRMRemoteWMIUsers__,95a99aa1-a771-4f86-bdce-7a6a3f00057a,Administrators,6a6ad877-180c-462b-9672-bfba20200cda,Users,038b03cf-1171-4546-b0af-a7654823e289,Guests,ed3995ae-6f77-492f-bcb5-bc197fa24996,Print Operators,b1f8301a-78e1-47ab-9e51-8e55525acadf,Backup Operators,3d23c4c0-71d9-4e08-a8ee-a9692a6ed61f,Replicator,d86e5619-5893-41b7-b3a8-eda4c2725562,Remote Desktop Users,473592e4-71c8-458f-b7fc-b474809933ff,Network Configuration Operators,c433a049-f9e5-404a-9940-5cf1f8ce4d82,Performance Monitor Users,1ce2daf3-5d97-4493-9ec1-c84a49326113,Performance Log Users,24b06a4c-f32b-4081-a002-6f1851f98256,Distributed COM Users
I am passing this into a string and parsing the data remotely using JavaScript.

That's fairly easy and consists of two steps: First separating the GUID and account name with a comma:
$items = Get-ADGroup -filter * -properties GroupCategory |
select objectguid,samaccountname
$combined = $items |
ForEach-Object { $_.objectguid + ',' + $_.samaccountname }
and then joining all those strings with a comma into a single string:
$result = $combined -join ','
We could also do it differently: First decompose the objects into simply two strings:
$separated = $items | % { $_.objectguid; $_.samaccountname }
and then joining all those with a comma:
$result = $separated -join ','
or take advantage of the $OFS variable which specifies with what separator arrays are converted to strings. Same start, we need a single array with everything that should be joined with a comma, and then we set the $OFS variable and convert the array to a string:
$OFS = ','
$result = [string] $separated

Related

Whitespace & $null variable handling in PowerShell?

I'm trying to create a script that will grab all users in an OU and change the current primary alias to a secondary alias while adding a new primary smtp address and retaining any other secondary aliases. We have users with 0 aliases, some with 1, some with 2, and some with 3. I am running into an issue when any one of the $sp1, $sp2, $sp3, $sp4, $sp5 are either white space or null. I'm still learning powershell so I'm not sure how to handle that without a lot of pain lol.
$Users = Get-AdUser -Filter * -SearchBase "OU=TestScriptedSMTPAddrChange,OU=***,DC=***,DC=com" -Properties proxyAddresses | Select-Object SamAccountName, proxyAddresses #Change first OU= to the OU you want to change
Foreach ($SAN in $Users){
$SecondaryProxyRaw = $SAN.proxyAddresses #grab proxyAddresses and dump them
$SecondaryProxyRed = $SecondaryProxyRaw.replace('SMTP','smtp') #change primary SMTP addr to secondary smtp addr
$sp1,$sp2,$sp3,$sp4,$sp5 = $SecondaryProxyRed.split(" ",1) #split the proxyAddresses array into variables
$NewPrimaryProxy = "SMTP:$($SAN.SamAccountName)#newdomain.com"} #assign new primary SMTP address
Set-ADUser -Identity $SAN.SamAccountName -replace #{proxyAddresses = "$NewPrimaryProxy","$sp1","$sp2","$sp3","$sp4","$sp5"}
}
Get-AdUser -Filter * -SearchBase "OU=TestScriptedSMTPAddrChange,OU=***,DC=***,DC=com" -Properties proxyAddresses | Select-Object SamAccountName, UserPrincipalName, #{Name="Proxyaddresses";Expression={$_.proxyAddresses -join "*"}}
You should not rely on a user having 1, 3 or perhaps 77 addresses in its proxyAddresses attribute by trying to split these into a fixed number of variables.
Just get them all, replace the uppercase SMTP: into lowercase 'smtp:', filter out the possible one that would be equal to the new proxy address and add the new primary address to the array.
Then, replace the entire proxyAddresses array with the strongly typed (i.e. cast to string[]]) new array.
$Users = Get-AdUser -Filter * -SearchBase "OU=TestScriptedSMTPAddrChange,OU=***,DC=***,DC=com" -Properties proxyAddresses
foreach ($SAN in $Users) {
$NewPrimaryProxy = 'SMTP:{0}#newdomain.com' -f $SAN.SamAccountName
# if you like you can sort the proxies but for the system this will have no effect
$proxies = #($SAN.ProxyAddresses -replace '^SMTP:', 'smtp:' | Where-Object { $_ -ne $NewPrimaryProxy }) + $NewPrimaryProxy
# Note: proxyAddresses needs a Strongly typed string array, that is why we cast $proxies array with [string[]]
$SAN | Set-ADUser -Replace #{proxyAddresses = [string[]]$proxies}
}
.split(" ",1)
doesn't split at all - by definition it returns the input string as-is, because you're asking for 1 token only - see the docs for the .NET [string] type's .Split() method.
To split by runs of whitespace, you can use the unary form of PowerShell's -split operator:
# Split by whitespace and collect tokens in an array.
# -ne '' filters out empty elements, so that if
# $SecondaryProxyRed is effectively empty, $sps becomes an empty array.
$sps = -split $SecondaryProxyRed -ne ''
You can then create an array with $NewPrimaryProxy as the first element, followed by the elements of $sps, if any:
Set-ADUser -Identity $SAN.SamAccountName -replace #{
proxyAddresses = #($NewPrimaryProxy) + $sps
}

Powershell - How to remove trailing spaces from a list of groups a user is in

I've copied/created a script to get all the members of a group that a user is part of, including nested groups. However, my output isn't quite the way I want it.
It goes in one of two ways. Either it outputs as one big string, which looks nice, but has trailing spaces on each line so I cannot simply copy and paste it into AD. Or if I change the Out-String to use -stream, it comes out as a garbled mess, but may allow me to trim the spaces.
I currently have the output going into a TextBox in a simple GUI.
Function Get-ADUserNestedGroups {
Param
(
[string]$DistinguishedName,
[array]$Groups = #()
)
#Get the AD object, and get group membership.
$ADObject = Get-ADObject -Filter "DistinguishedName -eq '$DistinguishedName'" -Properties memberOf, DistinguishedName;
#If object exists.
If($ADObject)
{
#Enummurate through each of the groups.
Foreach($GroupDistinguishedName in $ADObject.memberOf)
{
#Get member of groups from the enummerated group.
$CurrentGroup = Get-ADObject -Filter "DistinguishedName -eq '$GroupDistinguishedName'" -Properties memberOf, DistinguishedName;
#Check if the group is already in the array.
If(($Groups | Where-Object {$_.DistinguishedName -eq $GroupDistinguishedName}).Count -eq 0)
{
#Add group to array.
$Groups += $CurrentGroup;
#Get recursive groups.
$Groups = Get-ADUserNestedGroups -DistinguishedName $GroupDistinguishedName -Groups $Groups;
}
}
}
#Return groups.
Return $Groups;
}
Function Display-UserGroups {
#Get all groups.
$Groups = Get-ADUserNestedGroups -DistinguishedName (Get-ADUser -Identity $userSAM).DistinguishedName;
$ResultsTextBox.Text = $Groups | Select-Object Name| Sort-Object name | Out-String
The output with the first way looks like:
Group Name1(Eight Spaces Here)
Group Name2(Eight Spaces Here)
The output with the second way looks like:
Group Name1GroupName2GroupName3
Thanks for your help!
You need to trim your output, which can easily be done with String.Trim method. However, it can only be applied against strings. $Groups will be an array of ADObject types. You will need to return the Name values of those objects and apply the Trim() method to the values.
($Groups | Select -Expand Name | Sort).Trim() -join "`r`n"
You can use $Groups += $CurrentGroup.trimEnd() to add the value with the trailing spaces trimmed.
A few other methods you might want to research
.trim() # Trim leading and trailing
.trimEnd() # Trim trailing
.trimStart() # Trim leading
The padding is being caused by PowerShell's formatting system. Select-Object is returning single property (Name) objects. PowerShell outputs that as a table, which may have some padding. Out-String is keeping that padding which is why it was reflecting in your final output...
The name property of the group is already a string. There's no need to use Out-String if you unroll the Name property from your $Groups variable/collection.
With some other adjustments for readability & testing. Below will emit a single string with each group on a new line. That should be paste-able into AD, by which I think you meant Active Directory User & Computers.
Function Get-ADUserNestedGroups
{
Param
(
[string]$DistinguishedName,
[array]$Groups = #()
)
# Get the AD object, and get group membership.
$ADObject = Get-ADObject $DistinguishedName -Properties memberOf, DistinguishedName
# If object exists.
If( $ADObject )
{
# Enummurate through each of the groups.
Foreach( $GroupDistinguishedName in $ADObject.memberOf )
{
# Get member of groups from the enummerated group.
$CurrentGroup = Get-ADObject $GroupDistinguishedName -Properties memberOf, DistinguishedName
# Check if the group is already in the array.
If( $Groups.DistinguishedName -notcontains $GroupDistinguishedName )
{
# Add group to array.
$Groups += $CurrentGroup
# Get recursive groups.
$Groups = Get-ADUserNestedGroups -DistinguishedName $GroupDistinguishedName -Groups $Groups
}
}
}
# Return groups.
Return $Groups
}
$userSAM = 'UserName'
# Get all groups.
$Groups = Get-ADUserNestedGroups -DistinguishedName (Get-ADUser -Identity $userSAM).DistinguishedName
($Groups.Name | Sort-Object) -join [System.Environment]::NewLine
Among the secondary changes you'll see I removed the -Filter parameter in a few places. The DistinguishedName can be used as the -Identity parameter so no need to filter.
Also, where you were checking if the $Groups collection already had the current group I used the -notContains operator instead. That should be faster then repeatedly iterating the collection with |Where{...} The code is also shorter and more readable.
Note: if we reverse the operands we could use -notin which may look
nicer still
An aside; You should avoid appending arrays with +=. Doing so can causes performance problems because it creates a new array any copies the contents over. The best way to deal with this is to allow PowerShell to accumulate the results for you. If you must do the append directly, look into using Array Lists. There's a lot information on this, just google it.

Multiple rows in a grid [duplicate]

This question already has answers here:
Export hashtable to CSV with the key as the column heading
(2 answers)
Closed 4 years ago.
I'm trying to list all ad group memberships of specific users. The input would be a string of logins split with a comma 'login1,login2'.
So I go over each user and list their memberships with the username as title. Somehow it only shows the first entry. Also it shows the user groups in one row and I don't know how to change that.
Code below:
$users = $logon -split ','
$q = #()
foreach ($user in $users) {
$usernm = Get-ADUser -Filter 'samAccountName -like $user' | select Name
$useraccess = Get-ADPrincipalGroupMembership $user | Select-Object Name
$userobj = New-Object PSObject
$userobj | Add-Member Noteproperty $usernm.Name $useraccess.Name
$q += $userobj
}
Expected output would be something like:
fullnameuser1 fullnameuser2 list of users goes on...
------------- ------------- ------------------------
adgroup1 adgroup3 ...
adgroup2 adgroup4
... ...
In principle this would also mean that if i typed $q.'fullnameuser1' output would be:
fullnameuser1
-------------
adgroup1
adgroup2
...
Whenever the code is ran, it will only ever add the first user's access, also returning all groups on one row. So somehow I need to go over all the group memberships and add a row for each one.
First and foremost, PowerShell does not expand variables in single-quoted strings. Because of that Get-ADUser will never find a match unless you have a user with the literal account name $user. Also, using the -like operator without wildcards produces the same results as the -eq operator. If you're looking for an exact match use the latter. You probably also need to add nested quotes.
Get-ADUser -Filter "samAccountName -eq '${user}'"
Correction: Get-ADUser seems to resolve variables in filter strings by itself. I verified and the statement
Get-ADUser -Filter 'samAccountName -eq $user'
does indeed return the user object for $user despite the string being in single quotes.
If you want a fuzzy match it's better to use ambiguous name resolution.
Get-ADUser -LDAPFilter "(anr=${user})"
You may also want to avoid appending to an array in a loop, and adding members to custom objects after creation. Both are slow operations. Collect the loop output in a variable, and specify the object properties directly upon object creation.
$q = foreach ($user in $users) {
...
New-Object -Type PSObject -Property {
$usernm.Name = $useraccess.Name
}
}
Lastly, I'd consider using the user's name as the property name bad design. That would be okay if you were building a hashtable (which is mapping unique keys to values), but for custom objects the property names should be identical for all objects of the same variety.
New-Object -Type PSObject -Property {
Name = $usernm.Name
Group = $useraccess.Name
}
Basily query all the users and store it in $users, example:
Get-ADUser -Filter * -SearchBase "dc=domain,dc=local"
And then you can export the results as csv or a table.
To Export as CSV :
Get-ADPrincipalGroupMembership <Username> | select name, groupcategory, groupscope | export-CSV C:\data\ADUserGroups.csv`
To Format the result as Table in the console itslef :
Get-ADPrincipalGroupMembership <Username> | select name, groupcategory, groupscope | Format-Table

How to output list of objects to a single line with separators

New to PowerShell, great experience so far. How can I format the following cmd pipes to put the display to screen as a single line, with elements separated by ; (to easily allow copy/paste into Outlook)
PS C:\Users\amrgro-dennem04> get-adgroupmember -Identity "gbl-intel-l3-u" -Recursive|get-aduser -properties Mail|select-object Name
Name
----
AMRCVW-EDELSI
AMRMOP-REITES
amrmop-kruges
Basically, want the output to look like this:
AMRCVW-EDELSI;AMRMOP-REITES;amrmop-kruges
Try:
(Get-ADGroupMember "gbl-intel-l3-u" -Recursive| Get-ADUser -Properties Mail).Name -join ';'
Given that you don't need the -Properties parameter, because you're not using the .Mail property, you can simplify to:
(Get-ADGroupMember "gbl-intel-l3-u" -Recursive| Get-ADUser).Name -join ';'
Given that you're only accessing the .Name property and not really filtering by member type:
(Get-ADGroupMember "gbl-intel-l3-u" -Recursive).Name -join ';'
If you're using PSv5.1 or higher (on Windows), you can pipe the above commands to Set-Clipboard (... | Set-Clipboard) to copy the resulting text to the clipboard.
In lower PS versions, you can pipe to the external clip.exe utility instead (... | clip), but note that this invariably appends a line break and that you may run into encoding issues.
Note:
In PSv3+, you can extract the property values of a collection's elements simply by using .<propertyName> on the collection itself.
A simplified example:
#( [pscustomobject] #{ one = '1a' }, [pscustomobject] #{ one = '1b' } ).one yields array #( '1a', '1b' )
-join ';' then joins the array of resulting property values with ; as the separator to form a single output string.
Something like this should help, it's a one liner with two commands chained together:
$test = get-adgroupmember -Identity "gbl-intel-l3-u" -Recursive|get-aduser -properties Mail|select-object Name ; $test -join '; ';

Powershell & Get-ADUser - Split OU getting the 3rd, 4th and 5th elements from the end

Running the following in Powershell I get the result below.
Get-ADUser -Filter * -Properties DistinguishedName | select DistinguishedName | Select-Object -Property #{label='Result';expression={$_.DistinguishedName}}
Result
CN=User Full Name 1,OU=AMS,OU=DS,DC=domain,DC=local
CN=User Full Name 2,OU=TECHM,OU=DS,DC=domain,DC=local
CN=User Full Name 3,OU=Agencies,OU=HK,OU=Developers,DC=domain,DC=local
CN=User Full Name 4,OU=Agencies,OU=CH,OU=Developers,DC=domain,DC=local
CN=User Full Name 5,OU=Agencies,OU=US,OU=Developers,DC=domain,DC=local
CN=User Full Name 6,OU=Market,OU=PP,OU=Developers,DC=domain,DC=local
CN=User Full Name 7,OU=Market,OU=HK,OU=Developers,DC=domain,DC=local
This is my OU in Active Directory
DS
AMS
TECHM
Developers
CH
Agencies
Market
HK
Agencies
Market
I need a way to adapt this query (doing a split or whatever) so I am able to obtain the third item (comma separated) - most important - from the end and 4th and 5th. This is the output I'd like to get:
OU Where Type
--------------------------------
DS AMS N/A
DS TECHM N/A
Developers CH Agencies
Developers CH Market
Developers HK Agencies
Developers HK Market
I found some examples to split strings but nothing to accomplish what I am trying here.
Any ideas?!
Any help is greatly appreciated. Thanks in advance!
Given the values you're wanting to extract, I'd start with CanonicalName, rather than DistinguishedName:
Get-ADUser -Filter * -Properties CanonicalName |
select -ExpandProperty CanonicalName |
ForEach-Object {
$Parts = $_.split('/')
$Object =
[PSCustomObject]#{
OU = $Parts[1]
Where = $Parts[2]
Type = 'N/A'
}
if ($Parts.count -ge 5)
{ $Object.Type = $Parts[3] }
$Object
}
You are not interested in ",DC=domain,DC=local", so you might as well remove them by either -replace ",DC=domain,DC=local","" or by using substring method of string.
You really did not need that last select-object, nor specifying DistinguishedName, as by default you would get that with get-aduser
For example
$users = (get-aduser -filter *).distinguishedname -replace ",DC=domain,DC=local",""
Then, you split the results with "," to a temporary array variable and get the ones you like, starting from the last one using array index [-1]
$users | foreach {$where = $type = $OU = ""}{
$temp=#($_ -split ",")
if ($temp.count -eq 1) {
$OU = $temp[0].substring(3) # substring to remove the first 3 chars, that is OU= or CN=
} elseif ($temp.count -eq 2) {
$where = $temp[1].substring(3)
$OU = $temp[0].substring(3)
} else {
$type = $temp[-1].substring(3)
$where = $temp[-2].substring(3)
$ou = $temp[-3].substring(3)
}
# Finally create a custom obhect out of these
[PSCustomObject]#{
Type=$Type
Where=$where
OU=$OU
}
}
I am typing this on top of my head, you should test but I guess you get the idea..