Renaming computer based using Powershell and CSV - powershell

I'm trying to create a Powershell script that creates a CSV from a specific OU, takes the last created computer (ie computer-200), adds 1 (so computer-201) and renames the computer. I was able to create the CSV but haven't been able to add an increment of 1 to the name.
Here is the script so far:
Add-WindowsCapability –online –Name “Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0”
$OUpath = 'OU=Computers,OU=Test-Devices,DC=Test,DC=local'
$ExportPath = 'c:\temp\computers_in_ou.csv'
Get-ADComputer -Filter * -SearchBase $OUpath -Properties whenCreated | select-object Name,whenCreated | sort whenCreated | Export-Csv -NoType $ExportPath
$csvdata = Import-Csv 'c:\temp\computers_in_ou.csv'
$csvdata | Select-Object Name -Last 1 | Export-Csv -NoType 'c:\temp\renameWS.csv'
$name = Import-Csv 'c:\temp\renameWS.csv' | Select-Object Name -Last 1
The $name shows output of
Name: Computer-200
How can I take that 200 and add 1?
Thank you!

You can use replacing Regex.Replace with a script block to increment the digits in the computer's name by 1:
For example:
[regex]::Replace('computer-200', '\d+', {
param($s)
[int] $n = $s.Value; (++ $n)
})
# Results in: `computer-201`
If you have access to PowerShell Core, Replacement with a script block was added in PowerShell 6 and later:
'computer-200' -replace '\d+', {
$n = [int] $_.Value; (++ $n)
}
Following above examples, you could do the following to get the latest computer name and increment the digits by 1:
$computers = Get-ADComputer -Filter * -SearchBase $OUpath -Properties whenCreated |
Select-Object Name, whenCreated | Sort-Object whenCreated
[regex]::Replace($computers[-1].Name, '\d+', {
param($s)
[int] $n = $s.Value; (++ $n)
})

It really depends on the exact format/trustworthiness of your CSV data, but here's a non-regex way to accomplish this using your existing code.
$csvdata = Import-Csv 'c:\temp\renameWS.csv'
$split = $csvdata[-1].name.Split('-')
$addOne = [int]$split[1] + 1
$final = $split[0] + '-' + $addOne
You can then take that $final string output and append to your CSV, rename with other cmdlets, etc.

Related

Exporting certain users' samAccountName from AD to csv with only EmployeeNumbers known

