Search and export list of available names in AD - powershell

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

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

Powershell Cascading Foreach to export to Csv

I'm exporting my AAD users to CSV files, works fine with this code.
$allUsers = Get-AzureADUser -All $true
$users = $allUsers |
Select-Object -Property ObjectId,ObjectType,UserPrincipalName,DisplayName,AccountEnabled,AgeGroup,City,CompanyName,ConsentProvidedForMinor,Country,CreationType,Department,DirSyncEnabled,FacsimileTelephoneNumber,GivenName,IsCompromised,ImmutableId,JobTitle,LastDirSyncTime,LegalAgeGroupClassification,Mail,MailNickName,Mobile,OnPremisesSecurityIdentifier,PasswordPolicies,PhysicalDeliveryOfficeName,PostalCode,PreferredLanguage,RefreshTokensValidFromDateTime,ShowInAddressList,State,StreetAddress,Surname,TelephoneNumber,UsageLocation,UserState,UserStateChangedOn,UserType,DeletionTimestamp,AssignedLicenses,AssignedPlans,ProvisionedPlans |
ForEach-Object{
$_.DisplayName = $_.DisplayName -replace "\n", ' ' -replace '"', '`'
$_
}
$users | Export-Csv -Path $TempFileName -NoTypeInformation
$provisionedPlans = $users = $allUsers |
Select-Object -Property ObjectId,DisplayName,ProvisionedPlans
But, ProvisionedPlans comes out as a list, so I would like to export it for each entry in the list as 1 line.
This is a sample of the field
ProvisionedPlans : {class ProvisionedPlan {
CapabilityStatus: Enabled
ProvisioningStatus: Success
Service: MicrosoftCommunicationsOnline
}
, class ProvisionedPlan {
CapabilityStatus: Deleted
ProvisioningStatus: Success
Service: MicrosoftCommunicationsOnline
}
, class ProvisionedPlan {
CapabilityStatus: Deleted
ProvisioningStatus: Success
Service: MicrosoftCommunicationsOnline
}
, class ProvisionedPlan {
CapabilityStatus: Enabled
ProvisioningStatus: Success
Service: SharePoint
}
...}
So bottom line what I would like to see in the output would be
ObjectId,DisplayName,CapabilityStatus,ProvisioningStatus,Service
id1,User1,Enabled,Success,MicrosoftCommunicationsOnline
id1,User1,Deleted,Success,MicrosoftCommunicationsOnline
id1,User1,Deleted,Success,MicrosoftCommunicationsOnline
id1,User1,Enabled,Success,SharePoint
id2,User2,Enabled,Success,Whatever
So please feel free, i'm not a Powershell specialist.
Following your guidance of what you want as a bottom line please see the below adjustments to your script:
$allUsers = Get-AzureADUser -All $true
$Results = Foreach ($user in $allusers){
Foreach($Plan in $user.ProvisionedPlans){
$Plan | Select #{Name = 'ObjectId'; Expression = {$user.Objectid}},#{Name = 'DisplayName';Expression = {$user.DisplayName}},CapabilityStatus,ProvisioningStatus,Service
}
}
$Results | Export-Csv -Path $TempFileName -NoTypeInformation
I am not sure why you are replacing characters in the DisplayName but I have added this to the calculated properties in the Select Statemant.
I have also done this on the iteration of each provisioned plan as this seemed to be the easiest route.
I have removed the initial select with all of the properties as the properties you are interested in are being exported. (If you require all properties I would advise using Select * as it will pull the majority of properties in most cases and will look tidier in the code.)

Adding a ROW for missing Attribute values to Export-CSV

