Link to home
Start Free TrialLog in
Avatar of esdTeamsters
esdTeamstersFlag for United States of America

asked on

How do you query an MS Exchange 2000 mailbox using ADO.NET within a VB.NET application?

Hello,

I am currently querying an Exchange 2000 mailbox using an ADO connection, but have been trying to find a way to utilize ADO.NET.  A database connection I have to an Oracle server, was extremely easy to set up using the connection wizards in VS.NET 2003, and I can't help but think there is a method for Exchange which is just as simple.  When I try to establich a connection to the Exchange server, I'm unable to find a suitable provider.  The existing code is as follows:

      Dim objConnection As ADODB.Connection = New ADODB.Connection
      Dim objRecordSet As ADODB.Recordset = New ADODB.Recordset

      strUrl = "http://" + strServerName + "/Exchange/" + strMailBoxName + "/Inbox"

      'Open connection
      objConnection.Provider = "MSDAIPP.dso"
      objConnection.Open(strUrl, strAdUserName, strAdUserPassword, -1)

      'Build the SQL query
      strSql = ""
      strSql = "SELECT "
      strSql = strSql + " ""DAV:href"""
      strSql = strSql + ", ""DAV:displayname"" "
      strSql = strSql + ", ""urn:schemas:httpmail:from"" "
      strSql = strSql + ", ""urn:schemas:httpmail:subject"" "
      ...
      strSql = strSql + ", ""urn:schemas:httpmail:textdescription"" "
      strSql = strSql + ", ""RESOURCE_PARENTNAME"" "
      strSql = strSql + " FROM SCOPE ('deep traversal of " + """"
      strSql = strSql + strUrl + """') "
      strSql = strSql + " WHERE ""DAV:ishidden"" = false"

      'Open the recordset
      objRecordSet.Open(strSql, objConnection, ADODB.CursorTypeEnum.adOpenUnspecified, ADODB.LockTypeEnum.adLockOptimistic, 1)

Any advice would be greatly appreciated, as the deployment of my application is only delayed by this issue.  Thanks.
Avatar of Bob Learned
Bob Learned
Flag of United States of America image

Is this from ASP.NET solution?

Bob
Avatar of tusharashah
tusharashah

Check out this article with some sample code:

http://www.wimdows.net/articles/article.aspx?aid=13

-tushar
Avatar of esdTeamsters

ASKER

Bob,

It's a Visual Basic.NET solution created in Visual Studio.NET 2003.


Tushar,

Thanks for the article - it'll come in handy in the near future when I dive deeper into Active Directory queries.  But for the time being, I'm dealing solely with Exchange.  Is it possible to query an Exchange Mailbox Store using the same methods as Active Directory?  Thanks.
After searching other postings on this topic, I found the following:

https://www.experts-exchange.com/questions/20815034/Accessing-Exchange-Mailbox-via-ADO-NET.html

I converted the syntax to VB.NET but receive an error stating that 'Exoledb is not a registered provider on the local machine.'  Apparently it only exists on Exchange servers.  I have the dll but don't know if there is a way to force the registering of a new provider, or if there is a usable replacement.  Any ideas?
I made mine work and I can access the Exchange Server 2000 for as long as it is set to enable OWA or webDAV. You may update the HOST file to point an IP address to say a server name or an OWA address if necessary.

You need to use ADODB and CDO (reference C:\Program Files\Common Files\Microsoft Shared\CDO\CDOEX.DLL to create a CDO interop). Note that CDOEX.DLL comes with installing Office Outlook XP. Note also that using CDOEX.DLL is not a promised solution as Microsoft claims it is not designed to be used for a developer's purpose. Microsoft recommends that it can only be used as SDK on the same machine where Exchange Server is installed. I used it anyways on my PC (at my own risk). Surprisingly, it works for as long as you open only one (1) connection to the Exchange Server at any given time.

Anyways, here's how I did it:

You'll need:

Dim poRecord As ADODB.Record
Dim poRecordset As ADODB.Recordset
Dim poRecordMessage As ADODB.Record
Dim poMessage As CDO.Message

You use poRecord to open a connection:

