Split phone numbers from AD into separate columns using PowerShell - 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.

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)
}

How to look for Active Directory group name from csv in PowerShell?

If I have a .csv:
ClientCode,GroupCode
1234,ABC
1234,DEF
1235,ABC
1236,ABC
and I want to get a hashtable with ClientCode as key, and values to be all AD groups with ClientCode in it, for example:
ClientCode GroupCode
---------- ---------
1234 ClientGroup_InAD_1234, some_other_client_1234
1235 ClientGroup_InAD_1235, some_other_client_in_AD_1235
1236 ClientGroup_InAD_1236
How do I go about this?
Essentially, I have client groups in Active Directory and each client has a code which is the same as the 'ClientCode' in the csv. For example, I might have a client called 'Bob' which I have assigned a code '1234' to it. Therefore, the Group for Bob in the AD would be 'Bob_1234'. Essentially I want to be able to search for whatever groups have ClientCode in them. So i want to search for the all the AD groups that have '1234'. This would return 'Bob_1234' and whatever group in the AD also has '1234' in its name.
So far I have tried:
$clientTable = #{}
foreach($rec in $csv_data) {
$groups = #(get-adgroup -Filter "name -like '*$($rec.clientcode)_*'")
write-host "Found $($groups.count) group(s) for: $($rec.clientcode)"
$clientTable[$ClientCode] = #($groups)
}
$clientTable
but I'm not getting my desired output
You can use the loop like this. You will need to search with a * at the beginning of the name you are looking to find via the Filter.
foreach($rec in $csv) {
$clientCode = "*_$($rec.ClientCode)"
if (!($clientTable.ContainsKey($clientCode))) {
$names = Get-ADGroup -Filter 'Name -like $clientCode' | select Name
$clientTable[$clientCode] = $names -join ","
}
}
This will also check for any client IDs that have already been checked and ignore those.
If you want a hash table populated with the ClientCode value as the key name, you can do the following:
$clientTable = #{}
foreach($rec in $csv_data){
$groups = #(Get-ADGroup -Filter "Name -like '*_$($rec.ClientCode)'" | Select -Expand Name)
write-host "Found $($groups.count) group(s) for: $($rec.ClientCode)"
$clientTable[$rec.ClientCode] = $groups
}
$clientTable
Keep in mind here that each value in the hash table is an array of group names. If you want a single string with comma-delimited names, you can do $clientTable[$rec.ClientCode] = $groups -join "," instead.
You will need to de-duplicate the ClientCodes in the CSV before retrieving the groups.
Something like below should do it (assuming the ClientCode is always preceded by an underscore like in _1234 as shown in your examples)
$csv = Import-Csv -Path 'ClientGroupCodes.csv'
$clientTable = #{}
$csv | Select-Object -ExpandProperty ClientCode -Unique | ForEach-Object {
# $_ is a single clientcode in each iteration (string)
# get an array of goup names
$groups = #(Get-ADGroup -Filter "Name -like '*_$_'" | Select-Object -ExpandProperty Name)
Write-Host "Found $($groups.Count) group(s) for code : '$_'"
$clientTable[$_] = $groups -join ', '
}
$clientTable

Search and export list of available names in AD

I have AD with a lot of computers in it. computer names are made like this: XXXXNNNN (where X=constant part and N=numeric dynamic part of the name). Any thoughts how can I scan names from N=0 --> N=Nmax, and export all unused (free) names to *.txt?
[int]$NMax = (Get-ADComputer -Filter {name -like "XXXX*"} | Sort-Object name | select -ExpandProperty name -Last 1).SubString(4, 4)
$i = 0001
while ($i -ne ($NMax+1))
{
try
{
Get-ADComputer ("XXXX"+$($i.ToString("D4"))) | select name | out-null
}
catch
{
write "No ADComputer with the name: XXXX$($i.ToString("D4"))"
}
$i++
}

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

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

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