Welcome to TechNet Blogs Sign in | Join | Help

Using C# to get to MultiValuedProperty

Today's post is to address a question we dealt with fairly recently through a customer escalation. The customer was trying to figure out the best way to programmatically get access to the entries in a MultiValuedProperty collection returned as part of an Exchange object.

Specific example we'll use here: Read in one or more mailbox objects (using Get-Mailbox cmdlet) and then iterate across and output some properties. Since we're outputting "Name" and "EmailAddresses" properties here, one will be a singleton ("Name") and one will be a collection ("EmailAddresses").

To accomplish extracting this data, immediately the customer had driven straight into the Exchange.Management namespaces looking for Mailbox. But that's not the right approach. Vivek talks about why in this blog post, but the short version is that there's nothing to be gained by tying your code directly into Exchange (no useful public methods and limited benefit from the property strong-types) and quite a bit to be lost (you become tied to the assembly version, etc).

So, how then do you do it? Well, you use PSObject and non-Exchange types everywhere. There's a pretty good starter example in Technet: http://msdn2.microsoft.com/en-us/library/bb332449.aspx

Which leads to the customer's real question -- "I can get the object, but how do I drill into the strong-type properties that are of types like MultiValuedProperty?"

Good news! MultiValuedProperty type implements ICollection, so it's actually pretty simple. When you extract the property value, just cast it as ICollection and you're golden!

Here's some sample code (based on the Technet code) with a few comments added:

    RunspaceConfiguration rsConfig = RunspaceConfiguration.Create();
    PSSnapInException snapInException = null;
    PSSnapInInfo info = rsConfig.AddPSSnapIn("Microsoft.Exchange.Management.PowerShell.Admin", out snapInException);
    Runspace myRunSpace = RunspaceFactory.CreateRunspace(rsConfig);
    myRunSpace.Open();

    Pipeline pipeline = myRunSpace.CreatePipeline();
    Command myCommand = new Command("Get-Mailbox");

    pipeline.Commands.Add(myCommand);

    Collection<PSObject> commandResults = pipeline.Invoke();

    // Ok, now we've got a bunch of mailboxes, cycle through them
    foreach (PSObject mailbox in commandResults)
    {
        //define which properties to get
        foreach (String propName in new string[] { "Name", "EmailAddresses" })
        {
            //grab the specified property of this mailbox
            Object objValue = mailbox.Properties[propName].Value;
            // is it a collection? "Name" isn't, but "EmailAddresses" is in this example
            if (objValue is ICollection)
            {
                ICollection collection = (ICollection)objValue;
                // Loop through each entry in the collection and output it
                foreach (object value in collection)
                {
                    Console.WriteLine(value.ToString());
                }
            }
            else
            {
                Console.WriteLine(objValue.ToString());
            }
        }
    }
    myRunSpace.Close();

Thanks to Mike Hamler for assistance with the generic solution!

Posted by evand | 6 Comments

Generating LDP Dumps from PowerShell

Back in my PSS days, it was a common data-gathering/troubleshooting technique to collect "LDP Dumps" (ie - full AD propertyname+value data for a given object) as a way of collecting data for a troubleshooting investigation. If you're a really long-time Exchange administrator, just pretend I said "raw mode dump" and know that it's effectively the same thing, but for an AD object.

Recently, a customer suggested that we (Exchange) should produce a built-in cmdlet which can, given a pipeline input of an Exchange object, connect to the AD and provide this sort of LDP dump data, so that they could replace their use of LDP.exe. The rationale is that this could be pretty useful to collect this data more rapidly (and with fewer clicks) when troubleshooting an issue. I thought about it for a bit, and realized that because of the directory support built into PowerShell (or, rather, .Net) this would be something possible to write with a fairly simple script... no new cmdlet required!

Note that in an effort to keep the output looking roughly like the LDP output, I'm writing out strings rather than objects. This is a little counter to the spirit of PowerShell, of course, but it's also easily overcome with some minor changes to the script below.

Behold, the outcome of this experiment - I hope it's useful to you!

#
# LDPDump.ps1 script
# This script is a PowerShell way to simulate the effects of the old-school "LDP Dump" used by Exchange PSS and other Exchange power-administrators
#  (ie - connecting with LDP.exe, navigating to an object, and double-clicking to get all of the property and value data onto the screen)
#

#
# Discover whether the script is receiving piped input
#
if ( $input.movenext() )
{
    $inputExists = $true
    $input.reset()
}

