About the author

Name of author Author name
Something about me and what I do.

E-mail me Send mail

Calendar

<<  February 2012  >>
MoTuWeThFrSaSu
303112345
6789101112
13141516171819
20212223242526
2728291234
567891011

View posts in large calendar

Pages

Recent comments

    Tags

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2012

    Sign in

    Failure creating an Outlook application object on Vista

    by wes 11/4/2007 11:56:22 PM

    While creating a Outlook application object from another process in C# like:

    outlook = new Microsoft.Office.Interop.Outlook.Application();

    or powershell

    PS> $outlook = new-object -com Outlook.Application

    or straight up COM via CoCreateInstance on Vista it's possible to receive the following error:

    Retrieving the COM class factory for component with CLSID {0006F03A-0000-0000-C000-000000000046} failed due to the following error: 80080005

    Error 0x80080005 (CO_E_SERVER_EXEC_FAILURE) is sort of a generic COM error message that occurs for many reasons while calling CoCreateInstance. One reason someone could receive this error is because the client process and the server process (outlook.exe in this case) are running at different integrity levels. By default it doesn't appear that COM likes talking across two different processes that are running at different integrity levels. There supposedly is a way to implement the COM server in such a way to support it but currently the Outlook COM server doesn't support it.

    People who develop their applications on Vista using Visual Studio, which runs at integrity level high by default, will run into this issue often when Outlook is already running. By default Outlook runs at integrity level medium and if the client application is run from Visual Studio it will inherit the high integrity level and thus there will be an integrity level mismatch.

    To fix this one needs to make the integrity levels match so either start the client application outside Visual Studio at the normal medium integrity level or run Outlook at the high integrity level (i.e. as Administrator). However it is not recommended to run Outlook at integrity level high all the time. Another way to deal with this is to ensure Outlook is not already running so COM will start the process at the correct integrity level of the client process that created the application object.

    I don't know of any way to detect this exact situation programmatically but process explorer works well for manually checking the integrity levels of processes.

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags:

    .NET | Outlook | Code

    Why does my Outlook event seem to stop working?

    by wes 7/4/2007 12:53:03 AM

    Imagine we have some code in an Outlook addin that looks similar to code below. Does anyone see anything wrong with it? It simply places a button on the menu bar and shows a message box when the button is clicked. The code works for sometime but then all of a sudden the button mysteriously stops working. What gives? 

    using Office = Microsoft.Office.Core;
    using Outlook = Microsoft.Office.Interop.Outlook;
    ...
    void SetupCommandBar(Outlook.Application application)
    {
        Office.CommandBar menu = application.ActiveExplorer().CommandBars.ActiveMenuBar;
    
        Office.CommandBarButton button = menu.Controls.Add(Office.MsoControlType.msoControlButton,
            Type.Missing, Type.Missing, Type.Missing, true) as Office.CommandBarButton;
    
        button.Caption = "Click Me!";
        button.Click += new Office._CommandBarButtonEvents_ClickEventHandler(button_Click);
    }
    void button_Click(Microsoft.Office.Core.CommandBarButton Ctrl, ref bool CancelDefault)
    {
        System.Windows.Forms.MessageBox.Show("Clicked Button!");
    }

    The button stops working due to the mystical powers of the .Net garbage collector. If we look closely we notice that the button object is locally scoped in the SetupCommandBar function, thus once we execute that function the button object is free to be cleaned up. However, until the button object is actually destroyed by the garbage collector the button click event will fire and the button will work. Due to the non-deterministic nature of the garbage collector we have no idea how long the button will work. In my simple testing it seemed to work for a little while but if you want to speed up the process add a call go GC.Collect in the button_Click callback.

    The easiest fix for this problem is to change the scope of the button object to be a member variable of enclosing class. By doing this we ensure that the button object stays alive and works until we are ready for it to stop working.

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags:

    .NET | Outlook | Code

    Powershell script to find strings and highlight them in the output

    by wes 3/23/2007 12:11:47 AM

    After reading about Brad's find script I starting thinking about how cool it would be if I could highlight the search pattern in the output. So I wrote my own custom Find-String script to highlight the results.

    Find-String.ps1

    # Find-String.ps1
    #  Wrapper around dir | select-string which will highlight the pattern in the results
    param	( [string] $pattern = ""
    	, [string] $filter = "*.*"
    	, [switch] $recurse = $false
    	, [switch] $caseSensitive = $false)
    
    if ($pattern -eq $null -or $pattern -eq "") { Write-Error "Please provide a search pattern!" ; return }
    
    $regexPattern = $pattern
    if($caseSensitive -eq $false) { $regexPattern = "(?i)$regexPattern" }
    $regex = New-Object System.Text.RegularExpressions.Regex $regexPattern
    
    # Write the line with the pattern highlighted in red
    function Write-HostAndHighlightPattern([string]$inputText)
    {
    	$index = 0
    	while($index -lt $inputText.Length)
    	{
    		$match = $regex.Match($inputText, $index)
    		if($match.Success -and $match.Length -gt 0)
    		{
    			Write-Host $inputText.SubString($index, $match.Index   $index) -nonewline
    			Write-Host $match.Value.ToString() -ForegroundColor Red -nonewline
    			$index = $match.Index + $match.Length
    		}
    		else
    		{
    			Write-Host $inputText.SubString($index) -nonewline
    			$index = $inputText.Length
    		}
    	}
    }
    
    # Do the actual find in the files
    Get-ChildItem -recurse:$recurse -filter:$filter | 
    	Select-String -caseSensitive:$caseSensitive -pattern:$pattern |	
    	foreach {
    		Write-Host "$($_.FileName)($($_.LineNumber)): " -nonewline
    		Write-HostAndHighlightPattern $_.Line
    		Write-Host
    	}
    

    Sample Output

    PS> ./Find-String new-object
    Find-String.ps1(13): $regex = New-Object System.Text.RegularExpressions.Regex $regexPattern
    Get-ApptsUsingEWS.ps1(55): $responseXml = [xml](new-object System.IO.StreamReader $responseStream).ReadToEnd()
    Get-ApptsUsingOOM.ps1(6): $outlook = New-Object -ComObject Outlook.Application
    getappts.ps1(51): $responseXml = [xml](new-object System.IO.StreamReader $responseStream).ReadToEnd()
    printAppts.ps1(6): $outlook = New-Object -ComObject Outlook.Application

     

    For reference here are some other find scripts around the blogsphere: Brad Wilson, Ian Griffith and Keith Hill.

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags:

    .NET | Code | Powershell

    Retrieving your Outlook appointments for a given date range

    by wes 3/21/2007 12:42:48 AM

    Before we dive into the code sample lets take a quick look at what it means for an appointment to fall into a given date range.

    When you compare an appointment with a given date range (or any two time intervals) there are the 6 possible outcomes displayed in the diagram above. Usually as a first attempt people write a comparison that looks like:

    [Start] >= RangeStart AND [End] <= RangeEnd

    If you examine that comparison closely you will notice that it will only retrieve appointments of type 1. This maybe fine for most applications, like getting all appointments for a given week because there usually aren't any appointments spanning over the range edges. However, if you want to be more precise and include any appointments that overlap with a given date range (i.e. type 1, 2, 3, 4) you can use the following comparison:

    [End] >= RangeStart AND [Start] <= RangeEnd

    This type of restriction will help when you have smaller date/time ranges such as a few hours or a day. In general, unless you specifically only want type 1 appointments, I would recommend using this restriction which finds any appointments that overlap with the date/time range.

    Since Walter has already provided a VBA, WebDAV, and CDO code sample on how to find appointments within a specific time frame, I figured I would provide some Powershell code samples.

    Powershell script to retrieve appointments using the Outlook Object Model for a given date range.

    Keep in mind in order to get all the appointments, including any instances of recurring appointments, you need to get the items collection on the calendar folder and then Sort by the "[Start]" property and set IncludeRecurrences to true. Once you have done this the Count property on the items collection is bogus because there could potentially be an infinite number of recurring appointments. So to traverse this collection you need to use the enumerator (i.e. foreach) or use the Find/FindNext methods on the collection.

    # Get-ApptsUsingOOM.ps1
    #    Powershell script to retrieve all appointments for a given date range using the Outlook Object Model
    param ( [DateTime] $rangeStart = [DateTime]::Now
          , [DateTime] $rangeEnd   = [DateTime]::Now.AddDays(7))
    
    $outlook = New-Object -ComObject Outlook.Application
    
    # Ensure we are logged into a session
    $session = $outlook.Session
    $session.Logon()
    
    $olFolderCalendar = 9
    $apptItems = $session.GetDefaultFolder($olFolderCalendar).Items
    $apptItems.Sort("[Start]")
    $apptItems.IncludeRecurrences = $true $restriction = "[End] >= '{0}' AND [Start] <= '{1}'" -f $rangeStart.ToString("g"), $rangeEnd.ToString("g") foreach($appt in $apptItems.Restrict($restriction)) { "{0:MM/dd hh:mm tt} - {1:MM/dd hh:mm tt} : {2}" -f [DateTime]$appt.Start, [DateTime]$appt.End, $appt.Subject } $outlook = $session = $null;

    Powershell script to retrieve appointments using Exchange Web Services for a given date range

    For simplicity I built the soap message manually and submitted the request, but you could easily generate the web service proxy classes using wsdl.exe like I did in another example if you don't wish to build the soap message yourself.

    # GetApptsUsingEWS.ps1
    #    Powershell script to retrieve all appointments for a given date range using Exchange Web Services
    param ( [DateTime] $rangeStart = [DateTime]::Now
          , [DateTime] $rangeEnd   = [DateTime]::Now.AddDays(7)
          , [System.Net.NetworkCredential] $credentials = (Get-Credential).GetNetworkCredential())
    
    # Remember to set your exchange server address
    $exchangeServerAddress = "http<s>://<ExchangeServer>/EWS/Exchange.asmx"
    
    # Soap request derived from http://msdn2.microsoft.com/en-us/library/aa564515.aspx
    $soapRequest = @'
    <?xml version="1.0" encoding="utf-8"?>
    <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                   xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
                   xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
      <soap:Body>
        <FindItem Traversal="Shallow" xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">
          <ItemShape>
            <t:BaseShape>IdOnly</t:BaseShape>
            <t:AdditionalProperties>
              <t:FieldURI FieldURI="calendar:Start"/>
              <t:FieldURI FieldURI="calendar:End"/>
              <t:FieldURI FieldURI="item:Subject"/>
            </t:AdditionalProperties>
          </ItemShape>
          <CalendarView MaxEntriesReturned="100" StartDate="{0}" EndDate="{1}"/>
          <ParentFolderIds>
            <t:DistinguishedFolderId Id="calendar"/>
          </ParentFolderIds>
        </FindItem>
      </soap:Body>
    </soap:Envelope>
    '@
    
    # Put the range start and end date in the correct format
    $soapRequest = $soapRequest -f $rangeStart.ToString("yyyy-MM-ddTHH:mm:sszzz"), $rangeEnd.ToString("yyyy-MM-ddTHH:mm:sszzz")
    
    # Create the request 
    $webRequest = [System.Net.WebRequest]::Create($exchangeServerAddress)
    $webRequest.ContentType = "text/xml"
    $webRequest.Headers.Add("Translate", "F")
    $webRequest.Method = "Post"
    $webRequest.Credentials = $credentials
    
    # Setup the soap request to send to the server
    $content = [System.Text.Encoding]::UTF8.GetBytes($soapRequest)
    $webRequest.ContentLength = $content.Length
    $requestStream = $webRequest.GetRequestStream()
    $requestStream.Write($content, 0, $content.Length)
    $requestStream.Close()
    
    # Get the xml response from the server
    $webResponse = $webRequest.GetResponse()
    $responseStream = $webResponse.GetResponseStream()
    $responseXml = [xml](new-object System.IO.StreamReader $responseStream).ReadToEnd()
    $responseStream.Close()
    $webResponse.Close()
    
    foreach ($appt in $responseXml.GetElementsByTagName("t:CalendarItem"))
    {
        "{0:MM/dd hh:mm tt} - {1:MM/dd hh:mm tt} : {2}" -f [DateTime]$appt.Start, [DateTime]$appt.End, $appt.Subject
    }

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags:

    .NET | Outlook | Code | Powershell

    Don't buy from Brainpuzzles.com

    by wes 2/27/2007 1:00:03 AM

    I've had terrible customer service from them. I ordered a set of puzzles on Jan 1st and I was told it would take about a week to receive my order. After 2 weeks I sent an email enquiring my shipping status. It took another followup mail and a week later to get a response back. On the Jan 22nd they finally email me back and tell me there was some sort of mix up and they will mail it out immediately.

    Finally I recieve my order on Jan 26th. I'm thinking to myself, awesome I finally got my puzzles. However, there were two issues with my order. The set I ordered was not supposed to have duplicates but there was one duplicate. Then there was another puzzle which was broken. So in my set of 10 I have on broken puzzle and 1 duplicated puzzle (i.e. I got 8 unique non-broken puzzles).

    I sent an email the same day I received them, Jan 26, telling them about the issues and asking if I could exchange the duplicate and broken puzzles. I've sent a follow up email every week for the last 3 weeks and I'm yet to receive a response. So 4 emails and a 5 weeks after receiving my order I still haven't received any response from them.

    That was my first and that will be my last dealing with Brainpuzzles.com. I thought I was getting a pretty good price, but I guess their business model doesn't include customer service.

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags:

    Personal | News

    Reflector 5 Released

    by wes 2/20/2007 11:28:59 PM

    Lutz released Reflector for .NET 5.0

    If you do any .NET development and you don't use Reflector for .NET then you are missing out. Scott posted a brief review of the new version. I think I'm most excited about the new analyze feature, it should come in handy.

    Reflector for .NET
    Reflector for .NET Add-Ins

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags:

    .NET | Tools | News

    Image File Execution Options

    by wes 2/8/2007 9:29:21 PM

    Every now and than while debugging I need to either determine when a dll/module is loaded or need to attach a debugger to a process at startup that is started outside a debugger. I know there are settings that exist to do this but I always seem to forget exactly what they are. So for future reference here the registry entries.

     

    Force a break while debugging when a dll/module is loaded

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<modulename.dll>]
    "BreakOnDllLoad"=dword:00000001

    Force a process to start under the Visual Studio Debugger

    [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<processname.exe>]
    "Debugger"="vsjitdebugger.exe"

     

    Useful links:

    Junfeng  Image File Execution Options
    Greggm  Breaking when a module loads
    Greggm Inside 'Image File Execution Options' debugging
    Oldnewthing Beware the Image File Execution Options key

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags:

    Windows | Tips and Tricks

    Powershell version of cmd set

    by wes 2/8/2007 2:24:50 PM

    If you are like me and are just so used to typing set to list and set environment variables then you might find this script useful.

    if (test-path alias:set) { remove-item alias:set > $null }
    function set
    {
    	[string]$var = $args
    	if ($var -eq "")
    	{
    		get-childitem env: | sort-object name
    	}
    	else
    	{
    		if ($var -match "^(\S*?)\s*=\s*(.*)$")
    		{
    			set-item -force -path "env:$($matches[1])" -value $matches[2];		
    		}
    		else
    		{
    			write-error "ERROR Usage: VAR=VALUE"
    		}
    	}	
    }

    Just add this script to your Powershell profile and you will be all set :)

    PS: If anyone is interested I updated the Powershell Language definitions for CodeHTMLer, it now highlights more of the built-in stuff such as cmdlets and variables.

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags:

    Code | Powershell | CodeHTMLer

    Hanselminutes

    by wes 1/30/2007 10:09:41 PM

    I've been subscribed to Scott Hanselman's blog for a long time. I love all the tools, tips, etc he posts. Up until this point I have not really gotten into podcasts however due to Scott's awesome blog I figured I would give his podcast, Hanselminutes, a try.

    I've listened to about 10 of the shows now and I must say I really enjoy it. It gives me something to listen to during my daily bus trip. If your are into .Net or Technology in general you might want to give Hanselminutes a try, I don't think you will be disappointed. Scott's goal is "Avoid wasting the listener's time." IMHO he is succeeding in that goal. Actually if anything he leaves me wanting more information about certain topics.

     

    Thanks Scott and Carl keep up the good work!

     

    The only thing I need to figure out is how best to sync up the podcast onto my Sandisk Sansa. Currently I'm just manually putting the shows on. Anyone have any recommendations for tools to do this?

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags:

    .NET | News | Tips and Tricks

    How do I access my Outlook contacts from my web application?

    by wes 1/30/2007 9:48:29 PM

    Question

    How do I access my Outlook contacts from my web application?

    Short Answer

    You don't, well at least you shouldn't (It is theoretically possible to access Outlook data from a web application, assuming Outlook is installed and the profile you wish to access data from is setup on the web server).

    Long Answer

    To address this question we need to realize that Outlook is a client application which is only a front end and local cache for a mail server (typically exchange server). Most web applications are server applications and thus run on servers which usually don't have client applications, such as Outlook, installed on them. Perhaps a better question would be "How do I access my Exchange contacts from my web application?". 

    With that in mind lets explore a couple possible solutions for accessing data (not really Outlook data) from the Exchange server.

    • WebDAV - Protocol that Outlook Web Access (OWA) uses to access your Exchange store
    • Exchange Web Services (EWS) - New services added to Exchange 2007 to allow access to most data
    • Active Directory Services Interface (ADSI) - For accessing general Exchange user data information (i.e. access the Global Address List)

    These are just three common technologies for accessing data on a Exchange server, for more details see the Exchange Server Development Center or Overview of Programming Features for Exchange Server. To provide a more complete example I've included some code samples and links for each of the three technologies. The code examples demonstrate how to do find contacts using each of the three methods. Keep in mind these samples can be extended to other data types such as mail and appointments, with the exception of ADSI. All the code samples are written in C# and write the data to the console, they can easily be converted to be used by an ASP.Net web application. Also remember to substitute <ExchangeServer>, <username>, <password>, and <domain> with the appropriate values for your Exchange server.

    WebDAV

    The sample retrieves all contacts from an exchange store which have a first name beginning with 'wes'. Keep in mind before making any Exchange WebDAV requests you must make an forms authorization request first (assuming the Exchange server has forms authorization enabled, which seems to generally be the case). You need to make the authorization request to get the set of authorization cookies to use with any subsequent WebDAV requests.

    using System;

    using System.IO;

    using System.Net;

    using System.Text;

    using System.Xml;

     

    // When Exchange is setup for Forms Authentication you need to do the login separately

    public static CookieCollection GetAuthCookies(string server, NetworkCredential credentials)

    {

        // URI to OWA authorization dll

        string authURI = string.Format("{0}/exchweb/bin/auth/owaauth.dll",

            server, credentials.UserName);

     

        // Get byte stream of the post request

        byte[] bytes = Encoding.UTF8.GetBytes(string.Format(

            "destination={0}/exchange/{1}&username={2}\\{1}&password={3}",

            server, credentials.UserName, credentials.Domain, credentials.Password));

     

        HttpWebRequest request = WebRequest.Create(authURI) as HttpWebRequest;

        request.Method = "POST";

        request.ContentType = "application/x-www-form-urlencode";

        request.CookieContainer = new CookieContainer();

        request.ContentLength = bytes.Length;

        request.AllowAutoRedirect = false;

     

        using (Stream requestStream = request.GetRequestStream())

            requestStream.Write(bytes, 0, bytes.Length);

     

        // Get response cookies - keep in mind this may throw exceptions

        using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)

            return response.Cookies;

    }

     

    public static void PrintContactsUsingExchangeWebDAV()

    {

        string server = "http<s>://<ExchangeServer>";

        NetworkCredential credentials = new NetworkCredential("<username>", "<password>", "<domain>");

        string uri = string.Format("{0}/exchange/{1}", server, credentials.UserName);

     

        // Create a byte stream of the SQL query to run against the server

        // This query searches for contacts with the givenName the begins with 'wes'

        // Link to Exchange store property names

        byte[] contents = Encoding.UTF8.GetBytes(string.Format(

           @"<?xml version=""1.0""?>

            <g:searchrequest xmlns:g=""DAV:"">

                <g:sql>

                    SELECT

                        ""urn:schemas:contacts:sn"", ""urn:schemas:contacts:givenName"",

                        ""urn:schemas:contacts:email1"", ""urn:schemas:contacts:telephoneNumber""

                    FROM

                        Scope('SHALLOW TRAVERSAL OF ""{0}/exchange/{1}/contacts""')

                    WHERE

                        ""urn:schemas:contacts:givenName"" LIKE 'wes%'

                </g:sql>

            </g:searchrequest>",

          server, credentials.UserName));

     

        HttpWebRequest request = HttpWebRequest.Create(uri) as HttpWebRequest;

        request.Credentials = credentials;

        request.Method = "SEARCH";

        request.ContentLength = contents.Length;

        request.ContentType = "text/xml";

        request.CookieContainer = new CookieContainer();

        // Keep in mind you may actually want to cache these cookies for other requests

        request.CookieContainer.Add(GetAuthCookies(server, credentials));

     

        using (Stream requestStream = request.GetRequestStream())

            requestStream.Write(contents, 0, contents.Length);

     

        using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)

        using (Stream responseStream = response.GetResponseStream())

        {

            // Process the response as an XML document

            XmlDocument document = new XmlDocument();

            document.Load(responseStream);

     

            foreach (XmlElement element in document.GetElementsByTagName("a:prop"))

            {

                // Do work with data returned for each contact

                Console.WriteLine("Name:  {0} {1}\nEmail: {2}\nPhone: {3}",

                    (element["d:givenName"] != null ? element["d:givenName"].InnerText : ""),

                    (element["d:sn"] != null ? element["d:sn"].InnerText : ""),

                    (element["d:email1"] != null ? element["d:email1"].InnerText : ""),

                    (element["d:telephoneNumber"] != null ? element["d:telephoneNumber"].InnerText : ""));

            }

        }

    }

    Helpful WebDAV Links:

    Infinitec Exchange posts C# and JavaScript forms authentication examples
    Marc Charbonneau Using .NET and WebDAV to access an Exchange server
    Hitchhiker guide to enterprise development  Programmatically accessing to OWA through Web Dav
    Exchange store property names

    Exchange Web Services

    This sample code goes through the process of creating a Exchange web service FindItem request. In essentially searches through the contact folder looking for any contact with first name starting with 'wes'.

    using System;

    using System.Net;

    // Generate Exchange Web Services proxy classes by adding a VS web

    // reference to http<s>://<ExchangeServer>/EWS/Services.wsdl

    // then add a using reference to your proxy classes

     

    public static void PrintContactsUsingExchangeWebServices()

    {

        ExchangeServiceBinding esb = new ExchangeServiceBinding();

        esb.Credentials = new NetworkCredential("<username>", "<password>", "<domain>");

        esb.Url = @"http<s>://<ExchangServer>/EWS/Exchange.asmx";

     

        // Tell it you want all the item properties

        ItemResponseShapeType itemProperties = new ItemResponseShapeType();

        itemProperties.BaseShape = DefaultShapeNamesType.AllProperties;

     

        // Tell it you only want to look in the contacts folder

        DistinguishedFolderIdType[] folderIDArray = new DistinguishedFolderIdType[1];

        folderIDArray[0] = new DistinguishedFolderIdType();

        folderIDArray[0].Id = DistinguishedFolderIdNameType.contacts;

     

        PathToUnindexedFieldType field = new PathToUnindexedFieldType();

        field.FieldURI = UnindexedFieldURIType.contactsGivenName;

     

        ConstantValueType fieldValue = new ConstantValueType();

        fieldValue.Value = "wes";

     

        // Look for contacts which have a given name that begins with 'wes'

        ContainsExpressionType expr = new ContainsExpressionType();

        expr.ContainmentModeSpecified = true;

        expr.ContainmentMode = ContainmentModeType.Prefixed;

        expr.ContainmentComparisonSpecified = true;

        expr.ContainmentComparison = ContainmentComparisonType.IgnoreCase;

        expr.Constant = fieldValue;

        expr.Item = field;

     

        RestrictionType restriction = new RestrictionType();

        restriction.Item = expr;

     

        // Form the FindItem request

        FindItemType findItemRequest = new FindItemType();

        findItemRequest.Traversal = ItemQueryTraversalType.Shallow;

        findItemRequest.ItemShape = itemProperties;

        findItemRequest.ParentFolderIds = folderIDArray;

        findItemRequest.Restriction = restriction;

     

        // Send the request and get the response

        FindItemResponseType findItemResponse = esb.FindItem(findItemRequest);

     

        if (findItemResponse.ResponseMessages.Items.Length > 0)

        {

            FindItemResponseMessageType responseMessage =

                findItemResponse.ResponseMessages.Items[0] as FindItemResponseMessageType;

            ArrayOfRealItemsType realItems =

                responseMessage.RootFolder.Item as ArrayOfRealItemsType;

     

            foreach (ContactItemType contact in realItems.Items)

            {

                // Do work with data returned for each contact

                Console.WriteLine("Name:  {0} {1}\nEmail: {2}\nPhone: {3}",

                    contact.GivenName, contact.Surname,

                    (contact.EmailAddresses != null && contact.EmailAddresses.Length > 0 ?

                        contact.EmailAddresses[0].Value : ""),

                    (contact.PhoneNumbers != null && contact.PhoneNumbers.Length > 0 ?

                        contact.PhoneNumbers[0].Value : ""));

            }

        }

    }

    Useful Exchange Web Service Links:

    MSDN Exchange Web Services Reference
    Stephen GriffinExchange Web Services and MAPI Props
    Eric LeeExchange Server 2007 Web Service API for Developers

    Active Directory Services Interface

    This is a very simplified .Net sample of doing a search in the default active directory for any users that have a first name beginning with 'wes'. Keep in mind that this uses the default active directory on the machine you are running on, see DirectorySearcher.SearchRoot for more details. If you need to specify a particular machine/directory to start your search from then you need to create a DirectoryEntry and pass that to the DirectorySearcher.

    using System;

    using System.DirectoryServices;

     

    // Get user information from your default active directory repository

    public static void PrintUsersFromADSI()

    {

        // Find any user that has a name that begins with 'wes'

        string filter = "(&(objectCategory=person)(objectClass=user)(givenName=wes*))";

        DirectorySearcher search = new DirectorySearcher(filter);

        foreach(SearchResult result in search.FindAll())

        {

            // Do work with data returned for each address entry

            DirectoryEntry entry = result.GetDirectoryEntry();

            Console.WriteLine("Name:  {0} {1}\nEmail: {2}\nPhone: {3}",

                entry.Properties["givenName"].Value,

                entry.Properties["sn"].Value,

                entry.Properties["mail"].Value,

                entry.Properties["telephonenumber"].Value);

        }

    }

    Useful ADSI/LDAP Links:

    InfiniTec How to get the Global Address List programmatically
    Amit Zinman Creating a list of Users and their e-mail addresses
    Steve Schofield .NET sample LDAP query looking for a specific user name of (smith) and System.DirectoryServices namespace
    Mow PowerShell and Active Directory Part 1, Part 2, Part 3, Part 4, Part 5

     

    Disclaimer: The sample code described here is provided on an “as is” basis, without warranty of any kind, to the fullest extent permitted by law. It is for demonstration purposes only and is by now means production quality.

    Be the first to rate this post

    • Currently 0/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags:

    .NET | Outlook | Code | Tips and Tricks

    Powered by BlogEngine.NET 1.2.0.0
    Theme by Mads Kristensen