How to get Powershell to prompt for input parameter - powershell

I am fairly new to PowerShell. There is a command I run many times a day that checks if an AD user account belongs to a couple of AD security groups. Right now, I am pasting the user's account into the command from OneNote and then pasting that command into the PowerShell window. Ideally, I would love to be able to run a .ps1 file that would launch a popup where I could enter in the user's account and the popup would then provide the command output. If that is not possible, run the .ps1 file and have the PowerShell ask for input where I can paste the user's AD account and hit enter. Below is the command I am running. Thank you all in advance.
(Get-ADUser %ADACCOUNT% -Properties MemberOf).MemberOf | findstr /i %ADGROUP%

Here is an idea to get you started using InputBox function to get the input user, MessageBox.Show method in case the user was not part of any group and Out-GridView in case the user was member of at least one of the groups.
Usage is quite simple, you just name this script as whatever you want and then when calling it, you can do .\myScript.ps1 -ADGroups 'somegroup1', 'somegroup2', etc
param([string[]] $ADGroups)
Add-Type -AssemblyName Microsoft.VisualBasic, System.Windows.Forms
# Get user input
$choice = [Microsoft.VisualBasic.Interaction]::InputBox(
'Input User SamAccountName',
'Choose a Title for me'
)
# if the user didn't provide any input, exit script
if([string]::IsNullOrWhiteSpace($choice)) {
return
}
# get user membership and filter
$result = (Get-ADUser $choice -Properties memberOf).memberOf | Where-Object {
# where the DistinguishedName matches any of input AD Groups
foreach($group in $ADGroups) {
if($_ -match $group) { return $true }
}
}
# if no results found
if(-not $result) {
# show this message
[Windows.Forms.MessageBox]::Show(
"$choice was not a member of any AD Group",
'Choose a Title for me',
[Windows.Forms.MessageBoxButtons]::OK,
[Windows.Forms.MessageBoxIcon]::Warning
)
# and exit the script
return
}
# otherwise, show this grid that contains the list of DistinguishedNames
# the user is a member of
$result | Out-GridView

Related

Find if a user is part of some distribution lists

I want to get a script working in powershell which takes a user's email and look it up against a few distribution lists to see if the user is a part of any of them. It should also check the nested distribution groups if any under the main distribution lists.
here's what I have but can't get it to work. Any help would be appreciated, I am fairly new to this.
# Prompt for user email address
$UserEmail = Read-Host -Prompt 'Please enter the user email address'
# Read the CSV file
$DistributionLists = Import-Csv -Path '.\DLs.csv'
# Loop through each Distribution List
foreach ($DL in $DistributionLists) {
# Get List of Distribution Group Members
$GroupMembers = Get-DistributionGroupMember -Identity $DL -ResultSize Unlimited
# Loop through each member
foreach ($Member in $GroupMembers) {
# Check if the user's email address matches
if ($Member.PrimarySmtpAddress -eq $UserEmail) {
# Output the matches
Write-Output "User $UserEmail is a part of $($DL.Name)"
}
}
}
but i get below error on execution:
Write-ErrorMessage : Cannot process argument transformation on parameter 'Identity'. Cannot convert value "" to type
"Microsoft.Exchange.Configuration.Tasks.DistributionGroupMemberIdParameter". Error: "Parameter values of type Microsoft.Exchange.Configuration.Tasks.DistributionGroupMemberIdParameter can't be empty. Specify a value, and try again.
Parameter name: identity"
At C:\Users\abcd\AppData\Local\Temp\tmpA_hrt0empv.vlz\tmpA_hrt0empv.vlz.psm1:1087 char:13
+ Write-ErrorMessage $ErrorObject
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-DistributionGroupMember], ParameterTransformationException
+ FullyQualifiedErrorId : [Server=BNxxxxxx5601,RequestId=abcdef5-1e51-d5f0-2a56-77b30f23bf3a,TimeStamp=Thu, 09 Feb 2023 14:04:01 GMT],Write-ErrorMessage
Error screenshot
The error statement informs us "-Identify $DL" is empty; $DL returns the entire object row and not just the name to be matched. To correct, refactor to $DL.DistributionLists where "DistributionLists" is the column header in the imported CSV file.
As we confirmed together you have already imported ExchangeOnlineManagement and made the connected to Exchange Online.... I've kept these in the code below for future reader reference.
# Pearl-script below:
# Import the ExchangeOnlineManagement module
Import-Module ExchangeOnlineManagement
# Connect to Exchange Online
Connect-ExchangeOnline
# Prompt for user email address
$UserEmail = Read-Host -Prompt 'Please enter the user email address'
# Read the CSV file
$DistributionLists = Import-Csv -Path '.\DLs.csv'
# Loop through each Distribution List
foreach ($DL in $DistributionLists) {
# Get List of Distribution Group Members
$GroupMembers = Get-DistributionGroupMember -Identity $DL.DistributionLists -ResultSize Unlimited
# Loop through each member
foreach ($Member in $GroupMembers) {
# Check if the user's email address matches
if ($Member.PrimarySmtpAddress -eq $UserEmail) {
# Output the matches
Write-Output "User $UserEmail is a part of $($DL.DistributionLists)"
}
}
}

