Posts
254
Comments
120
Trackbacks
120
March 2007 Entries
Need some PowerShell help

Normally, when I write a blog post, I'm trying to help other people out. I forget that it can work both ways. So, today's post is a plea for help: if you know a lot about PowerShell, I could use an answer to the following three questions. If you've got any insights, please drop me an email using the Contact link.


Question the First:

I've got a script that manipulates a user's delivcontlength property in Exchange 2003. This helps me manage the situation where I've got a few users who need to be able to receive 20MB messages while most everyone else only needs 10MB. My script grabs all of the user objects in the directory, iterates through the collection, checks to see if the user is one of the special users, and if not it sets the per-user limit to be 10MB.

$ds=New-Object DirectoryServices.DirectorySearcher
$ds.Filter="(&(objectcategory=person)(objectclass=user))"
$AllUsers=$ds.FindAll()
Foreach ($User in $AllUsers) {
  $oUser=$User.GetDirectoryEntry()
  if ($oUser.sAMAccountName -ne "deving") {
    $oUser.Put("delivcontlength", "10240")
    $oUser.SetInfo()
    $oUser.psbase.RefreshCache()
  }
  $oUser | select displayname,delivcontlength
}

This script does what I want to do, but what I don't know how to do is reset the delivcontlength attribute. If there's no per-user limit set, this attribute doesn't exist on the user object -- so how do I remove an attribute through PowerShell? Setting it to 0 doesn't work.

Edit: The correct answer is to use the PutEx method, which allows you to handle a collection of attributes, as well as delete existing attributes. I'll post an updated snippet of code next week that shows how to use PutEx in live code. Thanks to Andy Webb for the answer.


Question the Second:

Continuing with the delivcontlength attribute, when I go to check its value on a single user:

$oUser.Get(“delivcontlength”)

This throws an exception if the attribute isn’t set. How do I trap that exception inside of a script so I know that the property doesn’t exist, and can do something else based on that information?

Edit: The answer, again from Andy Web, is to use the GetEx method and specify the delivcontlength as one of the attributes in the collection. Then, check to see if a value is returned in the array.


Question the Third:

Given a variable with a DN, what is the easiest way to open the corresponding object using ADSI? I've tried the following with no success:

$DN = "LDAP://red-dc01:389/CN=Devin Ganger,OU=Users,OU=3Sharp Accounts,DC=redmond,DC=3sharp,DC=com"
$oUser = [ADSI]$DN

The point, of course, is to be able to retrieve the DNs from some other list such as a CSV and perform some operation on the listed objects by iterating through with a loop.

Edit: I'm told that this should in fact work. When I go paste it into a clean instance, it does, in fact work. Weird!

posted @ Thursday, March 29, 2007 12:38 PM | Feedback (2)
Getting to know the legacy Routing Group Connector in Exchange 2007

If you install Exchange 2007 into a legacy Exchange organization (by legacy, I mean Exchange 2000/2003), the first time you install the Hub Transport (HT) role into the organization you are asked to designate one of the legacy Exchange servers as a LegacyRoutingServer. You may already know that Exchange uses this server, along with your new HT role, as the bridgeheads for a new bi-directional Routing Group Connector(RGC). This RGC connects the Exchange 2007 routing group with routing group your LegacyRoutingServer is in, thus giving your legacy Exchange server a valid route to the new Exchange 2007 servers.

However, once you go poking around inside the new Exchange Management Console, you'll quickly find that this RGC doesn't show up. It does show up if you fire up the legacy Exchange System Manager -- actually, you see the expected pair of connector objects, one in each routing group -- but if you go to look at their properties, ESM will politely tell you that the RGC objects were created in a newer version of Exchange, so keep your mitts off already. For small organizations, having a single legacy Exchange server connecting the legacy portion of the org to Exchange 2007 probably isn't that horrible, but in a larger org you may need to specify additional bridghead servers. The answer is found, of course, in the Exchange Management Shell.

As an example, let's say we have an Exchange 2003 organization with a single routing group. We set up our first Exchange 2007 HT role on machine EX27-HT01 and specified EX23-BH01 as the LegacyRoutingServer. Now, we need to rehome the legacy interoperability RGC to our permanent Exchange 2007 HT, EX27-HT02. I can use the Set-RoutingGroupConnector to modify the existing RGC (which, BTW, is named "Interop RGC"). Here's how I'd do it:

