I'm trying to list only unique HomeDrive for all users in a Universal Security group and remove nested groups errors.
Thanks for your help.
Denis
I've tried .TrimEnd(':'), can't seem to figure out where to put it
$Group = "Universal Security group"
$HomeDrive = Get-ADGroupMember $Group | `
ForEach-Object {
$UserName = $_.Name
Try {
#$ErrorActionPreference = "Stop"
Get-ADUser $UserName -Properties HomeDrive | Select HomeDrive
}
Catch {
Write-Host "Found a nested Group."
}
} | Sort-Object -Property 'HomeDrive' -Unique | Format-Table -HideTableHeaders | Out-String
Write-Host "$HomeDrive" -BackgroundColor DarkRed
The script does work but some users have their homedrives listed as only F while most are listed as F:. Basically making a lot of double entries and I do want the output to be only F. Also it generates 7 spaces after the :, That's why I have the background color.
Something like this:
$group = "Universal Security group"
$homeDrives = Get-ADGroupMember $Group |
ForEach-Object {
if ($_.ObjectClass -eq "User")
{
$user = Get-ADUser $_.Name -Properties "HomeDrive"
$homeDrive = $user.HomeDrive.Trim().TrimEnd(":")
return $homeDrive
}
} | Sort-Object -Unique
foreach ($homeDrive in $homeDrives)
{
Write-Host "Found home drive: $homeDrive" -BackgroundColor DarkRed
}
Related
Actually i have a powershell script which analyzes the ntfs permissions on a file server. i enter the group name, specify the folder and afterwards i get the list. now i want to implement a active directory picker dialog like this instead of typing the group name
is there any powershell code to add to my script? this is what i have.
$gruppe = read-Host "group name"
Function Get-Folder($initialDirectory)
{
[System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")|Out-Null
$Ordnername = New-Object System.Windows.Forms.FolderBrowserDialog
$Ordnername.Description = "Ordner auswählen"
$Ordnername.rootfolder = "MyComputer"
if($Ordnername.ShowDialog() -eq "OK")
{
$Ordner += $Ordnername.SelectedPath
}
return $Ordner
}
$o = Get-Folder
write-host
function Get-FolderRightsForAccount([string]$dn, [string]$rootfolder, [switch]$includeInheritedRights){
$sids = #()
$sids += (Get-ADObject $dn -Properties objectSid).objectSid.Value
$sids += Get-ADPrincipalGroupMembership $dn | select -Expand GroupName
$inherited = #{$true=($true,$false);$false=$false}[$includeInheritedRights.IsPresent]
(Get-ACL $rootfolder).Access | ?{try{$_.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]).Value -in $sids -and $_.IsInherited -in $inherited}catch{}} | select #{n='Folder';e={$rootfolder}},AccessControlType,#{n='Rights';e={$_.FileSystemRights}}
gci $rootfolder -Recurse -Directory -PipelineVariable f | %{
(Get-ACL $_.Fullname).Access | ?{try{$_.IdentityReference.Translate([System.Security.Principal.SecurityIdentifier]).Value -in $sids -and $_.IsInherited -in $inherited}catch{}} | select #{n='Folder';e={$f.Fullname}},AccessControlType,#{n='Rights';e={$_.FileSystemRights}}
}
}
Get-FolderRightsForAccount -dn (Get-ADGroup $Gruppe).DistinguishedName -rootfolder $o -includeInheritedRights | ft -AutoSize
It's not a picker like shown, but could be even more useful. You can utilize the cmdlet Out-GridView. You can allow choosing many or limit to one item. You can filter and/or sort the list as well.
$selectedgroup = Get-ADGroup -Filter * |
Select-Object -Property Name, GroupCategory,GroupScope, SamAccountName,DistinguishedName |
Sort-Object -Property Name | Out-GridView -OutputMode Single -Title "Please choose a group"
if(!$selectedgroup){
Write-Host "No group was selected" -ForegroundColor Yellow
}
I want to write script for getting AD Group Membership that is beginning with SSL_VPN for usernames listed in a CSV.
I have tried so far :
Import-Csv C:\Users.csv |
ForEach-Object -pv user { Get-AdUser -filter "displayname -eq '$($_.username)'"} |
Get-ADprincipalGroupMembership |
Select-Object #{ n = 'samaccountname'; e = { $user.samaccountname } }, name |
Export-csv -path C:\UserPermiss.csv -NoTypeInformation
Getting users by their DisplayName property is not the safest thing to do. It would be so much better if your CSV file has other, more unique properties to go by, like SamAccountName, UserPrincipalName, DistinguishedName or EmailAddress..
Anyway, in your loop, you should check if a user with that name can be found and only if so, get the group membership.
Import-Csv 'C:\Users.csv' | ForEach-Object {
$user = Get-ADUser -Filter "DisplayName -eq '$($_.username)'" -Properties DisplayName
if ($user) {
Get-ADprincipalGroupMembership -Identity $user.DistinguishedName |
Where-Object { $_.name -like 'SSL_VPN*' } |
Select-Object #{ Name = 'SamAccountName'; Expression = { $user.SamAccountName } },
#{ Name = 'Group'; Expression = { $_.name }}
}
else {
Write-Warning "User '$($_.username)' not found"
# if you want this message to also appear in your output CSV, do something like this:
[PsCustomObject]#{
'SamAccountName' = "User '$($_.username)' not found"
'Group' = ''
}
}
} | Export-Csv -Path 'C:\UserPermiss.csv' -NoTypeInformation
If you want to see a warning message when the user is not a member of the SSL_VPN group, you can do:
Import-Csv 'C:\Users.csv' | ForEach-Object {
$user = Get-ADUser -Filter "DisplayName -eq '$($_.username)'" -Properties DisplayName
if ($user) {
$group = Get-ADprincipalGroupMembership -Identity $user.DistinguishedName |
Where-Object { $_.name -like 'SSL_VPN*' }
if ($group) {
[PsCustomObject]#{
'SamAccountName' = $user.SamAccountName
'Group' = $group.name
}
}
else {
Write-Warning "User '$($_.username)' is not a member of ssl_vpn group"
}
}
else {
Write-Warning "User '$($_.username)' not found"
}
} | Export-Csv -Path 'C:\UserPermiss.csv' -NoTypeInformation
You can use something like this(frist line of csv must be samaccountname):
$users=Import-Csv D:\adusers.CSV
foreach($user in $users){
$groupname=Get-ADPrincipalGroupMembership -Identity $user.samaccountname |where {$_.name -like "SSL_VPN*"}|select -ExpandProperty name
if($groupname -ne $null){
foreach($group in $groupname){
[string]$data=($user|select -ExpandProperty samaccountname)+';'+$group
$data|Out-File -FilePath d:\stack.csv -Encoding utf8 -Append
}
}
}
I found this example but I am not sure how I can properly save the output to a .csv.
Import-Module ActiveDirectory
$Groups = Get-ADGroup -Filter {GroupCategory -eq "Distribution"} -Properties Members
ForEach ($g in $Groups) {
Write-Host $g.name
Write-Host $g.members `n
}
I have tried something such as:
Import-Module ActiveDirectory
$Groups = Get-ADGroup -Filter {GroupCategory -eq "Distribution"} -Properties Members
ForEach ($g in $Groups) {
$g.name | Export-CSV C:\log.csv -notypeinformation -Append
$g.members | Export-CSV C:\log.csv -notypeinformation -Append
}
It only saves 1 column to the CSV which is called length.
This also makes me remove the 'n at the end of Write-Host $g.members `n
Is there a way that I can grab this data and save it to .csv properly?
UPDATE
With help from TheMadTechnician and this link https://blogs.technet.microsoft.com/heyscriptingguy/2013/07/22/export-user-names-and-proxy-addresses-to-csv-file/ I was able to get closer to what I want.
Import-Module ActiveDirectory
$Groups = Get-ADGroup -Filter {GroupCategory -eq "Distribution"} -Properties Members
ForEach ($g in $Groups) {
$g.name | Export-CSV C:\log.csv -notypeinformation -Append
$g.members | Export-CSV C:\log.csv -notypeinformation -Append
}
$Groups | Select Name,#{L='Members_1'; E={$_.members[0]}}, #{L='Members_2';E={$_.Members[1]}}, #{L='Members_3';E={$_.Members[2]}}, #{L='Members_4';E={$_.Members[3gq]}} | Export-Csv C:\log.csv -notype
This gives me an output of the below in my CSV:
Name Members_1 Members_2 ETC...
NameOfGroup CN=Stormy Daniels,OU=IT,DC=DomainName,DC=com CN=Joe Bob,OU=IT,DC=DomainName,DC=com
Now the list of users can be huge so I would have to continue creating Members_3, Members_4, etc...
I'm not sure if there is a way I can specify all users or loop
#{L='Members_1'; E={$_.members[0]}}
and increment the number until all users are displayed.
I also only need the CN with the name. I don't need the Ou= or Dc=.
Ah this proved harder than I expected - due to the member counting (you have to do a count which can be comparable to integer). I have added a possibility to limit result size as for large queries the active directory produces timeouts.
$limit_result_size = 10
$group_name = Get-ADGroup -Filter {GroupCategory -eq "Distribution"} -Properties Name, Members -ResultSetSize:$limit_result_size | Select-object name
ForEach ($name in $group_name.name) {
If ((![String]::IsNullOrEmpty("$name")) -And ("$name" -notlike 'index')) {
$count_members = Get-ADGroupMember -Identity "$name" | Measure-Object | Select-Object Count
Write-Output "The AD group $name has $($count_members.Count) members.`n"
For($counter = 0; $counter -lt $count_members.Count; $counter++) {
$person = Get-ADGroup -Filter {Name -eq $name} -Properties Name, Members | Select-Object Name, #{N='Members';E={$_.Members[$counter]}}
$person.Members = $person.Members | Select-String 'CN=[0-9a-zA-Z]+' -AllMatches | % { $_.Matches } | % { $_.Value }
$person | export-csv -NoTypeInformation -Append -Path '<your_path>\log.csv'
}
}
}
Short description:
(![String]::IsNullOrEmpty("$name")) -And ("$name" -notlike 'index')) conditions which the AD group should satisfy.
Select-String 'CN=[0-9a-zA-Z]+' -AllMatches | % { $_.Matches } | % { $_.Value } Selects only CN=string_with_numbers. You could replace it with CN=\w+ if you prefer.
The script produces a pair in CV AD group and the CN=user_name. If anything else is unclear please ask.
EDIT
If you have spaces in the names of the Common Names (CN) you have to adjust the regexp to CN=[0-9a-zA-Z\s]+.
EDIT 2 Adding user's email addresses.
Since your question has in the title request for emails I'll answer here without new question. Note that this solution uses lookbehind in regexp to exclude the CN= from the output so it can be used as source for the user query. It also uses a PSCustomObject which gathers all the information together. I have renamed some variables to make better sense in the context of user details.
$limit_result_size = 10
$group_name = Get-ADGroup -Filter {GroupCategory -eq "Distribution"} -Properties Name, Members -ResultSetSize:$limit_result_size | Select-object name
ForEach ($name in $group_name.name) {
If ((![String]::IsNullOrEmpty("$name")) -And ("$name" -notlike 'index')) {
$count_members = Get-ADGroupMember -Identity "$name" | Measure-Object | Select-Object Count
Write-Output "The AD group $name has $($count_members.Count) members.`n"
For($counter = 0; $counter -lt $count_members.Count; $counter++) {
$person = Get-ADGroup -Filter {Name -eq $name} -Properties Name, Members | Select-Object Name, #{N='Members';E={$_.Members[$counter]}}
$person.Members = $person.Members | Select-String '(?<=CN=)[0-9a-zA-Z\s]+' -AllMatches | % { $_.Matches } | % { $_.Value }
$person_details = Get-AdUser -filter {name -eq $member} -Properties mail | Select-Object mail
$person_additional_details = [PSCustomObject]#{ group_name = $group.Name
user_name = $group.Members
email = $person_details.mail
}
If ([String]::IsNullOrEmpty($($person_additional_details.email))) {
$person_additional_details.psobject.properties["email"].value = '<empty>'
}
# For user to see the written data
Write-Output "AD Group: $($person_additional_details.group_name) `
AD User: $($person_additional_details.user_name) `
Users`'s email: $($person_additional_details.email)`n"
# writing into the CSV file
$person_additional_details | export-csv -NoTypeInformation -Append -Path '<your_path>\log.csv'
}
}
}
I cant get this script to give the right output, I want to check if a user (from the Users.csv) exists in a group (there is one group in each domain, this is a multi domain environment).
I think the problem lies in the second foreach.
Right now the output is the right numbers of lines for each domain, but they all say :
aa#aa.aa bb#bb.bb does not exists in the group PSO_StdPasswordPolicyWithNoAccountLockout
Where it should say:
aa#aa.aa does not exists in the group
PSO_StdPasswordPolicyWithNoAccountLockout
bb#bb.bb does not exists in the group
PSO_StdPasswordPolicyWithNoAccountLockout
Users.csv contains EmailAddress, DisplayName, objectGUID
Clear-Host
$user = Import-Csv ".\Users.csv"
$group = "PSO_StdPasswordPolicyWithNoAccountLockout"
$domains = (Get-ADForest).domains
foreach ($domain in $domains) {
Write-Host ="********** - $domain - **********" -ForegroundColor Yellow
$members = Get-ADGroupMember -Identity $group -Server $domain | Select-Object objectGUID
$exportMembers = $members | Export-Csv .\RemoveUsersTemp\$domain.csv -NoTypeInformation
$importFile = ".\RemoveUsersTemp\$domain.csv"
$amembers = import-csv $importFile | Select-Object objectGUID
foreach ($amember in $amembers) {
If ($amembers.objectGUID -contains $user.objectGUID) {
Write-Host $user.EmailAddress"exists in the group $group " -ForegroundColor Green
}
Else {
Write-Host $user.EmailAddress"does not exists in the group $group" -ForegroundColor Red
}
}
}
This is because you use $user in the second loop, but you're not looping $user, so you're referring the whole $user array, which has the content of users.csv.
I've created a form to create new AD Accounts. Part of the script determines which groups the new user will be added to based on their role (Doctor, Nurse, Admin or Other) which is captured in the following code in the form of a drop down pick box:
Write-Host "Based on this information" $FFN "has been added to the following Active Directory Groups:"
Write-Host
$ADGroup01 = Get-ADGroup "_XA_App_XenApp" |select -expandproperty name -first 1
Write-Host $ADGroup01
$ADGroup02 = Get-ADGroup "Web Proxy Users" |select -expandproperty name -first 1
Write-Host $ADGroup02
if($RadioButton1.Checked -eq $true)
{
$ADGroup03 = Get-ADGroup "allrot" |select -expandproperty name -first 1
Write-Host $ADGroup03
}
Else
{
$ADGroup03 = Get-ADGroup "alltpo" |select -expandproperty name -first 1
Write-Host $ADGroup03
}
if ($Role -eq "Doctor" -Or $Role -eq "Nurse")
{
$ADGroup04 = Get-ADGroup "PACS Web Access" |select -expandproperty name -first 1
Write-Host $ADGroup04
}
if ($Role -eq "Doctor")
{
$ADGroup05 = Get-ADGroup "CH-MFD" |select -expandproperty name -first 1
Write-Host $ADGroup05
$ADGroup06 = Get-ADGroup "ED-MFP" |select -expandproperty name -first 1
Write-Host $ADGroup06
$ADGroup07 = Get-ADGroup "SU-MFD" |select -expandproperty name -first 1
Write-Host $ADGroup07
}
Write-Host
Further on in the script this piece of code is called during the actual account creation process:
Add-ADPrincipalGroupMembership -Identity $UN -memberof $ADGroup01, $ADGroup02, $ADGroup03, $ADGroup04, $ADGroup05, $ADGroup06, $ADGroup07
The issue I'm facing is that if the user selects Nurse, Admin or Other I get the following error:
"Add-ADPrincipalGroupMembership : Cannot validate argument on parameter 'MemberO
f'. The argument is null, empty, or an element of the argument collection conta
ins a null value. Supply a collection that does not contain any null values and
then try the command again."
I know this is because there are no values being captured in the last $ADGroup[x] and short of creating a bunch of if statements to check if each $ADGroup contains data I'm wondering if there is a more elegant solution.
As always, thank you for taking the time review and happy to provide more information if required.
UPDATE - As per #Martin's advice I've implemented the following code into my script
$UN = "zooz"
$Role = "Nurse"
$Department = "Surgical"
If ($Role -eq "Doctor" -and $Department -eq "Surgical")
{
$ADGroups = #(
"PACS Web Access"
"CH-MFD"
"ED-MFP"
"SU-MFD"
)
}
If ($Role -eq "Nurse" -and $Department -eq "Surgical")
{
$ADGroups = #(
"_XA_App_XenApp"
"Web Proxy Users"
"allrot"
)
}
for ($i=0; $i -lt $ADGroups.length; $i++) {
Add-ADPrincipalGroupMembership -Identity $UN -memberof $adgroups[$i]
}
Make an object $adgroups and add your desired groups to it.
$adgroups = #()
At the end use a foreach Loop:
$adgroups | Add-ADPrincipalGroupMembership -Identity $UN or (weather or not the cmdlet likes pipelined Input)
$adgroups | % { Add-ADPrincipalGroupMembership -Identity $UN -memberof $_ }