ADUser assign specific department if null - powershell

I am trying to add users to a department when they are in a specific OU.
But I don't want to overwrite the users / alter them when it is not null. Because I don't want my file to grow.
How should I correct this?
$textfile=get-date -Format "yyyy-MM-dd"
Start-Transcript -Path "c:\results\location A\$textfile.txt"
Write-Host "Assigning / re-assigning users to a OU specific department..." -ForegroundColor Yellow
Get-ADUser -filter * -SearchBase "ou=Users,ou=Location A,ou=organization,dc=fabrikam,dc=com" |
ForEach-Object {
$user = $_
if ($user.Department -ne $null) {
try {
Set-ADUser $user -Department "Location A"
Write-Host $user.Name"moved to department" -BackgroundColor Green -ForegroundColor Black
}
catch {
Write-Host "Error occured" -BackgroundColor Red -ForegroundColor Black
}
}
}
Stop-Transcript

This is a common question about the mysteries of active directory filters. This filter will return objects with null department properties.
get-aduser -filter "department -notlike '*'" -ResultSetSize 5 -property department

as #js2010 pointed out, Get-ADUser will retrieve only a very few subset of AD properties, department, is not one of them, so when you test it, it will be always null. To avoid this add -Properties department parameter to Get-ADUser. (You should prefer his filter too, just add the searchbase you want)
But there is another problem if you want to test this after as you did, your condition is reverted : you are testing to replace only values that are already defined, -eqwill be better ;) as #iRon said, you should prefer $null -eq $user.department than $user.department -eq $null (#Theo's one is fine too)

Related

Issue with replacing a value of cell with returned variable - Incorrect formatting?

I'm currently struggling with some of the bits and pieces in my code.
I've got a SQL query that runs within powershell, that works fine, and dumps data into CSV - that's all working good.
Then, I'm importing that data into Powershell.
$csv = Import-Csv -Path "$Path" | where {$_.Fullname -ne "System created."} #this filtering is done to sort incosistent data.
And then I'm actually struggling, as I am carrying out some checks, and would like to replace a user's PIN number with a Manager's ID number.
Write-Host "initializing loop to go through each element"
foreach ($row in $csv)
{
if(($row.primarypin.length -lt 1) -or ($row.primarypin.length -gt 5) -or ($row.primarypin -contains 'T') -or ($row.primarypin -contains 'X'))
{
Write-Host "Doing Primary Check" -BackgroundColor Green
Write-Host $row.primarypin.Length
Write-Host $row.FullName
try{
$getTempUserUsername = $row.name
Write-Host "Replacing UserID with their Manager" -ForegroundColor Magenta -BackgroundColor Cyan
$getUsersManager = Get-ADUser -identity $getTempUserUsername -Properties department, Manager | Select-Object Manager
Write-Host "Replacing with String $getUsersManager"
$row.primarypin = $null
$row.primarypin -replace $null, $getUsersManager
}
catch{
Write-Host "Replacing With a Cannot find User in AD" -ForegroundColor Yellow -BackgroundColor Red
$row.primarypin -replace "Cannnot find user, this is a system user."
}
}
else
{
Write-Host "Went directly to the else loop" -ForegroundColor red -BackgroundColor Yellow
foreach($dataset in $row)
{
Write-Host "$dataset"
}
}
}
The issue here is that whenever i'm trying to do a replace, It does seem to replace it within console, however doesn't seem to be saving it correctly to CSV file (which i'm then mailing, but already got that part correctly).
Remove-Item $path
$csv | Export-Csv -Path $path -NoTypeInformation -NoClobber
So everytime I return the dataset It comes back as
"#{name=adnameexample; FullName=Lastname, Firstname; ColourCost=0.21600; Colour Pages Printed=13; primarypin=; Office=London; Department Number=}"
In this scenario I'd love for the primarypin to be returned as the manager's ID.
(I'm also trying to use try/catch in case there is some issue".
Has anyone got some idea on how to replace the data within that particular cell?
Please help guide me, wizards!
First, this command returns an object with a manager property
$getUsersManager = Get-ADUser -identity $getTempUserUsername -Properties department, Manager | Select-Object Manager
It seems you want just the value so add -Expandproperty to the Select-Object command. Just making sure you know, it will be a distinguished name. If you want just the name you'd need to look the manager up or extract it with regex. Also, why pull the department property if it's not being used? The new line can look like
$getUsersManager = Get-ADUser -identity $getTempUserUsername -Properties Manager | Select-Object -Expandproperty Manager
To just extract the name from the distinguished name here is one way.
$getUsersManager = $getUsersManager -replace '^.*?=(.*?),[a-z]{2}=.*$','$1'
Next, when you do the replace you also need to set it back to the primary pin. I would remove the set to $null and just replace whatever is in there, even if it's nothing, with the manager.
$row.primarypin = $row.primarypin -replace '.+', $getUsersManager

My Powershell Script Does Not Write Output to Logfile

My Powershell script works well enough for what I want to achieve. It polls the entered in name and places that user's groups in an array. That array loops until it deletes all listed groups. Domain Users is the only group left, but that is polled by "Get-ADPrincipalGroupMembership," not "Get-ADUser." "Domain Users" is the group the user's email ties into. Once all groups are removed from their account, they are permanently disabled, but they can still access their email for paystub information until we delete their account entirely.
That said, I'm unable to write the script's group removal output to a logfile. Ideally, this will be a .log file, but a .csv file fails as well. What am I missing? The script successfully runs without error, but nothing writes to the log file of my choice.
Here is my script:
#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 uesr'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
Start-Transcript -Path Y:\Scripts\remove_user_groups.log
Write-Host "Removing $samName " -f green -NoNewline; Write-Host "from $group" -f red
Remove-ADGroupMember -Identity $group -Members $samName
Stop-Transcript
}
} # End of if statement
} until ($response -eq 'n')
}
Disable-ADUser
Here is the solution that worked.
Write-Host "Removing $samName " -f green -NoNewline
Write-Host "from $group" -f red
$OutputLine="Removing $samName from $group"
Out-File -FilePath Y:\Scripts\remove_user_groups.log -InputObject $OutputLine -Append
Remove-ADGroupMember -Identity $group -Members $samName
Windows Server 2012 is most probably using Powershell 4. Start-Transcript ignores Write-Host in powershell Versions before 5. Use Write-Output instead.
You might aswell use the -Verbose parameter for Remove-ADGroupMember.
If you are trying to write the output of the cmdlet to a file, you can do this...
#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
Remove-ADGroupMember -Identity $group -Members $samName |
Out-File -FilePath 'Y:\Scripts\remove_user_groups.log' -Append
}
Also, there is no real reason to have this on the same line:
Write-Host "Removing $samName " -f green -NoNewline; Write-Host "from $group" -f red
... as this is not a one-liner. It is just all code on one line.
This is more prudent:
Write-Host 'Removing $samName ' -f green -NoNewline
Write-Host 'from $group' -f red
... and that screen output would still be on the same line. As a best practice. Use single quotes for simple strings, double for expansion, and some formatting use cases.