#   
# There is no piped input - provide some guidance and exit
#
if (!$inputExists )
{
    write-error "You need to pipe in some object!"
    exit
}

# Let's loop on each of the things piped into the script
foreach ($j in $input)
{
    # Grab out the distinguished name (this is a little bit Exchange-centric, but it's also sort of standard-ish)
    $dn=$j.DistinguishedName
    # Did we find a DistinguishedName property? If not, ABORT!
    if($dn -eq $null)
    {
        write-error "THIS OBJECT DOES NOT HAVE A DN: $($j.ToString())"
        write-host ""
    }
    else
    {   
        # OK, we found a DN... let's open a session to AD
        $ldapdn = "[ADSI]'LDAP://$dn'"
        $ldpdump = invoke-expression "$ldapdn"       
        # Print a header for this object
        write-host "$($ldpdump.psbase.path)"
    foreach ($k in $ldpdump.psbase.properties.PropertyNames)
        {
            # Make each count, propertyname and value output look pretty much like LDP does (ie - "#>Name:Value")
            write-host "$($ldpdump.psbase.properties[$k].count)>$($k):$($ldpdump.psbase.properties[$k])"
        }
        write-host ""
    }
}

Thanks to Sebastian Bengochea for help getting at the ProxyCollection data!

Posted by evand | 6 Comments

Interact 2008 - April 8-10, 2008

I just heard that (Exchange VP) Terry's going to be giving the keynote at Interact this year, and he's promised the first real public details about ExchangeLabs! Sweet... this is exciting stuff!

Plus -- Robert and Andrew will be presenting the PowerShell Automation talk, so that alone makes the conference worthwhile, of course. :)

Nested DL Membership in Exchange 2007

Aeons ago, Vivek posted about how to get DL membership in Exchange 2007. He commented that "This can be adapted to do nested membership as well—I’ll leave it to you to figure out how."

At the time, I remember reading this and thinking briefly about how I'd do this, but never really sitting down and doing it to prove my idea was correct.

Well, my time finally ran out on not looking at this. The other day, someone sent me a semi-working PowerShell function to get DL membership (including recursion) and asked me how to make it detect looping recursion. It's been over a year since Vivek delegated this problem "to you", so I guess that's about enough time and we should share an answer. Let's get to it!

Here's the function we started with:

function Get-DLMemberRecurse
{
                foreach ($varTemp in get-distributiongroupmember $args[0])
                {
                                $varTemp
                                if ($varTemp.RecipientType -like "Mail*Group") { Get-DLMemberRecurse $varTemp.Identity }
                }
}

Key problem? If you have DG1 which has DG2 as a member which then has DG1 as a member (a looping membership hierarchy which is totally possible to set, but totally useless practically), it loops forever until it overflows the stack. Whoops, that's no good!

