-split in PowerShell does not seem to work for me - powershell

I export a CSV file with SAM account name and MembersOf groups.
When I import that same CSV file and try to use the fields of group. I would to split them. When they are split I'm able to use them in Add-ADPrincipalGroupMemberShip.
elseif ($Answer -eq 'n') {
Write-Warning "Verander de groepen in het CSV bestand: $ExCSV"
Get-ADUser -Identity $ExSam -Properties sAMAccountName, MemberOf |
Select-Object #{Name="User";expression={$ImSam}},
#{Name="Group";expression={$ImGroups}} |
Export-Csv "$ExCSV" -Delimiter "," -Force -NoTypeInformation -Encoding UTF8
[ValidateSet('OK')] $correct = Read-Host "Type 'OK' als je klaar bent"
if ($correct = "OK") {
$csv = Import-Csv "$ExCSV"
foreach ($user in $csv) {
$csv2 = $csv.Group -replace ' ', ', '
}
Write-Output $csv2
Add-ADPrincipalGroupMembership -Identity $ImSam -MemberOf "$csv2"
return
}
}
The output I write is:
The error message I receive:
My CSV:

It looks like you want to transform a string that contains a list of names into an array of those names.
It is indeed the -split operator that enables that, which allows sophisticated splitting of a string into an array of tokens using regular expressions.
In the simplest case, if the string to split ($csv.Group, in your case) is always in the form '<name1>, <name2>[, ...]', use:
PS> 'test4, test5' -split ', '
test4
test5
To make this more robust to guard against leading and trailing whitespace and missing spaces after the comma:
PS> ' test4, test5,test6 ' -split ' +|,' -ne ''
test4
test5
test6
Specifically, you need an array of names rather than a string list, because Add-ADPrincipalGroupMembership's -MemberOf parameter expects an array of group identities (names).
Assuming that you've modified $csv2 to contain an array, as described above, note that then you mustn't reference the variable enclosed in "..." ("$csv2"), as that would turn the value back into a (single) string.
Therefore, make the call as follows:
Add-ADPrincipalGroupMembership -Identity $ImSam -MemberOf $csv2 # !! No "..."

Related

PowerShell CSV line break but without changing the cell in the generated CSV

I get a list of users that I store in a variable that will then be used to create a CSV. Originally the elements of the variable were separated by a comma using -join (","). I want the "," to be replaced by a line break so I used -join ("'n") the line break is done well but the elements of the variable are not in the same cell.
This is what the CSV gives me:
Here is the desired result:
What I tried and it doesn't seem to work :
-join [Environment]::NewLine
ReplaceCommaWithNewLine($Compare -join ",")
$data = Get-Content -Path $Chemin_File_CSV
$data = $data -replace ",","`n"
$data | Set-Content -Path $Chemin_File_CSV
$data = Import-Csv -Path $Chemin_CSV_File
Do you know how to solve my problem ?
You can find the corresponding script below :
# Retrieving the list of privileged groups to check
$GroupsToCheck = #("Administrateurs","Administrateurs du schéma","Administrateurs de l’entreprise","Admins du domaine", "Opérateurs de compte","Opérateurs de serveur" ,"Opérateurs de sauvegarde","Opérateurs d’impression")
# Retrieve the list of members of the AD group "Protected Users
$ADGroup_ProtectedUsers_Members = (Get-ADGroupMember "Protected Users").SamAccountName
# Comparison of the groups contained in the $GroupsToCheck table and in the AD group "Protected Users
$Compare = ((Compare-Object -ReferenceObject $GroupsToCheck -DifferenceObject $ADGroup_ProtectedUsers_Members) | Where-Object -Property SideIndicator -EQ "<=").InputObject
# If $Compare is empty, Conform
if (!$Compare) {
$Status = "Conform"
$Value = $null
# Else, Not Conform
} else {
$Status = "Non Conform"
$Value= ($Compare -join "`n")
}
$Path__CSV = "C:\Users\Public\Documents\test.csv"
$Content_CSV = (#"
"Status" ; "Value"
$Status ; $Value
"#) | Out-File -FilePath $Path_CSV -Encoding UTF8 -Append
Thank you in advance.
Don't use plain-text processing; create objects ([pscustomobject]), which you can pass to Export-Csv.
[pscustomobject] #{
Status = $Status
Value = $Value
} | # see note re -UseCulture and -Delimiter at the bottom
Export-Csv -NoTypeInformation -Encoding utf8 $Path_CSV -Append
Export-Csv automatically takes care of enclosing multi-line strings in "...", which preserves their embedded newlines as part of the field (column) value (in fact, all fields are enclosed in "...")[1], as the following example with its in-memory equivalent, ConvertTo-Csv, demonstrates:
[pscustomobject] #{
SomeColumn = 42
MultiLineColumn = 'foo', 'bar', 'baz' -join "`n"
} |
ConvertTo-Csv
Output:
"SomeColumn","MultiLineColumn"
"42","foo
bar
baz"
Note:
If your CSV format uses a culture-specific field separator in lieu of , - such as ; - add -UseCulture to your Export-Csv / ConvertTo-Csv calls, assuming the desired separator is the one associated with the current culture.
If you want to control the field separator (delimiter) explicitly, use the -Delimiter parameter.
[1] This is invariably true in Windows PowerShell, and true by default in PowerShell (Core) 7+, where you now get to control the quoting behavior via the -UseQuotes and -QuoteFields parameters.

