Bulk Deleting Users from Exchange Online Protection

During an office 365 migration, I was trying to delete all users from an old unused Exchange Online Protection (EOP) tenant so that I could remove the domain then verify it on a new tenant.

I connected by powerShell and tried to use

get-user -filter * | where-object {$_.Name -like "*domain.com"} | Remove-EOPMailUser

but the command ran so slowly, only deleting about 1 user every five minutes, due to throttling on Azure Active Directory (i think)

The following command ran MUCH more quickly, allowing me to delete 2,000 users in about 5 minutes:

get-MSOLuser -all | where-object {$_.Name -match "domain.com"} | Remove-MSOLuser

PowerShell Script to Forward Email for a Bulk Set of Users

I wrote a PowerShell script for an Exchange 2007/2010 migration that will forward email for a group of users to an external SMTP recipient, while also delivering mail to the user’s inbox.  The script uses an input csv file which specifies the following: the users that need their email forwarded, the address to forward the mail to, and the name of the contact that will be created in the source domain.

The script creates the contacts, forwards the email to the contacts, enables delivery to both the source user and the target contact, and hides the contact from the GAL.
Enjoy!
#####################################################
# Bulk Contact Creation and Mail Forward Script #
# for Exchange 2007/2010 #
# Ron Williams #
# ron dot williams at mail dot com #
# 3/20/13 #
#####################################################

#INSTRUCTIONS:
# 1. Update csv file with appropriate values, make sure to the keep header row. 
# SamAccountName is the SAMaccountName from the source domain of the user 
# whose mail should forward to ext recipient.
# ForwardingAddress is the SMTP address to forward the mail to. 
# Will existing mailbox with this value as -ForwardingAddress
# FirstName is the First Name value that will be created on the contact
# LastName is the Last Name value that will be created on the contact
# 2. Run from EMS in format "C:\pathname\BulkContactForward.ps1 C:\pathname\input.csv"
# 3. Update $OU in variables section below to the OU where you want to creat the contacts.

#CSV FILE FORMAT:
# SamAccountName,ForwardingAddress,FirstName,Lastname
# joeb,joe.blow@contoso.com,Joe,Blow
# mikes,michael.smith@contoso.com,Mike,Smith

#VARIABLES
$OU="contoso.com/TestOU"

# Loop through the object returned by Import-Csv with each element represented by $person
foreach ($person in (Import-Csv .\input.csv))
 {
 # Check the Mailbox for the person exists
 If ((Get-Mailbox $person.SamAccountName -ErrorAction SilentlyContinue)) 
 { 
 # Check the mail contact doesn't exist and if not add it, hide it from GAL
 If (!(Get-MailContact $person.SamAccountName -ErrorAction SilentlyContinue)) 
 {
 New-MailContact -name $person.SamAccountName -Firstname `
 $person.FirstName -Lastname $person.lastname `
 -ExternalEmailAddress $person.ForwardingAddress -OrganizationalUnit $OU;
 Set-MailContact -identity $person.SamAccountName `
 -HiddenFromAddressListsEnabled $true
 Set-Contact $person.SamAccountName -Notes `
 "Created for Email Migration Coexistence"
 # Set the Forwarding Address on the Mailbox 
 Set-Mailbox $person.SamAccountName -ForwardingAddress `
 $person.ForwardingAddress -DeliverToMailboxAndForward $true 
 }
 else {write-host "The contact for", $person.SamAccountName, "already `
 exists. No furthur action on this contact will be performed."}
 }
 else {write-host "The mailbox for", $person.SamAccountName, "did not exist. `
 No furthur action on this mailbox will be performed."}
}

Compacting a Dynamic Hyper-V Virtual Hard Drive

If you have ever tried to use the Hyper-V “compact” command on a dynamic vhd, you have probably noticed that it very rarely reduces the vhd file size.  If you ever delete files from within the guest OS, reducing the size of the volume, you will notice that the VHD doesn’t get smaller.  I found a very quick and easy way to reduce the size of dynamic vhd’s:

  1. For best results, first defrag the drive from within the guest (optional).  If you know you have empty space on the volume, this step isn’t really necessary.
  2. Shutdown the VM and make a copy of the vhd so you will be working from a backup (obvi…)
  3. From the hyper-v host computer type diskpart in a command prompt
  4. Type the following commands within the diskpart window:
select vdisk file="C:\path\to\copy\of\backup.vhd"
attach vdisk readonly
compact 
vdisk
detach vdisk 
exit

Sort Microsoft Outlook Contacts By Date Created

Have you ever added someone to Microsoft Exchange sync’d mobile device, then forgotten their name?  BUT you know a general time period of when you added the contact?

Well, I have, and never knew how to find the “created on” attribute… but i guess I never looked very hard.  But tonight I was really feeling frisky and decided to look at all the attributes on an item in Outlook.  There’s a whole bunch of attributes that you don’t normally see, which always kinda gets me interested…   Here’s how to sort your contacts by their creation date, showing the day that you added them to your phonebook or contact list:

In Outlook 2010:

  1. Click on the contacts view in Outlook
  2. Click the View Tab in the Ribbon
  3. Click Change View>List
  4. Click View Settings
  5. Click Columns
  6. From the pulldown menu choose “All Post Views”
  7. Hilite “Created” in the list
  8. Click “Add ->”
  9. If you want, put the Created as the first in the list
  10. Click OK>OK
  11. Sort at leisure!

In Outlook 2003:

  1. Open your contacts view in Outlook
  2. Go to View>Arrange By>Current View>Phone List
  3. Go to View>Arrange By>Current View>Customize Current View
  4. Click Fields
  5. From the pulldown menu, select All Post Fields
  6. Hilite “Created” in the list
  7. Click “Add ->”
  8. Click OK>OK
  9. Check out your new “Created” column in the view. BOOM
  10. Click the Column header to sort by date.

In outlook 2007, it’s probably really similar to OL2010

Query a SQL server then add the results to a Collection in Configuration Manager 2007(SCCM/ConfigMgr)

Here is a powershell script I wrote that will be run on a schedule in ConfigMgr and does the following:
1.  Removes all members of groups specified by their Collection ID
2.  Queries a remote SQL server for a listing of server names, followed by their appropriate Collection ID
3.  Adds the members to the Collections specified in the SQL database
4.  Writes to an error log for servers that are not found in SCCM
 
Here is the Script:

Sending a Parameter or Argument to Get-Alert as a Criteria

I was having issues sending an arguemnt into a get-alert using "criteria" .  The issue was due to all of the single (or strong) quotes in the criteria statement.
 
When i add an argument, it stopped working:
(passing script an argument, still all single quotes)
get-alert -criteria ‘Id = ”$args”’
 
Scott Moss on powershellcommunity.org sent me a working example!  Thanks for your help
Here is what I am using:
get-alert -criteria "Id = ‘$($args)’"
 
thanks Scott!