Blog - Title

November, 2008

Brijs Blogging... Looking Beyond the Obvious

  • Brijs Blogging... Looking Beyond the Obvious

    "Condition is not valid" error on Items.Find for Appointment Item using GlobalAppointmentID as filter

    • 1 Comments

    We are getting "Condition is not valid" error on Items.Find for Appointment Item using GlobalAppointmentID as filter.

    We are using the filter as: strFilter = "[GlobalAppointmentID] = 'apptidhere'" and getting following exception:

    runtime error '-2147352567(80020009)'  "Condition is not valid"

    Then we have tried finding the Item using DSAL  query based on Proptag for GlobalAppointmentID  to avoid exception as below:

    strFilter = "@SQL=""http://schemas.microsoft.com/mapi/id/{6ED8DA90-450B-101B-98DA-00AA003F1305}/00030102"" = 'ApptIDHere'"

    but it would NOT return any Item as result because for both Jet and DASL queries, you cannot restrict on a binary property such as EntryID.

    So, Binary properties are NOT SUPPORTED to Find or Restrict Outlook Items.

    However, We can store GlobalAppointmentID in UserDefinedProperty to find item based on it using Find or Restrict as a workaround.

    Here's what I have done in my sample VBA code and able to get Item from Items.Find using Custom Property :

    NOTE: Following programming examples is for illustration only, without warranty either expressed or implied,
    including, but not limited to, the implied warranties of merchantability and/or fitness for a particular purpose.
    This sample code assumes that you are familiar with the programming language being demonstrated and the tools used
    to create and debug procedures.

       1:  'Creating Apptointment Item with Custom property.
       2:  Sub CreateTestAppointmentWithCustomProp()
       3:      Dim myOlApp As Outlook.Application
       4:      Dim myItem As Outlook.AppointmentItem
       5:      Set myOlApp = CreateObject("Outlook.Application")
       6:      Set myItem = myOlApp.CreateItem(olAppointmentItem)
       7:      myItem.Start = DateAdd("n", 16, Now)
       8:      myItem.End = DateAdd("n", 60, myItem.Start)
       9:      myItem.Subject = "TestAppointment"
      10:      myItem.ItemProperties.Add "GAI", olText, True
      11:      myItem.Save
      12:      myItem.ItemProperties.Item("GAI").Value = myItem.GlobalAppointmentID
      13:      myItem.Save
      14:      myItem.Display
      15:  End Sub
      16:   
      17:  'Finding Item based on Custom Property
      18:  Sub FindItem()
      19:          Dim objOutlook As Outlook.Application
      20:          Set objOutlook = New Outlook.Application
      21:          Dim objNS As Outlook.NameSpace
      22:          Set objNS = objOutlook.Session
      23:          Dim objFolder As Outlook.MAPIFolder
      24:          Set objFolder = objNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar)
      25:          Dim objAppts As Outlook.Items
      26:          Set objAppts = objFolder.Items
      27:          Dim objAppt As Outlook.AppointmentItem
      28:          
      29:          Dim strFilter As String
      30:          strFilter = "@SQL=""http://schemas.microsoft.com/mapi/string/{00020329-0000-0000-C000-000000000046}/GAI"" = 'ApptIDHere'"
      31:       
      32:          Set objAppt = objAppts.Find(strFilter)
      33:          If objAppt Is Nothing Then
      34:              MsgBox ("Nothing Found")
      35:          Else
      36:              MsgBox ("Appt Found")
      37:          End If
      38:  End Sub

    To get property tag of your custom property for your DASL query we can use MFCMAPI available @ http://www.codeplex.com/MFCMAPI.

    I have also referred following articles:

  • Brijs Blogging... Looking Beyond the Obvious

    Issue: Prerequisites Packages are not available for the Office Add-in Setup Project developed using Visual Studio

    • 1 Comments

    We need to add Prerequisites Packages to Office Add-in Setup Project developed using Visual Studio; so that out Add-in works as expected when we deploy it on other machines.

    In case any of pre-requisite packages are not available/listed under Add Prerequisites dialog box(shown below) then we can include user-provided prerequisite packages because Prerequisites dialog box is extensible.

    Here's how we can do it.

    First download the required redistributable prerequisite package from the links below or get it from Microsoft Download Center

    prereq

    And then use Bootstrapper Manifest Generator available @ http://code.msdn.microsoft.com/bmg to add bootstrapper package manifest so that the package would appear in the Prerequisites dialog shown above.

    Also make sure that we select the "Download prerequisites from the same location as my application" option.

    Here is the list of few of common redistributable Pre-requisite packages for Office Add-ins:

    Office PIAs depending on version of Office we are targeting:

    .Net Framework for which we have targeted the Add-in:

    • .NET Framework 3.5
      Microsoft .NET Framework 3.5 contains many new features building incrementally upon .NET Framework 2.0 and 3.0, and includes .NET Framework 2.0 service pack 1 and .NET Framework 3.0 service pack 1.
    • .NET Framework 3.5 Service pack 1
      Microsoft .NET Framework 3.5 Service Pack 1 is a full cumulative update that contains many new features building incrementally upon .NET Framework 2.0, 3.0, 3.5, and includes cumulative servicing updates to the .NET Framework 2.0 and .NET Framework 3.0 subcomponents.
    • .NET Framework Version 2.0 Redistributable Package (x86)
      The Microsoft .NET Framework version 2.0 (x86) redistributable package installs the .NET Framework runtime and associated files required to run applications developed to target the .NET Framework v2.0.
    • .NET Framework Version 1.1 Redistributable Package
      The .NET Framework version 1.1 redistributable package includes everything you need to run applications developed using the .NET Framework.

    VSTO Runtime depending on the version of VSTO used for Add-in developed:

    Fixes

    If you are using Visual Studio 2008 then you have to follow the Workaround mentioned below to get KB908002 listed under add pre-requisites dialog:

    1.    Download and install the fix on a machine which has Visual Studio 2005 installed.
    2.    Navigate to *C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\BootStrapper\Packages*, locate KB908002 folder.
    3.    Log on to the machine which has Visual Studio 2008 installed and copy KB908002 folder to *C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages*
    4.    Now, if you go to pre-requisites list on Visual Studio 2008 machine you would see the fix listed.

    References:

    http://msdn.microsoft.com/en-us/magazine/cc163899.aspx

  • Brijs Blogging... Looking Beyond the Obvious

    How to check that outgoing Outlook Mail Item is with digital signature or encrypted from VSTO Add-in in C#?

    • 2 Comments

    How to capture whether user has checked to send Outlook Mail with digital signature or encrypted from VSTO Add-in in C# ?

    We can use the following code snippet with VSTO SE Outlook Skeleton project to build sample add-in:

    IMPORTANT NOTE: This add-in will only work if we are NOT using Word as default email editor.

    /*NOTE: Following programming examples is for illustration only, without warranty either expressed or implied,  
    including, but not limited to, the implied warranties of merchantability and/or fitness for a particular purpose.   
    This sample code assumes that you are familiar with the programming language being demonstrated and the tools used
    to create and debug procedures.*/

       1:  using System;
       2:  using System.Windows.Forms;
       3:  using Microsoft.VisualStudio.Tools.Applications.Runtime;
       4:  using Outlook = Microsoft.Office.Interop.Outlook;
       5:  using Office = Microsoft.Office.Core;
       6:   
       7:  namespace OutlookAddin1
       8:  {
       9:      public partial class ThisApplication
      10:      {
      11:          private void ThisApplication_Startup(object sender, System.EventArgs e)
      12:          {
      13:              this.ItemSend +=new Microsoft.Office.Interop.Outlook.ApplicationEvents_11_ItemSendEventHandler(ThisApplication_ItemSend);   
      14:          }
      15:   
      16:          private void ThisApplication_Shutdown(object sender, System.EventArgs e)
      17:          {
      18:          }
      19:          private Office.CommandBarButton EncButton = null;
      20:          private Office.CommandBarButton DigButton = null;
      21:          private void ThisApplication_ItemSend(object Item, ref bool Cancel)
      22:          {
      23:              Outlook.MailItem mItem = null;
      24:    
      25:              try
      26:              {
      27:                  mItem = Item as Outlook.MailItem;
      28:   
      29:                  EncButton = (Office.CommandBarButton) mItem.GetInspector.CommandBars.FindControl(Office.MsoControlType.msoControlButton , 718, Type.Missing, true);
      30:                  if (EncButton.State ==  Office.MsoButtonState.msoButtonDown )
      31:                  {
      32:                      MessageBox.Show ("Mail will be Encrypted");
      33:                  }
      34:   
      35:                  DigButton = (Office.CommandBarButton)mItem.GetInspector.CommandBars.FindControl(Office.MsoControlType.msoControlButton, 719, Type.Missing, true);
      36:                  if (DigButton.State == Office.MsoButtonState.msoButtonDown)
      37:                  {
      38:                      MessageBox.Show ("Mail will be Digitally signed");
      39:                  }
      40:                  
      41:              }
      42:              catch (Exception ex)
      43:              {
      44:                  System.Windows.Forms.MessageBox.Show(ex.Message);
      45:                  Cancel = true;
      46:              }
      47:   
      48:          }
      49:          #region VSTO generated code
      50:   
      51:          /// <summary>
      52:          /// Required method for Designer support - do not modify
      53:          /// the contents of this method with the code editor.
      54:          /// </summary>
      55:          private void InternalStartup()
      56:          {
      57:              this.Startup += new System.EventHandler(ThisApplication_Startup);
      58:              this.Shutdown += new System.EventHandler(ThisApplication_Shutdown);
      59:          }
      60:   
      61:          #endregion
      62:      }
      63:  }

    Please refer to following article related to working with CommandBars in Outlook Solution:

    How to Use CommandBars in Outlook Solutions
    http://support.microsoft.com/kb/201095

    The above article also have a Microsoft Excel Macro to generate a list of Outlook 2000/2003 CommandBar control IDs.

  • Brijs Blogging... Looking Beyond the Obvious

    How to send deferred delivery email using Exchange Web Services ?

    • 1 Comments

    We can send deferred delivery mail using Exchange Web Services by setting PR_DEFERRED_SEND_TIME and PR_DEFERRED_DELIVERY_TIME MAPI properties as extended properties on the EWS request.

    Here is the sample code in C#:

    NOTE: Following programming examples is for illustration only, without warranty either expressed or implied,
    including, but not limited to, the implied warranties of merchantability and/or fitness for a particular purpose.
    This sample code assumes that you are familiar with the programming language being demonstrated and the tools used
    to create and debug procedures.

       1:  using System;
       2:  using System.Collections.Generic;
       3:  using System.Linq;
       4:  using System.Text;
       5:  using SendMailWithDeferredDelivery.msgex07;
       6:  using System.Net;
       7:  using System.Net.Security;
       8:  using System.Security.Cryptography.X509Certificates;
       9:   
      10:  namespace SendMailWithDeferredDelivery
      11:  {
      12:      class Program
      13:      {
      14:          static void Main(string[] args)
      15:          {
      16:              //Please change the server, domain, username, password 
      17:              ExchangeServiceBinding esb = new ExchangeServiceBinding();
      18:              esb.Credentials = new NetworkCredential("user", "pass!", "domain");
      19:              esb.Url = @"https://<FQDN Server>/EWS/Exchange.asmx";
      20:              
      21:   
      22:              System.Net.ServicePointManager.ServerCertificateValidationCallback = delegate(Object obj, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
      23:              {
      24:                  // Replace this line with code to validate server certificate.
      25:                  return true;
      26:              };
      27:   
      28:   
      29:              esb.RequestServerVersionValue = new RequestServerVersion();
      30:              esb.RequestServerVersionValue.Version = ExchangeVersionType.Exchange2007_SP1;
      31:   
      32:              // Create a new message.
      33:              MessageType message = new MessageType();
      34:   
      35:              // Define the e-mail address of the recipient of the message.
      36:              EmailAddressType singleRecip = new EmailAddressType();
      37:              singleRecip.EmailAddress = "user@msglab.com";
      38:   
      39:              message.ToRecipients = new EmailAddressType[2];
      40:              message.ToRecipients[0] = singleRecip;
      41:   
      42:              // Set the subject and sensitivity properties.
      43:              message.Subject = "Siberian Tigers";
      44:              message.Sensitivity = SensitivityChoicesType.Personal;
      45:   
      46:              message.ExtendedProperty = new ExtendedPropertyType[2];
      47:   
      48:              message.ExtendedProperty[0] = new ExtendedPropertyType();
      49:   
      50:              message.ExtendedProperty[0].ExtendedFieldURI = new PathToExtendedFieldType();
      51:   
      52:              //NOTE: This PropertyID is equal to PropertyTag "0x3FEF" but you have to use PropertyID and not PropertyTag 
      53:              //otherwise it will NOT work as expected and this will not be visible via OOM or WebDAV, 
      54:              //you have to specify it as Integer value in PropertyTag field 
      55:              //PR_DEFERRED_SEND_TIME
      56:              message.ExtendedProperty[0].ExtendedFieldURI.PropertyTag = "16367";
      57:              
      58:              message.ExtendedProperty[0].ExtendedFieldURI.PropertyType = MapiPropertyTypeType.SystemTime;
      59:   
      60:              //Sending mail in another 5 Mins
      61:              DateTime deliverydatetime;
      62:              System.DateTime today = System.DateTime.Now;
      63:              System.TimeSpan duration = new System.TimeSpan(0,5, 0);
      64:              deliverydatetime = today.Add(duration);
      65:   
      66:              message.ExtendedProperty[0].Item = deliverydatetime.ToUniversalTime().ToString();
      67:   
      68:              //NOTE: This PropertyID is equal to PropertyTag "0x000F" but you have to use PropertyID and not PropertyTag 
      69:              //otherwise it will NOT work as expected and this will not be visible via OOM or WebDAV, 
      70:              //you have to specify it as Integer value in PropertyTag field 
      71:              //PR_DEFERRED_DELIVERY_TIME
      72:           
      73:              message.ExtendedProperty[1] = new ExtendedPropertyType();
      74:   
      75:              message.ExtendedProperty[1].ExtendedFieldURI = new PathToExtendedFieldType();
      76:   
      77:              message.ExtendedProperty[1].ExtendedFieldURI.PropertyTag = "15";
      78:             
      79:              //message.ExtendedProperty[1].ExtendedFieldURI.PropertyTag= "0x000F";
      80:   
      81:              message.ExtendedProperty[1].ExtendedFieldURI.PropertyType = MapiPropertyTypeType.SystemTime;
      82:   
      83:              message.ExtendedProperty[1].Item = deliverydatetime.ToUniversalTime().ToString();
      84:   
      85:               
      86:              // Set the body property.
      87:              message.Body = new BodyType();
      88:              message.Body.BodyType1 = BodyTypeType.HTML;
      89:              message.Body.Value =  "Did you know there are estimated to be only about 400 " +
      90:                                      "of these magnificent creatures left in the wild?";
      91:   
      92:              // Create a CreateItem request.
      93:              CreateItemType createItem = new CreateItemType();
      94:   
      95:              // Specify that the CreateItem operation should directly send the message
      96:              // and save a copy in the Sent Items folder.
      97:              createItem.MessageDisposition = MessageDispositionType.SendAndSaveCopy;
      98:              createItem.MessageDispositionSpecified = true;
      99:   
     100:              DistinguishedFolderIdType folder = new DistinguishedFolderIdType();
     101:              folder.Id = DistinguishedFolderIdNameType.outbox;
     102:   
     103:              TargetFolderIdType targetFolder = new TargetFolderIdType();
     104:              targetFolder.Item = folder;
     105:              createItem.SavedItemFolderId = targetFolder;
     106:   
     107:              createItem.Items = new NonEmptyArrayOfAllItemsType();
     108:              createItem.Items.Items = new ItemType[1] { message };
     109:   
     110:              // Call the CreateItem method and get its response. 
     111:              CreateItemResponseType response = esb.CreateItem(createItem);
     112:   
     113:              // Get the items returned by CreateItem.
     114:              ResponseMessageType[] itemsResp = response.ResponseMessages.Items;
     115:              
     116:          }
     117:      }
     118:  }
     
    EWS Rocks!!!
  • Brijs Blogging... Looking Beyond the Obvious

    How to send a copy of all SMTP mails to another recipient mailbox using SMTP Event Sink

    • 1 Comments

    Sometime we need to trap all the outgoing/incoming email messages and would like to forward a copy of it to another recipient mailbox.
    Here is sample script to achieve that:

    Step 1: Install Exchange 2003 SDK on your Exchange Server. You can download it at the following link.
    http://www.microsoft.com/downloads/details.aspx?FamilyID=a865936f-50da-47a0-9dce-f24e8307f38d&DisplayLang=en

    Step 2: Open Notepad and Paste the following code to it and save it as forward.vbs

    NOTE: Following programming examples is for illustration only, without warranty either expressed or implied, including, but not limited to, the implied warranties of merchantability and/or fitness for a particular purpose. This sample code assumes that you are familiar with the programming language being demonstrated and the tools used to create and debug procedures.

     

       1:  <SCRIPT LANGUAGE="VBScript"> 
       2:   
       3:  Sub ISMTPOnArrival_OnArrival(ByVal Msg, EventStatus) 
       4:   
       5:  Dim RecpList 
       6:   
       7:  recplist = Msg.EnvelopeFields("http://schemas.microsoft.com/cdo/smtpenvelope/recipientlist")
       8:   
       9:  'Change "administrator@dc.com" to the mailbox address to which you want to send a B’cc copy
      10:  If ( Instr(recplist,"SMTP:administrator@dc.com;") =< 0) then
      11:      recplist = recplist &  "SMTP:administrator@dc.com;" 
      12:  End If
      13:  Msg.EnvelopeFields("http://schemas.microsoft.com/cdo/smtpenvelope/recipientlist") = recplist 
      14:  Msg.EnvelopeFields.update
      15:  WriteLog(Msg.EnvelopeFields("http://schemas.microsoft.com/cdo/smtpenvelope/recipientlist"))
      16:  WriteLog("Done")
      17:  End Sub
      18:   
      19:  Sub WriteLog(ByVal strMessage)
      20:      Dim fs
      21:      Set fs = CreateObject("Scripting.FileSystemObject")
      22:      Dim file
      23:   
      24:  'change "C:\bnewlog.txt" name/path of the log file
      25:      Set file = fs.opentextfile("C:\bnewlog.txt", 8, True)
      26:      file.Write strMessage
      27:      file.Close
      28:  End Sub
      29:   
      30:  </SCRIPT>

    Step 3: Register the event sink
    ========================
    1. Click Start -> Run­, Type "cmd" and Click OK
    2. Type "CD C:\Program Files\Exchange SDK\SDK\Support\CDO\Scripts" and Press Enter
    3. Type cscript smtpreg.vbs /add 1 onarrival SMTPScriptingHost CDO.SS_SMTPOnArrivalSink "mail from=*" and Press Enter
    4. Type cscript smtpreg.vbs /setprop 1 onarrival SMTPScriptingHost Sink ScriptName "C:\forward.vbs" and Press Enter (make sure that the path to forward.vbs is correct)

    Now, all the incoming/outgoing emails bcc'ed/copied to administrator@dc.com.

    To unregister this event, type the following:
    cscript smtpreg.vbs /remove 1 OnArrival SMTPScriptingHost

    Please also refer to the following article 273233:You cannot modify MAPI messages that are trapped in an SMTP transport event sink.

    Feel free to post your comments or request for messaging related development issues.

  • Brijs Blogging... Looking Beyond the Obvious

    Resources for development tests and hands on experience with Microsoft's programming tools and technologies.

    • 1 Comments

    If you are looking for resources to test your development projects then read on... 

    Run IT on a Virtual Hard Disk
    http://www.microsoft.com/vhd

    You can now access the entire catalog of pre-configured Microsoft and partner products and solutions in the VHD format and start evaluating and testing today from www.microsoft.com/vhd.

    Using the power of virtualization, you can now use a series of pre-configured Virtual Hard Disks (VHDs). You can download the VHDs and evaluate them for free in your own environment without the need for dedicated servers or complex installations.

    A virtualization product that supports the VHD format is required to use this virtual machine. Microsoft Virtual PC or Microsoft Virtual Server are provided for free and can be used with these VHD based virtual machines.

    Few of the VHD avalilables:

    And if you are looking for some hands-on experience with Microsoft's programming tools and technologies then refer to the links below:

    Welcome to TechNet Virtual Labs
    http://www.microsoft.com/technet/traincert/virtuallab/default.mspx
    Quickly evaluate and test Microsoft's newest server products through a series of guided, hands-on labs you can complete in 90 minutes or less.

    MSDN Virtual Labs
    http://msdn2.microsoft.com/virtuallabs/
    These Virtual Labs for developers give you hands-on experience with Microsoft's programming tools and technologies.

Page 1 of 1 (6 items)