Remove certain characters from write-host output in Powershell (Get-ADuser)

I'm comparing users between two domains to make sure users that are disabled in one, are disabled in the other, using these two steps:
Domain 1:
Get-ADUser -SearchBase "OU=ou2,OU=ou1,DC=pre,DC=domain1,DC=com" -Filter * -Properties * | Select-Object Name | Export-Csv -encoding "utf8" Users.csv
Domain 2:
$input = import-csv -path "Users.csv"
ForEach ($User in $input) {
$result = get-aduser -SearchBase "OU=ou2,OU=ou1,DC=pre,DC=domain2,DC=com" -Filter "name -eq '$($User.Name)'" | Select-Object Enabled
If ($result -eq $null) { Write-host -ForegroundColor Yellow $User "Name not found. Please do a manual check"
}
elseif ($result -like '*False*')
{
Write-host -ForegroundColor Red "**" $User "** must be disabled!"
}
else {get-aduser -SearchBase "ou=Users,ou=SCS,ou=All,dc=osit,dc=ad" -Filter "name -eq '$($User.Name)'" -Properties * | Select-Object Name, Enabled}
}
This works, but gives me the following output:
Name Enabled
---- -------
Firstname1 Lastname1 True
#{Name=Firstname2 Lastname2} - Name not found. Please do a manual check
How do I remove "#{Name=" and "}"?
I have tried adding -ExtendProperity to $result, and Replace with no luck. I'm probably doing it wrong..
$User is a custom object (type [pscustomobject], as output by Import-Csv), and #{Name=Firstname2 Lastname2} is its stringified representation[1], because Write-Host stringifies its arguments for display.
Access the .Name property instead to get just the name:
Write-host -ForegroundColor Yellow $User.Name "- Name not found. Please do a manual check"
More idiomatically, using a single expandable string (string interpolation inside "..."):
Write-host -ForegroundColor Yellow "$($User.Name) - Name not found. Please do a manual check"
If you want to include the full object representation as it would appear if you printed it directly to the console, you need Out-String, but note that you'll end up with multi-line output:
Write-host -ForegroundColor Yellow "$($User | Out-String) - Name not found. Please do a manual check"
[1] You can verify this as follows: $user = [pscustomobject] #{ Name = 'Firstname1 LastName1' }; "$user". The output is string #{Name=Firstname1 LastName1}.