I am trying to export certain users' SamAccountName and EmployeeNumber from AD to csv. I only have EmployeeNumbers from HR in csv file and have to match it to SamAccountName in AD. My code does not work past 'if' condition. When I echo output there are same values for $a and $b all in String type. This file C:\temp\UsersToDisable.csv contains 4 and 3 number with column name "EmployeeNumber". This is what i came up with:
Import-Module ActiveDirectory
$Nums = Import-Csv "C:\powershell\EmployeeNumbers.csv"
$Users = Get-ADUser -Filter "*" -Property EmployeeNumber -SearchBase
"DC=my,DC=example,DC=com" | Where { $_.EmployeeNumber -ne $null } |
Select SamAccountName,EmployeeNumber
Foreach ($user in $Users)
{
$EmployeeNumber = $user.EmployeeNumber
foreach ($Line in $Nums)
{
$number = $line.EmployeeNumber
$a = $number.toString()
$b = $EmployeeNumber.toString()
echo $a $b
if($a -eq $b)
{
echo $user.SamAccountName
$result += ,(Get-ADUser $user.SamAccountName -Properties * | Select SamAccountName,employeeNumber)
}
}
} $result | Export-CSV "C:\temp\CCI_All_Users.csv" -NoTypeInformation
Thank you for any advice!
Loading all the users from the directory and then searching once again for the same user in the directory is not an ideal solution for performance reason.
Try the following code. For each number from the input file, search in the directory the user having the current EmployeeNumber, requesting to load the EmployeeNumber property. Then select only the desired properties and export them to CSV.
Import-Module ActiveDirectory
$Nums = Import-Csv "C:\powershell\EmployeeNumbers.csv"
$Nums | ForEach-Object {
Get-ADUser -LdapFilter "(EmployeeNumber=$_)" -Property EmployeeNumber -SearchBase "DC=my,DC=example,DC=com" |
Select-Object SamAccountName, EmployeeNumber
} | Export-CSV "C:\temp\CCI_All_Users.csv"
An alternative to Hazrelle's helpful answer, very similar but instead of looping over each line of the CSV, taking advantage of the LDAPFilter capabilities with the help of some string manipulation:
# This assumes there is a column named "EmployeeNumber" in the CSV
$Nums = (Import-Csv "C:\powershell\EmployeeNumbers.csv").EmployeeNumber
# Assuming Nums is an Array with Employee Numbers. i.e.:
# $Nums => A123,A456,A789
# $filter would look like this:
# (|(employeenumber=A123)(employeenumber=A456)(employeenumber=A789))
$filter = [string]::Format(
'(|(employeenumber={0}))',
($Nums -join ')(employeenumber=')
)
$params = #{
Properties = 'EmployeeNumber'
SearchBase = 'DC=my,DC=example,DC=com'
LDAPFilter = $filter
}
Get-ADUser #params | Select-Object samAccountName, EmployeeNumber |
Export-CSV "C:\temp\CCI_All_Users.csv" -NoTypeInformation
Worth mentioning, $result += ,(Get... is not recommended.

Importing CSV splits certain lines

I have a fairly simple script that needs to check around 20,000 AD Groups for their membership count. That all works fine, I can take the list of groups run it through the script and for the most entries it works fine. However I was getting some errors that I couldn't figure out and hopefully someone here can point me in the right direction.
I am using the DN of the object to query AD and for around 10% it fails, but when I copy the DN from the file, paste it into a command window and run the command manually it works fine. Some more checking and it seems that when I read an offending line into my variable there is a line break in the middle for some reason.
When looking at the value of the variable I get the following:
Working Example - "CN=ABC, OU=Location, OU=Distribution Lists, DC=Domain, DC=COM"
Error Example - "CN=ABC, OU=Location, OU=Distribution
Lists, DC=Domain, DC=COM"
It seems to insert a return in-between Distribution and Lists on certain entries in the file. I have tried deleting the character in-between and replacing it with a space but I get the same result.
Could it be the length? I am still looking for a common factor but any suggestions would be great.
Thanks
Updated with requested content.
$Groups = Import-Csv C:\Temp\DLName.csv
write-host ($Groups).Count
$i=1
foreach ($Group in $Groups)
{
$GroupInfo = Get-ADGroupMembersRecursive -Groups $Group.Name
$MembersCount = ($GroupInfo | Measure-Object).Count
$MembersList = $GroupInfo | Select Name -ExcludeProperty Name
$FriendlyName = Get-ADGroup -Identity $Group.Name
$Export = $FriendlyName.Name + ", " + $MembersCount
$Export | Out-File C:\Temp\DLMembers.csv -Append
Write-host $FriendlyName "," $MembersCount
$i
$i++
}
Entry 1 and 3 work 2 doesn't, but the formatting here seems to have wrapped the entries.
Name
"CN=Company - DL Name1,OU=Country1 Distribution Lists,OU=Europe,OU=Acc,DC=Domain,DC=Domain,DC=com"
"CN=Company - DL Name2,OU=Country2 Distribution Lists,OU=Europe,OU=Acc,DC=Domain,DC=Domain,DC=com"
"CN=Company - DL Name3,OU=Country3 Distribution Lists,OU=America,OU=Acc,DC=Domain,DC=Domain,DC=com"
Top pic is the failure second pic works.
List Creation:
$SearchScope = "OU=OUName,DC=Domain,DC=Domain,DC=com"
$SearchFilter = {GroupCategory -eq 'Distribution'}
$Groups = Get-ADGroup -SearchBase $SearchScope -Filter
$SearchFilter | Sort-Object Name
foreach ($Group in $Groups)
{
$Group.DistinguishedName | Select Name -ExpandProperty Name
$Group.DistinguishedName | Out-File C:\Temp\DLName.csv -Append
}
Do not use a self-combined comma separated string and Out-File to create CSV files, because that will get you into trouble when fields happen to contain the delimiter character like in this case the comma (which will lead to mis-aligned data).
Your List Creation code should be like this:
$SearchBase = "OU=OUName,DC=Domain,DC=Domain,DC=com"
$SearchFilter = "GroupCategory -eq 'Distribution'"
Get-ADGroup -SearchBase $SearchBase -Filter $SearchFilter |
Sort-Object Name | Select-Object Name, DistinguishedName |
Export-Csv -Path 'C:\Temp\DLName.csv' -NoTypeInformation
Then you can use that csv later to do:
$Groups = Import-Csv -Path 'C:\Temp\DLName.csv'
Write-Host $Groups.Count
$result = foreach ($Group in $Groups) {
$GroupInfo = Get-ADGroupMember -Identity $Group.DistinguishedName -Recursive
# unnecessary.. $MembersCount = ($GroupInfo | Measure-Object).Count
# unused.. $MembersList = $GroupInfo.Name
# unnecessary.. $FriendlyName = Get-ADGroup -Identity $Group.Name
# output an object with the wanted properties
[PsCustomObject]#{
GroupName = $Group.Name
MemberCount = #($GroupInfo).Count # #() in case there is only one member in the group
}
}
# show on screen
$result | Format-Table -AutoSize
# output to CSV file
$result | Export-Csv -Path 'C:\Temp\DLMembers.csv' -NoTypeInformation
As you can see, I'm not using your custom function Get-ADGroupMembersRecursive because I have no idea what that outputs.. Also, there is no need for that because you can use the Get-ADGroupMember cmdlet with the -Recursive switch added