So we need to make a couple of changes to solve this problem. We need to do at least two things (which I've color coded in my updated function below to highlight the changes):

  • Add some recursion protection, using PowerShell’s understanding of scope and recursion. This is useful to ensure we can effectively reset and subsequently build a list of DGs we’ve already traversed.
  • Build a list of DGs we’ve traversed, and update it each time we find a new one

function Get-DLMemberRecurse
{
      $ParentScriptBlock = (get-variable -scope 1 MyInvocation -value).MyCommand.ScriptBlock;
      if($ParentScriptBlock -ne $MyInvocation.MyCommand.ScriptBlock)
      {

            # we're not recursing (we should only hit this once and we'll use it to reset the DGList)
            $global:DGList = @()
            $global:DGList += (Get-DistributionGroup $args[0]).Identity

      }
      foreach ($varTemp in get-distributiongroupmember $args[0])
      {
            $varTemp

            if ($varTemp.RecipientType -like "Mail*Group" -and -not ($global:DGList -contains $varTemp.identity) ) { $global:DGList += $varTemp.Identity; Get-DLMemberRecurse $varTemp.Identity }

      }

}

Special thanks to my buds on the PowerShell team for getting me going with the "how to know if I'm inside a recursion loop using MyInvocation variable" tip.

Posted by evand | 1 Comments

Using PowerShell + WMI to manage legacy Exchange

Dmitry blogs all about it here. I'd been meaning to write pretty much this very same post ever since I attended Devin's talk on managing Legacy Exchange with PowerShell at ExchangeConnections last November this past April, so I'm glad to see Dmitry write it up!

Evan's TechEd session video is posted

It turns out that my TechEd Exchange Scripting with PowerShell session was recorded to video, and now it's available for all to download (no more having to provide TechEd credentials!). Link below on the session title to the video of my session and to the rest of the sessions they've just released!

Microsoft Windows PowerShell Scripting for Microsoft Exchange Server 2007

Evan Dodds, Program Manager, Microsoft Corporation

Level: 300

This session covers the new Windows PowerShell-based Exchange cmdline and scripting interface. Learn how to convert your multiple page Visual Basic and COM scripts to mere one-liners in Exchange 2007. We cover the basics of the management shell, as well as the underlying design and key concepts. Additionally, we go into more depth on how to build larger scripts that can be used to automate small, medium, as well as enterprise business scenarios.

Link to list of all Tech Ed 2007 Recorded Sessions for ITs Showtime:

http://www.microsoft.com/emea/itsshowtime/result_search.aspx?event=65&x=10&y=3

Posted by evand | 3 Comments

DynamicDistributionGroup for all users in a particular storage group

Lots of people are asking lots of questions at the ExchangeNinjas wiki! Glad to see so much participation both from within the Exchange team and also from the broad Exchange community!!

This question struck me as pretty interesting, so I figured I'd surface it on the blog as well as answering it (a few weeks ago) on the wiki... From the wiki's Recipient Management FAQs page (originally was posted to the Ask a Question page) :

Q: I want to create a custom dynamic distribution group for all users in a storage group. I can get the user if I use: get-mailbox | where {$_.Database -like "*<SGName>*"}
BUT this doesn't work for a new DDG :
new-DynamicDistributionGroup -alias test1a -name test1a -recipientfilter {Database -like "*SG01-SUKMSDMBX03*"} -org exchorg.local
I get no members!   It will work on a per server basis, but this it no good for me.  Can you help?  Is this possible?


A: The problem is that the "Database" filter can't do partial string matches, because underneath this property is actually a distinguished name value in the AD (which can't do substring matching). Building an infrastructure that allows you to direct email to mailboxes on a storage group is definitely possible -- just not like this. Instead, you need to ensure you're using the full distinguished name for each database you want to compare against, and not using wildcards (ie, asterisk *)

There's an easy way to do this and a hard way. The hard way I'll just talk about, then I'll show you the easy way. The hard way would be to iterate through all of the MDBs in your selected storage group, concatenating a filter-parser string made up of their DNs... with appropriately placed "-or" operators between. Then pass this string into the New-DDG cmdlet as the RecipientFilter. Yuck.

