Powershell & Get-ADUser - Part 2 - Putting A & B Together - powershell

I posted a question some time ago and it was answered to accomplish what I needed - Powershell & Get-ADUser - Split OU getting the 3rd, 4th and 5th elements from the end
ANSWER GIVEN
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
}
Now I need to add some other fields (Name, SAM Account, Email) and do a check on the email*. This is my second query.
Powershell Query
$Headers= #{Label="OU Path";Expression={$_.CanonicalName}},
#{Label="Distinguished Name";Expression={$_.DistinguishedName}},
#{Label="Name";Expression={$_.DisplayName}},
#{Label="SAM Account";Expression={$_.SAMAccountName}},
#{Label="E-mail";Expression={$_.EmailAddress}},
Get-ADUser -Filter * -Properties
CanonicalName,DistinguishedName,DisplayName,
SamAccountName,EmailAddress | Select $Headers
How can I combine what it was provided in the answer of my previous question and this query to have the following output?
Also I need to check the email and if #company.com then "EType" = YES.
EXPECTED END RESULT
OU Where Type Name SAM Email *EType
-----------------------------------------------------------------------------
DS AMS N/A Name1 brname1 name1#company.com YES
DS TECHM N/A Name2 xsname2 name2#company.com YES
Developers CH Agencies Name3 agname3 name3#gmail.com NO
Developers CH Market Name4 chname4 name4#company.com YES
Developers HK Agencies Name5 agname5 name5#other.com NO
Developers HK Market Name6 hkname6 name6#company.com YES
Thank you in advance!

I believe you are looking for something like if your #Headers where correct:
Get-ADUser -Filter * -Properties CanonicalName,DistinguishedName,DisplayName,SamAccountName,EmailAddress | Select-Object #{Label="OU Path";Expression={$_.CanonicalName.Split("/")[1]}},
#{Label="Where";Expression={$_.CanonicalName.Split("/")[2]}},
#{Label="Type";Expression={if ($_.CanonicalName.Split("/").Count -ge 5) { $_.CanonicalName.Split("/")[3] } else { 'N/A' }}},
#{Label="Distinguished Name";Expression={$_.DistinguishedName}},
#{Label="Name";Expression={$_.DisplayName}},
#{Label="SAM Account";Expression={$_.SAMAccountName}},
#{Label="E-mail";Expression={$_.EmailAddress}},
#{Label="EType";Expression={ if($_.EmailAddress.IndexOf("#company.com") -gt -1) { 'YES' } else { 'NO' } }} | Format-Table

Related

Powershell - Update field in AD from 2 txt files

