Archive

Posts Tagged ‘script’

Script: Set-Exchange2010FilterConfig.ps1 v2.0 – Cleaner Configuration of the FilterPack for Exchange Server 2010

May 10th, 2010 2 comments

Description

Late last year, I wrote Cleaner configuration of the FilterPack for Exchange Server 2010 to provide a cleaner script that handles registration of file types for the Office 2007 Filter Pack. This was because the default script would generate a bunch of exception errors when it encountered existing registration entries in the registry. This could be fairly confusing to some people. So my script just did some rudimentary checking before attempting to set the registration. Same end result, just a little cleaner.

Anyways, fast forward to last week, when Microsoft released v2.0 of the Filter Pack. The new version includes support for Office 2010 file types, as well as all of the legacy versions. The registration script didn’t need to change, since it’s based on file extensions, and there aren’t new file extensions in 2010 (like there was in 2007).

But, some people are also installing the Adobe PDF iFilter 9.0 package to enable Exchange to index PDF file attachments as well. Like the Office Filter Pack, the PDF Filter Pack requires a PowerShell script to run to register the file types. Combine that and the update to the script mentioned at Automated prerequisite installation via PowerShell for Exchange Server 2010 on Windows Server 2008 R2 – v2.0, and combining the two filter pack registration scripts just made sense.

This version allows you to register either the Office or the PDF Filter Pack, or both. If you register the PDF Filter Pack, a server reboot is required, as is running the script .\ResetSearchIndex.ps1, which is located in the \scripts folder (typically c:\Program Files\Microsoft\Exchange Server\V14\Scripts). Resetting the search index can be somewhat taxing if there is already a large amount of mail in databases on that server, so you may want to plan when to run this.

Check out the original post for more info, and get the updated script at Set-Exchange2010FilterConfig20.zip

Installation

Execution Policy: Third-party PowerShell scripts may require that the PowerShell Execution Policy be set to either AllSigned, RemoteSigned, or Unrestricted. The default is Restricted, which prevents scripts – even code signed scripts – from running. For more information about setting your Execution Policy, see Using the Set-ExecutionPolicy Cmdlet.

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

[Redirect] Automated Prerequisite Installation via PowerShell for Exchange Server 2010 on Windows Server 2008 R2 – v2.0

May 7th, 2010 No comments

Big changes in the fairly popular script at Automated prerequisite installation via PowerShell for Exchange Server 2010 on Windows Server 2008 R2. In an effort to make your job easier (as well as mine), I’ve updated it extensively. And, I’ve used better coding practices to make it more efficient.