The easy way is to create a DDG for each mailboxdatabase. Then create a DistributionGroup (doesn't have to be DDG) and add all of these per-MDB DDGs into the DG. Here's how that might look:

new-distributiongroup DG-MySg1 -Type Distribution -SamAccountName DG-MySg1
get-mailboxdatabase -Server Srv1 -StorageGroup MySG1 | % { New-DynamicDistributionGroup "DDG-$($_.Name)" -RecipientFilter "Database -eq '$($_.Identity.DistinguishedName)'" } | % { Add-DistributionGroupMember DG-MySg1 -Member $_.Identity }

Updated July10: Added -Server switch to make it a more real-world syntax.

Posted by evand | 6 Comments

Evan's TechEd 2007 Wrapup

I realized this week that all of the sessions (and video recordings of each session -- I didn't even realize they were recording ALL of the sessions!) are available online. This means even if you ended up double-booked for two interesting sessions and had to choose just ONE in person, you can still review the deck and the video for the session you missed. Of course, that means you probably don't need to see my sessions, since you SURELY chose to see those in person and missed the OTHER, conflicting session. Right? :)

Anyway, here are the links to sessions I participated in this year. I think you may have to be signed in to the TechEd site to get through to these (and note that if you're signed in, you can get to these directly by selecting "Content Downloads & Recordings" in the left of the screen).

  • UNC200 - Exchange 2007 Overview (Video). I did a short Exchange+PowerShell demo toward the end of Terry's overview talk.
  • UNC212R - Managing Exchange 2007  (PPT and Video). I covered the Friday morning repeat of the GUI+PowerShell talk.
  • UNC309 - Exchange 2007 Automation (PPT and Video). This is the Exchange+PowerShell session. There was also a 75min Q&A "Interactive Theatre" afterward, which was not recorded.

Also, I think the PowerShell session is going to be on the ITSShowtime site at some point in the near future as well. I'll post the link when it is up.

Posted by evand | 3 Comments

Quest's QAD Cmdlets

I'm generally very focused on Exchange and our PowerShell cmdlets, but I had an opportunity this week to attend a demo session for the Quest "ActiveRoles Management Shell" cmdlets, one of several PowerShell related tools from Quest. This suite of Cmdlets seems primarily targeted to supporting the Quest ActiveRoles server (their outboard provisioning system), but has the wonderful side effect of working directly against regular AD as well.

The cmdlets (in the version I downloaded this week, there are 22 in total) cover AD User, Group, and "Object" management, among several other things. They appear to be primarily wrappers for the LDAP DirectoryEntry behavior that I've blogged about here before. On the one hand, that really just means they're wrapping a function that's already available in the base PowerShell. But, as someone who's... er... "struggled" with the LDAP DirectoryEntry usage, there's definitely something to be said for a rich set of cmdlets to abstract that troublesome usability! Spoken like someone from the Exchange team, I realize -- in Exchange we have implemented lots of cmdlets and strongly-typed objects/properties to make usability easier and more predictable (rather than complex but generic syntax solutions). So, in that sense, I think this is a great solution!

In any case, these cmdlets are useful and FREE. So if that sounds interesting to you, here's the link.

Posted by evand | 2 Comments
Filed under:

Validation (and DirectoryEntry) demo from TechEd 2007

I didn't get a chance to do this demo in my Exchange Automation with PowerShell session at Teched 2007, mostly due to time. However, I had a conversation with someone prior to my talk and I said that I'd cover it at some point. Well, let's cover it here in the blog and call it done. :)

The point of this blog/demo is primarily to show how Exchange 2007 object validation works, and how to use the powerful validation programmatically. A secondary benefit of this demo is that in order to "hack up" the object to get validation to fail, the most effective way is to use an LDAP DirectoryEntry object... so you get a brief view into how to do this as well. Hopefully together or separate these things are useful to you!

Ok, let's set the stage. Here's a simple mailbox object:

[PS] C:\>get-mailbox user1 | ft *quota*

ProhibitSendQuo ProhibitSendRec UseDatabaseQuot IssueWarningQuo RulesQuota
ta              eiveQuota             aDefaults ta
--------------- --------------- --------------- --------------- ----------
unlimited       unlimited                  True 2GB             64KB

Next, let's set some quota values on it so we have a baseline:

[PS] C:\>set-mailbox user1 -UseDatabaseQuotaDefaults:$false

[PS] C:\>set-mailbox user1 -ProhibitSendQuota 800kb
Set-Mailbox : The value of property 'ProhibitSendQuota' must be greater than or equal to that of property 'IssueWarningQuota'. ProhibitSendQuota: '800KB', IssueWarningQuota: '2GB'.
At line:1 char:12
+ set-mailbox  <<<< user1 -ProhibitSendQuota 800kb

Oh yeah, that won't work. We have logic in place to ensure that ProhibitSendQuota is always the same size or larger than IssueWarningQuota. Set-mailbox won't let us violate this rule. We still have a valid mailbox object at this point, because no ProhibitSendQuota value was written to the mailbox object (and we can easily confirm it's still valid):

[PS] C:\>(get-mailbox user1).IsValid
True

But this demo is about validation FAILING; let's hack it so it'll fail!

[PS] C:\>$a = new-object System.DirectoryServices.DirectoryEntry "LDAP://$((get-mailbox user1).DistinguishedName)"
[PS] C:\>$a.psbase.invokeset("mDBOverQuotaLimit",900*1024)
[PS] C:\>$a.psbase.CommitChanges()
[PS] C:\>Get-Mailbox user1

Name                      Alias                ServerName       ProhibitSendQuo
                                                                ta
----                      -----                ----------       ---------------
user1                     user1                e12              900MB
WARNING: Object e12dom.local/Users/user1 has been corrupted and it is in an inconsistent state. The following validation errors have been encountered:
WARNING: The value of property 'ProhibitSendQuota' must be greater than or equal to that of property 'IssueWarningQuota'. ProhibitSendQuota: '900MB', IssueWarningQuota: '2GB'.

Quick digression to talk about what we did here... we created a new LDAP DirectoryEntry object as $a. Then we updated one of the values (LDAP attribute mDBOverQuotaLimit) with the InvokeSet method. Finally, we saved the updated DirectoryEntry object with CommitChanges(). There are some useful references for how to use DirectoryEntry objects (including some explanation about psbase, etc) on the net. I blogged it here, pointing to BenP's post... that's probably the best place to start.

Anyway, back to the demo. We've now, evidently, succeeded in "hacking" the mailbox object into an invalid state. We got an error back telling us just what's wrong. And as a person, we can read the error, slap our forehead, and fix it up with a proper Set-mailbox operation that resets the proper quota relationship (note, you won't be able to make any other writes to this object through Set-Mailbox cmdlet until you fixup the Quota values).

But, what if you want to do it programmatically? You're in a script or whatever. Surely there has to be a way to check if an object is valid during the processing of a script? Well, of course there is. We've already used it just above... let's try it again now:

[PS] C:\>(Get-mailbox user1).IsValid
WARNING: Object e12dom.local/Users/user1 has been corrupted and it is in an inconsistent state. The following validation errors have been encountered:
WARNING: The value of property 'ProhibitSendQuota' must be greater than or equal to that of property 'IssueWarningQuota'. ProhibitSendQuota: '900MB', IssueWarningQuota: '2GB'.
False

And, since it's a boolean result, we can test it with if(), etc. Very powerful.

But we can go even one step further... what if I want to test if an object is valid before I even try to change the values? Great example of this one is now that I have an invalid object, I can't change any other properties on the object until I fix the invalid values (and make it valid again). So maybe my script should be super-smart and "test out" setting some value to see if it'll make the object valid before I try to write it back:

[PS] C:\>$b = get-mailbox user1
WARNING: Object e12dom.local/Users/user1 has been corrupted and it is in an inconsistent state. The following validation errors have been encountered:
WARNING: The value of property 'ProhibitSendQuota' must be greater than or equal to that of property 'IssueWarningQuota'. ProhibitSendQuota: '900MB', IssueWarningQuota: '2GB'.
[PS] C:\>$b.validate() | fl description

Description : The value of property 'ProhibitSendQuota' must be greater than or
               equal to that of property 'IssueWarningQuota'. ProhibitSendQuota
              : '900MB', IssueWarningQuota: '2GB'.

[PS] C:\>$b.ProhibitSendQuota = "unlimited"
[PS] C:\>$b.validate() | fl description        <----- Note, nothing is returned here because the $b instance/object is valid now
[PS] C:\>$b.isvalid
True
[PS] C:\>set-mailbox -Instance $b
[PS] C:\>(get-mailbox user1).isvalid
True

So, you can see how this could be useful to "test the waters" in your scripts as you read/write/change objects. For instance, try the same sequence I used just above to set $b.ProhibitSendQuota back to "800kb" and you'll find it lets you do it... right up until you try to save the instance back with Set-Mailbox cmdlet. "Testing the water" with IsValid and Validate() can help you programmatically avoid this sort of error!

Posted by evand | 2 Comments

SMTP .net object demo from my TechEd 2007 PowerShell session

Wolfgang requested a reprint of the details from the "SMTP Demo" part of my TechEd talk last week. Here is (roughly) the transcript of the steps, and my comments interspersed...

[PS] C:\>$dl = Get-DistributionGroup SomeGroup

Ok, now we've got $dl variable loaded up with a distribution group object.

[PS] C:\>$dladdr = $dl.PrimarySmtpAddress.ToString()
[PS] C:\>$dladdr
SomeGroup@somedomain.com

And we've extracted the SMTP address from this group into the $dladdr variable.

[PS] C:\>$smtpclient = new-object System.Net.Mail.SmtpClient E12Server1, 587
[PS] C:\>$smtpclient

Host : E12Server1
Port : 587
UseDefaultCredentials : False
Credentials :
Timeout : 100000
ServicePoint : System.Net.ServicePoint
DeliveryMethod : Network
PickupDirectoryLocation :
EnableSsl : False
ClientCertificates : {}

Created a DotNet object (thanks PowerShell!!) of System.Net.Mail.SmtpClient type. This sort of usability is a big part of why PowerShell is so wicked cool!

[PS] C:\>$cred = get-credential domain\exadmin
[PS] C:\>$cred

UserName Password
-------- --------
e12dom\exadmin System.Security.SecureString

[PS] C:\>$smtpclient.Credentials = $cred.GetNetworkCredential()

Save off a credential variable we can use in a moment (we'll need to authenticate to the connector since it's configured for basic auth and no anonymous relay).

[PS] C:\>$smtpclient.Send("exadmin@somedomain.com", $dladdr, "Welcome", "New list created.")

And... voila! Email is sent!

Now, challenge for the reader -- can you take these steps and build out a "mail-storm" script? I'd love to see your results on this idea posted here in the comments or at http://www.exchangeninjas.com/ wiki! Or any other cool variations or uses for this sort of functionality that you can come up with.

Posted by evand | 2 Comments

Post-Session at TechEd 2007

Thanks to all those die-hards who attended UNC309 session this morning at 8:30am, and to those who spent some time at the "Interactive Theatre" (ie - chalk-talk) session afterward for Q&A, much appreciated!

The session seemed to go fairly well, although even with placing a clock up on the presenter station to keep me on pace, I still ended up running a little long (and had to drop a couple of the more involved demos). 75 minutes just isn't enough time to demo the entirety of the greatness that is PowerShell+Exchange! At least not without talking EVEN FASTER than I already, naturally do!

So, in any case, sorry to the folks who I'd talked with before hand about the validation demo and using DirectoryEntry objects... I'll plan to post something up here on this topic in the near future since we didn't get to the demo in the breakout session.

After the primary session (PPT+Demos), we ended up back in the TLC area at "Green Threatre #5" for another 75 mins or so which we used directly for Q&A. Sorry to anyone who didn't find space in the theatre area - we ended up with quite a big crowd for this session, spilling out of the theatre, so I suspect it might have been hard to hear/see what was going on! Thanks to all for the great questions asked, and also to /n Software (Booth 1149 - check out their NetCmdlets product!) for the >_ stickers we handed out as freebies for asking questions during this session!

I'm going to step back and strategize what are the best couple of posts I can draw from the questions asked, demos skipped, etc. I'll try to post some good stuff here over the next week or so to wrap up. If you have any suggestions -- questions you didn't get to ask, things you thought of during lunch, whatever... please feel free to post here in the comments or send me an email!

Posted by evand | 2 Comments

TechEd 2007, Day 1: Exchange 2007 Overview

The first Exchange breakout session this morning served as a bit of an "Exchange 2007 Keynote" talk, with our General Manager Terry Myerson doing the delivery. He covered E2k7's features and characteristics end-to-end in 75 mins, and had a couple of us help out with demos to dig in on a few areas (Unified Messaging, OWA, SysMgmt/PowerShell).

I covered the last of these three demos with a slimmed down version of my PowerShell opener demo that I'll be doing in my Wednesday Session. Now I'm super jazzed about the Wednesday talk; It's a shame it's not until Wednesday!

Here are the details for those of you who are here in Orlando:

UNC309: Microsoft Windows PowerShell Scripting for Microsoft Exchange Server 2007
Wednesday, June 6th
Bright-and-early AM (ie - 8:30-9:45am)
Location: S220 D

Some emails and comments on the previous post asking whether the outcome of the session will be posted afterward. I'll probably post some debrief from the session, and I know that the TechEd A/V staff are also planning to record the session. That said, I'm not sure what they'll do with the recording...? If it turns up online or somewhere I can link to, I'll be sure to do so.

Thanks everyone for your interest and hope you can make it on Wednesday (there's still time to get your plane ticket). :)

Posted by evand | 0 Comments

TechEd 2007

Wow, time sure flies. No posts since end of April; sorry about that! I'm (more or less) caught back up at work from these crazy few weeks (months?) just passed, and I'm even just returning from a week vacation... raring to go!

 

 

 

So what's next? Well... this is a short week, and then next week (June 4-8) is TECHED in Orlando!

 

I'll be down there to spend some time at the Exchange booth ("Technical Learning Center") and meet some of you folks, and also to present a breakout session and chalk talk on Exchange automation/scripting with PowerShell!

 

 

Here are the session details:

UNC309 - Microsoft Windows PowerShell Scripting for Microsoft Exchange Server 2007
Track(s)
: Unified Communications
Level: 300
Speaker(s): Evan Dodds

This session covers the new Windows PowerShell-based Exchange cmdline and scripting interface. Learn how to convert your multiple page Visual Basic and COM scripts to mere one-liners in Exchange 2007. We cover the basics of the management shell, as well as the underlying design and key concepts. Additionally, we go into more depth on how to build larger scripts that can be used to automate small, medium, as well as enterprise business scenarios.

This is a great deck/presentation with great demos, so it should definitely be fun! Hope to see you there!

Posted by evand | 3 Comments

Why no blog posts lately?

You might have noticed that after several weeks of very regular blog posts, they suddenly and abruptly stopped. I have an explanation: I'm super busy this month at work!

This should continue for a few more weeks. But expect to see more regular posts again for a while after that -- I've got a good queue of topics-to-be-written built up.

Posted by evand | 1 Comments
More Posts Next page »
 
Page view tracker