How to reference a property from another command? - powershell

So im trying to setup a script for unlocking users accounts.
Right now this is what i have:
function unlocktm
{
$user = read-host "Who is the user?"
Unlock-ADAccount -Identity $user -Credential adminaccount
Write-host "Account for $user has been unlocked!"
}
now here is the difficult part, our users usernames are based off their email. and we switched email formats like last year. So some peoples emails are jdoe#company.com and others are john.doe#company.com
So when that script i have now asks "who is the user?" i have to put in and know that users username style (either first.lastname or flastname). Well with 1500 users, i dont exactly know every ones emails off the top of my head.
So what im trying to do is make it so that when it asks for "who is this user?" i can just put in John Doe, itll run a second script i have setup that can search for that user in AD, pull the attribute and apply it into the first script. Let me explain better. For the time being i have a second script that is this:
function findtm
{
$Firstname = Read-Host "What is the users Firstname?"
$Lastname = Read-Host "What is the Users Lastname?"
Get-ADUser -Filter "Surname -like '$Lastname*' -and GivenName -like '$Firstname*'"
}
and that pulls the info about that user and shows me what their email style is. That email style is under the "samaccountname".
So ultimately, what i need it to do is:
I run the function, it asks me for the user.
I can just put in "John Doe"
and it will then run that second script in the background that searches for "John Doe" and then if it finds a John Doe, its grabs the "samaccountname" property (either john.doe or jdoe), attaches that to the answer in replace of the "john doe" and then the script runs the unlockad command for john doe and unlocks his account.
Im probably over thinking this by a large margin, but i was thinking a If-else could do it but i have no clue how to to set it up to pull that "samaccountname" property.

In my opinion you should think of your functions as independent units, that take in the information they need as parameters. I would typically leave prompting or user interaction to the outermost layer.
Consider that Get-ADUser returns an object that can be used with Unlock-ADAccount as well.
function unlocktm
{
param($Identity)
Unlock-ADAccount -Identity $Identity -Credential adminaccount
Write-host "Account for $($Identity.SamAccountName) has been unlocked!"
}
function findtm
{
param($Firstname, $Lastname)
Get-ADUser -Filter "Surname -like '$Lastname*' -and GivenName -like '$Firstname*'"
}
# the outer script area
$Firstname = Read-Host "What is the users Firstname?"
$Lastname = Read-Host "What is the Users Lastname?"
$Id = findtm -Firstname $Firstname -Lastname $Lastname
unlocktm -Identity $id
Now, if you want to make it a little more fancy:
function unlocktm
{
[CmdletBinding()]
param(
[Parameter(ValueFromPipeline=$true)]
$Identity
)
Process {
Unlock-ADAccount -Identity $Identity -Credential adminaccount
Write-host "Account for $($Identity.SamAccountName) has been unlocked!"
}
}
function findtm
{
param($Firstname, $Lastname)
Get-ADUser -Filter "Surname -like '$Lastname*' -and GivenName -like '$Firstname*'"
# by simply calling this, the value returned becomes the return value of your function
}
# the outer script area
$Firstname = Read-Host "What is the users Firstname?"
$Lastname = Read-Host "What is the Users Lastname?"
findtm -Firstname $Firstname -Lastname $Lastname | unlocktm
There are lots of possibilities, but perhaps this is a good start?

Related

Variable not passing to Where-Object in Powershell

