10. Bulk updates
Those faced with the task of bulk updates (either to create a
lot of new mailboxes or other objects or to modify many existing
objects) before the advent of PowerShell support for Exchange had quite
a lot of work ahead of them because Exchange offered no good way to
perform the work. You could create comma-separated value (CSV) or other
load files and use utilities such as CSVDE or LDIFDE to process data in
the files against Active Directory, or you could write your own code to
use CDOEXM or ADSI to update Active Directory. Either approach involved
a lot of detailed work and made it quite easy to make a mistake. Using
a console to make the necessary changes was boring and an invitation to
make a mistake. The cause of Exchange’s problems with bulk changes was
the lack of a programmable way to automate common management
operations, a situation that changed with the arrival of EMS.
You
can combine the Get-User and Set-Mailbox cmdlets effectively to solve
many problems. Here is an example in which you need to update the send
quota property on every mailbox for a set of users whose business group
has decided to fund additional storage. You can identify these users by
their department, which always starts with “Advanced Tech” but
sometimes varies into spellings such as “Advanced Technology” and
“Advanced Technology Group.” Conceptually, the problem is easy to solve:
Look for all users who have a department name beginning with “Advanced Tech.”
Update the send quota property for each user.
You
could use the Find option in Active Directory Users and Computers to
build a suitable filter to establish the set of users, but then you
have to open each user’s mailbox that Active Directory Users and
Computers locates to update his quota through the GUI, which could
become boring after several accounts. You could also export a
CSV-formatted list of users to a text file, manipulate the file to find
the desired users, and then process that list through CSVDE to make the
changes, but you have to search for all matching users across the
complete directory first. That is a lot of work to do.
The
process is easier in EMS. First, you use the Get-User cmdlet with a
suitable filter to establish the collection of mailboxes you want to
change. The following command returns all users who have a department
name that begins with “Advanced Tech” and then updates the
ProhibitSendQuota property to the desired amount (say, 20 GB). Because
you have a collection of user objects established, you can use the
Set-Mailbox cmdlet to perform the update. Note that some of these users
might not be mail-enabled, but error handling is another day’s work.
Get-User | Where {$_.Department –like '*Advanced Tech*'} | Set-Mailbox
–ProhibitSendQuota 20GB –UseDatabaseQuotaDefaults $False
Mergers,
acquisitions, and internal reorganizations pose all sorts of problems
for email administrators. EMS will not solve the big problems, but it
can automate many of the mundane tasks that are necessary. For example,
department names tend to change during these events. EMS makes it easy
to find all users who belong to a specific department and update their
properties to reflect the new organizational naming conventions. If
only executing organizational change were as easy as this one-line
command, which transfers everyone who works for the Old Designs
department over to the Cutting Edge Design department, things would be
much easier:
Get-User | Where {$_.Department –eq 'Old Designs'} | Set-User –Department 'Cutting Edge Design'
Note
the use of $_.Department; this indicates a value fetched from the
current pipeline object. In this case, it is the department property of
the current user object that Get-User fetched. To verify that you have
updated all the users you wanted to (and maybe provide a report to
human resources or management), you can use code like this:
Get-User | Where {$_.Department –eq 'Cutting Edge Design'} | Select Name, Department | Sort-Object Name
| Format-Table > c:\temp\Cutting-Edge.tmp
A
variation on this theme is to output the data to a CSV file to make the
data easier to work with in Microsoft Excel, Microsoft Access, or
another tool that can read CSV data.
Get-User | Where {$_.Department –eq 'Cutting Edge Design'} | Select Name, Department | Sort Name
| Export-CSV c:\temp\Cutting-Edge.CSV
Things are even easier if you just need to change everyone’s company name after your company is acquired.
Get-User | Set-User –Company 'New Company'
You can even do such things as alter only the users whose mailbox belongs to a particular database:
Get-Mailbox –Database 'VIP Mailboxes' | Set-User –company 'Big Bucks' –Department 'Executives'
Tip
All
the examples discussed so far depend on you being able to identify some
property you can use as the basis for a filter. But what about when you
do not have a common property value to check for? In this case, you can
build a simple list of mailbox names (or any other format the –Identity
parameter will accept, such as a Universal Principal Name [UPN]), use
the Get-Content cmdlet to read the names one by one, and pipe these
values to whatever other command you need to use. For example, here is
how you can use that trick to enable ActiveSync access for a set of
users. In this example, the Get-Content cmdlet reads lines containing
the identities of the mailboxes you want to change from a text file and
pipes them as input to the Set-CASMailbox cmdlet:
Get-Content c:\temp\Users.txt | Set-CASMailbox –ActiveSyncEnabled $True
Another
example of when EMS excels is when you want to apply a common setting
across all servers in your organization. For example, assume that you
want to apply a new deleted item retention limit of 150 days (perhaps
mandated by the legal department) to all servers:
Get-MailboxDatabase | Set-MailboxDatabase –DeletedItemRetention 150.00:00:00
These simple examples demonstrate the value of having a scripting language that supports automation of common management tasks.
After
you have written a script, you have to decide where to keep it. You
could put the new script in the directory that stores the Exchange
binaries, but this is a bad idea for many reasons, not least because
your script could be overwritten by the installation of a future
Exchange service pack, a roll-up update, or even a completely new
version.
The basic rule of
calling a script is that if the script is in the working directory (the
directory you are currently in), you prefix the name with “.\”
C:>.\Get-All-Users.ps1
If you’re not in the right directory, you can move to where you want to be by using the cd command:
C:> cd c:\Scripts\
Alternatively, you can supply the full path to where the script is located:
C:>c:\Scripts\Get-All-Users.ps1
If there are spaces in the directory names, then you need to enclose the path in single or double quotation marks:
C: '\Program Files\Microsoft\Exchange Server\V15\Scripts\CollectOverMetrics.ps1'
Even
better, you can amend the path PowerShell uses by looking for scripts
and adding your directory to it. For example, running this command adds
the C:\MyScripts directory to the path:
$env:path = $env:path + ";c:\MyScripts'
After a script is in a directory that’s included in the path, you can invoke it by just typing its name.