Set-RoutingGroupConnector `
  -Identity "Exchange Routing Group (DWBGZMFD01QNBJR)\Interop RGC" `
  -SourceTransportServers "EX27-HT02"
Set-RoutingGroupConnector `
  -Identity "First Routing Group\Interop RGC" `
  -TargetTransportServers "EX27-HT02"

Conversely, if we're retiring EX23-BH01 and moving the RGC to a second Exchange 2003 server, EX23-BH02, we'd do it like this:

Set-RoutingGroupConnector `
  -Identity "Exchange Routing Group (DWBGZMFD01QNBJR)\Interop RGC" `
  -TargetTransportServers "EX23-BH02"
Set-RoutingGroupConnector `
  -Identity "First Routing Group\Interop RGC" `
  -SourceTransportServers "EX23-BH02"

Note that I've enclosed the server names in quotes. You don't have to do this, but I've gotten into the habit of quoting server names for a reason: it allows me to specify multiple servers easily if I need to, without any chance of confusing PowerShell. Here's what it would look like if I wanted to designate all four of our servers in this example as bridgheads:

Set-RoutingGroupConnector `
  -Identity "Exchange Routing Group (DWBGZMFD01QNBJR)\Interop RGC" `
  -SourceTransportServers "EX27-HT01","EX27-HT02"
  -TargetTransportServers "EX23-BH01","EX23-BH02"
Set-RoutingGroupConnector `
  -Identity "First Routing Group\Interop RGC" `
  -SourceTransportServers "EX23-BH01","EX23-BH02"
  -TargetTransportServers "EX27-HT01","EX27-HT02"

For those of you running bigger organizations, you may need to have multiple legacy RGCs. There are several things to consider before you do this, and as usual, the Exchange team blog tells you all you need to know. Before you go run off and read that link, though, here's a summary of the highlights:

  • All Exchange 2007 servers in the forest are members of the same routing group, regardless of which AD domain and site they're in. As a result, Exchange 2007 message routing only takes routing groups into consideration when routing into legacy servers.
  • Exchange 2007 will always route messages through Exchange 2007 servers as long as possible, even if the legacy routing topology would be shorter. It will never try to use a shortcut through legacy RGCs to transfer a message from one Exchange 2007 server to another. Likewise, legacy Exchange servers try to route through their legacy topology as long as possible, even if the AD site topology is shorter.
  • Having multiple RGCs from the Exchange 2007 routing group to the legacy routing groups requires you to change the way linkstate updates work in Exchange 2000/2003. This prevents the possibility of message loops that would otherwise be caused by a mix of linkstate-aware routing combined with Exchange 2007's complete lack of linkstate. However, this also has implications on your legacy mailflow and is intended as a transition state only.
  • It's easier to create additional legacy interop RGCs using the New-RoutingGroupConnector cmdlet in EMS. While you can use the legacy ESM to create additional legacy interop RGCs, you'll have to make sure to do three things:
    1. Home the new RGC in the legacy routing group.
    2. Create both directions of the RGC at the same time.
    3. Add the legacy bridgehead servers to the "ExchangeLegacyInterop" group so they have the proper permissions to authenticate to the Exchange 2007 HT servers.
  • As long as you have servers in legacy routing groups, you should always have a legacy routing patch for all routing groups and RGCs to talk to each other. If you force them to communicate solely through the Exchange 2007 routing group, you will break the flow of linkstate information, and your legacy routing groups will become islands.

9/6/2007: Edited to fix the typo in LegacyRoutingServer. Thanks to fellow Exchange MVP William Lefkovics for the catch.

posted @ Tuesday, March 06, 2007 12:49 AM | Feedback (2)
Validating MD5 checksums in Windows

In my last post I briefly mentioned MD5 hash checksums. If you don't know what this is, the short version is that people who offer files for download also post the MD5 hash checksums of those files. This way, people who download the files can compute the checksums separately and see if they match. If so, the downloaders can be pretty positive the files weren't tampered with (or that if they were tampered with, the person who did not only took the time to recalculate the checksums, but posted the tampered results).