Powershell - Set-ADUser after Gridview

I've very new to PowerShell and just starting learn. I'm very appreciative for any help.
Here is what I'm after: I would like to set several OUs to search for AD users who have the Dial-In tab selected as True or Null (Control access through NPS Network Policy) and display the results in gridview. the first part of my script is working, at least displaying the correct users in gridview. Once user(s) are selected in gridview pass those user to have their setting changed to False (deny access).
The error I have is: Set-ADUser : Cannot validate argument on parameter 'Identity'. The argument is null.
$OUs = 'OU=Test,DC=Test,DC=net'
$users = $OUs | Foreach {
Get-ADUser -Filter {(msNPAllowDialin -eq $True) -or (msNPAllowDialin -notlike "*")} -SearchBase $_ -Properties msNPAllowDialin,description,SamAccountName |
Select-Object Name,#{Name="BT UserID";Expression={$_.SamAccountName}},Description | Sort-Object name |
Out-GridView -Title "Select One or More Users to Change Setting" -PassThru
}
$user = $users | foreach {
Set-ADUser $user -replace #{msnpallowdialin=$False}
Write-Host "$($_.name) Dial-In Setting Changed" -ForegroundColor cyan
}

Get-ADUser Check for conflicting proxyAddresses

Currently I have a script that creates user accounts.
Note: Not all users have the same UPN (UserPrincipalName)
User accounts are in the following format: <firstinit><lastname>.
If this conflicts, the format will be changed to: <firstinit><middleinit><lastname>
Recently I have ran into an issue where the user's proxyAddress is conflicting with existing users. This is a problem because AD will not catch this.
Issue:
Checking every AD-User's proxy address is very time consuming if not included in the filter. However, when including proxyAddresses in the filter the results are inconsistent. I am assuming this is because the proxyAddresses attribute is an array.
Inconsistent:
Import-Module ActiveDirectory
$FirstLast = "jrider#ChuckNorrisKills.com"
$conflictCheck = Get-ADUser -Properties mail, proxyAddresses -Filter "mail -eq '$FirstLast' -or UserPrincipalName -eq '$FirstLast' -or proxyAddresses -eq `"smtp:'$FirstLast'`"" | measure
if($conflictCheck.Count -gt 0)
{
Write-Host "New user conflicts with existing user" -ForegroundColor Red
}
I have come up with a solution that will resolve me issue. Unfortunately this is very slow (expected):
Import-Module ActiveDirectory
function Test-NewADUser
{
Param(
[Parameter(Mandatory=$true)][string]$firstname,
[Parameter(Mandatory=$true)][string]$lastname,
[Parameter(Mandatory=$false)][string]$middle
)
[bool]$proxExsists = $false
$domain = '#chuckNorrisKills.com'
$FirstLast = $firstname.Substring(0,1)+$lastname+$domain
Get-ADUser -Filter * -Properties proxyAddresses | foreach {
#xpand the proxy address and iterate through it
foreach($address in $_.proxyAddresses)
{
#As you can see this goes through every user
Write-Host "Address: " $address -ForegroundColor Yellow
if($address -eq "smtp:$FirstLast")
{
Write-Host "Found Conflict" -ForegroundColor Red
$proxExsists = $true
}
}
}
}
Test-NewADUser -firstname jack -lastname Rider
Question(s):
Is there a way to expand proxyAddresses and check for conflicts in the -Filter?
If not, should I bother with Jobs, or an alternate way of checking for conflicts?
Thank you in advance for any help
You don't need to expand it, as the proxyAddress filter should be reliable.
So, this should be very straightforward:
function Validate-proxyAddress($email)
{
if (Get-ADUser -Filter "proxyAddresses -eq 'smtp:$email'")
{
return $true
}
elseif (Get-ADUser -Filter "mail -eq '$email'")
{
return $true
}
elseif (Get-ADUser -Filter "UserPrincipalName -eq '$email'")
{
return $true
}
return $false
}
or you can join it all in one like your code, hasn't tested it, so if you get false, the user not exist, should be ok to continue...
Also, you can use -like instead of -eq if you need (in cases where missing the smtp prefix somehow):
"proxyAddresses -like '*$email*'"