Dim psEMailboxURL As String
psEMailboxURL = "http://ServerNameOrIPOrOWAAddress/MailboxName/"
poRecord.Open(psEMailboxURL & "Inbox", , , , , userID, password)

You use poRecordset to open a recordset:

If poRecord.State = ADODB.ObjectStateEnum.adStateOpen Then
 Dim psEMailboxQuery As String
 psEMailboxQuery = "SELECT * " & _
                              "FROM """ & psEMailboxURL & "Inbox"" " & _
                              "WHERE ""urn:schemas:httpmail:read"" = false"
 poRecordset.Open(psEMailboxQuery, poRecord.ActiveConnection)
End If

You use poRecordMessage and poMessage to extract a message from poRecordset:

poRecordMessage.Open(poRecordset, _
 poRecord.ActiveConnection, _
 ADODB.ConnectModeEnum.adModeReadWrite, _
 ADODB.RecordCreateOptionsEnum.adFailIfNotExists)
poMessage.DataSource.OpenObject(poRecordMessage, "_Record")

Be sure to add in your exception handling here and there. Be sure to close where Close() is a method of an object. Refer to the Exchange SDK for information about the many Exchange Store Schema properties (great samples too). Note that this solution relies on webDAV which according to some documents may not be supported in future versions of the Exchange Server.

Have fun.
Thanks for the info etmendz.

I've been able to pull down data with no problem, but my real dilemma is being able to efficiently *update* Exchange.  Is it possible to do this by simply updating the recordset?  The only information I've been able to find on this in the past, has been to update/create one object at a time.  And that was done using 'System.Net.HttpWebRequest' and alot of XML - which I'm trying to avoid at this point if at all possible.  I'd like to simply 'resync' the local recordset with the remote data source - if there is such a method.  The non-working code I have now is:

      Dim objConnection As ADODB.Connection = New ADODB.Connection
      Dim objRecordSet As ADODB.Recordset = New ADODB.Recordset

      strUrl = "http://" + strServerName + "/Exchange/" + strMailBoxName + "/Inbox"

      'Open connection
      objConnection.Provider = "MSDAIPP.dso"
      objConnection.Open(strUrl, strAdUserName, strAdUserPassword, -1)

      'Build the SQL query
      strSql = ""
      strSql = "SELECT "
      strSql = strSql + " ""DAV:href"""
      strSql = strSql + ", ""DAV:displayname"" "
      strSql = strSql + ", ""urn:schemas:httpmail:from"" "
      strSql = strSql + ", ""urn:schemas:httpmail:subject"" "
      ...
      strSql = strSql + ", ""urn:schemas:httpmail:textdescription"" "
      strSql = strSql + ", ""RESOURCE_PARENTNAME"" "
      strSql = strSql + " FROM SCOPE ('deep traversal of " + """"
      strSql = strSql + strUrl + """') "
      strSql = strSql + " WHERE ""DAV:ishidden"" = false"

      'Open the recordset
      objRecordSet.Open(strSql, objConnection, ADODB.CursorTypeEnum.adOpenUnspecified, ADODB.LockTypeEnum.adLockOptimistic, 1)

      objRecordSet.AddNew()
      objRecordSet.Fields("urn:schemas:httpmail:subject").Value = "Test Value"
      ...
      objRecordSet.Fields("urn:schemas:httpmail:textdescription").Value = "Test Value"
      objRecordSet.Update()

      objRecordSet.Close()
      objConnection.Close()


This returns an error stating that 'The recordset doesn't support updating which may be a limitation of the Provider or Lock Type.'  Does anyone know of a provider that supports this?

I did some more digging and found a way to move the data queried in my existing ADO connection/recordset into an ADO.NET DataSet for manipulation.  Unfortunately, I'm finding out that there is no direct support between Exchange and ADO.NET.  I can deal with this if there is a way to handle everything (querying/updating) using ADO.  Thanks again.
ASKER CERTIFIED SOLUTION
Avatar of etmendz
etmendz

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks for all the input etmendz.  Unfortunately I think you're right in that there is no direct support between ADO.NET and Exchange - hopefully that will change in the future.