Using powershell to list AD users and making an interactive menu to remove specific user

so what i want to do is use powershell to list all ADusers into a basic interactive menu so that a specific user can be chosen and removed.
This is what I got so far, and this all users and allows me to select a specific one. But the Remove-ADUser -identity $ouEntry (on line: 18) runs right after I start the script and selects all the users for removal before I can select a specific one. I need it to run after i select an option, and with the correct user. I have been looking into a switch menu, but with poor results since I cant embed the ForEach properly.
Appreciate all help. I'm also open to alternate solutions
Clear-Host
$ouCounter = 1
$MenuArray = #()
$DomainName = ($env:USERDNSDOMAIN).split('.')[0]
$Tld = ($env:USERDNSDOMAIN).split('.')[1]
Write-Host "`nChoose the user you want to delete"
foreach ($ouEntry in ((Get-ADUser -SearchBase "DC=$DomainName,DC=$Tld" -Filter *).name))
{
$(" "+$ouCounter+".`t"+$ouEntry)
$ouCounter++
$MenuArray += $ouEntry + " was removed"
$MenuArray += Remove-ADUser -identity $ouEntry
}
do
{ [int]$menuSelection = Read-Host "`n Enter Option Number"}
until ([int]$menuSelection -le $ouCounter -1)
$MenuArray[ $menuSelection-1]
Output
Choose the user you want to delete
1. Administrator
2. Guest
3. user1
4. user2
5. user3
6. user4
7. user5
8. user6
9. Jon Snow
Enter Option Number:
Previous reference: Making a dynamic menu in Powershell
You might consider doing this in a Windows Forms GUI, so the list to choose from can have a scrollbar.
Having said that, the code you have now writes the entry on screen as menu item and immediately removes that user.
Below code first gets the users in an array once and creates a List object from that.
The reason for using a List object is because with that it is easy to remove an item (unlike with using an array).
$DomainName = ($env:USERDNSDOMAIN).Split('.')[0]
$Tld = ($env:USERDNSDOMAIN).Split('.')[1]
# get an array of users in the given OU, sorted on the Name property
$users = Get-ADUser -SearchBase "DC=$DomainName,DC=$Tld" -Filter * | Sort-Object Name
# store them in a List object for easy removal
$list = [System.Collections.Generic.List[object]]::new()
$list.AddRange($users)
# now start an endless loop for the menu handling
while ($true) {
Clear-Host
# loop through the users list and build the menu
Write-Host "`r`nChoose the user you want to delete. Press Q to quit." -ForegroundColor Yellow
$index = 1
$list | ForEach-Object { " {0}.`t{1}" -f $index++, $_.Name }
$menuSelection = Read-Host "`r`nEnter Option Number."
# if the user presses 'Q', exit the loop
if ($menuSelection -eq 'Q') { break }
# here remove the chosen user if a valid input was given
if ([int]::TryParse($menuSelection, [ref]$index)) {
if ($index -gt 0 -and $index -le $list.Count) {
$userToDelete = $list[$index - 1]
Write-Host "Removing user $($userToDelete.Name)" -ForegroundColor Cyan
Remove-ADUser -Identity $userToDelete.DistinguishedName
# remove the user from the list
$list.RemoveAt($index - 1)
}
}
# add a little pause and start over again
Start-Sleep -Seconds 1
}
Hope that helps

How to get a PowerShell do-while loop to print on the first iteration before looping [duplicate]

This question already has an answer here:
PowerShell output is crossing between functions
(1 answer)
Closed 3 years ago.
ISSUE:
My issue is that I have a very simple do..while loop. However, it does not print the output of the Get-ADPrincipalGroupMembership query on the first iteration. For example, I run the script and enter a username then click enter. Instead of my expected result which is print the memberships, it loops around and asks for username again without printing the results of the first inputted username. Once I enter the username the second time in the loop and click enter then it prints the results of the first input and the results of the second input. Any time after the second iteration the script works fine and actually prints the results correctly after I provide the input. Below is the script in question.
EXPECTED RESULT:
The code below is simply supposed to ask the user for a username then run a query in AD to list the memberships of a given user. After providing the memberships of a user the script should ask for another user and repeat the process until the user enters "exit" and the script exits out.
CODE SNIPPET:
do {
$user = Read-Host -Prompt 'Enter the username of the user';
Get-ADPrincipalGroupMembership $user | select name;
} while ($user -ne 'exit');
Stop-Process -Id $PID;
Just got an answer form anther forum. The simplest solution to this is to simply add "| Out-String" after "| select name". The updated example is below.
do {
$user = Read-Host -Prompt 'Enter the username of the user'
Get-ADPrincipalGroupMembership $user | select name | Out-String
} while ($user -ne 'exit')
stop-process -id $PID
The property Name is an object from type string:
name Property System.String name {get;}
So you may simplify a bit:
do {
$user = Read-Host -Prompt 'Enter the username of the user'
(Get-ADPrincipalGroupMembership -Identity $user).name
} while ($user -ne 'exit')
stop-process -id $PID
Best regards,
Ivan