I have tried the "filter" and "param" options from the post
-- In powershell passing variable to where-object not working -- with no luck. I am fairly new to powershell since I have not used it since 2014. Can anyone assist me in finding out why the $UName variable is not being passed to the Where-Object command?
cls
$UName = Read-Host -Prompt "Name or part of name to search"
Write-Output "Searching for: $UName, please wait"
Get-ADUser -Filter * -Properties * | Where-Object {
$_.name -like "*$UName*" -and
$_.company -like "*XYZ Corp*"
} | select Name, title, company, Country, mailnickname
Pause
My only output is:
Name or part of name to search: Justin
Searching for: Justin, please wait
Press Enter to continue...
I have even tried using -Contains $UName and -Contains "$UName" yet still get the same results as above.
I have searched, and searched but cannot figure this out. Any assistance would really help!
Your script can be simplified as follows, you really shouldn't query all Domain Users (-Filter *) to then filter them with PowerShell (Where-Object). Instead, you should use the Active Directory Filter. Same goes for querying all users properties (-Properties *) when you actually only need some of them (Name, title, company, Country, mailnickname).
# using Trim() to remove any excess whitespace (trailing and leading)
$UName = (Read-Host -Prompt "Name or part of name to search").Trim()
# if there was no input or input was purely whitespace
if(-not $UName) {
# exit this script
return
}
# if input was valid
Write-Output "Searching for: $UName, please wait"
# try to search for the user
$props = 'Name', 'title', 'company', 'Country', 'mailnickname'
Get-ADUser -LDAPFilter "(&(name=*$UName*)(company=*XYZ Corp*))" -Properties $props |
Select-Object $props | Format-Table -AutoSize

Searching for User in Powershell. Allow Choice for Duplicate User