I'm using Powershell to update the manager attribute in AD using data from 2 txt files.
One txt file has employee IDs in one column their manager's ID in the other like this:
1111 2222
4444 3333
The other txt file has all employee info listed by IDs like this:
1111 POTTER HARRY HPOTTER 200 3108675309
2222 GRANGER HERMIONE HGRANGER 201 3107942312
HPOTTER and HGRANGER are the samaccountnames. I want to use the IDs to grab all the samaccountnames to update the manager attribute for each employee.
There are several employeeIDs listed in the first txt file that are not listed in the second txt file (they are no longer employed). I thought that wouldn't really matter, but what I wrote so far hasn't been updating every employee correctly. I rewrote it and am stuck on how to loop through $employees to get both the employee samaccountname and the manager samaccountname.
$employees = Get-Content -Path 'Staff.txt'
$supervisors = Get-Content -Path 'Supervisors.txt'
foreach($supervisor in $supervisors){
$employeeID = $supervisor.substring(0,7)
$managerID = $supervisor.substring(8,7)
foreach($employee in $employees){
if ($employee.contains($employeeID)){
$empsamName = $employee.split("`t")[3]
#some code to get the manSamName
$ADUser = Get-ADUser -Filter "samaccountname -like '$empSamName'"
$manager = Get-ADUser -Filter "samaccountname -like '$manSamName'"
if($ADUser -and $manager){
$ADUser | Set-ADUser -manager $manager
}
}
}
}
Thanks for the help!
Instead of running a loop through each line to check if it matches the employee/manager ID, uou would want to use Where-Object to find a match.
Example
$employees | Where-Object {$_ -like "*1111*"}
I've provided a full solution below that's a little more thorough, allowing you to reference each employee as a separate object, and their attributes using dot-notation
Result
Line 1
EmployeeID
EmployeeSamAccountName
ManagerID
Manager
1111
HPOTTER
2222
HGRANGER
Line 2
Employee ID 4444 no longer employed
EmployeeID
EmployeeSamAccountName
ManagerID
Manager
4444
3333
Code
$employees = Get-Content -Path 'Staff.txt'
$supervisors = Get-Content -Path 'Supervisors.txt'
$employeeTable = foreach ($employee in $employees) {
# From the staff file, split each column into an array
$employeeSplit = $employee.Split(" ")
# Create a table from all the split columns, and add this employee object into another array (the $employeeTable)
[PSCustomObject] #{
EmployeeID = $employeeSplit[0]
EmployeeFirstName = $employeeSplit[1]
EmployeeSurname = $employeeSplit[2]
EmployeeSamAccountName = $employeeSplit[3]
Manager = "" # Leave this blank #
Column5 = $employeeSplit[4]
Column6 = $employeeSplit[5]
}
}
foreach ($supervisor in $supervisors) {
# From the supervisor file, split the 2 columns into separate variables
$employeeID, $managerID = $supervisor.Split(" ")
# From the employee table, get the employee that matches the ID from column 1 of the supervisors file
$employee = ($employeeTable | Where-Object { $_.EmployeeId -eq $employeeId } )
# Continue if the employee is still employed
if ($employee -ne $null) {
# Update the employee table to add the manager's name
$employee.Manager = ($employeeTable | Where-Object { $_.EmployeeId -eq $managerID } ).EmployeeSamAccountName
# Do your stuff
$ADUser = Get-ADUser -Filter "samAccountName -eq '$($employeeTable.EmployeeSamAccountName)'"
$manager = Get-ADUser -Filter "samAccountName -eq '$($employeeTable.Manager)'"
}
# Build a new table for the supervisor file
$outputTable = [PSCustomObject] #{
EmployeeID = $employeeID
EmployeeSamAccountName = $($employee.EmployeeSamAccountName)
ManagerID = $managerId
Manager = $($employee.Manager)
}
# Sample output
Write-Host "Line $($supervisors.IndexOf($supervisor))" -BackgroundColor DarkCyan
if ($employee.EmployeeSamAccountName -eq $null) {
Write-Host "Employee ID $($employeeID) no longer employed" -ForegroundColor Red
}
Write-Host ($outputTable | ft | Out-String)
}

Split phone numbers from AD into separate columns using PowerShell

I am using the powershell script below:
Get-ADUser -SearchBase "OU=Domain Users,DC=nwvp,DC=local" -filter * -properties TelephoneNumber,DisplayName,mobile | select DisplayName,TelephoneNumber,mobile
and it gives me an output like this:
DisplayName TelephoneNumber mobile
----------- --------------- ------
Paul Strong +1 (902) 444-4444,6405 +1 (506) 111-1111
Katie White +1 (416) 333-3333,2204 +1 (905) 222-2222
I am looking for updating the format of the output like below:
LastName FirstName InternationalCode AreaCode PhoneNumber Extension DeviceType
Strong Paul 1 902 4444444 6405 Work
Strong Paul 1 506 1111111 Mobile
White Katie 1 416 3333333 2204 Work
White Katie 1 905 2222222 Mobile
How can I format the original output to get the desired output shown?
Thanks!
Check to see if the number exists and if it does then create the desired object
Get-ADUser -SearchBase 'OU=Domain Users,DC=nwvp,DC=local' -Filter * -Properties TelephoneNumber, DisplayName, mobile |
ForEach-Object {
if ($_.TelephoneNumber) {
[PSCustomObject]#{
LastName = ($_.DisplayName.Split(' '))[1]
FirstName = ($_.DisplayName.Split(' '))[0]
InternationalCode = if ($_.TelephoneNumber -match '\+(\d+)') { $Matches[1] }
AreaCode = if ($_.TelephoneNumber -match '\((\d{3})\)') { $Matches[1] }
PhoneNumber = if ($_.TelephoneNumber -match '[\d-]{7,}') { $Matches[0] -replace '\s|\-' }
Extension = if ($_.TelephoneNumber -match ',(\d+)') { $Matches[1] }
DeviceType = 'Work'
}
}
if ($_.Mobile) {
[PSCustomObject]#{
LastName = ($_.DisplayName.Split(' '))[1]
FirstName = ($_.DisplayName.Split(' '))[0]
InternationalCode = if ($_.Mobile -match '\+(\d+)') { $Matches[1] }
AreaCode = if ($_.Mobile -match '\((\d{3})\)') { $Matches[1] }
PhoneNumber = if ($_.Mobile -match '[\d-]{7,}') { $Matches[0] -replace '\s|\-' }
Extension = ''
DeviceType = 'Mobile'
}
}
}
I think you can use PowerShell Name, Expression to customize your output in required format
First store your output to an array (I think AD query give output in different data type so better to specifically define data type to array)
[array]$myArray=Get-ADUser -SearchBase "OU=Domain Users,DC=nwvp,DC=local" -filter * -properties TelephoneNumber,DisplayName,mobile | select DisplayName,TelephoneNumber,mobile
Then select the data by using n & e customization like below
$myArray|select #{n="LastName";e={([string]($_.DisplayName)).Split(" ")[1]}},
#{n="FirstName";e={([string]($_.DisplayName)).Split(" ")[0]}},
#{n="InternationalCode";e={([string]($_.TelephoneNumber)).Split(" ")[0]}},
#{n="AreaCode";e={(([string]($_.TelephoneNumber)).Split(")")[0]).Split("(")[1]}},
#{n="PhoneNumber";e={((([string]($_.TelephoneNumber)).Split(")")[1]).Split(",")[0]).Trim()}},
#{n="Extension";e={([string]($_.TelephoneNumber)).Split(",")[1]}}
I could not get how you determining the DeviceType !
check is something it is available in AD query output itself
you can check it by running -properties *
also I think First and Last name is available as a property , just check it out.