Powershell - Checking Security Group Members against another list

A bit of context, I am trying to get a list of users from a security group, then check if any of those users do not have an assigned XenDesktop.
Please forgive me, I only started using Powershell yesterday so my formatting is off. It first grabs the users from the AD group then checks if that user has an assigned desktop, which works but I what I can't seem to get working is that if the user is found in that list, I want it to move onto the next username, instead it continues to check against every machine and then onto the final bits of code.
$checkusernames = Get-ADGroupMember "***AD security Group***" | Select SamAccountName
$desktops = get-brokerdesktop -DesktopGroupName Personal_WIN8 | Select MachineName, #{Name='AssociatedUserNames';Expression={[string]::join(“;”, ($_.AssociatedUserNames))}}
foreach ($username in $checkusernames.SamAccountName) {
foreach ($desktop in $desktops) {
If ($desktop.AssociatedUserNames -like "*$username*") {
write-host $username "is assigned to" $desktop.machinename
}
write-host $username "is not assigned to a desktop"
}
Write-host $username "is not assigned to anything"
pause
}
If you want to exit from a ForEach loop early you can do so with the Break keyword. For example:
$checkusernames = Get-ADGroupMember "***AD security Group***" | Select SamAccountName
$desktops = get-brokerdesktop -DesktopGroupName Personal_WIN8 | Select MachineName, #{Name='AssociatedUserNames';Expression={[string]::join(“;”, ($_.AssociatedUserNames))}}
foreach ($username in $checkusernames.SamAccountName) {
$machine = ''
foreach ($desktop in $desktops) {
If ($desktop.AssociatedUserNames -like "*$username*") {
$machine = $desktop.machinename
break
}
}
If ($machine) {
write-host $username "is assigned to" $desktop.machinename
} Else {
write-host $username "is not assigned to a desktop"
pause
}
}
This will stop the current cycle of the inner ForEach loop (once it has completed in it's entirety) without interrupting the ongoing cycle of the outer one.
Per the dicussion in the comments, i've also reorganised the code so that you only get a single output dependent on whether a desktop is matched to a user or not and it only pauses if it does not find a match.

Line break issue when configuring "send on behalf of"

I have a script to set send on behalf of permissions in Exchange Management Shell, but when you try and use it it fails because the output of the first part is too long and truncates over 2 lines.
First thing we do is build our array from lists of people and put them into some variables to pass:
function Add-Send ($mailbox, $target) {
#"Granting send on behalf for $mailbox to $target"
Set-Mailbox -Identity $mailbox -GrantSendOnBehalfTo #{ Add = $target }
}
We pass a long list as the $target and the maibox name is $mailbox and if we output the text we get:
Set-Mailbox -Identity "mr.jeff" -GrantSendOnBehalfTo #{ Add = "alan.alanson", "bob.bobson", "steve.stevenson" }
All fine and good but if there are more than N characters in the output then we get a line break:
Set-Mailbox -Identity "mr.jeff" -GrantSendOnBehalfTo #{ Add = "alan.alanson", "bob.bobson", "steve.stevenson", ...
..., "cath.cathdotir" }
When you run this script with the overlength output, then command fails as the output which should be passed to the CLI is passed over more than one line. PowerShell treats each line as a separate command, and they obviously fail with bad syntax.
Our string is output from an array that we build like this:
function Send-Array ($mailbox) {
$target = Get-Content ".\list\dpt1.txt"
$target += Get-Content ".\list\$mailbox.txt"
$target += Get-Content ".\list\dpt2.txt"
$target = $target | Select-Object -Unique
$separator = '", "'
$target= $target -replace '^|$','"' -join ','
Add-Send $mailbox $target
}
This gives us an array with strings that look like:
"alan.alanson", "bob.bobson", "steve.stevenson"
From here I am at a loss any ideas would be much appreciated.
The obvious solution would be to pass the names one at a time, but due to a gotcha with Exchange Server every time you set send on behalf of permissions with PowerShell it wipes the existing permissions, so you only end up with he last person granted permissions being able to send on behalf of.
See this link for help with your underlying issue.
Very basically, you will have to:
get the DistinguishedName of the user you need to add
store the current value of GrantSendOnBehalfTo in a variable
append the new user's distinguished name to the list
replace GrantSendOnBehalfTo with the new list
Afterwards you should not need to pass endless strings to the EMS (I hope so).