It's a great idea -- and while it may not keep your files safe if you keep your checksums in the same place you keep your files (so the attacker can easily post both the bogus checksums and the bogus files), it at least lets your downloaders know they've correctly downloaded the entire file. This is really nice when you're downloading large ISO images -- you can verify the file, at least, is good before you start making coasters.

Unfortunately, Windows doesn't offer built-in support for calculating or verifying checksums. However, there are a variety of little third-party apps that do. The one I've been using is Colony West Software's DigestIT 2004. This little puppy is very useful, because it installs as a Windows Explorer shell extension. Simply right-click on a file and you get checkcum calculation and verification options at your fingertips. Best of all, it supports not only MD5 hashes but SHA-1, and it can work with multiple files at once. Very cool!

posted @ Thursday, March 01, 2007 5:27 PM | Feedback (1)
Downloading from the Red Hat online store

For a recent project, I needed to obtain copies of the current release of Red Hat Enterprise Linux. For the most part I had a very easy time with this, but there were a couple of aspects of the experience that proved to be extremely frustrating that I wanted to share.

Getting RHEL4 was simple: head over to Red Hat's website, add the proper package to my cart, and check out. Once the purchase had been verified, I headed over to the download section of Red Hat Network to grab the ISO images. So far, so good; the Red Hat website could use a slight navigation refresh to make it a touch easier to use, and I suffered a delay in getting my purchase to go through thanks to a self-inflicted credit card handling incident, but all-in-all, it was straightforward and exactly what you'd expect to see in a modern e-commerce site.

My problems started when I created my RHN account and logged in to get my downloads. Like many online vendors, Red Hat gives you access to most (if not all) of their commercial offerings for download; when you make a purchase and get a subscription to a product, you get a subscription activation that entitles you to register that system and get updates for it. Here's where I ran into problems, and my suggestions to Red Hat for fixing them:

  • Highlight the products I've purchased. After I've purchased a product, the system should know what product entitlements I have. While giving me a list of all products is nice (see Figure 1), having some way to highlight the ones I've purchases (and would therefore be most likely to want to download) would be really useful. This is a minor gripe, granted, but given the multiple products and bundles Red Hat offers, it would make selecting the right downloads easier.

    image
    Figure 1: RHEL4 product channels
  • Generate links that don't die immediately. When you click on one of the products in Figure 1, you're taken to a page that generates custom download links for you, along with the MD5 hash verification checksums (see Figure 2). On this page, Red Hat helpfully suggests that you use a download manager or use the command-line tools wget or curl (available from Linux, but versions are also available from Windows). Again, this is really useful advice -- ISO images take time even when you're sitting on top of a T-1. However -- and this part proved to be a huge pain -- the links you're given are only good for a short amount of time before they expire and must be regenerated by relogging in to Red Hat Network and following the navigation links back to your product. I didn't test it extensively, but it felt like they were good for around four hours. While four hours is adequate to download a single image, it's not adquate to download the five installation images, the four source images, and the documentation DVD image, even if you're on one of the better-than-a-T-1 cablemodem/DSL connections available today. So even if you follow their advice and use the automated tools, you're still not going to get everything in one go. Worse, I found that they removed a file while it was being actively downloaded. Happily, I was using wget so I was able to resume the download (once I got the new URL). 4 hours? C'mon, give us at least 24. Better yet, don't be stingy and give us 72 or 96 hours to complete our downloads -- at least for files that haven't been accessed yet.

  • image
    Figure 2: RHEL4 download links
  • I'm not even going to gripe about hiding the downloads in a registration-required section; I can perfectly understand why a company might want to do that, especially when their free product is available for anyone to anonymously download. But if you're going to make it inconvenient to download files directly, at least make it so I can follow your directions and get my files downloaded without having to keep going through the inconvenient process to begin with.
posted @ Thursday, March 01, 2007 5:16 PM | Feedback (1)
News

Devin has moved on
to new adventures.
This blog is preserved
for historical purposes.

Please follow his
personal blog at:

Devin on Earth


Virtual Devin