Changes to the script include at least the following:

  1. Downloads now use BITS on the machine. If BITS isn’t installed, the script will install it to download the files, and remove it when you exit. The script also detects whether the server you’re running it on has Internet access before trying to download files.
  2. Microsoft Office 2010 Filter Packs has replaced the 1.0 file. This adds support for indexing of content in Office 2010 file attachments in addition to the previously available Office 2007 files. For more info, see Bharat Suneja’s Released: Microsoft Office 2010 Filter Packs post.
  3. Adobe PDF iFilter 9 support has been added to (only) option #11. This adds support for indexing of .pdf files. See the Exchange Product Groups Introducing Attachment Inspection in Transport Rules for more info. Option #11 is the same as #6, but with .pdf filter, and is what I use for my server builds.
  4. Better detection of a successful installation of the filter packs
  5. Added an option (#13) to disable TCP/IP v6
  6. Updated the option (#12) to download the latest Update Rollup to get UR3
  7. Added an option (#7) due to a project requirement
  8. Removed the auto rebooting of the server if a reboot was required. It now just displays a warning that a reboot is needed before installing Exchange. This allows you to inspect what the script has done, and identify any issues, as well as execute more options, like disabling TCP/IP v6, before rebooting.

With the change in the Office filter pack, as well as the addition of the .pdf filter pack, I’ll have a new version of the configuration script for those available at Cleaner configuration of the FilterPack for Exchange Server 2010 in the next couple of days.

Visit the original post at the link above for the original info and a link to the updated script.

As always, if you’d like to see an option added, or have questions or comments, please feel free to let me know.

Script: Set-Exchange2010RedirectSSL.ps1 – Redirecting the Root Web Site to /owa and Forcing SSL in Exchange 2010

April 28th, 2010 46 comments

Exchange2010LogoA common practice is to redirect the default website to the OWA site in IIS. This allows for a shorter URL for users to remember, and catches those who don’t append “/owa “. It’s a simple enough task for an administrator to do, but I wanted to script it so that I could include it in other Exchange 2010 build scripts to help streamline the process.

Another common practice is to force SSL on specific virtual directories to help enhance security of client access to Exchange. This can take a few extra minutes, but can easily be scripted as well, so I combined both into a simple script. Some of the initial code came from colleague and Exchange Ranger Mark Smith, but I converted it to PowerShell, and added some checks and balances.

Run the script after installing Exchange, and pass it the destination to forward to. An example would be

.\Set-Exchange2010RedirectSSL.ps1 -url "https://mail.ucunleashed.com/owa"

This will redirect the root site to the URL listed. If you don’t specify the ForceSSL option, it will automatically secure the recommended virtual directories. To override that, set it to $false, such as

.\Set-Exchange2010RedirectSSL.ps1 -url "https://mail.ucunleashed.com/owa" -ForceSSL $false

The script starts by verifying the web-http-redirect feature is installed. If not, it will install it. Then, the script will backup the current IIS config, apply the changes, then do an IISRESET for them to take effect.

If you’re not sure of how to run it, there is built in help. Just run

Get-Help .\Set-Exchange2010RedirectSSL.ps1

UPDATE: I forgot to mention that the script also assigns permissions to the web.config file for the Offline Address Book to resolve a problem where downloading of the OAB would stop in the middle after configuring HTTP redirection. Microsoft Exchange PFE Bhargav Shukla has pointed out that this was mentioned in fellow MVP Henrik Walther’s post OAB issues after simplifying the OWA 2010 URL? As mentioned earlier, I got initial code from someone else, and didn’t realize that Henrik had already posted about it. So rather than go into details on the issue, please visit Henrik’s excellent post if you’d like more info. Thanks to both Henrik and Bhargav.

Installation

Execution Policy: Third-party PowerShell scripts may require that the PowerShell Execution Policy be set to either AllSigned, RemoteSigned, or Unrestricted. The default is Restricted, which prevents scripts – even code signed scripts – from running. For more information about setting your Execution Policy, see Using the Set-ExecutionPolicy Cmdlet.

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Download

v1.5 – 04-29-2014 – Set-Exchange2010RedirectSSL.v1.5.zip

v1.4 – 01-27-2014 – Set-Exchange2010RedirectSSLv1.4.zip

v1.3 – 01-30-2012 – Set-Exchange2010RedirectSSL.v1.3.zip

v1.2 – 10-19-2011 – Set-Exchange2010RedirectSSL.v1.2.zip

v1.0 – 04-26-2010 – Set-Exchange2010RedirectSSL.zip

Changelog

See the changelog for this script which details all versions and their features

Script: New-WelcomeEmail.ps1 – Automatically Sending a ‘Welcome’ Email to All New User Accounts

March 25th, 2010 47 comments

PowerShell-logo-128x84Note: I’ve updated this script to address a couple of issues. The first is that if a scheduled task was configured for a time frame other than what was configured in the script itself, this would yield sporadic results. I’ve addressed this by writing a time stamp to the registry when the script runs. This removed the requirement of configuring the time in the script itself, and provides resiliency if the script runs at different times. Run the script once manually to set the configuration. I’ve also added some code that verifies the Exchange PowerShell snapin is loaded before attempting to run. If you’d like a feature added, please let me know in the comments below.

Note #2: If you’re using a server that’s not configured for the normal U.S. style time-date format, such as in the U.K., see Neil Hobson’s post at http://neilhobson.blogspot.com/2010/11/powershell-bug.html for information.

Anything that we can do to cut down on repetitive calls to the Help Desk staff is a good thing. When a new employee starts, there are always questions about ‘what is my email address?’, and ‘how do I get to email from the web?”. For years, admins have come up with sometimes complicated methods to send a new user a canned email that tries to answer these questions. With Exchange 2007 and Exchange Management Shell (PowerShell), we can do this quite easily. In fact, the hardest part is deciding what to include in the email message. Let’s get started..

Let’s read some info from the registry to see when was the last time the script ran. If it hasn’t run before, let’s set some initial info:

$strScriptName =  $MyInvocation.MyCommand.Name
if (!(Get-ItemProperty HKLM:\Software\Innervation\$strScriptName -Name LastRun -EA SilentlyContinue)){
# this is the first time the script has run - let's create the registry key and value for future runs
New-Item -path HKLM:\Software\Innervation -EA SilentlyContinue | Out-Null
New-Item -path HKLM:\Software\Innervation\$strScriptName | Out-Null
New-ItemProperty -path HKLM:\Software\Innervation\$strScriptName -Name "LastRun" -Value (Get-Date) -propertyType String | Out-Null
write-host "Initial configuration completed." -ForegroundColor green
}
# get time stamp from registry so we know when it last ran
$LastRun = Get-Date ((Get-ItemProperty -path HKLM:\Software\Innervation\$strScriptName -Name LastRun).LastRun)
$ElapsedTime = ((Get-Date) - $lastrun).TotalSeconds

Let’s define some variables that we’ll use throughout the process.

$strMsgFrom = "Contoso HelpDesk "
$strMsgTitle = "Welcome to Contoso!"

These set the From and Title for the email that we’ll send, as well as get today’s date, and the name of the script. Next, we create a new object to allow sending SMTP email:

$SMTPClient = New-Object Net.Mail.SmtpClient("localhost")

We can replace “localhost” with the IP address of a remote hub transport server if the script is not running on a hub transport server.

Next, we get a list of mailboxes that we need to send the email to. We’ll use a scheduled task to actually run the task. I run mine every 4 hours, but the code doesn’t care how often it runs. It will use the time stamp established above to email all mailbox created since then. We also want to avoid any mailboxes that are disabled. So our query looks like this:

$MBXArray = @(Get-Mailbox -ResultSize Unlimited | ? {($_.WhenCreated -gt (Get-Date).AddSeconds(-$ElapsedTime)) -and ($_.ExchangeUserAccountControl -ne "AccountDisabled")})

We now have an array, $MBXArray, that contains all of the mailboxes that we’ll email. We now cycle through the array via ForEach, and begin to assemble a personalized email message to each user. $mailbox holds the current account in the loop, so we can pull specific info for each user. Note that the text in $strBody is completely arbitrary – you can include whatever you want. Here’s a sample of one I did for a recent client:

ForEach ($mailbox in $MBXArray ) {
$strMsgTo = $mailbox.PrimarySMTPAddress
$strMsgBody = "Hello, "+$mailbox.DisplayName+", and welcome to the Contoso family! Please keep this email for future use. It contains vital information.
--------------------------------------
Username and password
--------------------------------------
Your network username is '"+$mailbox.SamAccountName+"'. Use your username and password to login to the network. Your password should NEVER be shared with anyone except the I.T. department, and only then when requested. Please do not write it down on anything that can be seen by your coworkers. You will be prompted to change it regularly.
--------------------------------------
Email
--------------------------------------
Your email address is '"+$mailbox.PrimarySMTPAddress+"'.

To access your email, calendar, contacts, and tasks from outside of the building, such as from home, you can do so from any Internet connected computer. Simply open Internet Explorer and go to the Outlook Web Access (OWA) page at https://mail.contoso.com/ and log in using your username and password. Please note the 's' in https.

If you’d like to have access to your email and contacts from your cell phone, you will need a cell phone that has Windows Mobile 5 or later, or an Apple iPhone. Blackberry phones are not supported. Instructions for configuring your device can be found in the Frequently Asked Questions (FAQ) section of the Contoso Intranet at https://intranet.contoso.com/helpdesk/Lists/SupportFaq/AllItems.aspx
--------------------------------------
Contact information
--------------------------------------
Once you’re situated, please go to http://directory/DirectoryUpdate and update your information. Log in using your username and password. It’s important that you update your information anytime something changes, such as title, department, phone number, etc. This information is used in various systems and applications, and is your responsibility to keep up to date.
--------------------------------------
Computer, Email, and Internet policies
--------------------------------------
Contoso, Inc. provides a computer for your work tasks. The use of personally owned computers and related equipment is not permitted on our network. Additional information about use of Contoso computers, email, Internet, etc. can be found in the Employee Handbook located in the HR section of the intranet at https://intranet.contoso.com/hr/
--------------------------------------
Technical assistance
--------------------------------------
Should you need technical assistance, please check the Frequently Asked Questions (FAQ) section of the Contoso Intranet at https://intranet.contoso.com/helpdesk/Lists/SupportFaq/AllItems.aspx. If you cannot find an answer there, submit a Service Request on the Contoso intranet at https://intranet.contoso.com/helpdesk. If you are unable to access the intranet site, only then should you email HelpDesk@contoso.com. It is monitored by the whole IT department, and will ensure your issue is resolved in a timely manner.

Thank you, and, again, welcome to Contoso!
The Information Technology Department"

As you can see, we insert the user’s actual account name, email address, etc since that info is available in the ForEach loop. The message is just plain text, so spacing is preserved. URLs will be clickable links as well. Note: You’ll want to pay close attention to quotes and variables, as having an extra or missing quote can cause an error.

Now we actually send the message:

$SMTPClient.Send($strMsgFrom,$strMsgTo,$strMsgTitle,$strMsgBody)
}
# update registry here with a fresh time stamp
Set-ItemProperty HKLM:\Software\Innervation\$strScriptName -Name "LastRun" -Value (Get-Date) | Out-Null

We’ll run this script on a hub transport server. So take the script, available in the DOWNLOAD section below, and save it in your \scripts folder. You’ll also need an Exchange receive connector that will accept email sent from PowerShell scripts. For that, see Creating a receive connector to use for sending email from PowerShell. Now, schedule a task to run every 4 hours using the info in Running PowerShell scripts via Scheduled Tasks.

Point of interest: In the text I send to the users, you’ll see a link to the Directory Update (http://directory/DirectoryUpdate in the example above). This is for Directory-Update, a VERY lightweight ASP app developed by fellow MVP and author Jim McBee and another developer. It’s completely customizable, and allows users to update selected fields of their AD account to help keep the Global Address List (GAL) current. It is worth the small cost, and really helps you keep the GAL full of correct info. I have another PowerShell script that checks AD account fields, and when it finds empty fields (phone number, title, etc), it sends them an email with a link to the Directory-Update web page. Combine that with Automatically updating the Global Address List with mobile numbers from Exchange ActiveSync and it’s like a self-cleaning oven!

Installation

Execution Policy: Third-party PowerShell scripts may require that the PowerShell Execution Policy be set to either AllSigned, RemoteSigned, or Unrestricted. The default is Restricted, which prevents scripts – even code signed scripts – from running. For more information about setting your Execution Policy, see Using the Set-ExecutionPolicy Cmdlet.

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Download

v1.3 – 02-24-2013 – New-WelcomeEmail.v1.3.zip

Send-NewUserWelcome.zip

ScriptImages.zip – image files used in emails

Changelog

See the changelog for this script for information on versions and what’s included/addressed in each.

Updated: Installing Exchange 2010 Rollups on DAG servers – Now With a Script!

December 29th, 2009 1 comment

Having had to install rollups on a bunch of Exchange 2010 servers recently, I took the info from the original post Installing Exchange 2010 rollups on DAG servers and combined it all into a PowerShell script. I also updated the original article to include steps using Exchange Management Console (EMC). Take a look at the original post for the updated info and script.

Script: DAG-InstallRollup.ps1 – Installing Exchange 2010 Rollups on DAG Servers

December 15th, 2009 2 comments

As you’ve probably heard, Microsoft recently released the first rollup package for Exchange 2010. Like the Exchange 2007 versions, installation on typical servers is fairly straightforward. However, when we get to Database Availability Group (DAG) servers, there are a few more steps involved. We’ll take a look at those steps here today.

When using DAGs, the idea is to provide a high availability solution. This can include having activated databases spread among 2 or more servers. This is a fabulous feature that is quite popular. But we have to take this into account when applying updates that will either stop services, or require a reboot. We’ll need to make sure there are no activated databases on the DAG server we’re installing the rollup on. To do this, we perform two steps: stop the server from activating any more databases, and take the activated databases and activate them (make them “live”) elsewhere. This will leave us with a DAG server that has no live mailbox connections, and thus, available for updating.

First, we’ll stop the current server from activating databases using some PowerShell. On the server you’re about to update, open Exchange Management Shell and run this:

Get-MailboxDatabaseCopyStatus -Server (hostname) | Suspend-MailboxDatabaseCopy -ActivationOnly -Confirm:$false

Note the “(hostname)”, which basically just says the local server – no need to put an actual server name there (OK, I’ll admit, I’m lazy). At this point, the server will continue to have databases kept up to date, but won’t activate any if another DAG member goes down. Now we perform a switchover, which takes all databases activated on this server and activates them on another DAG node instead. In this example, we’ll activate them on Ex2 using this:

Move-ActiveMailboxDatabase -Server (hostname) -ActivateOnServer Ex2

However, if this is a case where there are more than two nodes in the DAG, we could let the system automatically determine the best mailbox server to use by not specifying the -ActivateOnServer parameter, such as this:

Move-ActiveMailboxDatabase -Server (hostname)

In either case, enter “Y” at the prompt.

This can also be accomplished via the Exchange Management Console a couple of different ways. We can manually activate the individual databases on other DAG members. To do so, open EMC, and navigate to Organization Configuration>Mailbox. Find the database(s) that need to be activated on another server, right click, and choose Move Active Mailbox Database. Click Browse and pick the server you’d like to activate it on, as shown below, and click Move. When it’s done, click Finish. Do this for each of the databases currently activated on the server you want to update.


(click for larger image)

We can also do a full switchover, activating all databases on a single DAG server, or letting the wizard pick. To do so, in EMC, go to Server Configuration>Mailbox. Right click on the server you’re going to update, and choose Switchover Server. In the resulting box, as shown below, choose “Automatically choose a target server” to have Exchange pick the best server to activate a database on, or “Use the specified server as the target of the switchover” to manually pick a server (and then click browse and pick the server).


(click for larger image)

Click Ok, and the switchover will take place. When it’s finished, there is no confirmation that it’s done. You can look in EMC at Organization Configuration>Mailbox. On the Database Management tab, verify that all databases are mounted on a server other than the one you’re updating.

Once that’s finished, we install the rollup. There really isn’t much need to detail that here – just pick ‘next’ all of the way through. It will take some time to run. Click Finish when it’s done.

Once we’re sure the installation was successful, and all services are started, we enable the server to activate databases again using this:

Get-MailboxDatabaseCopyStatus -Server (hostname) | Resume-MailboxDatabaseCopy

This doesn’t activate databases right away – it just allows the server to do so if the activated copy on another DAG node (or the node itself) goes down.

Follow this same process for the remaining servers in your DAG. Disable activation, switchover, install the rollup, and resume activation.

Once all of the servers are updated, we need to make sure that each database is active on the correct server. Each database has a parameter called ActivationPreference that lists the order of preference that a database is activated on servers that hold a copy. This can be viewed in EMS by using

Get-MailboxDatabase | Select Name, ActivationPreference, Server

The Server field shows which server the database is currently activated on, as seen here:


(click image for larger version)

You could use EMC to manually activate the databases back on the original server, or use the code or script below.

Paul Flaherty posted a couple of one liners that we’ll use here. First, we’ll activate the databases on the correct servers using this:

Get-MailboxDatabase | Sort Name | ForEach {$db=$_.Name; $xNow=$_.Server.Name ;$dbown=$_.ActivationPreference| Where {$_.Value -eq 1};  Write-Host $db "on" $xNow "Should be on" $dbOwn.Key -NoNewLine; If ( $xNow -ne $dbOwn.Key){Write-host " WRONG" -ForegroundColor Red; Move-ActiveMailboxDatabase $db -ActivateOnServer $dbOwn.Key -confirm:$False} Else {Write-Host " OK" -ForegroundColor Green}}

This will essentially look at each database, determine which server has the preference of ‘1’, and make sure the database is activated on that server.
(click image for larger version)

Then, we can verify that they are all activated correctly using another one liner from Paul:

Get-MailboxDatabase | Sort Name | ForEach {$db=$_.Name; $xNow=$_.Server.Name ;$dbown=$_.ActivationPreference| Where {$_.Value -eq 1};  Write-Host $db "on" $xNow "Should be on" $dbOwn.Key -NoNewLine; If ( $xNow -ne $dbOwn.Key){Write-host " WRONG" -ForegroundColor Red; } Else {Write-Host " OK" -ForegroundColor Green}}


(click image for larger version)

At this point, we have the rollup installed on all DAG members, and the databases are activated on the correct server. We can also take a script written by Bhargav Shukla to verify which servers have which rollup(s) installed. This is helpful in an environment with a lot of servers to help validate that they are all at the same patch level.

Update: I’ve created a quick PowerShell script that will perform many of these tasks. I used the commands listed here, as well as some basic error handling. Thanks to the contributions of others listed here, it’s now much easier. Perform steps 1 and 2 before installing the update, and 3,4, and 5 after the update.

Installation

Execution Policy: Third-party PowerShell scripts may require that the PowerShell Execution Policy be set to either AllSigned, RemoteSigned, or Unrestricted. The default is Restricted, which prevents scripts – even code signed scripts – from running. For more information about setting your Execution Policy, see Using the Set-ExecutionPolicy Cmdlet.

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Download

DAG-InstallRollup.zip

Also – if you’re installing the rollup on servers that don’t have Internet access, take a look at Installing Exchange 2007 & 2010 rollups on servers that don’t have Internet access

Set-Exchange2010FilterConfig.ps1 – Cleaner Configuration of the FilterPack for Exchange Server 2010

December 14th, 2009 No comments

One of the prerequisites for installing Exchange 2010 Hub Transport and/or Mailbox roles is the installation of the Microsoft Filter Pack. This registers IFilters so that Office 2007 attachments can be indexed. Once Exchange 2010 is installed, the filters must be registered in Exchange. Microsoft provides a PowerShell script that can be copied/pasted and used to accomplish this. But if you’ve run that script, you notice a bunch of messages about settings already existing. Also, once you’re done, you must restart the Exchange Search service.

I’ve cleaned up the PowerShell script a little to check if the setting already exists, and only attempt those that don’t. This yields a much cleaner console output. Also, the script will prompt, and execute, restating the search service. Once you’ve installed Exchange 2010, simply run the script.

Between this script and the previous script released under Automated prerequisite installation via PowerShell for Exchange Server 2010 on Windows Server 2008 R2, installation of Exchange 2010 is getting much more streamlined.

Installation

Execution Policy: Third-party PowerShell scripts may require that the PowerShell Execution Policy be set to either AllSigned, RemoteSigned, or Unrestricted. The default is Restricted, which prevents scripts – even code signed scripts – from running. For more information about setting your Execution Policy, see Using the Set-ExecutionPolicy Cmdlet.

Download

Set-Exchange2010FilterConfig.zip

Script: Set-Exchange2010Features.ps1 – Automated prerequisite installation for Exchange Server 2010

December 12th, 2009 18 comments

Update: This version resolves two bugs and adds the Adobe PDF Filter Pack and Windows Update menu options.

A while ago, fellow Exchange MVP Anderson Patricio released a script to help automate some of the tasks required before installing Exchange 2010 on Server 2008 R2. While it’s fairly straightforward to do it manually, automating the tasks can help reduce errors and issues – especially for consultants who may install Exchange 2010 often. Not long after Anderson released his script, Paul Flaherty released a revised version Bhargav Shukla released a revised version that streamlined it a little and added some functionality. Now it’s my turn.

More of an exercise to learn a method in PowerShell than anything else, I took Paul’s version and added functionality to the script. Over time, that has increased exponentially, and has become the most popular script on this site.

While SP1 added the functionality to install the required Windows features, I find this method a little nicer, as some tasks can be performed in a more structure manner. This is handy if you’re building a bunch of servers and want a standardized, error-free installation. Tasks such as disabling IPv6, downloading the latest updates, installing required Windows features, etc. are now just a menu option away.

I’ll likely tweak this some more when I have more time. But I’ve used this to build probably a dozen Exchange 2010 boxes so far, and it’s worked well. I welcome any comments or suggestions.

Installation

Execution Policy: Third-party PowerShell scripts may require that the PowerShell Execution Policy be set to either AllSigned, RemoteSigned, or Unrestricted. The default is Restricted, which prevents scripts – even code signed scripts – from running. For more information about setting your Execution Policy, see Using the Set-ExecutionPolicy Cmdlet.

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Download

v3.3 Set-Exchange2010Features.v3.3.zip

v3.2 Set-Exchange2010Features.v3.2.zip

v1.0 Set-Exchange2010Prereqs.zip

Changelog

See the changelog for information on features added in each version

Script: Add-BadPhrasesFromFile.ps1 – Importing a File of Bad Words and Phrases into the Content Filter in Exchange Server 2010

November 8th, 2009 No comments

Description

Once upon a time, we didn’t have to worry about our sensitive eyes seeing offensive words in emails. Times have changed, and now we have some built-in features to help prevent us from seeing terms and phrases that might be deemed offensive. Exchange has had the capacity to define a list of words that are considered bad, and bounce messages if it comes across a message containing any.

But that can take quite a while to manually add each one to the Content Filter, especially if you’re starting out with a long list of words you’d like to filter for. If that’s the case, PowerShell to the rescue! We can use Get-Content to open a text file, and then a ForEach loop to cycle through each line, adding each to the content filter phrase list via Add-ContentFilterPhrase. Add-ContentFilterPhrase can add words and phrases to either the GoodWord list, which will allow words through, or the BadWords list, which will get blocked.

The text file containing the words and phrases to be filtered just needs to have each word/phrase on a new line. No special formatting or anything. So if you have an existing text file, such as the sample word list previously supplied with Microsoft Forefront Security for Exchange, it will work fine. Copy this script to Notepad:

$a = hostname
If ((Get-TransportServer $a).AntispamAgentsEnabled -eq $false) {
    write-host "Please install the antivirus agents first, then rerun this script"
    exit
}
$phrases=Get-Content badwordlist.txt

if ($args[0] -ne "uninstall"){
 ForEach ($phrase in $phrases)           {
  Add-ContentFilterPhrase -Phrase $phrase -Influence BadWord
 }
}else{
 ForEach ($phrase in $phrases)           {
  write-host "Removing $phrase"
  Remove-ContentFilterPhrase -Phrase $phrase -confirm:$false
 }
}

Save that as Add-BadWordsFromFile.ps1, and your text file as badwordlist.txt in the same folder. If you’ve already installed the anti-spam agents on your transport server, then run

.\Add-BadWordsFromFile.ps1

and it will import the contents of the text file, and add them to the Content Filter. If you don’t have the anti-spam agents installed, the script will exit without trying to import the list. If you decide later that you’d like to remove the complete list from the Content Filter, just run the script again as

.\Add-BadWordsFromFile.ps1 uninstall

and it will remove those words contains in the file (preserving any other words you may have manually added).

Once the words and phrases are imported, you can view/add/remove them manually by opening Exchange Management Console and navigating to Organization Configuration>Hub Transport>Anti-spam>Content Filtering>Properties>Custom Words. You’ll see the list in the lower half of the window, as shown below:

This should make importing a list into the Content Filter a little quicker and easier. I welcome any comments.

Installation

Execution Policy: Third-party PowerShell scripts may require that the PowerShell Execution Policy be set to either AllSigned, RemoteSigned, or Unrestricted. The default is Restricted, which prevents scripts – even code signed scripts – from running. For more information about setting your Execution Policy, see Using the Set-ExecutionPolicy Cmdlet.

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Download

Add-BadPhrasesFromFile.zip

Script: Update-MobileNumber.ps1 – Automatically Updating the Global Address List with Mobile Numbers from Exchange ActiveSync

October 13th, 2009 2 comments

Description

In some organizations, the Global Address List is used extensively as a phone list and corporate directory. When that’s the case, keeping the information current can be time-consuming. Users don’t always notify you of changes, and Help Desk staff have better things to do than updating stuff like that. There are applications like fellow Jim McBee’s awesome web-based Directory Update, which provides a simple interface for users to update GAL info. But that still requires that the user take the time to update the info. Here, we’ll automate the process of updating the GAL with a new mobile number when a user syncs a new ActiveSync device for the first time.

When a user synchronizes a device, information about the device is stored in Active Directory. The info can be viewed using the Get-ActiveSyncDeviceStatistics.

Get-ActiveSyncDeviceStatistics -mailbox dbingham
FirstSyncTime         : 10/2/2009 5:45:54 PM
LastPolicyUpdateTime  : 10/2/2009 5:46:38 PM
LastSyncAttemptTime   : 10/13/2009 4:46:38 PM
LastSuccessSync       : 10/13/2009 4:46:38 PM
DeviceType            : PocketPC
DeviceID              : AF053AA9D0FE3D37C5A2AC3C77ACB9F8
DeviceUserAgent       :
DeviceWipeSentTime    :
DeviceWipeRequestTime :
DeviceWipeAckTime     :
LastPingHeartbeat     :
RecoveryPassword      : ********
DeviceModel           : RAPH800
DeviceIMEI            : 0x80046B09
DeviceFriendlyName    : Pocket_PC
DeviceOS              : Windows CE 5.2.19965
DeviceOSLanguage      : English
DevicePhoneNumber     : 5865311234
Identity              : Danielle.Bingham@mydomain.org\AirSync-PocketPC-AF053AA9D0FE3D37C5A2AC3C77ACB9F8

We see that the next-to-last field contains the device’s phone number*. So, we’ll use some code that will accomplish the following tasks:

  • Get a list of all user mailboxes
  • Get ActiveSync data for all devices that:
    • have a phone number
    • have synced for the first time in the last 24 hours
  • filter out any old devices still listed (in case a user has had more than one EAS device)
  • format the number in a human friendly version (hyphenate)
  • Update the user’s AD account with the number

That can be accomplished using the following code:

$mailboxes = @(Get-Mailbox | ? {$_.RecipientType -eq 'UserMailbox'})
ForEach ($mailbox in $mailboxes){
  $devices = @(Get-ActiveSyncDeviceStatistics -mailbox $mailbox.Alias | Where-Object {($_.DevicePhoneNumber -ne '') -and ($_.FirstSyncTime -gt (Get-Date).addhours(-24))}) | Sort-Object LastSuccessSync -descending | Select-Object -first 1
ForEach ($device in $devices){
  if($device.DevicePhoneNumber){
   $NumberLength = $device.DevicePhoneNumber.length
   if ($NumberLength -eq 10) {$DeviceNumber = $device.DevicePhoneNumber.SubString(0,3)+"-"+$device.DevicePhoneNumber.SubString(3,3)+"-"+$device.DevicePhoneNumber.SubString(6,4)}
   if ($NumberLength -eq 11) {$DeviceNumber = $device.DevicePhoneNumber.SubString(1,3)+"-"+$device.DevicePhoneNumber.SubString(4,3)+"-"+$device.DevicePhoneNumber.SubString(7,4)}
   Set-User $mailbox.Alias -MobilePhone $DeviceNumber
  }
 }
}

Copy that code to notepad and save it in your scripts folder as Update-MobileNumber.ps1. Then we just run the script via a scheduled task every 24 hours. If you don’t run it every 24 hours, make sure you adjust the (Get-Date).addhours(-24) line accordingly.

* – Most devices have the number stored there. Some devices, like the Apple iPhone, unfortunately don’t.

Installation

Execution Policy: Third-party PowerShell scripts may require that the PowerShell Execution Policy be set to either AllSigned, RemoteSigned, or Unrestricted. The default is Restricted, which prevents scripts – even code signed scripts – from running. For more information about setting your Execution Policy, see Using the Set-ExecutionPolicy Cmdlet.

Donations

I’ve never been one to really solicit donations for my work. My offerings are created because *I* need to solve a problem, and once I do, it makes sense to offer the results of my work to the public. I mean, let’s face it: I can’t be the only one with that particular issue, right? Quite often, to my surprise, I’m asked why I don’t have a “donate” button so people can donate a few bucks. I’ve never really put much thought into it. But those inquiries are coming more often now, so I’m yielding to them. If you’d like to donate, you can send a few bucks via PayPal at https://www.paypal.me/PatRichard. Money collected from that will go to the costs of my website (hosting and domain names), as well as to my home lab.

Download

Update-MobileNumber.zip.