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!
 

High Health Service Handle Count on RMS

If you experience a high handle count on a RMS,  apply the steps in http://support.microsoft.com/kb/938626/en-us   and apply KB951979.

If you still experience the problem, create an override to up to 50,000 handles, or create a recovery action to restart the health service.

Microsoft is aware and working on fix.

To measure health service handle count, open perfmon, and add the counter for Process>Handle Count>HealthService.exe

clip_image002

Batch Script to Force Windows Update Downloads

I recently had an issue where a client needed to quickly download and install all windows updates.  They originally had all clients pointed to a non-existent SUS server, so most of their servers and workstations were out of date.

We removed the line from the GPO that pointed the clients to the nonexistent SUS server, meaning that the agents will look on the internet for updates; however, they still didn’t get the updates.

Windows Update logs are located here:  %systemdrive%\windows\SoftwareDistribution

When I opened the log file, I saw several errors that looked like this: Windows Update Client failed to detect with error 0x80072efd.

There errors are due to the fact that windows update uses WINhttp, and the client had a proxy server configured, but did not have a proxy server set using proxcfg.

You can check to see if a proxy server is configured for WINhttp by typing proxycfg at the command prompt.

I wrote a batch script to run on all agents that updates the proxy for WINhttp, stops the windows update service, removes the registry keys that indicate when windows update last ran, restarts the service, then forces an update download.

Here is the script, save as a .bat file, and run at will!:

@echo off
REM ======================================================================
REM
REM Batch File
REM
REM NAME: Force Auto Updates Download
REM
REM AUTHOR: Ron Williams ,
REM DATE  : 4/8/2009
REM COMMENT  : Replace [proxyserverIP]:[proxyserverPort] with the ip and port of
REM              your proxy server in the format 192.168.1.2:8080  (no brackets)
REM ======================================================================

proxycfg -p [proxyserverIP]:[proxyserverPort]
net stop wuauserv
REG DELETE "HKLM\Software\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v LastWaitTimeout /f
REG DELETE "HKLM\Software\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v DetectionStartTime /f
Reg Delete "HKLM\Software\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update" /v NextDetectionTime /f
net start wuauserv
wuauclt /detectnow

Installing Additional OpsMgr Component Fails After Applying Hotfixes

Environment Details: OpsMgr SP1 on Server 2008 Std 64-bit with the following OpsMgr hotfixes applied: KB951256, KB954049, and 954903.  These KB’s are request only, and cant be uninstalled using Programs and Features like a normal OS hotfix.

I had a MonitoringHost.exe application hang error on the RMS which was causing console crashes, high CPU usage, WerFault.exe high CPU usage, and general system instability.  I determined the error might be related to the installation of .NET 1.1 which was installed on the RMS and has known compatibility issues with Server 2008.
Here is the Application Hang error i was getting:
Log Name:      Application
Source:        Application Error
Date:          1/21/2009 9:21:41 AM
Event ID:      1000
Task Category: (100)
Level:         Error
Keywords:      Classic
User:          N/A
Computer:      RMS
Description:
Faulting application MonitoringHost.exe, version 6.0.6278.0, time stamp 0x47b71488, faulting module HealthServiceRuntime.dll, version 6.0.6278.0, time stamp 0x47b71484, exception code 0x40000015, fault offset 0x0000000000004321, process id 0xf24, application start time 0x01c97bdb36ec44ea.

My Original Plan For Troubleshooting:

  1. Uninstall OpsMgr Console/Command Shell/Web Console (all of the .NET dependent components) using the Programs and Features control panel
  2. Uninstall .NET 1.1 using Programs and Features control panel (NEVER TO BE INSTALLED AGAIN)
  3. Remove the .NET 3.0 Feature using REMOVE FEATURE
  4. Reboot
  5. Reinstall only the .NET 3.0 feature using ADD FEATURE
  6. Reinstall the OpsMgr Console/Command Shell/Web Console

So I uninstalled .NET 1.1, the OpsMgr console, command shell, and web console.  Then removed the .NET 3.0 feature, rebooted, and added the .NET 3.0 feature.

Then to reinstall the OpsMgr components, I double clicked the mom.msi from the OpsMgrSP1 media, chose Console, Shell, and Web Console and hit OK.  The got a huge glaring error that the installation failed because “The file F_Microsoft.MOM.UI.Console.exe.E6A9F744_14F8_46BE_9DA9_B6BAB981D36E cannot be installed because the file cannot be found in cabinet file Data.Cab.

The following event was logged in the application log:

Log Name:      Application
Source:        MsiInstaller
Date:          1/21/2009 2:44:32 PM
Event ID:      11334
Task Category: None
Level:         Error
Keywords:      Classic
User:          FS\catapult
Computer:      RMS
Description:
Product: System Center Operations Manager 2007 — Error 1334.The file F_Microsoft.MOM.UI.Console.exe.E6A9F744_14F8_46BE_9DA9_B6BAB981D36E cannot be installed because the file cannot be found in cabinet file Data.Cab. This could indicate a network error, an error reading from the CD-ROM, or a problem with this package.

The components would not reinstall, because the product version was different due to the hotfixes that were installed.  We figured out a way to trick the installer into thinking that this was a base SP1 install by deleting contents the following registry key, after backing up the registry key

HKEY_CLASSES_ROOT\Installer\Products\DF6E5EFF035E66C49971553D96AA0E4D\Patches\
(The long number starting with DF6E5 in the path would be different on another system).  I identified the right key location, because under the long number key name,  there is a value “ProductName” which is equal to “System Center Operations Manager”. 

I copied the current value of the “Patches” value to notepad then deleted the data in the value (E525AFA…), leaving the REG_MULTI_SZ value, but just emptying it.
image

After clearing this value, I was able to reinstall the console, command shell, and web console.

Then I restored the key’s original value, and have not seen any more application hang errors.

WHEW!!!