Adding a string to a extensionattribute in Powershell

I try to add value X to a Active Directory Member Y that has already some values in extensionAttribute10. How do I add a specific string into that? Also I want to scan the extensionAttribute and remove a specific entry.
Testparameters:
$ThisUser = "Testaccount01"
#{extensionAttribute10=Computer01, Computer02}
$adding = "Computer03"
$delete = "Computer01"
assuming the target is a user account:
#Replace existing value with a new one
set-aduser -identity [userSamAccountName] -replace #{extensionAttribute10=$value}
#Add new value to
set-aduser -identity [userSamAccountName] -add #{extensionAttribute10=$value}
If your target is a different object type, e.g. a computer use the related cmdlets, the syntax is equal....
As response to your comment: Sure the code does work but you need to consider the datatype of the target attribute, which is not an array it's a single value. So if you need to store multiple values there you need to transform the array into a delimited string, e.g.:
$value = #('comp1','comp2')
$valueString = $value -join ","
set-aduser -identity [userSamAccountName] -add #{extensionAttribute10=$valueString}
But be aware that this attribute has a size limit.
Ok based on your code sample, you cast the output as string array ([string[]]) but as outlined earlier you need a string and not an array:
your code
$newAttribute = [string[]]($user.extensionAttribute10 -split '[,\s]+' | ?{$_ -ne $delete}) + $add
replace with:
$valueArray = #($user.extensionAttribute10 -split ',' | ?{$_ -ne $delete})
$valueArray += $add
$valueString = $valueArray -join ","
set-aduser -identity [userSamAccountName] -replace #{extensionAttribute10=$valueString}
$ThisUser = "Test"
$delete = "Computer2"
$add = "Computer3"
$user = Get-ADUser -Identity $ThisUser -Properties extensionAttribute10
$newAttribute = [string[]]($user.extensionAttribute10 -split '[,\s]+' | ?{$_ -ne $delete}) + $add
Set-ADUser $thisUser -Replace #{extensionAttribute10=$newAttribute}

There are spaces in string, but I can't split it in powershell

