I need some help with a script :)
This script look in our AD for disabled accounts.
Import to CSV then "compare through 0365 and check if the user have E3 license.
So what I would need help with is maybe if else or try catch statements.
So if user are disabled in AD and have a E3 license export to CSV file.
When I ran script I get user not found red text is the maybe a way to handle all error text?
Thanks in advance
$DisabledAccounts = Get-ADUser -Filter {Enabled -eq $false} |
Select userprincipalname |
Export-csv "C:\\Temp\\disabledADUser.csv"
$user = Import-Csv "C:\\Temp\\disabledADUser"
$user | ForEach-Object {
$0365User= Get-MsolUser -UserPrincipalName $\_.UserPrincipalName |
Where-Object {($\_.licenses).AccountSkuId -match "SPE\_E3"} |
Select userprincipalnameione -ErrorAction SilentlyContinue
if ($0365User) {
Write-Host " " -ForegroundColor "red"
}else {
Write-Host "" -ForegroundColor "green"
}
}
You should avoid filtering with curly brackets : -Filter { Enabled -eq $false }, but use instead double quotes -Filter "Enabled -eq $false"
However, since you only need UserPrincipalName attributes, I would prefer Search-ADAccount cmdlet.
Search-ADAccount -AccountDisabled -UsersOnly | ForEach-Object `
-Begin { $o365Users = #() } `
-Process { $o365Users += Get-MsolUser -UserPrincipalName $_.UserPrincipalName |
Where-Object {($_.Licenses).AccountSkuId -match "SPE_E3"} |
Select UserPrincipalName -ErrorAction SilentlyContinue } `
-End { $o365Users } | Export-CSV "C:\Temp\DisabledADUserWithLicenseAttached.csv"
the -Begin parameter for the ForEach-Object cmdlet is called at start only once to create an array which is populate in the -Process block, when all users have been verified, the -End block outputs the array to be converted into a csv.
For your information MSOnline PowerShell Module will be removed at the end of the year. You should consider using the Microsoft.Graph module instead (Here some informations about license management with it). You can also use PnP.PowerShell which is a very powerfull non-Microsoft and open source module but referenced by Microsoft here.
Related
Im trying to write a script that goes through a CSV-File, searches up the Username in our AD and then gives me these users, that have a specific E-Maildomain and hasn't logged in for the last 90 days.
Here's what I got so far:
import-csv C:\pathtofile\user.csv | ForEach-Object {
Get-ADUser $_.SamAccountName -Filter "EMailAddress -like '*#thedomain.com'" -Properties SamAccountName,LastLogonDate | Where { ($_.LastLogonDate -lt (Get-Date).AddDays(-90)) -and ($_.LastLogonDate -ne $NULL)} | Sort | Select Name,SamAccountName,LastLogonDate
}
But it gives me this weird error:
Get-ADUser : A positional parameter cannot be found that accepts argument 'Username'.
I tried to put the E-Mailsorting into my where-statement, but it was not able to find any users then...
Can you guys may see what I'm doing wrong?
Thank you for your help.
Kind regards,
Gabe
You cannot use parameter -Filter together with -Identity.
(using Get-ADUser $_.SamAccountName implicitely uses the -Identity parameter)
To filter out only users that are in your CSV file AND that have a specific domain in their email address, you can do:
$refDate = (Get-Date).AddDays(-90).Date # set to midnight
$result = Import-Csv -Path 'C:\pathtofile\user.csv' | ForEach-Object {
$userSam = $_.SamAccountName
try {
$user = Get-ADUser $userSam -Properties EmailAddress, LastLogonDate -ErrorAction Stop
if (($user.LastLogonDate) -and $user.LastLogonDate -lt $refDate -and
$user.EmailAddress -like '*#thedomain.com') {
$user | Select-Object Name,SamAccountName,EmailAddress,LastLogonDate
}
}
catch {
Write-Warning "User '$userSam' not found"
}
}
To filter out all users that have a specific domain in their email address, so not using the csv at all, you can do:
$refDate = (Get-Date).AddDays(-90).Date # set to midnight
$result = Get-ADUser -Filter "EmailAddress -like '*#thedomain.com'" -Properties EmailAddress, LastLogonDate |
Where-Object { ($_.LastLogonDate) -and $_.LastLogonDate -lt $refDate } |
Select-Object Name,SamAccountName,EmailAddress,LastLogonDate | Sort-Object Name
# show the result on screen
$result | Format-Table -AutoSize
# and/or save to a new csv file
$result | Export-Csv -Path 'C:\pathtofile\filteredusers.csv' -NoTypeInformation
I'm looking to find users whos primary smtp is our domain.com that are not part of certain office365 distribution lists we have. For example Dist1, Dist2, Dist3, Dist4. I'm not very good with PowerShell but I found this script and I'm hoping someone can help me adjust this.
This script pulls the group membership of all groups.
Get-Mailbox | Where-Object {$_.PrimarySMTPAddress -like "*domain.com"} | ForEach-Object {
$user = Get-User -Identity $_.DistinguishedName
$groups = Get-Group | Where-Object {$_.Members -contains $User}
$_ | Select-Object DisplayName, Alias, PrimarySMTPAddress,
#{Name = 'Groups' ; Expression = {$groups.Name -join '; '}}
} | Export-Csv -Path 'X:\O365UserGroups.csv' -NoTypeInformation
I have made a script that checks if users whos primary smtp is your domain.com and if they are members of distributionsgroup 1 or 2. If the user is not a member of a distributionsgroup it will output this. You can add export to csv etc easily yourself.
$Users = Get-Mailbox | ? {$_.PrimarySmtpAddress -like "*domain.com"} #Enter your domain
$DistributionGroups = #("dist1","dist2") #Enter names of your distributiongroups
foreach($DistributionGroup in $DistributionGroups)
{
$DistributionGroupMembers = Get-DistributionGroupMember $DistributionGroup
foreach($User in $Users)
{
foreach($DistributionGroupMember in $DistributionGroupMembers)
{
if($DistributionGroupMember.PrimarySmtpAddress -ne $User.PrimarySmtpAddress)
{
Write-Host "$($User.PrimarySmtpAddress) missing in $DistributionGroup" #Export output here fx.
}
}
}
}
I am trying to move mailboxes to a new Exchange server on a different O365 tenant. This script is a portion of this move which attempts to list all Exchange Online users who have licenses, create a contact for each user pointing to their new email address, and forwards their email to their new address as well as their mailbox
#requires -Version 3 -Modules MSOnline
$mailboxlist = Get-Mailbox | Select-Object -Property userprincipalname |
Get-MsolUser | Where-Object -Property islicensed -EQ -Value $true |
Select-Object -Property firstname, lastname, userprincipalname |
Where-Object -Property firstname -NE -Value $null |
Format-list -AutoSize
#Begin foreach loop
foreach ($item in $mailboxlist)
{
#Create the forwarding address
$forwardingaddress = $item.firstname + '.' + $item.lastname + '#newdomain.com'
#Check for a contact, add if not present
If (!(Get-MailContact $forwardingaddress -ErrorAction silentlycontinue)){
New-MailContact $forwardingaddress -ExternalEmailAddress $forwardingaddress
}
#assign forwarding address
set-mailbox -ForwardingAddress $forwardingaddress -DeliverToMailboxAndForward $true
}
The result of the above is a $mailboxlist which is populated with first and last names and the users UPN which is also an email address. The result of $forwardingaddress is .#newdomain.com.
I don't think I am creating the initial data correctly for the foreach loop. I know that if I replace the $item.firstname with $_.firstname I get the same empty result. I would much appreciate if someone knowledgeable on the topic could assist.
Thanks!
Edit: Final config with Kiran's suggestion
#requires -Version 3 -Modules MSOnline
$mailboxlist = Get-Mailbox | Get-MsolUser | Where-Object { ($_.islicensed -eq $true) -and ($_.firstname -ne $null) }
#Begin foreach loop
foreach ($item in $mailboxlist)
{
#Create the forwarding address
$forwardingaddress = $item.firstname + '.' + $item.lastname + '#newdomain.com'
#Remove any spaces from the email address
$forwardingaddress = ($forwardingaddress -replace " ","").trim()
#Check for a contact, add if not present
If (!(Get-MailContact $forwardingaddress -ErrorAction silentlycontinue))
{
New-MailContact $forwardingaddress -ExternalEmailAddress $forwardingaddress
}
#assign forwarding address
Set-Mailbox -ForwardingAddress $forwardingaddress -DeliverToMailboxAndForward $true
}
try this:
$mailboxlist = Get-Mailbox | Get-MsolUser |
Where-Object { ($_.islicensed -eq $true) -and ($_.firstname -ne $null) }
the UserPrincipalName of get-Msoluser accepts pipeline input by propertyname so you should just pipe the output of get-mailbox to get-msoluser
select-object should be preferred over format-* commands because of the type of objects that are created.
Use format* when you want to show data on the console.
The where-object clause allows you to create complex conditions so try to combine them where you can. This should be the flow of commands:
cmdlet | where-object { some condition(s)} | select properties
This morning some awesome people helped me make a script to move user accounts based on their displayName to a certain OU. I tested and it worked. I cannibalized the script to make another one that will rename the same accounts based off of the same criteria. I've gone through several errors but basically it all boils down to "I am having an identity crisis!". I can't seem to figure out exactly what I need to input as the $Identity. Here is what I have:
Import-Module ActiveDirectory
$Renames = #(
#{
Filter = 'DisplayName -like "*Supply*"'
NewName = "Supplies"
},
#{
Filter = 'DisplayName -like "*Accountant*"'
NewName = "Accounting"
}
) | ForEach-Object {New-Object -TypeName PSCustomObject -Property $_}
$OriginOU = "OU=Test,OU=Standard Users,OU=Domain Users,DC=com"
foreach ($Rename in $Renames) {
Get-ADUser -SearchBase $OriginOU -Filter $Rename.Filter -Properties displayName |
Where-Object {($_.Enabled -eq 'True') -and ($_.DistinguishedName -notlike '*DontTouch*')} |
%{Set-ADUser $_ -DisplayName {$_.DisplayName -replace '(.EPSILON ).+',"`$1$Rename.NewName"}}
}
You can't use the current object variable ($_) if you have Set-ADUser read directly from the pipeline. And since Set-ADUser apparently doesn't play nice with scriptblock arguments, you have to put the statement in a loop:
... | % { Set-ADUser $_ -DisplayName ($_.DisplayName -replace '(.EPSILON ).+',"`$1$($Rename.NewName)") }
Note that if you want to expand object properties inside a string you have to put $Rename.NewName in a subexpression ($()), otherwise the whole object $Rename would be stringified and the string ".NewName" would be appended to it.
I have a .CSV file that I'm filling in some AD info with. The following script is supposed to fill in "Office" on a given users AD properties. The Header in the CSV file with the different "Office" names is called 'office'.
Other Info:
Exchange 2013 Hybrid Server
Forrest Functional Level = 2003 (Just demoted old dc's last week)
All DC's are now 2012 R2. Any suggestions would be appreciated.
This used to work with QADuser cmdlets so I simply found the cmdlet/parameter equivilents and changed them.
New script that doesn't work:
Import-CSV d:\scripts\ExchangeExportQuery.csv | ForEach-Object {$myOff = $_.Office if ($_.DistinguishedName -ne $null -and ($_.DistinguishedName.StartsWith("CN=")) ) {Get-User -ResultSize 'unlimited' -identity $_.DistinguishedName | foreach-object { Set-User -identity $_.DistinguishedName -Office $myOff}}}
Old script that actually worked on old exchange 2007 server with QAD cmdlets:
Import-CSV d:\scripts\ExchangeExportQuery.csv | ForEach-Object {
$myOff = $_.Office
if ($_.DN -ne $null -and ($_.DN.StartsWith("OU=")) ) {
Get-QADUser -SizeLimit 0 -SearchRoot $_.DN |
foreach-object { Set-QADUser -identity $_.DN -Office $myOff}
I may be way off here and better off starting from scratch, but any help would be appreciated.
The issue is syntax. You either need to make it multiple lines or insert a semicolon to separate commands after $myOff = $_.Office and before If (. My suggestion is the following, or make it easier to read:
Import-CSV d:\scripts\ExchangeExportQuery.csv | ForEach-Object {
$myOff = $_.Office
if ($_.DistinguishedName -ne $null -and ($_.DistinguishedName.StartsWith("CN=")) ) {
Get-User -ResultSize 'unlimited' -identity $_.DistinguishedName | foreach-object {
Set-User -identity $_.DistinguishedName -Office $myOff
} #End nested ForEach
} #End If
} #End Outer ForEach