Active Directory Powershell to fixed width txt file

Trying to export 4 objects from Ad to a fixed-width txt file with no header.
I need the following columns to be the width that follows.
Employee ID 10
Work Phone 10
Work Phone Extension 5
Work Email Address 50
User ID 20
The following gives me the best output, but doesn't size the columns the way I need. I have been digging around, and think what I need is a bit beyond what I'm comfortable with.
I'm not sure if i need to export with export-csv and then import that into reformat or if I can do out-file directly.
$DateTime = Get-Date -f "yyyyMMdd"
#// Set CSV file name
$CSVFile = "d:\scripts\workday\int002_"+$DateTime+".txt"
Get-ADGroup -Filter {(name -like "*Group Name*")} `
| Get-ADGroupMember -Recursive | Where { $_.objectClass -eq "user" } `
| Get-ADUser -properties * | where {$_.enabled -eq $true} `
| select employeeid,telephoneNumber,mail,sAMAccountName -unique | FT employeeid,telephoneNumber,mail,sAMAccountName -hidetableheaders -autosize | out-file $CSVFile
Sample Output:
8855 2122445710 xxxry.michalsen#companydomain.com michalsenm
You might need to do it manually...
$result = foreach($user in $users) {
$user.employeeid.PadRight(10),
$user.telephoneNumber.PadRight(10),
$user.mail.PadRight(50),
$user.sAMAccountName.PadRight(20) -join ' '
}
$result | Out-File $CSVFile
A revised version that also works if the property is not a string:
$result = foreach($user in $users) {
'{0,-10}{1,-10}{2,-50}{3,-20}' -f
$user.employeeid,
$user.telephoneNumber,
$user.mail,
$user.sAMAccountName
}
$result | Out-File $CSVFile

Get-ADuser and export to multiple CSV files

I'm using the following command to grab users from an OU and export to csv file:
Get-ADUser -Filter * -SearchBase 'OU=Contoso Users,OU=Contoso,DC=domain,DC=local' -Properties * | Select UserPrincipalName, EmailAddress | Sort UserPrincipalName | Export-CSV $UsersToMigrate -NoTypeInformation -Force
Is there anyway to export to multiple csv files of 10 users per file?
Append to the respective output file in a loop and use a counter and integer division to determine the actual filename.
$i = 0
... | Sort UserPrincipalName | ForEach-Object {
$csv = "C:\path\to\output_$([Math]::Floor([int]$i/[int]10)).csv"
$_ | Export-Csv $csv -NoType -Append
$i++
}
$Users = Get-ADUser -Filter * -SearchBase 'OU=Contoso Users,OU=Contoso,DC=domain,DC=local' -Properties * | Select UserPrincipalName, EmailAddress | Sort UserPrincipalName
$Users | ForEach-Object -Begin {$i = 1} {
$_ | Export-CSV "$UsersToMigrate-$([Math]::Ceiling($i++ / 10)).csv" -NoTypeInformation -Append
}
Explanation
Iterates through the collection of users with ForEach-Object, initialising a counter variable $i as 1 in a Begin block first.
Divides the counter by 10 and rounds up to the nearest integer. Uses this as part of the CSV name and exports to the CSV with the -Append switch (requires PSv3+ I believe).

Output department and direct reports

I am trying to create an "initial" text file that will hold a script run of all users + department + direct reports. My next step after making this file is to create another file the same way but compare it to the original to see if the department for the users ever changed. (not sure yet how to compare the department value just yet)
My current issue is that the department, even though the process is identical to another program I have made in the past, won't print it. Furthermore, when it prints my direct reports it prints only the first one with the whole extension of CN=..., OU=... etc.
I want it to print this way:
username | Department(extensionAttribute14) | Direct Reports (as a single string)
we38432 | IT-Security | cm03456: 04555a: ....etc
My original script used this code for department:
$deps = Get-Aduser -filter {name -like *} -Properties name, extensionAttribute14 | Select name, extensionAttribute14 | Export-CSV $listing -notypeinformation
and this worked. I tried the {name -like *} but that gave me errors in my current program. I know the Export-CSV makes it work but I can't use this format anymore.
for the direct reports my original was this:
foreach ($ID in $directReports){
if ($ID -ne $Null){
$directreports = get-aduser $ID
$directreports.name | Out-File $output -Append
}
This code printed line by line the direct reports but I want them all listed in the same excel cell when I send it there.
I have printed a listing of all the members in the past using ":" and it worked but it is not the case with the direct reports listing. I just get errors when I use this format from my other program:
foreach ($member in $empty.members){
$string = $member.substring(3,$member.indexof(",")-3)
$members = $members + ":" + $string
}
I hope someone can help me with my two issues.
Import-Module ActiveDirectory
$documentOld = "C:\Temp\Old_Supervisor_list_mo_yyyy.txt"
Clear-Content $documentOld
$Header = `
"User ID" <#+ "|" + `
"Department" + "|" + `
"Direct Reports"#>
$Header | Out-File $documentOld -Append
$Users = Get-AdUser -Filter * -Properties name, Enabled, Manager, extensionAttribute14 | Select Enabled, name, Manager, extensionAttribute14
foreach ($user in $Users){
if ($user.enabled –eq $true) {
$name = $user.name
$directReports = Get-ADUser -Identity $name -Properties directreports | Select -ExpandProperty directreports
$department = $user.extensionAttribute14
foreach ($ID in $directReports){
if ($ID -ne $Null){
$directreports = get-aduser $ID
# $string = $directreports + ":"
}#end if $ID
}#end foreach $ID
$listing = `
$name + "|" + $deparment + "|" + $directreports#$string
$listing | Out-File $documentOld -Append
}# end if
}# end foreach $user
Let see if we can make this a little easier and efficient.
Import-Module ActiveDirectory
$documentOld = "C:\Temp\Old_Supervisor_list_mo_yyyy.txt"
$Users = Get-AdUser -Filter * -Properties name,Enabled,Manager,extensionAttribute14 | Where-Object{$_.Enabled}
$Users | ForEach-Object{
$props = #{
Name = $_.Name
Department = $_.extensionAttribute14
DirectReports = ($_.Manager | Where-Object{$_} | ForEach-Object{Get-Aduser $_ | Select-object -ExpandProperty Name}) -join ":"
}
New-Object -TypeName psobject -Property $props
} | Select-Object Name,Department,DirectReports | Export-CSV -Delimiter "|" -NoTypeInformation -Path $documentOld
First we get all the users from your directory with Get-AdUser -Filter * taking all the properties outside the norm that we want. Since you just wanted accounts that are enabled we filter those out now with Where-Object{$_.Enabled}.
The fun part is creating the custom object array ( which is necessary for input for Export-CSV). Create a small hashtable called $props where we set the properties by their friendly names. The special one being DirectReports where we take all the users manager DN's ( Assuming they have one where is what Where-Object{$_} does by filtering out nulls/empty strings.) and use Get-Aduser to get there names. Since you could have more than one manager an array is most likely returned we use -join to ensure only a single string is given for the DirectReports property. That property collection is created for every user and it is then used to create a New-Object which is sent to the output stream.
The Select-Object that follows is just to ensure the order of columns in the CSV that is created. No need for making a CSV file with lots of Out-Files when Export-CSV and -Delimiter "|" will do the hard work for you.