I want to compare user's groups and DFS's groups to find out if the user has access authority to DFS. but I got stuck in split string.
here is part of my code:
$folder = Read-Host 'Enter the folder path'
$User = Read-Host 'Enter the sAMAccountName of user'
$getSGs = (get-acl $folder).Access | Select-Object -uniq -ExpandProperty IdentityReference
$getSGsSplit = $getSGs -split('.*\\')
$arr = $getSGsSplit -split ' '
Write-Host $arr
the value of $getSGs:
domain-ORG\xxx-Read domain-ORG\xxx-Modify domain-ORG\xxx-Admin domain-ORG\xxx-Center domain-ORG\xxxx-Admin BUILTIN\Administrators
the value of $getSGsSplit:
xxx-Read xxx-Modify xxx-Admin xxx-Center xxxx-Admin Administrators
What I Want is to split the $getSGsSplit by spaces:
xxx-Read
xxx-Modify
xxx-Admin
xxx-Center
xxxx-Admin
BUILTIN\Administrators
BUT I have been tried lots of patterns, all of them doesn't work.
$getSGsSplit -split ' .-`t`n`r'
$getSGsSplit -replace ' ','\n'
$getSGsSplit.split(' ').trim()
$getSGsSplit.split('\s').trim()
$getSGsSplit -split ' '
And no matter which pattern I used , the console of write-host $arr[2] still were spaces. And console of write-host $arr[2].getType() always were System.String
PS C:\Users\zzz\Desktop> C:\Users\zzz\Desktop\12.ps1
Enter the folder path: \\domain.org\xxx\xx\xxx
Enter the sAMAccountName of user: zzz
PS C:\Users\zzz\Desktop>
Can anyone advise how to resolve this?
Why not simply loop over the values returned by Get-Acl and replace the domain part on every item?
Something like
((Get-Acl $folder).Access |
Select-Object IdentityReference -Unique).IdentityReference |
ForEach-Object { $_ -replace '^domain-ORG\\' }
P.S.
Your code $getSGs = (get-acl $folder).Access | Select-Object -uniq -ExpandProperty IdentityReference does not return a string, but an array of objects with a Value property in which the account name is held.
Because you later use -split('.*\\') on it, the result becomes an array of strings, but if you simply leave that out the code can be much simpler.
Just considering the string that you already have:
Below should give you what you are looking for:
$a= "domain-ORG\xxx-Read domain-ORG\xxx-Modify domain-ORG\xxx-Admin domain-ORG\xxx-Center domain-ORG\xxxx-Admin BUILTIN\Administrators"
($a -split '\s').replace('domain-ORG\','')

Trouble with $arrayList.Remove($item)

I am having trouble with this.
What i am trying to do is I have 2 different array, and I am trying to exclude $items in $ignore from $users
I can't use where $users | where {$ignore -notcontains $_} because the string in the $ignore array may contain wildcard (e.g., admin*)
But here is the main problem, when I matched the $item that i want to remove, it removes my entire array instead of the selected value.
[System.Collections.ArrayList]$users = Get-ADUser -Filter * | Select Name
$users = $users.name
$ignore = $audArr[5] -Split(",")
foreach ($item in $ignore) {
if ($item.Contains("*")) {
foreach ($user in $users) {
$matchResult = $user -like $item
if ($matchResult -eq $true){
$users = $users.Remove($item)
}
}
}
else {
$users = $users.Remove($item)
}
}
However, I if i try to .Add it works despite showing error
Cannot convert the "3" value of type "System.Int32" to type "System.Collections.ArrayList".
At C:\users\administrator\desktop\scannerTest.ps1:326 char:17
+ $users = $users.Add($item)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [], RuntimeException
+ FullyQualifiedErrorId : ConvertToFinalInvalidCastException
Also, since i am already asking about powershell items.. Does anyone know what how to get LogonTime, KickoffTime via powershell? Adn what is ACB?
Santiago Squarzon's helpful answer uses a good approach with regex matching. We can further enhance the regex matching to include a combination of wildcard and exact matches.
$users = 'John Doe','Wolverine','Mr. Pants','Administrator','Jane Doe','Master Administrator'
# two exact matches and one wildcard match
$ignore = 'john doe','jane doe','admin*'
$regex = '^({0})$' -f (($ignore -replace '\*','.*') -join '|')
# List users who don't match $ignore
$users -notmatch $regex # Jane Doe, John Doe, Administrator not listed
If you must use an ArrayList, you can apply the same technique as above by
removing successful matches:
[collections.ArrayList]$users = 'John Doe','Wolverine','Mr. Pants','Administrator','Jane Doe','Master Administrator'
# two exact matches and one wildcard match
$ignore = 'john doe','jane doe','admin*'
$regex = '^({0})$' -f (($ignore -replace '\*','.*') -join '|')
$users -match $regex | Foreach-Object {
[void]$users.Remove($_)
}
Explanation:
In regex, alternations (basic OR logic) are separated by |. .* greedily matches any number of characters in a string. ^ denotes the beginning of a string. $ denotes the end of a string. Putting that all together, your exact matches would look like ^exact$ and your partial matches would look like ^admin.*$ (for admin*) or ^.*admin.*$ (for *admin*). Using alternation, you can combine those matches for an OR effect with ^(admin.*|Benjamin Dover|Johnny Lawrence)$.
What you're trying to do could be simplified to something like this:
Create a test case, the array will have User00 to User10 plus Administrators and Domain Admins.
$ignore = #(
'Administrators'
'Domain Admins'
'User05'
'User10'
)
[System.Collections.ArrayList]$users = 0..10 |
ForEach-Object { [pscustomobject]#{Name="User{0:00}" -f $_} }
$users.Add([pscustomobject]#{Name="Administrators"})
$users.Add([pscustomobject]#{Name="Domain Admins"})
Now you can simply use the .Where(..) method filtering those elements of the $users array that do not match the $ignore array on one side and those that do match on the other side.
$toIgnore = $ignore -join '|'
$notIgnoredUsers, $ignoredUsers = $users.Where({$_.Name -notmatch $toIgnore},'Split')
$notIgnoredUsers
Name
----
User00
User01
User02
User03
User04
User06
User07
User08
User09
$ignoredUsers
Name
----
User05
User10
Administrators
Domain Admins
As for how you're using the .Remove(..) method, since it doesn't produce any output, by doing $users = $users.Remove($item) you're actually setting the variable to null:
PS /> [System.Collections.ArrayList]$arr = 'one','two','three'
PS /> $arr = $arr.Remove('one')
PS /> $null -eq $arr
True
If you want to remove one from the list you would simply do $arr.Remove('one').

Find AD-user by Email

I'm trying to get users from active directory, who have a certain email address.
I've got a CSV-File, which contains the emails.
$data = import-csv -path .\are.csv -delimiter +
foreach($i in $data)
{
get-aduser -filter {UserPrincipalName -like '$i.email'}
}
My problem is, that I don't get any output. No error, no data. When I replace $i.email with one of the email addresses, I get the right user information for the one user. So hard coding works.
When I do:
foreach($i in $data)
{
$i.email
}
I get a list of all the emails.
What is wrong with the code?
Your variable is within single quotes thus doesn't get populated. You have to three options to fix that:
Use double quotes with a sub expression $():
UserPrincipalName -like "$($i.email)"
Just omit the quotes:
UserPrincipalName -like $i.email
And finally you could use a format string (even with single quotes):
UserPrincipalName -like ('{0}' -f $i.email)
Here is an example to demonstrate what actual value gets passed using the Write-Host cmdlet:
$data =
#'
email, id
myname#web.de, 1
'# | convertfrom-csv
foreach($i in $data)
{
Write-Host '$i.email' # This is your current approach
Write-Host "$($i.email)"
Write-Host $i.email
Write-Host ('{0}' -f $i.email)
}
Output:
$i.email # This is the output of your current approach
myname#web.de
myname#web.de
myname#web.de