I using the following POWER SHELL script, to extract ( to csv ) managers name , from a "Manager" user attribute.
#This script, , Exports the Manager name of the employee`s in the TXT file.
# users.txt file - contains a simply list of user names ( samaccount-names )
Get-Content D:\powershell\permmisions\Users.txt | Foreach-Object {
Get-ADUser -Identity $_ -Properties Manager | Select-Object name, Manager | Export-Csv D:\Powershell\ADuserinformation\Export-Managers-of-specific-users.csv
-Append
}
The challenge i am facing, is when is on the exported CSV file,
the list "SKIPS" blank value-fields,In case there is no manager set for the user.
And a ROWS is not created , where MANAGER is missing.
What i would like to do , is the script to enter a charcter ( ~ ) for example, where, value is blank.
That way , a row will be created for the blank MANAGER value, on the CSV file
Please help ,
Thanks all in advance.
Note: At least the Name property should exist on all AD users retrieved, so you would get a row even for users where Manager is empty, but with an empty Manager column. If you do need to deal with possibly not all users named in Users.txt actually existing, see Theo's helpful answer.
The simplest approach is to use a calculated property:
Get-ADUser -Identity $_ -Properties Manager |
Select-Object Name, #{ Name='Manager';
Expression={ if ($_.Manager) { $_.Manager } else { '~' } } }
Note:
It is common to abbreviate the key names of the hashtable that defines the calculated property to n and e.
The if statement takes advantage of the fact that an empty string (or $null) evaluates to $false in a Boolean context; for an overview of PowerShell's implicit to-Boolean conversion, see the bottom section of this answer.
In PowerShell [Core] 7.0 or above, you could additionally take advantage of the ternary operator (<condition> ? <valueIfTrue> : <valueIfFalse>) to further shorten the command:
# PSv7+
Get-ADUser -Identity $_ -Properties Manager |
Select-Object Name, #{ n='Manager'; e={ $_.Manager ? $_.Manager : '~' } }
Note: If $_.Manager were to return $null rather than the empty string ('') if no manager is assigned, you could use ??, the PSv7+ null-coalescing operator instead: $_.Manager ?? '~'
Not concise at all, but this allows you to insert more properties of interest in your report, and does some error-checking if the user listed in your input file does not exist:
$report = foreach ($account in (Get-Content D:\powershell\permmisions\Users.txt)) {
$user = Get-ADUser -Filter "SamAccountName -eq '$account'" -Properties Manager -ErrorAction SilentlyContinue
if ($user) {
if (!$user.Manager) { $mgr = '~' }
else {
# the Manager property is the DistinghuishedName for the manager.
# if you want that in your report, just do
$mgr = $user.Manager
# if you want the Name for instance of that manager in your report,
# comment out the above line and do this instead:
# $mgr = (Get-ADUser -Identity $user.Manager).Name
}
# now output an object
[PsCustomObject]#{
UserName = $user.Name
Manager = $mgr
}
}
else {
Write-Warning "User '$account' does not exist"
}
}
# output on screen
$report | Format-Table -AutoSize
# output to CSV file
$report | Export-Csv -Path 'D:\Powershell\ADuserinformation\Export-Managers-of-specific-users.csv' -NoTypeInformation

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

Setting IDs per PowerShell script

I have a PowerShell script, which fills the Usrid custom attribute with EMP$ID value. $ID is a continuous number, which is normally stored in a text file and continuously written after setting the ID and set it one up. First I get with Get-ADUser all users without a ID, then will set the ID into Usrid attribute.
My problem is: I want to check if the ID or value exists.
If ID exists → $ID++
else → set ID from File and write it to file again
The if part in the script looks like this:
# I'm calling the content or the last ID
$lastid = Get-Content "C:\startid.txt"
# Convert the content into a decimal string
$Usrid = [System.Decimal]::Parse($lastid)
# Find out all userProxyFull Object without an ID
Get-ADObject -Filter {(objectClass -eq "userProxyFull") -and (-not(Userid -like "*"))} -Searchbase "DC=MY,DC=SEARCHBASE" -Searchscope subtree -Server myIP |
ForEach-Object {
# Then the problem part here, see description above
if ({Usrid -eq "EMP$ID"}) {
$ID++
Set-ADObject $_ -Partition "DC=my,DC=partition" -Add #{Usrid="EMP$ID"}
} else {
Set-ADObject $_ -Partition "DC=my,DC=partition" -Add #{Usrid="EMP$ID"}
}
}
But the script doesn't check. Or how can I check the highest ID and set the highest ID into Usrid attribute?
Assuming that Usrid needs to be unique you need to compare your input value against the already existing attribute values.
$existing = #{}
Get-ADUser -LDAPFilter '(UserId=*)' -Property Usrid | ForEach-Object {
$existing[$_.Usrid] = $true
}
while ($existing.ContainsKey("EMP$ID") {
$ID++
}
At this point you have a $ID where none of the existing accounts has a Usrid attribute with the value EMP$ID. Then you can go ahead and assign the attribute on all account objects where it doesn't have a value yet while incrementing $ID after each assignment:
Get-ADObject ... | ForEach {
Set-ADObject $_ -Partition "DC=my,DC=partition" -Add #{Usrid="EMP$ID"}
$ID++
}
Note, however, that the above is assuming that there are no gaps in your numbering (i.e. you don't have a situation where you have attribute values ..., EMP25, EMP26, EMP28, ...). If that assumption doesn't apply you're better off determining the next available ID by getting the highest already assigned ID and incrementing that value by 1:
$ID = Get-ADUser -LDAPFilter '(Userid=*)' -Property Usrid |
ForEach-Object { [int]($_.Usrid -replace '^EMP') } |
Sort-Object |
Select-Object -Last 1
$ID++