To show you how to use some of the existing COM interfaces in your .NET applications, I'll show you a simple application (in both Visual Basic .NET and Visual C#) that uses the CDO 1.21 object model.
The application creates a new CDO session, logs on, queries the user's inbox to display some information, and then sends an e-mail from the user 's account. Here it is in Visual Basic:
Imports MAPI Public Class Form1 Inherits System.Windows.Forms.Form #Region " Windows Form Designer generated code " #End Region Dim oSession As New MAPI.Session() Private Sub cmdLogon_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles cmdLogon.Click Err.Clear() 'Attempt to Logon 'Check to make sure server and user alias are filled in If txtExServer.Text = "" Then MsgBox("You must enter a server name!") Exit Sub End If If txtAlias.Text = "" Then MsgBox("You must enter an alias!") Exit Sub End If Try 'Attempt to logon oSession.Logon("", "", True, True, 0, True, _ txtExServer.Text & vbLf & txtAlias.Text) 'Get the Inbox Dim oInbox As MAPI.Folder = oSession.GetDefaultFolder( _ MAPI.CdoDefaultFolderTypes.CdoDefaultFolderInbox) Dim oMessages As MAPI.Messages = oInbox.Messages lblInbox.Text = "There are " lblInbox.Text &= oMessages.Count & " items in your inbox." MsgBox("Logon successful.") Catch 'Some error has occurred! Dim oException As System.Exception oException = Err.GetException MsgBox("ERROR: " & Err.Number & " " & Err.Description & _ " Line number: " & Err.Erl & " Stack dump: " & _ oException.StackTrace) End Try End Sub Private Sub cmdSend_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles cmdSend.Click Try If txtTo.Text = "" Then MsgBox("You must enter a To address!") Exit Sub End If If txtSubject.Text = "" Then MsgBox("Please enter a subject.") Exit Sub End If If txtBody.Text = "" Then MsgBox("Please enter a body.") Exit Sub End If 'Send the message Dim oMessage As MAPI.Message Dim oOutbox As MAPI.Folder oOutbox = oSession.GetDefaultFolder( _ MAPI.CdoDefaultFolderTypes.CdoDefaultFolderOutbox) oMessage = oOutbox.Messages.Add() Dim oRecips As MAPI.Recipients oRecips = oMessage.Recipients Dim oRecip As MAPI.Recipient = oRecips.Add(txtTo.Text, , _ MAPI.CdoRecipientType.CdoTo) oMessage.Subject = txtSubject.Text oMessage.Text = txtBody.Text 'Resolve the recipients oRecips.Resolve(True) If oRecips.Resolved <> True Then MsgBox("You must resolve the recipients!") Exit Sub End If oMessage.Send(True) Catch 'Some error has occurred! Dim oException As System.Exception oException = Err.GetException MsgBox("ERROR: " & Err.Number & " " & Err.Description & _ " Line number: " & Err.Erl & " Stack dump: " & _ oException.StackTrace) End Try End Sub End Class
The C# sample has the same functionality as the Visual Basic version. You need to know a couple of things about programming with C# to be successful programming against CDO 1.21. First, you must declare the default threading for your application to be a single-threaded apartment (STA). You do this by using the [STAThread] attribute. This is what CDO expects your application threading model to be. If you skip this step, you will probably get a MAPI_E_UNKNOWN error.
Second, you must pass Missing.Value for any optional object arguments in the method calls in CDO. Otherwise, C# will throw a compilation error because it will not be able to find CDO function prototypes that match your calls. Be sure to include the System.Reflection namespace to take advantage of the Missing.Value statement.
Besides these two differences and the difference in language semantics between Visual Basic and C#, the code is pretty much the same. Here is the C# version:
using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Windows.Forms; using System.Data; using System.Reflection; namespace CDO121CSharp { /// <summary> /// Summary description for Form1. /// </summary> public class frmMain : System.Windows.Forms.Form { private System.Windows.Forms.Button cmdGo; /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; public frmMain() { // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after // InitializeComponent call // } /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> . . . #endregion /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.Run(new frmMain()); } private void cmdGo_Click(object sender, System.EventArgs e) { // Class variables MAPI.Session oSession; string strExchangeServer = "thomrizwin2k"; string strUserName = "thomriz"; // Establish a new Session oSession = new MAPI.Session(); // Connect to the Exchange Server and establish try { oSession.Logon( Missing.Value, Missing.Value, false, true, -1, true, strExchangeServer + "\n" + strUserName); MessageBox.Show("Logon Successful!"); MAPI.Folder oInbox = MAPI.Folder)oSession.GetDefaultFolder( MAPI.CdoDefaultFolderTypes.CdoDefaultFolderInbox); MAPI.Messages oMessages = (MAPI.Messages)oInbox.Messages; MessageBox.Show("There are " + oMessages.Count + " items in your inbox!"); //Send a new message MAPI.Folder oOutBox = (MAPI.Folder)oSession.GetDefaultFolder( MAPI.CdoDefaultFolderTypes.CdoDefaultFolderOutbox); MAPI.Messages oOutMessages = (MAPI.Messages)oOutBox.Messages; MAPI.Message oMsg = (MAPI.Message)oOutMessages.Add(Missing.Value, Missing.Value,Missing.Value,Missing.Value); MAPI.Recipients oRecips = (MAPI.Recipients)oMsg.Recipients; MAPI.Recipient oRecip = (MAPI.Recipient)oRecips.Add("Thomas Rizzo", Missing.Value,Missing.Value,Missing.Value); oRecips.Resolve(true); oMsg.Subject = "New Test Message"; oMsg.Text = "Test 123"; oMsg.Send(Missing.Value,Missing.Value,Missing.Value); } catch (System.Exception oException) { throw new Exception( "Could not logon to Exchange Server " + strExchangeServer, oException); } } } }
Note | To use ASP.NET with CDO 1.21, you must have the nonsecure version of CDO 1.21 on your server machines by installing Exchange or Outlook Web Access (OWA) on the server. (The version of CDO that ships with Outlook is secure, so it will not work.) This is the only way to get CDO 1.21 on the machine. You can get CDO 1.21 installed on your Web server with the administration-tools-only installation of Exchange. You will not run into issues when an ASP.NET application that uses CDO 1.21 and your Exchange server are on the same machine. However, if they are on separate machines, you might get a MAPI_E_FAILONEPROVIDER error or a MAPI_E_LOGON_FAILED error. Removing the secure CDO installation and installing a server-side version of CDO should fix this problem. Also, with ASP.NET the worker thread does not have access to the Windows file directory; if you use dynamic profiles with CDO, you might get errors. To fix this problem, follow the steps in Microsoft Knowledge Base Article Q166599. |