I wrote a PowerShell script that searches for a user based on given input and then removes said user from all groups (except for Domain Users). However, while you can't have a user with the same name in an OU group, you can have a user with the same name in a different OU group in the organization. Would it be possible to search for a user (John Smith), and allow one to select which user to remove from all groups if a duplicate user is returned? Here is my script so far. It works, but this is the functionality I would like to add.
#Requires -Module ActiveDirectory
Import-Module ActiveDirectory
function Disable-ADUser{
$msg = "Do you want to remove a user from all Security groups? [Y/N]"
do {
$response = Read-Host -Prompt $msg
if ($response -eq "y") { # Beginning of if statment
#Asks user via a text prompt to ender the firstname and lastname of the end user to remove
$firstName = Read-Host "Please provide the First name of the User"
$lastName = Read-Host "Please provide the Last name of the User"
#The user's samaccoutname is found by searching exactly for the user's first name and lastname given in the above prompts
$samName = Get-ADUser -Filter "GivenName -eq '$firstName' -and Surname -eq '$lastName'"| Select-Object -ExpandProperty "SamAccountName"
#All of the user's groups are queried based on their sam name
$listGroups = Get-ADUser -Identity $samName -Properties MemberOf | Select-Object -ExpandProperty MemberOf
#All of the user's groups are placed in an array
[System.Collections.ArrayList]$groupsArray = #($listGroups)
#Every group in the groupsArray is cycled through
foreach ($group in $groupsArray) {
#A text output is displayed before the user is removed from each group listed in the above array
#Once all groups have been cycled through, the for loop stops looping
Write-Host "Removing $samName " -f green -NoNewline
Write-Host "from $group" -f red
$OutputLine="Removing $samName from $group"
Out-File -FilePath remove_user_groups.log -InputObject $OutputLine -Append
Remove-ADGroupMember -Identity $group -Members $samName
}
} # End of if statement
} until ($response -eq "n")
}
Disable-ADUser
I use Out-GridView. It allows me to select user(s) with mouse, or to select no one. See -OutputMode parameter.
<# Example part #>
$data = #'
[
{displayName: "Don Pedro Fizikello", employeeNumber: "Emp001", phone: "+888888888" },
{displayName: "Don Pedro Gonzalez", employeeNumber: "Emp002", phone: "+77777777777" },
{displayName: "Natalia Marisa Oreiro", employeeNumber: "Emp456", phone: "+987654321" },
{displayName: "Juan Carlos Rodrigez", employeeNumber: "Emp123", phone: "+1234567890"}
]
'# | ConvertFrom-Json
$userList = #($data | Where-Object { $_.displayName -like 'Don*' })
#Real-world case from Active Directory: $userList = #( Get-ADUser -Filter "(displayName -like 'Don*')" -Properties #('displayName', 'phone') )
<# /Example part #>
$user = $null
if ($userList.Count -eq 1) {
$user = $userList[0] # // The only entry
} elseif ($userList.Count -gt 1) {
$user = $userList | Out-GridView -OutputMode Single -Title 'Select User you want co tall to or press cancel'
}
if ($null -eq $user) {
# // There is no users found or selected by human
Write-Host "Nothing to do" -f Yellow
} else {
# // Work with User
Write-Host "Call $($user.displayName) : $($user.phone)" -f Green
}
The negative option is that Out-GridView can not hide parameters that it will display. There are some workarounds depending on task. Example: I show only DisplayName and some ID in Out-GridView (no phone property), but I use returned ID to take full user (with phone) from cache I've created before.
This allows me not to break the original object ( if it's from Get-ADUser, it contains tons of human-useless data like SID, GUID, ObjectClass, ObjectCategory, etc. )
<# Example part #>
Same as previous
<# /Example part #>
$user = $null
$userCacheOriginal = #{}
$userCacheCut = #{}
for ($i = 0; $i -lt $userList.Count; $i++)
{
# !! Here I assign some entryUniqueId to two collections -
# - userCacheOriginal - Original user object with Phone field ( and others )
# - userCacheCut - Transformed objects that contains only ID and info I want to show in Out-GridView
$entryUniqueId = "Idx$($i)"
$userCacheOriginal[$entryUniqueId] = $userList[$i]
$userCacheCut[$entryUniqueId] = [PSCustomObject]#{ID = $entryUniqueId; displayName = $userList[$i].DisplayName;}
}
if ($userList.Count -eq 1) {
$user = $userList[0] # // The only entry
} elseif ($userList.Count -gt 1) {
$userChoice = $userCacheCut.Values | <# Set order of columns this way#> Select #('ID', 'DisplayName') | Out-GridView -OutputMode Single -Title 'Select User or press cancel'
if (($null -ne $userChoice.ID) -and ($userCacheOriginal.ContainsKey($userChoice.ID))) # Check if returned value contains ID,
{ # And select original user object from userCacheOriginal
$user = $userCacheOriginal[$userChoice.ID]
}
}
if ($null -eq $user) {
# // There is no users found or selected by human
Write-Host "Nothing to do" -f Yellow
} else {
# // Work with User
Write-Host "Call $($user.displayName) : $($user.phone)" -f Green
}
If you want to keep it console based, you can add a while loop that requires further input from the user.
#The user's samaccoutname is found by searching exactly for the user's first name and lastname given in the above prompts
$samName = Get-ADUser -Filter "GivenName -eq '$firstName' -and Surname -eq '$lastName'"|
Select-Object -ExpandProperty "SamAccountName"
if ($samname.count -gt 1) {
$newsamname = $null
while ($newsamname -notin $samname) {
$newsamname = Read-Host "Multiple names were found:`n$($samname -join ""`n"")`nPlease type the SamAccountName of the target user"
}
$samname = $newsamname
}
The idea is if multiple user objects are found, then $samname will initially be a collection of count greater than one. Here the executor will be required to enter a valid SamAccountName value from the presented list. Otherwise, the loop will go on forever until the program is manually halted. You could build in a counter to automatically exit the program after a certain number of retries or exit when no value is entered. You could implement a menu system where a number can be entered, which corresponds to the index of the list.

Looping Through All Calendars With Get-MailboxFolderPermission

I have researched this extensively and used much trial-and-error, but I have yet to get a scrip to work that performs the function I want it to. What I want is to create a script that will allow the user to type a username, and then run through all the mailboxes and show the user's permissions on those user's calendars. I've gotten very close with the below script, but this only works on the mailbox as a whole, and does not work if I simply add ":\Calendar" to the $Box variable. Any input on how to get this to show the calendar permissions would be welcome.
$Username = Read-Host "Enter the user whose access you would like to view"
foreach ($Box in Get-Mailbox) {
Get-MailboxFolderPermission -Identity $Box -User $Username
}
I know this is a repeat of a previous question, but as I've altered my code significantly, I thought it was worth asking again. Here's the link to my prior question:
Exchange Powershell: Get-MailboxFolderPermission for all calendars
Thanks for any help!
You could refer to the below code:
(Get-Mailbox) | ForEach-Object {
Get-Mailboxfolderpermission (($_.PrimarySmtpAddress)+":\calendar") `
-User happyboy -ErrorAction SilentlyContinue
} | Select-Object Identity, User, Accessrights
For more information, please refer to this link:
Display all mailbox calendars which a user has access to
Using the suggestion by #Alina-Li, I was able to work out the following code. Everything works well now:
(Get-Mailbox) | ForEach-Object {
$Permission = Get-Mailboxfolderpermission ($_.PrimarySMTPAddress.Local + "#" + $_.PrimarySMTPAddress.Domain +":\calendar") `
-User $User -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Accessrights
if ($Permission -ne $null) {
echo ("Calendar: "+($_.Name))
echo ($User+"'s Permission: "+$Permission)
echo ""
}
}

Change AD user attributes of users in group

I copied and pasted together this script that looks at all the member in a certain group, and then changes all of their company names. I would now like to expand this script to be able to ask for which attribute of the users you want to change.
Clear-Host
$GPNAME = Read-Host 'Provide the Group Name here'
#$whatwhat = Read-Host 'Which Attribute do you want to change | Put a - infront'
$attrib = Read-Host 'Give new company name here' #This should later change to "Give new info of Attribute you want to change"
$description = "-description"
$offeece = "-office"
$department = "-department"
$company = "-company"
$Userslist = Get-ADGroupMember $GPNAME
ForEach($User in $Userslist)
{
$user1 = $User.name
#Write-Host $user1
get-aduser -filter { name -eq $User1 } | set-aduser -company $attrib
}
at the end of the script i would like to change the -company with $whatwhat.
I have tried it, but no matter how, with the - or without, with ' and " around the - or the $whatwhat, it keeps on giving me this error.
Set-ADUser : A positional parameter cannot be found that accepts argument 'newly'
can anyone assist my to expand this script a little bit by giving the user options to choose from, or allowing him/her to type: company or description or office
you could use invoke-expression cmdlet
$cmd="get-aduser -filter { name -eq $User1 } | set-aduser $whatwhat $attrib -whatif"
invoke-expression $cmd
test :
PS>$what=read-host "attribute to change :" attribute to change ::
company
PS>$c="set-aduser test -$what 'testcpny' -whatif"
PS>iex $c
WhatIf : Opération « Set » en cours sur la cible « CN=TEST,CN=Users,DC=....,DC=com ».

Setting a domainusers P.O. Box via Powershell set-ADUser doesn't work?

I'm just wondering if anyone of you is using powershell to set a users P.O. Box via
Set-ADUser
Im comparing domainaccounts between two different domains and let my script write the differences back to one of the DCs. At the first run, the script detects that there's a different POBox on DC1 than on DC2 and writes the one from DC1 back to DC2.
This works perfectly well with all of the atributes except the postOfficeBox.
As stated above, on the first run, the script detects the changes and writes the changes back. That does not apply to the postOfficeBox however. If I open the userobject on DC2, it remains blank! What is even more strange is, that the script doesn't detect that the POBox is blank if I run it again! I have to modify the postOfficeBox manually in order for the script to see any changes again. (and with blank I mean not even spaces)
All other attributes are working fine. Is this a possible bug on Win Server 2012 and WPS?
Here's the code:
$attributes = "c","co","company","countryCode","department","displayName","postOfficeBox","sAMAccountName"
$user1 = Try{Get-ADUser -Identity $_.SamAccountName -Properties $attributes}
catch{}
$user2 = try{Get-ADUser -Identity $_.SamAccountName -Properties $attributes -Credential $AdminCredentials -Server $dc2}
catch{}
if ($user1.SamAccountName -eq $user2.SamAccountName) {
$chk_modified = #{}
$attributes | ? { $user1.$_ -ne $user2.$_ } | % {
$chk_modified[$_] = $user2.$_
}
if ($chk_modified.Count -ge 1) {
Set-ADUser -Identity $_.SamAccountName -Replace $chk_modified
}
}
I see a field in Active Directory called 'POBox' is this the field you mean?
Here is how I would update it
Get-ADUser $userName | Set-ADUser -POBox $pobox -Credential $cred
or this:
'Get-ADUser -Identity $_.SamAccountName | Set-ADUser -postOfficeBox "the new box 42" -credential $cred'
Hope this helps.