How to merge 2 properties into single output of AD Objects?

I need to merge two properties into one column, name of user is in DisplayName while Name of group is stored in Name how ever both types of objects has DisplayName, Name properties so I need to show them in one column.
Suppose Group is 'Test Group'
CN : …
ObjectGUID : 123-456-XXXX
ObjectClass: group
DisplayName:
Name: 'Test Group'
And 'Test User' Properties are
CN: …
ObjectGUID : 789-456-XXXX
ObjectClass: user
DisplayName: 'Test User'
Name:
I have tried using a for each looping but can't figure out the use of select statement.
Get-ADGroupMember -Identity $GroupGUID |
ForEach-Object{
if($_.ObjectClass -eq 'User'){
# process user object
$_ | Get-ADUser -Properties DisplayName
}elseif ($_.ObjectClass -eq 'User'){
# process group
$_ | Get-ADGroup -Properties Name
}
}
The expected output need to be
MemberName ObjectGUID
---------------- ------------------
Test Group 123-456-XXXX
Test User 789-456-XXXX
I'd use a switch statement to process each item depending on if it is a user or group, and then replace the MemberName property depending on what it is:
$Results = Switch(Get-ADGroupMember -Identity $GroupGUID){
{$_.ObjectClass -eq 'User'} {$_ | Get-ADUser -Prop DisplayName | Select *,#{l='MemberName';e={$_.DisplayName}} -ExcludeProperty MemberName}
{$_.ObjectClass -eq 'Group'} {$_ | Get-ADGroup | Select *,#{l='MemberName';e={$_.Name}} -ExcludeProperty MemberName}
}
$Results|Select MemberName,ObjectGUID
Or if you really want it all done in the pipeline you could do this:
Get-ADGroupMember -Identity $GroupGUID -PipelineVariable 'Member' | ForEach{If($Member.ObjectClass -eq 'User'){$_ | Get-ADUser -Properties DisplayName}Else{$_ | Get-ADGroup}} | Select #{l='MemberName';e={If($Member.ObjectClass -eq 'User'){$_.DisplayName}Else{$_.Name}}},ObjectGUID
i think you are wanting to merge the sources into one output object.
the usual way to add values from multiple sources into one object is to use a [PSCustomObject] to build a ... custom object. [grin] i don't have any AD access, so this is done with local user & group info. you can do some fairly complex structuring by calculating what you want to work with and stuffing it all into one neatly structured object.
here's a demo of the idea using local accounts ...
$GroupName = 'Homonymic_Tuu'
$MemberList = Get-LocalGroupMember -Group $GroupName |
Where-Object {$_.ObjectClass -eq 'User'}
$GroupInfo = Get-LocalGroup -Name $GroupName
foreach ($ML_Item in $MemberList)
{
$UserInfo = Get-LocalUser -Name $ML_Item.Name.Split('\')[-1]
if ([string]::IsNullOrEmpty($UserInfo.LastLogon))
{
$LastLogon = '_Never_'
}
else
{
$LastLogon = $UserInfo.LastLogon
}
[PSCustomObject]#{
Group_Name = $GroupInfo.Name
Group_Description = $GroupInfo.Description
User_Name = $UserInfo.Name
User_Description = $UserInfo.Description
User_Enabled = $UserInfo.Enabled
User_LastLogon = $LastLogon
}
}
truncated output ...
Group_Name : Homonymic_Tuu
Group_Description : Homonym - sounds like Tuu
User_Name : 22
User_Description : The Digit 2 Twice
User_Enabled : True
User_LastLogon : 2018-11-27 9:19:10 PM
[*...snip...*]
Group_Name : Homonymic_Tuu
Group_Description : Homonym - sounds like Tuu
User_Name : TwoTwo
User_Description : Repeating the name of the number after One.
User_Enabled : True
User_LastLogon : _Never_
the data will also export to a CSV file quite easily. [grin]

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..

In PowerShell, how can I combine the results of two commands that have a 1-to-1 relashionship?

This particular example is Get-User and Get-Mailbox (Exchange 2010). Get-User returns some of the columns I need, and Get-Mailbox some others. I am having difficulty figuring out how I can combine the results of the two into a single table with the results from both.
Get-User -Filter "..." | Get-Mailbox -Filter "..."
How do I take the results of a command similar to the above and turn it into results similar to below?
FirstName LastName Alias CustomAttribute1
--------- -------- ------ ----------------
Bob Smith bsmith Example
Johnny NoMail
Adam Blye ablye Has a Mailbox
Note that FirstName and LastName are not returned by Get-Mailbox, and conversely Alias and CustomAttributes are not returned from Get-User. Not every user has a mailbox, so sometimes a portion of the columns would be null. But I'm having a devil of a time figuring out the best way to return a combined table like this.
Get the users, save each user in a variable, get the mailbox for each user and then create a new object with properties from both variables
Get-User -Filter ... | Foreach-Object{
$user = $_
$mbx = Get-Mailbox $user
New-Object -TypeName PSObject -Property #{
FirstName = $user.FirstName
LastName = $user.LastName
Alias = $mbx.Alias
CustomAttribute1 = $mbx.CustomAttribute1
}
}
I make a custom object, which may be overkill, but it's the simplest way I've found.
Here's some sample code to play with. Let me know if it generates any trouble or additional questions:
$outputCollection = #()
$users = Get-User -Filter "..."
$mailboxes = Get-Mailbox -Filter "..."
$users | Foreach-Object {
#Associate objects
$userObject = $_
$mailboxObject = $mailboxes | Where-Object {$_.Name -eq $userObject.Name}
#Make a combined object
$outputObject = "" | Select Name, UserAttribute, MailboxAttribute
$outputObject.Name = $userObject.Name
$outputObject.UserAttribute = $userObject.UserAttribute
$outputObject.MailboxAttribute = $mailboxObject.MailboxAttribute
#Add the object to the collection
$outputCollection += $outputObject
}
$outputCollection
Another option that should work is called calculated properties:
Get-User -Filter "..." | Select Name, UserAttribute, #{Name="OtherAttribute"; Expression={(Get-Mailbox $_.Name).MailboxAttribute}}
...note that this will run a new Get-Mailbox command for each entry, potentially increasing execution time
Thank you guys. I spent a hell of a lot of time trying to figure out my own issue and your code helped me get it right. I needed to find all the calendars were the default account was set to none. Below is what I needed up using.
Get-Mailbox | ForEach-Object{
$user = $_
$calPerms = Get-MailboxFolderPermission $user":\calendar" -User Default | Where-Object {$_.AccessRights -eq "none"}
New-Object -TypeName PSObject -Property #{
Name = $user
Permissions = $calPerms.AccessRights
Users = $calPerms.user
}
}
One liner to get FirstName, LastName, Alias and CustomAttribute1:
Get-User | Select Firstname, Lastname, #{Name="Alias"; Expression={(Get-Mailbox $_.Name).Alias}}, #{Name="CustomAttribute1"; Expression={(Get-Mailbox $_.Name).CustomAttribute1}}