none
location property of exceptions in rceurring appointment are not updating RRS feed

  • Question

  • Hi,

    i am using visual studio 2010 to develop addin for outlook 2010.

    i am facing a problem where i can not figure out that whats the problem with my code. i found that location property of exceptions in recurring appointment are not updating

    Steps to replicate.

    1) create a addin which will update the location property of exceptions in a recurring appointment, you can do it either one by one or in a loop

    2) create a recurring appointment without attendees.

    3) make exception in the recurring appointment by changing time or location or subject.

    4) run your addin which will try to update the location of exceptions in a recurring appointment.

    after some time , you will find location are not updating.  here is the sample code of my addin


    Imports Microsoft.Office.Interop.Outlook
    Imports Microsoft.Office.Core
    Public Class ThisAddIn
    	Public OutlookNS As Outlook.NameSpace
    	Dim WithEvents AppInspectors As Outlook.Inspectors
    	Dim WithEvents AppInspector As Outlook.Inspector
    	Dim WithEvents appitem As Outlook.AppointmentItem
    	Dim WithEvents app As Outlook.Application
    	Dim WithEvents CalendarItems As Outlook.Items
    	Dim Id As String = ""
    
    
    	Private Sub ThisAddIn_Startup() Handles Me.Startup
    		OutlookNS = Application.GetNamespace("MAPI")
    		'CodeSite.Send(OutlookNS.ToString)
    		app = Application
    		AppInspectors = Application.Inspectors
    		Dim Calendar As Outlook.MAPIFolder = OutlookNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar)
    		Id = Calendar.StoreID
    		CalendarItems = Calendar.Items
    		OutlookNS = Application.GetNamespace("MAPI")
    	End Sub
    
    	Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown
    
    	End Sub
    
    	Private Sub appinspector1(ByVal Inspector As Microsoft.Office.Interop.Outlook.Inspector) Handles AppInspectors.NewInspector
    		appitem = Inspector.CurrentItem
    		AppInspector = Inspector
    	End Sub
    	Private Sub appinspector_close() Handles AppInspector.Close
    		'appitem = Inspector.CurrentItem
    		
    
    	End Sub
    
    	Private Sub AppItem_Write(ByRef Cancel As Boolean) Handles appitem.Write
    		MsgBox("write")
    		'If appitem.IsRecurring And appitem.RecurrenceState = OlRecurrenceState.olApptMaster Then
    		'	Dim rp As Outlook.RecurrencePattern = Nothing
    		'	rp = appitem.GetRecurrencePattern()
    		'	If rp.Exceptions.Count > 0 Then
    		'		Dim exceptions As Outlook.Exceptions = rp.Exceptions
    		'		Dim rpex As Outlook.Exception = Nothing
    		'		Dim exception As Outlook.AppointmentItem = Nothing
    		'		Dim e As Int16
    		'		For e = 1 To exceptions.Count
    		'			rpex = exceptions(e)
    		'			If (Not rpex.Deleted) Then
    		'				exception = rpex.AppointmentItem
    		'				exception.Location = appitem.Location
    		'				exception.Save()
    		'			End If
    		'			NAR(exception)
    		'			NAR(rpex)
    		'		Next
    		'	End If
    		'	NAR(rp)
    		'End If
    	End Sub
    
    	Private Sub NAR(ByVal o As Object)
    		Dim Count As Integer = 1
    		Try
    			'While Count > 0
    			Count = System.Runtime.InteropServices.Marshal.ReleaseComObject(o)
    			'Log("Released object: count=" & Count)
    			'End While
    		Catch
    		Finally
    			o = Nothing
    		End Try
    	End Sub
    
    	Private Function GetException(ByVal rp As Outlook.RecurrencePattern, ByVal ExceptionDate As Date) As Outlook.AppointmentItem
    		Dim Exceptions As Outlook.Exceptions = rp.Exceptions
    		Dim RPex As Outlook.Exception = Nothing
    		Dim App As Outlook.AppointmentItem = Nothing
    		Dim e As Int16
    		For e = 1 To Exceptions.Count
    			RPex = Exceptions(e)
    			If (Not RPex.Deleted) Then
    				App = Exceptions(e).AppointmentItem
    				If App.Start = ExceptionDate Then
    					NAR(RPex)
    					NAR(Exceptions)
    					Return App
    				Else
    					NAR(App)
    				End If
    			End If
    			NAR(RPex)
    		Next
    		NAR(Exceptions)
    		Return Nothing
    	End Function
    	Private Sub contextmenu(ByVal CommandBar As Office.CommandBar, ByVal Selection As Outlook.Selection) Handles app.ItemContextMenuDisplay
    		'If Selection.Item(1).Class = olAppointment Then
    		' Add a new button to the bottom of the CommandBar
    		' (which represents the selection context menu.)
    		Dim objButton As Office.CommandBarButton
    
    		objButton = CommandBar.Controls.Add(Office.MsoControlType.msoControlButton)
    
    		With objButton
    			.FaceId = 1000
    			'.Tag = "syncthisitem"
    			'.OnAction = _
    			'"OutlookAddin1.ThisOutlookSession.syncthisitem"
    			.Parameter = Selection.Item(1).EntryId
    			.Caption = "Sync"
    			.BeginGroup = True
    
    
    
    		End With
    		AddHandler objButton.Click, AddressOf syncthisitem
    		'endif
    	End Sub
    	Private Sub syncthisitem(ByVal ctrl As Microsoft.Office.Core.CommandBarButton, ByRef CancelDefault As Boolean)
    		Dim frm As New Form1
    		frm.entryid = ctrl.Parameter
    		frm.thisaddin = Me
    		frm.Show()
    	End Sub
    
    	Public Sub setlocation(eid As String, location As String, ourdate As String)
    		Dim app As Outlook.AppointmentItem = Nothing
    		Dim excp As Outlook.AppointmentItem = Nothing
    		app = OutlookNS.GetItemFromID(eid, Id)
    		Dim rp As Outlook.RecurrencePattern = Nothing
    		rp = app.GetRecurrencePattern()
    		excp = GetException(rp, ourdate)
    		NAR(rp)
    		'MsgBox(app.RecurrenceState)
    		excp.Location = location
    		excp.Save()
    		NAR(excp)
    		NAR(app)
    	End Sub
    
    	Public Sub savemainitem(eid As String)
    		'Dim app As Outlook.AppointmentItem = Nothing
    		'app = OutlookNS.GetItemFromID(eid, Id)
    		'Dim UserProperties As Outlook.UserProperties
    		'Dim DDLSignature As Outlook.UserProperty
    		'UserProperties = app.UserProperties
    		'DDLSignature = UserProperties.Find("test")
    		'If DDLSignature Is Nothing Then DDLSignature = UserProperties.Add("test", OlUserPropertyType.olText, True)
    		''Things that can be changed without opening the booking
    		'DDLSignature.Value = Now.t
    		'NAR(DDLSignature)
    		'NAR(UserProperties)
    		'app.Save()
    		'NAR(app)
    	End Sub
    
    	Private Sub setprop(dateer)
    
    	End Sub
    End Class
    
    
    

    class for form

    Public Class Form1
    	Public entryid As String = Nothing
    	Public thisaddin As ThisAddIn
    
    	Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    		thisaddin.setlocation(entryid, TextBox1.Text, "2012-06-03 21:00")
    		thisaddin.setlocation(entryid, TextBox1.Text, "2012-06-04 21:00")
    		thisaddin.setlocation(entryid, TextBox1.Text, "2012-06-05 21:00")
    		thisaddin.setlocation(entryid, TextBox1.Text, "2012-06-06 21:00")
    		thisaddin.setlocation(entryid, TextBox1.Text, "2012-06-07 21:00")
    		'thisaddin.savemainitem(entryid)
    		Me.Close()
    	End Sub
    
    	Private Sub NAR(ByVal o As Object)
    		Dim Count As Integer = 1
    		Try
    			'While Count > 0
    			Count = System.Runtime.InteropServices.Marshal.ReleaseComObject(o)
    			'Log("Released object: count=" & Count)
    			'End While
    		Catch
    		Finally
    			o = Nothing
    		End Try
    	End Sub
    End Class


    By running above addin you will find that when you right click on appointment , you will find a sync option in context menu. clicking on it will open up a form

    in Location field, just add anything and then click on button1, location for the exception on the date given in code will try to update location, either in first attempt or after some more attempts you will find that locations are not updating either for some of the exceptions or for all exceptions.

    i am not sure whats problem with above code , this code is releasing com objects timely, but still can not understand why its happening.

    let me know what problem with above code

    Thanks



    Friday, May 25, 2012 3:18 PM

Answers

  • All of this sort of thing is much more an art than a science in my experience. Generally in a case like that I'd make sure of each instance of objects I'd create and make sure to declare the objects outside any loops and then instantiate them inside the loops.
     
    In every loop pass I first start by nulling the objects and seeing if that's enough and I can avoid calling the GC repeatedly, as that's expensive in terms of time. If that isn't enough I call Marshal.ReleaseComObject() in every pass, then set the object to null. I'd try calling the GC not on every pass in the loop, but at intervals such as maybe every 30 or 100 passes in the loop. If that's not enough, I'd call the GC on each pass.
     
    If I was running into problems I'd probably start out with the most comprehensive types of nulling objects and make sure that fixed the problem. If it did I'd maybe try to back off a bit until the problem came back, assuming any performance problems surfaced.
     
    I'd avoid using Marshal.FinalReleaseComObject() until the end of the procedure, when the objects and their RCW's aren't needed any longer. Otherwise I'd expect to see RCW errors unless I declared a new object and instantiated it each time, which is really expensive.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Nitrup" <=?utf-8?B?Tml0cnVw?=> wrote in message news:2897e0f7-a3bd-40e7-98bb-5f6ec766ef01...

    Ok ken, i will see what i can i do .

    Thanks for your help and valuable time.

    But before closing thread, can you give some tips on how we should loop through all the exceptions, like at what point we should release the exception, exceptions and recurrencepattern type object while looping through ,to make sure all com objects has been released during this loop execution.

    when we should call GC.Collect and GC.WaitForPendingFinalizers, is it ok if we call just at the end of calling function or everytime when we will release

    com objects?

    it will be better if you can give some snippet of code

    Thanks



    Ken Slovak MVP - Outlook
    • Marked as answer by Nitrup Tuesday, June 19, 2012 2:34 PM
    Tuesday, June 19, 2012 2:14 PM
    Moderator

All replies

  • If this is for Outlook 2010 why are you handling the context menus using deprecated code and not using ribbon callbacks for the context menu?
     
    Does it help at all if you change your NAR() procedure to call Marshal.FinalReleaseComObject? Does it make a diffference if instead of initializing the form using Public entryid As String = Nothing, you used Public entryid As String = "" ?
     
    What about if you don't try to update the location 5 times in a row and wait a while before seeing if the first update worked and then change it again? What about if you call GC.Collect() and Marshal.WaitForPendingFinalizers() after releasing objects and before trying to update the location again?

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Nitrup" <=?utf-8?B?Tml0cnVw?=> wrote in message news:ca931aa7-09fa-4254-a47c-b2bc1799e0db...

    Hi,

    i am using visual studio 2010 to develop addin for outlook 2010.

    i am facing a problem where i can not figure out that whats the problem with my code. i found that location property of exceptions in recurring appointment are not updating

    Steps to replicate.

    1) create a addin which will update the location property of exceptions in a recurring appointment, you can do it either one by one or in a loop

    2) create a recurring appointment without attendees.

    3) make exception in the recurring appointment by changing time or location or subject.

    4) run your addin which will try to update the location of exceptions in a recurring appointment.

    after some time , you will find location are not updating.  here is the sample code of my addin


    Imports Microsoft.Office.Interop.Outlook
    Imports Microsoft.Office.Core
    Public Class ThisAddIn
    	Public OutlookNS As Outlook.NameSpace
    	Dim WithEvents AppInspectors As Outlook.Inspectors
    	Dim WithEvents AppInspector As Outlook.Inspector
    	Dim WithEvents appitem As Outlook.AppointmentItem
    	Dim WithEvents app As Outlook.Application
    	Dim WithEvents CalendarItems As Outlook.Items
    	Dim Id As String = ""
    
    
    	Private Sub ThisAddIn_Startup() Handles Me.Startup
    		OutlookNS = Application.GetNamespace("MAPI")
    		'CodeSite.Send(OutlookNS.ToString)
    		app = Application
    		AppInspectors = Application.Inspectors
    		Dim Calendar As Outlook.MAPIFolder = OutlookNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar)
    		Id = Calendar.StoreID
    		CalendarItems = Calendar.Items
    		OutlookNS = Application.GetNamespace("MAPI")
    	End Sub
    
    	Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown
    
    	End Sub
    
    	Private Sub appinspector1(ByVal Inspector As Microsoft.Office.Interop.Outlook.Inspector) Handles AppInspectors.NewInspector
    		appitem = Inspector.CurrentItem
    		AppInspector = Inspector
    	End Sub
    	Private Sub appinspector_close() Handles AppInspector.Close
    		'appitem = Inspector.CurrentItem
    		
    
    	End Sub
    
    	Private Sub AppItem_Write(ByRef Cancel As Boolean) Handles appitem.Write
    		MsgBox("write")
    		'If appitem.IsRecurring And appitem.RecurrenceState = OlRecurrenceState.olApptMaster Then
    		'	Dim rp As Outlook.RecurrencePattern = Nothing
    		'	rp = appitem.GetRecurrencePattern()
    		'	If rp.Exceptions.Count > 0 Then
    		'		Dim exceptions As Outlook.Exceptions = rp.Exceptions
    		'		Dim rpex As Outlook.Exception = Nothing
    		'		Dim exception As Outlook.AppointmentItem = Nothing
    		'		Dim e As Int16
    		'		For e = 1 To exceptions.Count
    		'			rpex = exceptions(e)
    		'			If (Not rpex.Deleted) Then
    		'				exception = rpex.AppointmentItem
    		'				exception.Location = appitem.Location
    		'				exception.Save()
    		'			End If
    		'			NAR(exception)
    		'			NAR(rpex)
    		'		Next
    		'	End If
    		'	NAR(rp)
    		'End If
    	End Sub
    
    	Private Sub NAR(ByVal o As Object)
    		Dim Count As Integer = 1
    		Try
    			'While Count > 0
    			Count = System.Runtime.InteropServices.Marshal.ReleaseComObject(o)
    			'Log("Released object: count=" & Count)
    			'End While
    		Catch
    		Finally
    			o = Nothing
    		End Try
    	End Sub
    
    	Private Function GetException(ByVal rp As Outlook.RecurrencePattern, ByVal ExceptionDate As Date) As Outlook.AppointmentItem
    		Dim Exceptions As Outlook.Exceptions = rp.Exceptions
    		Dim RPex As Outlook.Exception = Nothing
    		Dim App As Outlook.AppointmentItem = Nothing
    		Dim e As Int16
    		For e = 1 To Exceptions.Count
    			RPex = Exceptions(e)
    			If (Not RPex.Deleted) Then
    				App = Exceptions(e).AppointmentItem
    				If App.Start = ExceptionDate Then
    					NAR(RPex)
    					NAR(Exceptions)
    					Return App
    				Else
    					NAR(App)
    				End If
    			End If
    			NAR(RPex)
    		Next
    		NAR(Exceptions)
    		Return Nothing
    	End Function
    	Private Sub contextmenu(ByVal CommandBar As Office.CommandBar, ByVal Selection As Outlook.Selection) Handles app.ItemContextMenuDisplay
    		'If Selection.Item(1).Class = olAppointment Then
    		' Add a new button to the bottom of the CommandBar
    		' (which represents the selection context menu.)
    		Dim objButton As Office.CommandBarButton
    
    		objButton = CommandBar.Controls.Add(Office.MsoControlType.msoControlButton)
    
    		With objButton
    			.FaceId = 1000
    			'.Tag = "syncthisitem"
    			'.OnAction = _
    			'"OutlookAddin1.ThisOutlookSession.syncthisitem"
    			.Parameter = Selection.Item(1).EntryId
    			.Caption = "Sync"
    			.BeginGroup = True
    
    
    
    		End With
    		AddHandler objButton.Click, AddressOf syncthisitem
    		'endif
    	End Sub
    	Private Sub syncthisitem(ByVal ctrl As Microsoft.Office.Core.CommandBarButton, ByRef CancelDefault As Boolean)
    		Dim frm As New Form1
    		frm.entryid = ctrl.Parameter
    		frm.thisaddin = Me
    		frm.Show()
    	End Sub
    
    	Public Sub setlocation(eid As String, location As String, ourdate As String)
    		Dim app As Outlook.AppointmentItem = Nothing
    		Dim excp As Outlook.AppointmentItem = Nothing
    		app = OutlookNS.GetItemFromID(eid, Id)
    		Dim rp As Outlook.RecurrencePattern = Nothing
    		rp = app.GetRecurrencePattern()
    		excp = GetException(rp, ourdate)
    		NAR(rp)
    		'MsgBox(app.RecurrenceState)
    		excp.Location = location
    		excp.Save()
    		NAR(excp)
    		NAR(app)
    	End Sub
    
    	Public Sub savemainitem(eid As String)
    		'Dim app As Outlook.AppointmentItem = Nothing
    		'app = OutlookNS.GetItemFromID(eid, Id)
    		'Dim UserProperties As Outlook.UserProperties
    		'Dim DDLSignature As Outlook.UserProperty
    		'UserProperties = app.UserProperties
    		'DDLSignature = UserProperties.Find("test")
    		'If DDLSignature Is Nothing Then DDLSignature = UserProperties.Add("test", OlUserPropertyType.olText, True)
    		''Things that can be changed without opening the booking
    		'DDLSignature.Value = Now.t
    		'NAR(DDLSignature)
    		'NAR(UserProperties)
    		'app.Save()
    		'NAR(app)
    	End Sub
    
    	Private Sub setprop(dateer)
    
    	End Sub
    End Class
    
    
    

    class for form

    Public Class Form1
    	Public entryid As String = Nothing
    	Public thisaddin As ThisAddIn
    
    	Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    		thisaddin.setlocation(entryid, TextBox1.Text, "2012-06-03 21:00")
    		thisaddin.setlocation(entryid, TextBox1.Text, "2012-06-04 21:00")
    		thisaddin.setlocation(entryid, TextBox1.Text, "2012-06-05 21:00")
    		thisaddin.setlocation(entryid, TextBox1.Text, "2012-06-06 21:00")
    		thisaddin.setlocation(entryid, TextBox1.Text, "2012-06-07 21:00")
    		'thisaddin.savemainitem(entryid)
    		Me.Close()
    	End Sub
    
    	Private Sub NAR(ByVal o As Object)
    		Dim Count As Integer = 1
    		Try
    			'While Count > 0
    			Count = System.Runtime.InteropServices.Marshal.ReleaseComObject(o)
    			'Log("Released object: count=" & Count)
    			'End While
    		Catch
    		Finally
    			o = Nothing
    		End Try
    	End Sub
    End Class


    By running above addin you will find that when you right click on appointment , you will find a sync option in context menu. clicking on it will open up a form

    in Location field, just add anything and then click on button1, location for the exception on the date given in code will try to update location, either in first attempt or after some more attempts you will find that locations are not updating either for some of the exceptions or for all exceptions.

    i am not sure whats problem with above code , this code is releasing com objects timely, but still can not understand why its happening.

    let me know what problem with above code

    Thanks




    Ken Slovak MVP - Outlook
    Friday, May 25, 2012 6:26 PM
    Moderator
  • Hi Ken,

    Thanks for your Reply..

    The code i used was just a quick sample code to demonstrate problem, so i was least concern about context menu option.

    Now, as you suggested using GC.Collect() and GC.WaitForPendingFinalizers(), it worked for my sample code.

    But in my actual application , where location will also be updating one by one in a loop , i tried using GC.Collect() and GC.WaitForPendingFinalizers(), i found that , location property for corresponding appointment is being updated, but its not updating on calendar. if i debug it through outlook spy, it shows correct location but not on calendar and opening inspector window also shows correct location

    using Marshal.FinalReleaseComObject is not helping either.

    i do not know whats going wrong.

    it only updates location first time on calendar, its like , i created an appointment and a webservice is initiated to update it in database, but due to some criteria location has been changed and request handler will come up with new locations and tried to update locations in the appointment and will make all of them exception. this time change appears on calendar.

    now, after that if i try to update the appointment and then requesthandler tries to update appointment, location on calendar do not update but on outlook spy , change is appearing.

    any idea, what else i can try

    Thanks

    Monday, May 28, 2012 11:19 AM
  • Outlook folder updating in an Explorer view is a problem that has no real good solutions. Usually a switch to another folder and then back again is what's done, but that causes a flicker in the display when the ActiveExplorer().CurrentFolder is switched to a different folder and then switched back again.

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Nitrup" <=?utf-8?B?Tml0cnVw?=> wrote in message news:3ac3b538-f350-43f8-a62e-8b26ae026113...

    Hi Ken,

    Thanks for your Reply..

    The code i used was just a quick sample code to demonstrate problem, so i was least concern about context menu option.

    Now, as you suggested using GC.Collect() and GC.WaitForPendingFinalizers(), it worked for my sample code.

    But in my actual application , where location will also be updating one by one in a loop , i tried using GC.Collect() and GC.WaitForPendingFinalizers(), i found that , location property for corresponding appointment is being updated, but its not updating on calendar. if i debug it through outlook spy, it shows correct location but not on calendar and opening inspector window also shows correct location

    using Marshal.FinalReleaseComObject is not helping either.

    i do not know whats going wrong.

    it only updates location first time on calendar, its like , i created an appointment and a webservice is initiated to update it in database, but due to some criteria location has been changed and request handler will come up with new locations and tried to update locations in the appointment and will make all of them exception. this time change appears on calendar.

    now, after that if i try to update the appointment and then requesthandler tries to update appointment, location on calendar do not update but on outlook spy , change is appearing.

    any idea, what else i can try

    Thanks


    Ken Slovak MVP - Outlook
    Tuesday, May 29, 2012 1:55 PM
    Moderator
  • ken,

    In previous reply you said that while updating location in a row wait a while before seeing if the first update worked and then change it again, is there any other way instead of GC.Collect() and GC.WaitForPendingFinalizers() which i can use to make sure location has been updated.

    Thanks

    Tuesday, May 29, 2012 2:57 PM
  • I think you're going to need to have a complete release of the items before they can update correctly, the tests you did with calling the garbage collector seem to prove that. Why is calling those methods a problem, other than possible performance issues?

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Nitrup" <=?utf-8?B?Tml0cnVw?=> wrote in message news:06613215-16f0-47f3-940f-c730ca6fce6d...

    ken,

    In previous reply you said that while updating location in a row wait a while before seeing if the first update worked and then change it again, is there any other way instead of GC.Collect() and GC.WaitForPendingFinalizers() which i can use to make sure location has been updated.

    Thanks


    Ken Slovak MVP - Outlook
    Tuesday, May 29, 2012 3:03 PM
    Moderator
  • Hi,

    i think it may be due to the fact that in my actual application , when write event fires, my addin sets same location for all exception . it does something like this

    If appitem.IsRecurring And appitem.RecurrenceState = OlRecurrenceState.olApptMaster And Not exceptionupadated Then
    			Dim rp As Outlook.RecurrencePattern = Nothing
    			rp = appitem.GetRecurrencePattern()
    			If rp.Exceptions.Count > 0 Then
    				Dim exceptions As Outlook.Exceptions = rp.Exceptions
    				Dim rpex As Outlook.Exception = Nothing
    				Dim exception As Outlook.AppointmentItem = Nothing
    				Dim e As Int16
    				For e = 1 To exceptions.Count
    					rpex = exceptions(e)
    					If (Not rpex.Deleted) Then
    						exception = rpex.AppointmentItem
    						exception.Location = appitem.Location
    						exception.Save()
    					End If
    					NAR(exception)
    					NAR(rpex)
    				Next
    			End If
    			NAR(rp)
    			exceptionupadated = True
    			GC.Collect()
    			GC.WaitForPendingFinalizers()
    			GC.Collect()
    		End If

    then after that , request handler comes up with new set of locations and then tries to update location again, there we find a problem.

    i can replicate this in following sample code, not that i changed it from what i told earlier.

    Imports Microsoft.Office.Interop.Outlook
    Imports Microsoft.Office.Core
    Public Class ThisAddIn
    	Public OutlookNS As Outlook.NameSpace
    	Dim WithEvents AppInspectors As Outlook.Inspectors
    	Dim WithEvents AppInspector As Outlook.Inspector
    	Dim WithEvents appitem As Outlook.AppointmentItem
    	Dim WithEvents app As Outlook.Application
    	Dim WithEvents CalendarItems As Outlook.Items
    	Dim Id As String = ""
    	Dim exceptionupadated As Boolean = False
    	Dim tm As New Timers.Timer
    	Dim entryid As String = Nothing
    
    	Private Sub ThisAddIn_Startup() Handles Me.Startup
    		OutlookNS = Application.GetNamespace("MAPI")
    		'CodeSite.Send(OutlookNS.ToString)
    		app = Application
    		AppInspectors = Application.Inspectors
    		Dim Calendar As Outlook.MAPIFolder = OutlookNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar)
    		Id = Calendar.StoreID
    		CalendarItems = Calendar.Items
    		OutlookNS = Application.GetNamespace("MAPI")
    	End Sub
    
    	Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown
    
    	End Sub
    
    	Private Sub appinspector1(ByVal Inspector As Microsoft.Office.Interop.Outlook.Inspector) Handles AppInspectors.NewInspector
    		appitem = Inspector.CurrentItem
    		entryid = appitem.EntryID()
    		AppInspector = Inspector
    	End Sub
    	Private Sub appinspector_close() Handles AppInspector.Close
    		'appitem = Inspector.CurrentItem
    		If appitem.RecurrenceState = OlRecurrenceState.olApptMaster Then
    			AddHandler tm.Elapsed, update()
    			tm.Interval = 1000
    			tm.Start()
    		End If
    	End Sub
    
    	Private Sub AppItem_Write(ByRef Cancel As Boolean) Handles appitem.Write
    		MsgBox("write")
    		If appitem.IsRecurring And appitem.RecurrenceState = OlRecurrenceState.olApptMaster And Not exceptionupadated Then
    			Dim rp As Outlook.RecurrencePattern = Nothing
    			rp = appitem.GetRecurrencePattern()
    			If rp.Exceptions.Count > 0 Then
    				Dim exceptions As Outlook.Exceptions = rp.Exceptions
    				Dim rpex As Outlook.Exception = Nothing
    				Dim exception As Outlook.AppointmentItem = Nothing
    				Dim e As Int16
    				For e = 1 To exceptions.Count
    					rpex = exceptions(e)
    					If (Not rpex.Deleted) Then
    						exception = rpex.AppointmentItem
    						exception.Location = appitem.Location
    						exception.Save()
    					End If
    					NAR(exception)
    					NAR(rpex)
    				Next
    			End If
    			NAR(rp)
    			exceptionupadated = True
    			GC.Collect()
    			GC.WaitForPendingFinalizers()
    			GC.Collect()
    		End If
    	End Sub
    
    	Private Sub NAR(ByVal o As Object)
    		Dim Count As Integer = 1
    		Try
    			'While Count > 0
    			Count = System.Runtime.InteropServices.Marshal.ReleaseComObject(o)
    			'Log("Released object: count=" & Count)
    			'End While
    		Catch
    		Finally
    			o = Nothing
    		End Try
    	End Sub
    
    	Private Function GetException(ByVal rp As Outlook.RecurrencePattern, ByVal ExceptionDate As Date) As Outlook.AppointmentItem
    		Dim Exceptions As Outlook.Exceptions = rp.Exceptions
    		Dim RPex As Outlook.Exception = Nothing
    		Dim App As Outlook.AppointmentItem = Nothing
    		Dim e As Int16
    		For e = 1 To Exceptions.Count
    			RPex = Exceptions(e)
    			If (Not RPex.Deleted) Then
    				App = Exceptions(e).AppointmentItem
    				If App.Start = ExceptionDate Then
    					RPex = Nothing
    					Exceptions = Nothing
    					Return App
    				Else
    					App = Nothing
    				End If
    			End If
    			RPex = Nothing
    		Next
    		Exceptions = Nothing
    		Return Nothing
    	End Function
    	Private Sub contextmenu(ByVal CommandBar As Office.CommandBar, ByVal Selection As Outlook.Selection) Handles app.ItemContextMenuDisplay
    		'If Selection.Item(1).Class = olAppointment Then
    		' Add a new button to the bottom of the CommandBar
    		' (which represents the selection context menu.)
    		'Dim objButton As Office.CommandBarButton
    
    		'objButton = CommandBar.Controls.Add(Office.MsoControlType.msoControlButton)
    
    		'With objButton
    		'	.FaceId = 1000
    		'	'.Tag = "syncthisitem"
    		'	'.OnAction = _
    		'	'"OutlookAddin1.ThisOutlookSession.syncthisitem"
    		'	.Parameter = Selection.Item(1).EntryId
    		'	.Caption = "Sync"
    		'	.BeginGroup = True
    
    
    
    		'End With
    		'AddHandler objButton.Click, AddressOf syncthisitem
    		'endif
    	End Sub
    	Private Sub syncthisitem(ByVal ctrl As Microsoft.Office.Core.CommandBarButton, ByRef CancelDefault As Boolean)
    		'Dim frm As New Form1
    		'frm.entryid = ctrl.Parameter
    		'frm.thisaddin = Me
    		'frm.Show()
    	End Sub
    
    	Public Sub setlocation(eid As String, location As String, ourdate As String)
    		Dim app As Outlook.AppointmentItem = Nothing
    		Dim excp As Outlook.AppointmentItem = Nothing
    		app = OutlookNS.GetItemFromID(eid, Id)
    		Dim rp As Outlook.RecurrencePattern = Nothing
    		rp = app.GetRecurrencePattern()
    		excp = GetException(rp, ourdate)
    		rp = Nothing
    		'MsgBox(app.RecurrenceState)
    		excp.Location = location
    		excp.Save()
    		NAR(excp)
    		NAR(app)
    		GC.Collect()
    		GC.WaitForPendingFinalizers()
    		GC.Collect()
    	End Sub
    
    	Public Sub savemainitem(eid As String)
    		'Dim app As Outlook.AppointmentItem = Nothing
    		'app = OutlookNS.GetItemFromID(eid, Id)
    		'Dim UserProperties As Outlook.UserProperties
    		'Dim DDLSignature As Outlook.UserProperty
    		'UserProperties = app.UserProperties
    		'DDLSignature = UserProperties.Find("test")
    		'If DDLSignature Is Nothing Then DDLSignature = UserProperties.Add("test", OlUserPropertyType.olText, True)
    		''Things that can be changed without opening the booking
    		'DDLSignature.Value = Now.t
    		'NAR(DDLSignature)
    		'NAR(UserProperties)
    		'app.Save()
    		'NAR(app)
    	End Sub
    
    	Private Sub setprop(dateer)
    
    	End Sub
    
    	Private Function update() As Object
    		setlocation(entryid, "TextBox1.Text", "2012-06-03 21:00")
    		setlocation(entryid, "TextBox1.Text", "2012-06-04 21:00")
    		setlocation(entryid, "TextBox1.Text", "2012-06-05 21:00")
    		setlocation(entryid, "TextBox1.Text", "2012-06-06 21:00")
    		setlocation(entryid, "TextBox1.Text", "2012-06-07 21:00")
    		tm.Stop()
    		Return (Nothing)
    	End Function
    
    End Class
    
    
    

    can you find out any flaw?


    Tuesday, May 29, 2012 3:52 PM
  • I hope the code that you're using isn't using the Outlook object model from the timer handler event. I don't see that event handler in your code.
     
    I'm not sure what you're trying to do with your code, so I'm not sure what kinds of flaws there might be. I also don't understand why you need to update every exception in rapid fire sequence.
     
    I do see that in NewInspector() you're seeing the entryid variable to the Inspector's CurrentItem.EntryID. That of course will be null for new items where they haven't been saved previously.

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Nitrup" <=?utf-8?B?Tml0cnVw?=> wrote in message news:e06c686d-39e5-4c0e-8d1f-04a72126d009...

    Hi,

    i think it may be due to the fact that in my actual application , when write event fires, my addin sets same location for all exception . it does something like this

    If appitem.IsRecurring And appitem.RecurrenceState = OlRecurrenceState.olApptMaster And Not exceptionupadated Then
    			Dim rp As Outlook.RecurrencePattern = Nothing
    			rp = appitem.GetRecurrencePattern()
    			If rp.Exceptions.Count > 0 Then
    				Dim exceptions As Outlook.Exceptions = rp.Exceptions
    				Dim rpex As Outlook.Exception = Nothing
    				Dim exception As Outlook.AppointmentItem = Nothing
    				Dim e As Int16
    				For e = 1 To exceptions.Count
    					rpex = exceptions(e)
    					If (Not rpex.Deleted) Then
    						exception = rpex.AppointmentItem
    						exception.Location = appitem.Location
    						exception.Save()
    					End If
    					NAR(exception)
    					NAR(rpex)
    				Next
    			End If
    			NAR(rp)
    			exceptionupadated = True
    			GC.Collect()
    			GC.WaitForPendingFinalizers()
    			GC.Collect()
    		End If

    then after that , request handler comes up with new set of locations and then tries to update location again, there we find a problem.

    i can replicate this in following sample code, not that i changed it from what i told earlier.

    Imports Microsoft.Office.Interop.Outlook
    Imports Microsoft.Office.Core
    Public Class ThisAddIn
    	Public OutlookNS As Outlook.NameSpace
    	Dim WithEvents AppInspectors As Outlook.Inspectors
    	Dim WithEvents AppInspector As Outlook.Inspector
    	Dim WithEvents appitem As Outlook.AppointmentItem
    	Dim WithEvents app As Outlook.Application
    	Dim WithEvents CalendarItems As Outlook.Items
    	Dim Id As String = ""
    	Dim exceptionupadated As Boolean = False
    	Dim tm As New Timers.Timer
    	Dim entryid As String = Nothing
    
    	Private Sub ThisAddIn_Startup() Handles Me.Startup
    		OutlookNS = Application.GetNamespace("MAPI")
    		'CodeSite.Send(OutlookNS.ToString)
    		app = Application
    		AppInspectors = Application.Inspectors
    		Dim Calendar As Outlook.MAPIFolder = OutlookNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar)
    		Id = Calendar.StoreID
    		CalendarItems = Calendar.Items
    		OutlookNS = Application.GetNamespace("MAPI")
    	End Sub
    
    	Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown
    
    	End Sub
    
    	Private Sub appinspector1(ByVal Inspector As Microsoft.Office.Interop.Outlook.Inspector) Handles AppInspectors.NewInspector
    		appitem = Inspector.CurrentItem
    		entryid = appitem.EntryID()
    		AppInspector = Inspector
    	End Sub
    	Private Sub appinspector_close() Handles AppInspector.Close
    		'appitem = Inspector.CurrentItem
    		If appitem.RecurrenceState = OlRecurrenceState.olApptMaster Then
    			AddHandler tm.Elapsed, update()
    			tm.Interval = 1000
    			tm.Start()
    		End If
    	End Sub
    
    	Private Sub AppItem_Write(ByRef Cancel As Boolean) Handles appitem.Write
    		MsgBox("write")
    		If appitem.IsRecurring And appitem.RecurrenceState = OlRecurrenceState.olApptMaster And Not exceptionupadated Then
    			Dim rp As Outlook.RecurrencePattern = Nothing
    			rp = appitem.GetRecurrencePattern()
    			If rp.Exceptions.Count > 0 Then
    				Dim exceptions As Outlook.Exceptions = rp.Exceptions
    				Dim rpex As Outlook.Exception = Nothing
    				Dim exception As Outlook.AppointmentItem = Nothing
    				Dim e As Int16
    				For e = 1 To exceptions.Count
    					rpex = exceptions(e)
    					If (Not rpex.Deleted) Then
    						exception = rpex.AppointmentItem
    						exception.Location = appitem.Location
    						exception.Save()
    					End If
    					NAR(exception)
    					NAR(rpex)
    				Next
    			End If
    			NAR(rp)
    			exceptionupadated = True
    			GC.Collect()
    			GC.WaitForPendingFinalizers()
    			GC.Collect()
    		End If
    	End Sub
    
    	Private Sub NAR(ByVal o As Object)
    		Dim Count As Integer = 1
    		Try
    			'While Count > 0
    			Count = System.Runtime.InteropServices.Marshal.ReleaseComObject(o)
    			'Log("Released object: count=" & Count)
    			'End While
    		Catch
    		Finally
    			o = Nothing
    		End Try
    	End Sub
    
    	Private Function GetException(ByVal rp As Outlook.RecurrencePattern, ByVal ExceptionDate As Date) As Outlook.AppointmentItem
    		Dim Exceptions As Outlook.Exceptions = rp.Exceptions
    		Dim RPex As Outlook.Exception = Nothing
    		Dim App As Outlook.AppointmentItem = Nothing
    		Dim e As Int16
    		For e = 1 To Exceptions.Count
    			RPex = Exceptions(e)
    			If (Not RPex.Deleted) Then
    				App = Exceptions(e).AppointmentItem
    				If App.Start = ExceptionDate Then
    					RPex = Nothing
    					Exceptions = Nothing
    					Return App
    				Else
    					App = Nothing
    				End If
    			End If
    			RPex = Nothing
    		Next
    		Exceptions = Nothing
    		Return Nothing
    	End Function
    	Private Sub contextmenu(ByVal CommandBar As Office.CommandBar, ByVal Selection As Outlook.Selection) Handles app.ItemContextMenuDisplay
    		'If Selection.Item(1).Class = olAppointment Then
    		' Add a new button to the bottom of the CommandBar
    		' (which represents the selection context menu.)
    		'Dim objButton As Office.CommandBarButton
    
    		'objButton = CommandBar.Controls.Add(Office.MsoControlType.msoControlButton)
    
    		'With objButton
    		'	.FaceId = 1000
    		'	'.Tag = "syncthisitem"
    		'	'.OnAction = _
    		'	'"OutlookAddin1.ThisOutlookSession.syncthisitem"
    		'	.Parameter = Selection.Item(1).EntryId
    		'	.Caption = "Sync"
    		'	.BeginGroup = True
    
    
    
    		'End With
    		'AddHandler objButton.Click, AddressOf syncthisitem
    		'endif
    	End Sub
    	Private Sub syncthisitem(ByVal ctrl As Microsoft.Office.Core.CommandBarButton, ByRef CancelDefault As Boolean)
    		'Dim frm As New Form1
    		'frm.entryid = ctrl.Parameter
    		'frm.thisaddin = Me
    		'frm.Show()
    	End Sub
    
    	Public Sub setlocation(eid As String, location As String, ourdate As String)
    		Dim app As Outlook.AppointmentItem = Nothing
    		Dim excp As Outlook.AppointmentItem = Nothing
    		app = OutlookNS.GetItemFromID(eid, Id)
    		Dim rp As Outlook.RecurrencePattern = Nothing
    		rp = app.GetRecurrencePattern()
    		excp = GetException(rp, ourdate)
    		rp = Nothing
    		'MsgBox(app.RecurrenceState)
    		excp.Location = location
    		excp.Save()
    		NAR(excp)
    		NAR(app)
    		GC.Collect()
    		GC.WaitForPendingFinalizers()
    		GC.Collect()
    	End Sub
    
    	Public Sub savemainitem(eid As String)
    		'Dim app As Outlook.AppointmentItem = Nothing
    		'app = OutlookNS.GetItemFromID(eid, Id)
    		'Dim UserProperties As Outlook.UserProperties
    		'Dim DDLSignature As Outlook.UserProperty
    		'UserProperties = app.UserProperties
    		'DDLSignature = UserProperties.Find("test")
    		'If DDLSignature Is Nothing Then DDLSignature = UserProperties.Add("test", OlUserPropertyType.olText, True)
    		''Things that can be changed without opening the booking
    		'DDLSignature.Value = Now.t
    		'NAR(DDLSignature)
    		'NAR(UserProperties)
    		'app.Save()
    		'NAR(app)
    	End Sub
    
    	Private Sub setprop(dateer)
    
    	End Sub
    
    	Private Function update() As Object
    		setlocation(entryid, "TextBox1.Text", "2012-06-03 21:00")
    		setlocation(entryid, "TextBox1.Text", "2012-06-04 21:00")
    		setlocation(entryid, "TextBox1.Text", "2012-06-05 21:00")
    		setlocation(entryid, "TextBox1.Text", "2012-06-06 21:00")
    		setlocation(entryid, "TextBox1.Text", "2012-06-07 21:00")
    		tm.Stop()
    		Return (Nothing)
    	End Function
    
    End Class
    
    
    

    can you find out any flaw?



    Ken Slovak MVP - Outlook
    Tuesday, May 29, 2012 6:05 PM
    Moderator
  • Ken,

    Sorry for late reply!

    The code i have shown you is just a sample model is assuming the appointment has already been created  and its trying replicate my original problem  which i found in one of the addin we are building for a Room booking System. i am sorry but i can not share that part of code because its huge.

    My Room booking System addin is also trying to update the location one by one, the only difference is , In  Room booking System addin i am trying to update location through a loop and the same logic is working fine in outlook 2007 but note in outlook 2010.

    when write event of appointment fires,  Room booking System addin go through all the exceptions and save them with the same location, so all occurrence including exceptions now have same locations.

    After this an ajax request initiate which tries to update the corresponding records in database and as a response i got some json data which i use to update the the recurring appointment in calendar, note that inspector will be closed before update starts.

    Now as its a json data i have to loop through it and then location will start updating one by one. i do not know any way to wait, untill location for particular exception has been updated, except  GC.Collect() and GC.WaitForPendingFinalizers() which i am already using, but still i found that data of particular occurrence has been updated but on calendar it still previous one.

    so, its by design i have to go through all the exception in a row and update location. my sample addin  tries to do in similar way and is replicating same issue.

    so if you can run this sample addin on outlook 2010 and let me know the problem area. try this sample as it is , but before that create a recurring appointment  and make all of its occurrence an exception and make sure their start time is 21:00

    Imports Microsoft.Office.Interop.Outlook Imports Microsoft.Office.Core Public Class ThisAddIn Public OutlookNS As Outlook.NameSpace Dim WithEvents AppInspectors As Outlook.Inspectors Dim WithEvents AppInspector As Outlook.Inspector Dim WithEvents appitem As Outlook.AppointmentItem Dim WithEvents app As Outlook.Application Dim WithEvents CalendarItems As Outlook.Items Dim Id As String = "" Dim exceptionupadated As Boolean = False Dim tm As New Timers.Timer Dim entryid As String = Nothing Private Sub ThisAddIn_Startup() Handles Me.Startup OutlookNS = Application.GetNamespace("MAPI") 'CodeSite.Send(OutlookNS.ToString) app = Application AppInspectors = Application.Inspectors Dim Calendar As Outlook.MAPIFolder = OutlookNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar) Id = Calendar.StoreID CalendarItems = Calendar.Items OutlookNS = Application.GetNamespace("MAPI") End Sub Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown End Sub Private Sub appinspector1(ByVal Inspector As Microsoft.Office.Interop.Outlook.Inspector) Handles AppInspectors.NewInspector appitem = Inspector.CurrentItem entryid = appitem.EntryID() AppInspector = Inspector End Sub Private Sub appinspector_close() Handles AppInspector.Close 'appitem = Inspector.CurrentItem If appitem.RecurrenceState = OlRecurrenceState.olApptMaster Then AddHandler tm.Elapsed, update() tm.Interval = 1000 tm.Start() End If End Sub Private Sub AppItem_Write(ByRef Cancel As Boolean) Handles appitem.Write MsgBox("write") If appitem.IsRecurring And appitem.RecurrenceState = OlRecurrenceState.olApptMaster And Not exceptionupadated Then Dim rp As Outlook.RecurrencePattern = Nothing rp = appitem.GetRecurrencePattern() If rp.Exceptions.Count > 0 Then Dim exceptions As Outlook.Exceptions = rp.Exceptions Dim rpex As Outlook.Exception = Nothing Dim exception As Outlook.AppointmentItem = Nothing Dim e As Int16 For e = 1 To exceptions.Count rpex = exceptions(e) If (Not rpex.Deleted) Then exception = rpex.AppointmentItem exception.Location = appitem.Location exception.Save() End If NAR(exception) NAR(rpex) Next End If NAR(rp) exceptionupadated = True GC.Collect() GC.WaitForPendingFinalizers() GC.Collect() End If End Sub Private Sub NAR(ByVal o As Object) Dim Count As Integer = 1 Try 'While Count > 0 Count = System.Runtime.InteropServices.Marshal.ReleaseComObject(o) 'Log("Released object: count=" & Count) 'End While Catch Finally o = Nothing End Try End Sub Private Function GetException(ByVal rp As Outlook.RecurrencePattern, ByVal ExceptionDate As Date) As Outlook.AppointmentItem Dim Exceptions As Outlook.Exceptions = rp.Exceptions Dim RPex As Outlook.Exception = Nothing Dim App As Outlook.AppointmentItem = Nothing Dim e As Int16 For e = 1 To Exceptions.Count RPex = Exceptions(e) If (Not RPex.Deleted) Then App = Exceptions(e).AppointmentItem If App.Start = ExceptionDate Then RPex = Nothing Exceptions = Nothing Return App Else App = Nothing End If End If RPex = Nothing Next Exceptions = Nothing Return Nothing End Function Private Sub contextmenu(ByVal CommandBar As Office.CommandBar, ByVal Selection As Outlook.Selection) Handles app.ItemContextMenuDisplay 'If Selection.Item(1).Class = olAppointment Then ' Add a new button to the bottom of the CommandBar ' (which represents the selection context menu.) 'Dim objButton As Office.CommandBarButton 'objButton = CommandBar.Controls.Add(Office.MsoControlType.msoControlButton) 'With objButton ' .FaceId = 1000 ' '.Tag = "syncthisitem" ' '.OnAction = _ ' '"OutlookAddin1.ThisOutlookSession.syncthisitem" ' .Parameter = Selection.Item(1).EntryId ' .Caption = "Sync" ' .BeginGroup = True 'End With 'AddHandler objButton.Click, AddressOf syncthisitem 'endif End Sub Private Sub syncthisitem(ByVal ctrl As Microsoft.Office.Core.CommandBarButton, ByRef CancelDefault As Boolean) 'Dim frm As New Form1 'frm.entryid = ctrl.Parameter 'frm.thisaddin = Me 'frm.Show() End Sub Public Sub setlocation(eid As String, location As String, ourdate As String) Dim app As Outlook.AppointmentItem = Nothing Dim excp As Outlook.AppointmentItem = Nothing app = OutlookNS.GetItemFromID(eid, Id) Dim rp As Outlook.RecurrencePattern = Nothing rp = app.GetRecurrencePattern() excp = GetException(rp, ourdate) rp = Nothing 'MsgBox(app.RecurrenceState) excp.Location = location excp.Save() NAR(excp) NAR(app) GC.Collect() GC.WaitForPendingFinalizers() GC.Collect()

    exceptionupdated = false

    End Sub Public Sub savemainitem(eid As String) 'Dim app As Outlook.AppointmentItem = Nothing 'app = OutlookNS.GetItemFromID(eid, Id) 'Dim UserProperties As Outlook.UserProperties 'Dim DDLSignature As Outlook.UserProperty 'UserProperties = app.UserProperties 'DDLSignature = UserProperties.Find("test") 'If DDLSignature Is Nothing Then DDLSignature = UserProperties.Add("test", OlUserPropertyType.olText, True) ''Things that can be changed without opening the booking 'DDLSignature.Value = Now.t 'NAR(DDLSignature) 'NAR(UserProperties) 'app.Save() 'NAR(app) End Sub Private Sub setprop(dateer) End Sub Private Function update() As Object setlocation(entryid, "TextBox1.Text", "2012-06-03 21:00") setlocation(entryid, "TextBox1.Text", "2012-06-04 21:00") setlocation(entryid, "TextBox1.Text", "2012-06-05 21:00") setlocation(entryid, "TextBox1.Text", "2012-06-06 21:00") setlocation(entryid, "TextBox1.Text", "2012-06-07 21:00") tm.Stop() Return (Nothing) End Function End Class

    Thanks


    Thursday, May 31, 2012 3:22 PM
  • I'll test this out next week, I won't have time until then.

    --
    Ken Slovak
    MVP - Outlook
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
     
     
    "Nitrup" <=?utf-8?B?Tml0cnVw?=> wrote in message news:4ae6fa84-d244-45d4-b751-eecbac633425...

    Ken,

    Sorry for late reply!

    The code i have shown you is just a sample model is assuming the appointment has already been created  and its trying replicate my original problem  which i found in one of the addin we are building for a Room booking System. i am sorry but i can not share that part of code because its huge.

    My Room booking System addin is also trying to update the location one by one, the only difference is , In  Room booking System addin i am trying to update location through a loop and the same logic is working fine in outlook 2007 but note in outlook 2010.

    when write event of appointment fires,  Room booking System addin go through all the exceptions and save them with the same location, so all occurrence including exceptions now have same locations.

    After this an ajax request initiate which tries to update the corresponding records in database and as a response i got some json data which i use to update the the recurring appointment in calendar, note that inspector will be closed before update starts.

    Now as its a json data i have to loop through it and then location will start updating one by one. i do not know any way to wait, untill location for particular exception has been updated, except  GC.Collect() and GC.WaitForPendingFinalizers() which i am already using, but still i found that data of particular occurrence has been updated but on calendar it still previous one.

    so, its by design i have to go through all the exception in a row and update location. my sample addin  tries to do in similar way and is replicating same issue.

    so if you can run this sample addin on outlook 2010 and let me know the problem area. try this sample as it is , but before that create a recurring appointment  and make all of its occurrence an exception and make sure their start time is 21:00

    Imports Microsoft.Office.Interop.Outlook Imports Microsoft.Office.Core Public Class ThisAddIn Public OutlookNS As Outlook.NameSpace Dim WithEvents AppInspectors As Outlook.Inspectors Dim WithEvents AppInspector As Outlook.Inspector Dim WithEvents appitem As Outlook.AppointmentItem Dim WithEvents app As Outlook.Application Dim WithEvents CalendarItems As Outlook.Items Dim Id As String = "" Dim exceptionupadated As Boolean = False Dim tm As New Timers.Timer Dim entryid As String = Nothing Private Sub ThisAddIn_Startup() Handles Me.Startup OutlookNS = Application.GetNamespace("MAPI") 'CodeSite.Send(OutlookNS.ToString) app = Application AppInspectors = Application.Inspectors Dim Calendar As Outlook.MAPIFolder = OutlookNS.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderCalendar) Id = Calendar.StoreID CalendarItems = Calendar.Items OutlookNS = Application.GetNamespace("MAPI") End Sub Private Sub ThisAddIn_Shutdown() Handles Me.Shutdown End Sub Private Sub appinspector1(ByVal Inspector As Microsoft.Office.Interop.Outlook.Inspector) Handles AppInspectors.NewInspector appitem = Inspector.CurrentItem entryid = appitem.EntryID() AppInspector = Inspector End Sub Private Sub appinspector_close() Handles AppInspector.Close 'appitem = Inspector.CurrentItem If appitem.RecurrenceState = OlRecurrenceState.olApptMaster Then AddHandler tm.Elapsed, update() tm.Interval = 1000 tm.Start() End If End Sub Private Sub AppItem_Write(ByRef Cancel As Boolean) Handles appitem.Write MsgBox("write") If appitem.IsRecurring And appitem.RecurrenceState = OlRecurrenceState.olApptMaster And Not exceptionupadated Then Dim rp As Outlook.RecurrencePattern = Nothing rp = appitem.GetRecurrencePattern() If rp.Exceptions.Count > 0 Then Dim exceptions As Outlook.Exceptions = rp.Exceptions Dim rpex As Outlook.Exception = Nothing Dim exception As Outlook.AppointmentItem = Nothing Dim e As Int16 For e = 1 To exceptions.Count rpex = exceptions(e) If (Not rpex.Deleted) Then exception = rpex.AppointmentItem exception.Location = appitem.Location exception.Save() End If NAR(exception) NAR(rpex) Next End If NAR(rp) exceptionupadated = True GC.Collect() GC.WaitForPendingFinalizers() GC.Collect() End If End Sub Private Sub NAR(ByVal o As Object) Dim Count As Integer = 1 Try 'While Count > 0 Count = System.Runtime.InteropServices.Marshal.ReleaseComObject(o) 'Log("Released object: count=" & Count) 'End While Catch Finally o = Nothing End Try End Sub Private Function GetException(ByVal rp As Outlook.RecurrencePattern, ByVal ExceptionDate As Date) As Outlook.AppointmentItem Dim Exceptions As Outlook.Exceptions = rp.Exceptions Dim RPex As Outlook.Exception = Nothing Dim App As Outlook.AppointmentItem = Nothing Dim e As Int16 For e = 1 To Exceptions.Count RPex = Exceptions(e) If (Not RPex.Deleted) Then App = Exceptions(e).AppointmentItem If App.Start = ExceptionDate Then RPex = Nothing Exceptions = Nothing Return App Else App = Nothing End If End If RPex = Nothing Next Exceptions = Nothing Return Nothing End Function Private Sub contextmenu(ByVal CommandBar As Office.CommandBar, ByVal Selection As Outlook.Selection) Handles app.ItemContextMenuDisplay 'If Selection.Item(1).Class = olAppointment Then ' Add a new button to the bottom of the CommandBar ' (which represents the selection context menu.) 'Dim objButton As Office.CommandBarButton 'objButton = CommandBar.Controls.Add(Office.MsoControlType.msoControlButton) 'With objButton ' .FaceId = 1000 ' '.Tag = "syncthisitem" ' '.OnAction = _ ' '"OutlookAddin1.ThisOutlookSession.syncthisitem" ' .Parameter = Selection.Item(1).EntryId ' .Caption = "Sync" ' .BeginGroup = True 'End With 'AddHandler objButton.Click, AddressOf syncthisitem 'endif End Sub Private Sub syncthisitem(ByVal ctrl As Microsoft.Office.Core.CommandBarButton, ByRef CancelDefault As Boolean) 'Dim frm As New Form1 'frm.entryid = ctrl.Parameter 'frm.thisaddin = Me 'frm.Show() End Sub Public Sub setlocation(eid As String, location As String, ourdate As String) Dim app As Outlook.AppointmentItem = Nothing Dim excp As Outlook.AppointmentItem = Nothing app = OutlookNS.GetItemFromID(eid, Id) Dim rp As Outlook.RecurrencePattern = Nothing rp = app.GetRecurrencePattern() excp = GetException(rp, ourdate) rp = Nothing 'MsgBox(app.RecurrenceState) excp.Location = location excp.Save() NAR(excp) NAR(app) GC.Collect() GC.WaitForPendingFinalizers() GC.Collect()

    exceptionupdated = false

    End Sub Public Sub savemainitem(eid As String) 'Dim app As Outlook.AppointmentItem = Nothing 'app = OutlookNS.GetItemFromID(eid, Id) 'Dim UserProperties As Outlook.UserProperties 'Dim DDLSignature As Outlook.UserProperty 'UserProperties = app.UserProperties 'DDLSignature = UserProperties.Find("test") 'If DDLSignature Is Nothing Then DDLSignature = UserProperties.Add("test", OlUserPropertyType.olText, True) ''Things that can be changed without opening the booking 'DDLSignature.Value = Now.t 'NAR(DDLSignature) 'NAR(UserProperties) 'app.Save() 'NAR(app) End Sub Private Sub setprop(dateer) End Sub Private Function update() As Object setlocation(entryid, "TextBox1.Text", "2012-06-03 21:00") setlocation(entryid, "TextBox1.Text", "2012-06-04 21:00") setlocation(entryid, "TextBox1.Text", "2012-06-05 21:00") setlocation(entryid, "TextBox1.Text", "2012-06-06 21:00") setlocation(entryid, "TextBox1.Text", "2012-06-07 21:00") tm.Stop() Return (Nothing) End Function End Class

    Thanks



    Ken Slovak MVP - Outlook
    Friday, June 1, 2012 7:18 PM
    Moderator
  • Hi Ken,

    Have you got any chance to figure it out?

    Thanks

    Thursday, June 7, 2012 12:24 PM
  • Not yet, I've been setting up a new development machine and moving over all my virtual machines to it, today is the first time I've been in the forums with the new machine. I'll try to test this tomorrow.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Nitrup" <=?utf-8?B?Tml0cnVw?=> wrote in message news:97c3365f-2b92-49d2-bd4c-793484aec826...

    Hi Ken,

    Have you got any chance to figure it out?

    Thanks


    Ken Slovak MVP - Outlook
    Thursday, June 7, 2012 2:40 PM
    Moderator
  • I did get a chance to look this over, and I see a number of problems in the test sample code.
     
    For one thing the timer you set up to call the update (using the Outlook object model) will run on a different thread than the addin or Outlook. That's bad and not supported and will lead to crashing or hanging Outlook. I wouldn't even run code like that even in a test addin.
     
    Second, you are creating a lot of undeclared objects that can't get released in a timely manner. For example, this line in GetException():
     

    App = Exceptions(e).AppointmentItem

    You already got RPex as that Exception object but you're creating a new undeclared object that's the same Exception in your call. Exceptions(e) creates an Exception object.

    There are a number of things like that in the sample.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Nitrup" <=?utf-8?B?Tml0cnVw?=> wrote in message news:97c3365f-2b92-49d2-bd4c-793484aec826...

    Hi Ken,

    Have you got any chance to figure it out?

    Thanks


    Ken Slovak MVP - Outlook
    Thursday, June 7, 2012 7:09 PM
    Moderator
  • Hi Ken,

    Thanks for looking into it.

    ok, i changed Exceptions(e).AppointmentItem to RPex.AppointmentItem and removed timer control from appinspector close event and instead i am trying to update location in write event

    Private Sub AppItem_Write() Handles appitem.Write
            'MsgBox("write")
            If appitem.IsRecurring And appitem.RecurrenceState = OlRecurrenceState.olApptMaster And Not exceptionupadated Then
                Dim rp As Outlook.RecurrencePattern = Nothing
                rp = appitem.GetRecurrencePattern()
                If rp.Exceptions.Count > 0 Then
                    Dim exceptions As Outlook.Exceptions = rp.Exceptions
                    Dim rpex As Outlook.Exception = Nothing
                    Dim exception As Outlook.AppointmentItem = Nothing
                    Dim e As Int16
                    For e = 1 To exceptions.Count
                        rpex = exceptions(e)
                        If (Not rpex.Deleted) Then
                            exception = rpex.AppointmentItem
                            exception.Location = appitem.Location
                            exception.Save()
                            'MsgBox(exception.Location)
                        End If
                        NAR(exception)
                        NAR(rpex)
                    Next
                    NAR(exceptions)
                End If
                NAR(rp)
                exceptionupadated = True
                update()
                GC.Collect()
                GC.WaitForPendingFinalizers()
                GC.Collect()
            End If
        End Sub

    but you said there are many undeclared objects, can you point out those one as well?

    i think they all are declared now. Should there be any order in which specific objects should be released?

    like in case of GetException() , do you see any problem now?

    Private Function GetException(ByVal rp As Outlook.RecurrencePattern, ByVal ExceptionDate As Date) As Outlook.AppointmentItem
            Dim Exceptions As Outlook.Exceptions = rp.Exceptions
            Dim RPex As Outlook.Exception = Nothing
            Dim App As Outlook.AppointmentItem = Nothing
            Dim e As Int16
            For e = 1 To Exceptions.Count
                RPex = Exceptions(e)
                If (Not RPex.Deleted) Then
                    App = RPex.AppointmentItem
                    If App.Start = ExceptionDate Then
                        NAR(RPex)
                        NAR(Exceptions)
                        Return App
                    Else
                        NAR(App)
                    End If
                End If
                NAR(RPex)
            Next
            NAR(Exceptions)
            Return Nothing

    end sub

    Public Sub setlocation(eid As String, location As String, ourdate As String)
            Dim app As Outlook.AppointmentItem = Nothing
            Dim excp As Outlook.AppointmentItem = Nothing
            app = OutlookNS.GetItemFromID(eid, Id)
            Dim rp As Outlook.RecurrencePattern = Nothing
            rp = app.GetRecurrencePattern()
            excp = GetException(rp, ourdate)
            NAR(rp)
            'MsgBox(app.RecurrenceState)
            excp.Location = location
            excp.Save()
            NAR(excp)
            GC.Collect()
            GC.WaitForPendingFinalizers()
            GC.Collect()
            NAR(app)
            GC.Collect()
            GC.WaitForPendingFinalizers()
            GC.Collect()
            exceptionupadated = False
        End Sub

    Private Function update() As Object

            setlocation(entryid, "TextBox1.Text", "2012-06-10 21:00")
            setlocation(entryid, "TextBox1.Text", "2012-06-11 21:00")
            setlocation(entryid, "TextBox1.Text", "2012-06-12 21:00")
            setlocation(entryid, "TextBox1.Text", "2012-06-13 21:00")
            setlocation(entryid, "TextBox1.Text", "2012-06-14 21:00")
            tm.Stop()
            exceptionupadated = False
            Return (Nothing)
        End Function

    I am sorry if these are dumb questions, but i  never looked my code from this prospective which you pointed out. Are there any tips or recommendations for declaring and releasing such com objects, so that i can implement them in my code

    Thanks

    Friday, June 8, 2012 12:11 PM
  • As an example, take this innocent looking If statement:
     
        If rp.Exceptions.Count > 0 Then
    That creates an invisible Exceptions collection object. An approach that declares all objects would look like this:
     
        Dim colExcept As Outlook.Exceptions = rp.Exceptions
        If colExcept.Count > 0 Then
     
    The culprit is using compound dot operators. You should look with suspicion on any phrase that has more than 1 dot operator:
     
        rp.Exceptions.Count
     
    As opposed to
     
        colExcept.Count
     
    If all objects are declared they all can be released when you want to release them.
     
    You might want to take a look at a series of blog posts by Matt Stehle, an Outlook support engineer about releasing objects and Outlook object leaks.
     
    This is the second in the series, the entire series of posts is well worth reading: http://blogs.msdn.com/b/mstehle/archive/2007/12/07/oom-net-part-2-outlook-item-leaks.aspx
     
    The entire series of posts is indexed at http://blogs.msdn.com/b/mstehle/archive/tags/oom-net/, and the articles are all well worth reading.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Nitrup" <=?utf-8?B?Tml0cnVw?=> wrote in message news:5c72fd93-67ec-454c-a497-daba237486be...

    Hi Ken,

    Thanks for looking into it.

    ok, i changed Exceptions(e).AppointmentItem to RPex.AppointmentItem and removed timer control from appinspector close event and instead i am trying to update location in write event

    Private Sub AppItem_Write() Handles appitem.Write
            'MsgBox("write")
            If appitem.IsRecurring And appitem.RecurrenceState = OlRecurrenceState.olApptMaster And Not exceptionupadated Then
                Dim rp As Outlook.RecurrencePattern = Nothing
                rp = appitem.GetRecurrencePattern()
                If rp.Exceptions.Count > 0 Then
                    Dim exceptions As Outlook.Exceptions = rp.Exceptions
                    Dim rpex As Outlook.Exception = Nothing
                    Dim exception As Outlook.AppointmentItem = Nothing
                    Dim e As Int16
                    For e = 1 To exceptions.Count
                        rpex = exceptions(e)
                        If (Not rpex.Deleted) Then
                            exception = rpex.AppointmentItem
                            exception.Location = appitem.Location
                            exception.Save()
                            'MsgBox(exception.Location)
                        End If
                        NAR(exception)
                        NAR(rpex)
                    Next
                    NAR(exceptions)
                End If
                NAR(rp)
                exceptionupadated = True
                update()
                GC.Collect()
                GC.WaitForPendingFinalizers()
                GC.Collect()
            End If
        End Sub

    but you said there are many undeclared objects, can you point out those one as well?

    i think they all are declared now. Should there be any order in which specific objects should be released?

    like in case of GetException() , do you see any problem now?

    Private Function GetException(ByVal rp As Outlook.RecurrencePattern, ByVal ExceptionDate As Date) As Outlook.AppointmentItem
            Dim Exceptions As Outlook.Exceptions = rp.Exceptions
            Dim RPex As Outlook.Exception = Nothing
            Dim App As Outlook.AppointmentItem = Nothing
            Dim e As Int16
            For e = 1 To Exceptions.Count
                RPex = Exceptions(e)
                If (Not RPex.Deleted) Then
                    App = RPex.AppointmentItem
                    If App.Start = ExceptionDate Then
                        NAR(RPex)
                        NAR(Exceptions)
                        Return App
                    Else
                        NAR(App)
                    End If
                End If
                NAR(RPex)
            Next
            NAR(Exceptions)
            Return Nothing

    end sub

    Public Sub setlocation(eid As String, location As String, ourdate As String)
            Dim app As Outlook.AppointmentItem = Nothing
            Dim excp As Outlook.AppointmentItem = Nothing
            app = OutlookNS.GetItemFromID(eid, Id)
            Dim rp As Outlook.RecurrencePattern = Nothing
            rp = app.GetRecurrencePattern()
            excp = GetException(rp, ourdate)
            NAR(rp)
            'MsgBox(app.RecurrenceState)
            excp.Location = location
            excp.Save()
            NAR(excp)
            GC.Collect()
            GC.WaitForPendingFinalizers()
            GC.Collect()
            NAR(app)
            GC.Collect()
            GC.WaitForPendingFinalizers()
            GC.Collect()
            exceptionupadated = False
        End Sub

    Private Function update() As Object

            setlocation(entryid, "TextBox1.Text", "2012-06-10 21:00")
            setlocation(entryid, "TextBox1.Text", "2012-06-11 21:00")
            setlocation(entryid, "TextBox1.Text", "2012-06-12 21:00")
            setlocation(entryid, "TextBox1.Text", "2012-06-13 21:00")
            setlocation(entryid, "TextBox1.Text", "2012-06-14 21:00")
            tm.Stop()
            exceptionupadated = False
            Return (Nothing)
        End Function

    I am sorry if these are dumb questions, but i  never looked my code from this prospective which you pointed out. Are there any tips or recommendations for declaring and releasing such com objects, so that i can implement them in my code

    Thanks


    Ken Slovak MVP - Outlook
    Friday, June 8, 2012 3:23 PM
    Moderator
  • Hi Ken,

    I tried out replacing compound dot operator in both my example and actualaddin, but things are still same.

    I found one thing, in write event of recurring appointment, if we try to get exceptions of recurring appointment, then it creates problem. i think i can show you my actual addin code,

    In below snippet of code , In  DDLMSOI class, here SetLocation function updates outlook appointment,  the function SetSignature and GetGignature and BuildSignature are defined in DDLAppItem . These functions  look for a userproperty name as "DDL Signature". Note that if an item is recurring, signature  for item will build form  exceptions properties and this looks like creating a problem in write event of item and when a particular exception is being held for updation.

    it looks like if outlook held an exception already and with in same thread again we try to get its instance of that exception then problem arises and  it do not update things correctly

    I think , the main problem area are Setlocation in DDLMSOI class and Appt_write method in DDLAppItem. In both of them you will see i am using BuildSignature , which further calls GetRecurrenceProperties() which look through all exception while items are being saved and there i am getting problem.

    I Apologise if i am not able to make you understand about my problem. this code without any change is working fine in outlook 2007

    Public Class DDLMSOI

    Public Sub SetLocation(ByVal Loc As String, Optional ByVal Warning As Boolean = False, _ Optional ByVal onDate As String = "", _ Optional ByVal email As String = "", _ Optional ByVal LastMoved As String = "") Dim SearchItems As Outlook.Items = Nothing Dim FoundItem As Outlook.AppointmentItem = Nothing Dim DAppItem As New ddlAppItem Dim CalendarFolderItems As Outlook.Items = Nothing 'Dim UID As String 'MsgBox(Loc) 'MsgBox(onDate) Dim OurDate As Date = Nothing Dim DateProvided As Boolean = onDate.Length > 0 If DateProvided Then OurDate = New Date(Left(onDate, 4), Mid(onDate, 6, 2), Mid(onDate, 9, 2)) Else OurDate = Now End If If (LastMoved = "") Then LastMoved = Me.LastMoved Log("ddlMSOI setlocation: " + Loc) If LastMoved.Length > 0 Then Try If (email <> "") Then Dim index As Integer For index = 1 To CalendarCollection.Count If (CalendarCollection(index).EmailAddress = email) Then CalendarFolderItems = CalendarCollection(index).FolderItems Exit For End If Next End If SearchItems = CalendarFolderItems.Restrict("[DDL Reference] = '" & LastMoved & "' And [start] > '" & Format(DateAdd(DateInterval.Minute, -1, LastMovedTime), "dd-MMM-yyyy hh:mm") & "'") 'SearchItems = CalendarItems.Restrict("[start] > '" & Format(DateAdd(DateInterval.Minute, -1, LastMovedTime), "dd-MMM-yyyy hh:mm") & "'") If SearchItems.Count > 0 Then 'Dim i As Int16 'For i = 1 To SearchItems.Count ' FoundItem = SearchItems(i) ' Dim DAppItem As New ddlAppItem ' DAppItem.AppItem = FoundItem ' UID = DAppItem.GetReference() ' If LastMoved = UID Then ' Exit For ' Else ' NAR(FoundItem) ' End If 'Next FoundItem = SearchItems(1) DAppItem.AppItem = SearchItems(1) Dim Isrecurring As Boolean = FoundItem.IsRecurring If (onDate.Length > 0) Then CodeSite.Send(onDate) Dim App As Outlook.AppointmentItem = Nothing If Isrecurring And onDate.Length > 0 Then 'GetException(FoundItem, onDate) 'If App Is Nothing Then Dim rp As Outlook.RecurrencePattern = FoundItem.GetRecurrencePattern() Try Dim start As Date = FoundItem.Start App = rp.GetOccurrence(OurDate + " " + start.ToShortTimeString) Catch End Try If App Is Nothing Then App = GetException(rp, onDate) 'App.ClearRecurrencePattern() 'End If NAR(FoundItem) NAR(rp) If Not App Is Nothing Then FoundItem = App Else FoundItem = Nothing End If End If CodeSite.Send(FoundItem.Start) If Not FoundItem Is Nothing Then If FoundItem.Location <> Loc Then Dim msg As String = "Room " Dim oldloc As String = FoundItem.Location FoundItem.Location = Loc FoundItem.Save() If Warning Then If Loc = "No Room Booked" Then 'No message - they already had it msg = "" ElseIf FoundItem.Location = "No Room Booked" Then msg = msg + "booking" If DateProvided Then msg = msg + " on " + Format(OurDate, "dd-MMM-yyyy") msg = msg + " has been reinstated in " + Loc ElseIf InStr(Loc, "(Waiting)") > 0 And InStr(oldloc, "(Waiting)") <= 0 Then msg = msg + "booking requested" If DateProvided Then msg = msg + " on " + Format(OurDate, "dd-MMM-yyyy") msg = msg + " and is on the waiting list" ElseIf InStr(Loc, "(Waiting)") <= 0 And InStr(oldloc, "(Waiting)") > 0 Then msg = msg + "booking has been confirmed in" + Loc Else msg = msg + oldloc + " not available at this time" If DateProvided Then msg = msg + " on " + Format(OurDate, "dd-MMM-yyyy") msg = msg + ". Booking has been moved to " + Loc End If End If 'FoundItem.Location = Loc 'MsgBox("i am gng to save with location" & Loc & "on date " + OurDate) Dim meetingStatus As Outlook.OlMeetingStatus = FoundItem.MeetingStatus If (meetingStatus = OlMeetingStatus.olMeeting) Then FoundItem.Send() NAR(FoundItem) Dim oldsignature As String = DAppItem.GetSignature Dim newsignature As String = DAppItem.BuildSignature 'If (Loc <> "No Room Booked" And oldsignature = "CancelledFromBrowser") Then DAppItem.SetSignature(newsignature) 'If (meetingStatus = OlMeetingStatus.olNonMeeting) Then ' 'FoundItem.Recipients.Remove(1) ' 'FoundItem.MeetingStatus = OlMeetingStatus.olMeeting 'End If 'FoundItem.Save() 'If (meetingStatus = OlMeetingStatus.olNonMeeting) Then FoundItem.Close(Outlook.OlInspectorClose.olSave) If (msg <> "" And Warning) Then If (Isrecurring) Then Dim oldmsg As String = Me.GetMsgProperty(SearchItems(1)) Dim newmsg As String = oldmsg & Chr(10) & msg Me.SetMsgProperty(SearchItems(1), newmsg) If (oldsignature <> newsignature) Then DAppItem.SetSignature(newsignature) DAppItem.AppItem.Save() 'End If Else MsgBox("Room booking status for " + FoundItem.Subject + Chr(10) + Chr(10) + msg, MsgBoxStyle.OkOnly, "Datacraft Calendar Integration") End If End If 'If meetingStatus = OlMeetingStatus.olNonMeeting Then ' FoundItem = App ' FoundItem.MeetingStatus = meetingStatus ' FoundItem.Save() 'End If End If End If Me.LastMoved = "" End If Catch ex As System.Exception Log("Setlocation error: " + ex.Message) End Try 'FoundItem.MeetingStatus = OlMeetingStatus.olNonMeeting NAR(FoundItem) NAR(DAppItem.AppItem) NAR(SearchItems) ReleaseMemory() End If End Sub Private Function GetException(ByVal rp As Outlook.RecurrencePattern, ByVal ExceptionDate As Date) As Outlook.AppointmentItem Dim Exceptions As Outlook.Exceptions = rp.Exceptions Dim RPex As Outlook.Exception = Nothing Dim App As Outlook.AppointmentItem = Nothing Dim e As Int16 For e = 1 To Exceptions.Count RPex = Exceptions(e) If (Not RPex.Deleted) Then App = RPex.AppointmentItem If App.Start = ExceptionDate Then NAR(RPex) NAR(Exceptions) Return App Else NAR(App) End If End If NAR(RPex) Next NAR(Exceptions) Return Nothing End Function Public Sub NAR(ByVal o As Object) Dim Count As Integer = 1 Try Count = System.Runtime.InteropServices.Marshal.ReleaseComObject(o) CodeSite.Send(Count & " Such" & o.GetType.ToString & "Left To Release") 'End While Catch Finally o = Nothing End Try End Sub Public Function GetMsgProperty(ByVal item As AppointmentItem) As String Dim UserProperties As Outlook.UserProperties Dim MsgProperty As Outlook.UserProperty UserProperties = item.UserProperties MsgProperty = UserProperties.Find("MsgProperty") If MsgProperty Is Nothing Then GetMsgProperty = "" Else GetMsgProperty = MsgProperty.Value End If NAR(MsgProperty) NAR(UserProperties) ReleaseMemory() End Function Public Sub SetMsgProperty(ByVal item As AppointmentItem, ByVal msg As String) Dim UserProperties As Outlook.UserProperties Dim MsgProperty As Outlook.UserProperty UserProperties = item.UserProperties MsgProperty = UserProperties.Find("MsgProperty") If MsgProperty Is Nothing Then MsgProperty = UserProperties.Add("MsgProperty", OlUserPropertyType.olText) 'Things that can be changed without opening the booking MsgProperty.Value = msg NAR(MsgProperty) NAR(UserProperties) ReleaseMemory() End Sub Private Sub ReleaseMemory() Log("Memory used before collection: " & GC.GetTotalMemory(False)) GC.Collect() GC.WaitForPendingFinalizers() GC.Collect() Log("Memory used after full collection: {1}: " & GC.GetTotalMemory(True)) 'CodeSite.AddSeparator() End Sub

    End class

    This is ddlappitem class where write event of appointment is being captured
    Public Class ddlAppItem
        
        Public WithEvents AppItem As Outlook.AppointmentItem
        Public Owner As New DDLMSOI
            Public MeetingRef As String                
       
        Public ItemSaved As Boolean = False
        Public ItemSent As Boolean = False
        Public ItemCancelled As Boolean = False
        Public DUE As Boolean = False               
        
        Public RoomBookingPage As Boolean          'Set 
        Dim OurLocation As String
    	Dim PrevLocation As String
    	Dim PrevSubject As String
        Dim LastSavedReference As String
       
        Dim StartTime As Date
    	Dim EndTime As Date
    	Dim PreviousStartTime As Date
    	Dim PreviousEndTime As Date
        Dim Attendees As String
        Dim RecurrenceState As Integer
    	Dim RecurrencePattern As String
    	Dim meetingTimeSet As Boolean = True
    
    
    Private Sub AppItem_Write(ByRef Cancel As Boolean) Handles AppItem.Write
    
    		CodeSite.EnterMethod("AppItem_Write")
    		If buttonClicked Then
    			Cancel = True
    		Else
    			Dim signature As String = GetSignature()
    			Dim jsonMtgTimes As String = ""
    			Log("ddlAppItem.AppItem_Write: Item Save")
    			'logAppointment("AppItem_Write")
    			If ItemSent And ItemSaved Then
    				ItemSent = False	 'reset for next time - but skip the write event code - we've already dome it
    				Log("ddlAppItem.AppItem_Write: Ignoring Save - just done a Save and a Send")
    			ElseIf signature = "CancelledFromBrowser" And AppItem.Location = "No Room Booked" Then
    				Log("Ignored, due to signatures are CancelledFromBrowser and location is No Room Booked")
    			Else
    				If ItemOpen Then
    					If AppItem.MeetingStatus = OlMeetingStatus.olMeetingCanceled Then
    						If ItemCancelled = False Then
    							AppItem_BeforeDelete(AppItem, Cancel)
    							SetSignature(BuildSignature())
    						End If
    					Else
    						ItemCancelled = False
    						If RoomBookingPage Then
    							If DUE Then	' reload webpage as we need to get new booking details
    								LoadWebPage("", Me)
    							Else
    								RoomBookingPage = False
    								If InStr(AppItem.MessageClass, "IPM.OLE.CLASS") = 1 Then
    									jsonMtgTimes = "{meetingStart:\""" & ToISO8601DateTime(AppItem.Start) & "\"""
    									jsonMtgTimes = jsonMtgTimes & ",meetingEnd:\""" & ToISO8601DateTime(AppItem.End) & "\""}"
    									SetPageProperty(Browser, "meetingTimes", jsonMtgTimes)
    									SetPageProperty(Browser, "title", System.Net.WebUtility.HtmlEncode(AppItem.Subject))
    								End If
    								If InStr(AppItem.Location, "No Rooms") > 0 Then
    									'SetReference("")
    									MsgBox("No matching room - no room booking will be made while saving. Try a different time or room collection." + Chr(13) + "If you want to try booking later then close this window and press NO when prompted to save", MsgBoxStyle.OkOnly, "Datacraft Calendar Integration")
    									RoomBookingPage = True
    									Cancel = True
    								Else
    									CodeSite.Clear()
    									SetPageProperty(Browser, "bookingLoaded", "")
    									If (Not Me.BookingDetailsLoaded) Then
    										RoomBookingPage = True
    										Cancel = True
    										MsgBox("Booking details are still being processed. Please try again. ", MsgBoxStyle.OkOnly, "Datacraft Calendar Integration")
    									Else
    										'BookingDetailsLoaded = True
    										If (Not meetingTimeSet) Then
    											meetingTimeSet = True
    											jsonMtgTimes = "{meetingStart:\""" & ToISO8601DateTime(AppItem.Start) & "\"""
    											jsonMtgTimes = jsonMtgTimes & ",meetingEnd:\""" & ToISO8601DateTime(AppItem.End) & "\""}"
    											SetPageProperty(Browser, "meetingTimes", jsonMtgTimes)
    											Dim NewRP As String = GetRecurrenceProperties()
    											Select Case AppItem.RecurrenceState
    												Case OlRecurrenceState.olApptMaster
    													SetPageProperty(Browser, "setRecurring", True)
    													SetPageProperty(Browser, "setEditSeries", True)
    													SetPageProperty(Browser, "recurrencePatternObject", NewRP)
    												Case OlRecurrenceState.olApptException, OlRecurrenceState.olApptOccurrence
    													SetPageProperty(Browser, "setRecurring", True)
    													SetPageProperty(Browser, "setEditSeries", False)
    												Case OlRecurrenceState.olApptNotRecurring
    													SetPageProperty(Browser, "setRecurring", False)
    													SetPageProperty(Browser, "setEditSeries", False)
    											End Select
    										End If
    										'If AppItem.RecurrenceState <> OlRecurrenceState.olApptOccurrence And (signature <> "CancelledFromBrowser" Or AppItem.Location <> "No Room Booked") Then
    										'	' Don't do occurrences or you make them into exceptions unnecesarily
    										'	'SetSignature(BuildSignature())
    										'	'Dim str As String = GetRecurrenceProperties()
    										'End If
    										'If AppItem.IsRecurring And (PrevLocation <> AppItem.Location) And AppItem.RecurrenceState = OlRecurrenceState.olApptMaster Then
    										'	Dim rp As Outlook.RecurrencePattern = Nothing
    										'	rp = AppItem.GetRecurrencePattern()
    										'	Dim exceptions As Outlook.Exceptions = rp.Exceptions
    										'	If exceptions.Count > 0 Then
    										'		Dim rpex As Outlook.Exception = Nothing
    										'		Dim exception As Outlook.AppointmentItem = Nothing
    										'		Dim e As Int16
    										'		For e = 1 To exceptions.Count
    										'			rpex = exceptions(e)
    										'			If (Not rpex.Deleted) Then
    										'				exception = rpex.AppointmentItem
    										'				exception.Location = AppItem.Location
    										'				exception.Save()
    										'			End If
    										'			NAR(exception)
    										'			NAR(rpex)
    										'		Next
    										'	End If
    										'	NAR(exceptions)
    										'	NAR(rp)
    										'	ReleaseMemory()
    										'End If
    										PrevLocation = ""
    										SetPageProperty(Browser, "saveBooking", "")
    										If AppItem.RecurrenceState <> OlRecurrenceState.olApptOccurrence And (signature <> "CancelledFromBrowser" Or AppItem.Location <> "No Room Booked") Then
    											' Don't do occurrences or you make them into exceptions unnecesarily
    											SetSignature(BuildSignature())
    											'Dim str As String = GetRecurrenceProperties()
    										End If
    										'CodeSite.Send("afterpageprop", GetSignature)
    										Log("ddlAppItem.AppItem_Write: Room Booking Saved")
    										ItemSaved = True
    									End If
    								End If
    								If (GetSignature() <> "CancelledFromBrowser") Then ddlForm.Hide()
    							End If
    						End If
    					End If
    				End If
    			End If
    		End If
    		CodeSite.ExitMethod("AppItem_Write")
    	End Sub
    
    
    Private Function GetRecurrenceProperties() As String
            Dim RP As Outlook.RecurrencePattern          'recurrence pattern object
    		Dim RPex As Outlook.Exception				 'exception object
            Dim jsonRP As String                         'holds json format string
            GetRecurrenceProperties = ""
            Try
                If AppItem.IsRecurring Then
                    RP = AppItem.GetRecurrencePattern
                    jsonRP = "{recurrenceType:\""" & CStr(RP.RecurrenceType) & "\"","
                    jsonRP = jsonRP & "recurrenceInterval:" & CStr(RP.Interval) & ","
                    jsonRP = jsonRP & "instance:" & CStr(RP.Instance) & ","
                    jsonRP = jsonRP & "startTime:\""" & CStr(RP.StartTime) & "\"","
                    jsonRP = jsonRP & "endTime:\""" & CStr(RP.EndTime) & "\"","
                    jsonRP = jsonRP & "patternStartDate:\""" & ToISO8601DateTime(RP.PatternStartDate) & "\"","
                    jsonRP = jsonRP & "patternEndDate:\""" & ToISO8601DateTime(RP.PatternEndDate) & "\"","
                    jsonRP = jsonRP & "occurrences:" & CStr(RP.Occurrences) & ","
                    jsonRP = jsonRP & "DOWMask:" & RP.DayOfWeekMask & ","
                    jsonRP = jsonRP & "DOM:" & RP.DayOfMonth & ","
                    jsonRP = jsonRP & "MOY:" & RP.MonthOfYear & ","
                    jsonRP = jsonRP & "exceptions: ["
                    ' Pass any exception dataf
    				Dim Exceptions As Outlook.Exceptions = RP.Exceptions
    				If Exceptions.Count > 0 Then
    					Dim e As Int16
    					For e = 1 To Exceptions.Count
    						RPex = Exceptions(e)
    						jsonRP = jsonRP & "{"
    						jsonRP = jsonRP & "rpexOriginalDate:\""" & ToISO8601DateTime(RPex.OriginalDate) & "\"","
    						If RPex.Deleted = False Then
    							Dim Exception As Outlook.AppointmentItem = RPex.AppointmentItem
    							jsonRP = jsonRP & "rpexDeleted: false,"
    							jsonRP = jsonRP & "rpexStart:\""" & ToISO8601DateTime(Exception.Start) & "\"","
    							jsonRP = jsonRP & "rpexEnd:\""" & ToISO8601DateTime(Exception.End) & "\"","
    							jsonRP = jsonRP & "rpexTitle:\""" & System.Net.WebUtility.HtmlEncode(Exception.Subject) & "\""},"
    							NAR(Exception)
    						Else
    							jsonRP = jsonRP & "rpexDeleted: true,"
    							jsonRP = jsonRP & "rpexStart:\""\"","
    							jsonRP = jsonRP & "rpexEnd:\""\"","
    							jsonRP = jsonRP & "rpexTitle:\""\""},"
    						End If
    						NAR(RPex)
    						ReleaseMemory()
    					Next
    				End If
    				NAR(Exceptions)
                    If Right(jsonRP, 1) = "," Then jsonRP = Left(jsonRP, Len(jsonRP) - 1)
                    jsonRP = jsonRP & "]}"
                    ' Tell Our page that we're done - object can be used
                    GetRecurrenceProperties = jsonRP
    				NAR(RP)
    				ReleaseMemory()
                End If
            Catch ex As System.Exception
                Log(ex.Message)
            End Try
        End Function
    
    
    Private Function GetException(ByVal rp As Outlook.RecurrencePattern, ByVal ExceptionDate As Date) As Outlook.AppointmentItem
            Dim Exceptions As Outlook.Exceptions = rp.Exceptions
            Dim RPex As Outlook.Exception = Nothing
            Dim App As Outlook.AppointmentItem = Nothing
            Dim e As Int16
            For e = 1 To Exceptions.Count
                RPex = Exceptions(e)
                If (Not RPex.Deleted) Then
    				App = RPex.AppointmentItem
    				If App.Start = ExceptionDate Then
    					NAR(RPex)
    					NAR(Exceptions)
    					Return App
    				Else
    					NAR(App)
    				End If
                End If
                NAR(RPex)
            Next
            NAR(Exceptions)
            Return Nothing
        End Function
    
    Public Function BuildSignature() As String
            BuildSignature = ToISO8601DateTime(AppItem.Start) & ToISO8601DateTime(AppItem.End) & AppItem.Subject
            If AppItem.IsRecurring Then
                BuildSignature = BuildSignature & GetRecurrenceProperties()
    		End If
        End Function
    
        Public Function GetSignature() As String
            Dim UserProperties As Outlook.UserProperties
            Dim DDLSignature As Outlook.UserProperty
    		UserProperties = AppItem.UserProperties
    		DDLSignature = UserProperties.Find("DDL Signature")
            If DDLSignature Is Nothing Then
                GetSignature = ""
            Else
                GetSignature = DDLSignature.Value
            End If
            NAR(DDLSignature)
    		NAR(UserProperties)
    		ReleaseMemory()
        End Function
    
        Public Sub SetSignature(ByVal Signature As String)
            Dim UserProperties As Outlook.UserProperties
            Dim DDLSignature As Outlook.UserProperty
            UserProperties = AppItem.UserProperties
            DDLSignature = UserProperties.Find("DDL Signature")
    		If DDLSignature Is Nothing Then DDLSignature = UserProperties.Add("DDL Signature", OlUserPropertyType.olText)
            'Things that can be changed without opening the booking
            DDLSignature.Value = Signature
            NAR(DDLSignature)
    	NAR(UserProperties)
    	ReleaseMemory()
        End Sub
    
    
    
    


    • Edited by Nitrup Tuesday, June 12, 2012 4:20 PM
    Tuesday, June 12, 2012 4:18 PM
  • You say "within the same thread". Are you using any other threads at all, any others with the Outlook object model?
     
    If getting Exceptions in the Write() event is causing a problem, don't do it. Whether or not the code works in Outlook 2007 isn't the problem, it's what you're doing not working in 2010 that's the problem.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Nitrup" <=?utf-8?B?Tml0cnVw?=> wrote in message news:40eaa807-ca3c-4d86-8979-79b28b05b09e...

    Hi Ken,

    I tried out replacing compound dot operator in both my example and actualaddin, but things are still same.

    I found one thing, in write event of recurring appointment, if we try to get exceptions of recurring appointment, then it creates problem. i think i can show you my actual addin code,

    In below snippet of code , In  DDLMSOI class, here SetLocation function updates outlook appointment,  the function SetSignature and GetGignature and BuildSignature are defined in DDLAppItem . These functions  look for a userproperty name as "DDL Signature". Note that if an item is recurring, signature  for item will build form  exceptions properties and this looks like creating a problem in write event of item and when a particular exception is being held for updation.

    it looks like if outlook held an exception already and with in same thread again we try to get its instance of that exception then problem arises and  it do not update things correctly

    I think , the main problem area are Setlocation in DDLMSOI class and Appt_write method in DDLAppItem. In both of them you will see i am using BuildSignature , which further calls GetRecurrenceProperties() which look through all exception while items are being saved and there i am getting problem.

    I Apologise if i am not able to make you understand about my problem. this code without any change is working fine in outlook 2007

    Public Class DDLMSOI

    Public Sub SetLocation(ByVal Loc As String, Optional ByVal Warning As Boolean = False, _ Optional ByVal onDate As String = "", _ Optional ByVal email As String = "", _ Optional ByVal LastMoved As String = "") Dim SearchItems As Outlook.Items = Nothing Dim FoundItem As Outlook.AppointmentItem = Nothing Dim DAppItem As New ddlAppItem Dim CalendarFolderItems As Outlook.Items = Nothing 'Dim UID As String 'MsgBox(Loc) 'MsgBox(onDate) Dim OurDate As Date = Nothing Dim DateProvided As Boolean = onDate.Length > 0 If DateProvided Then OurDate = New Date(Left(onDate, 4), Mid(onDate, 6, 2), Mid(onDate, 9, 2)) Else OurDate = Now End If If (LastMoved = "") Then LastMoved = Me.LastMoved Log("ddlMSOI setlocation: " + Loc) If LastMoved.Length > 0 Then Try If (email <> "") Then Dim index As Integer For index = 1 To CalendarCollection.Count If (CalendarCollection(index).EmailAddress = email) Then CalendarFolderItems = CalendarCollection(index).FolderItems Exit For End If Next End If SearchItems = CalendarFolderItems.Restrict("[DDL Reference] = '" & LastMoved & "' And [start] > '" & Format(DateAdd(DateInterval.Minute, -1, LastMovedTime), "dd-MMM-yyyy hh:mm") & "'") 'SearchItems = CalendarItems.Restrict("[start] > '" & Format(DateAdd(DateInterval.Minute, -1, LastMovedTime), "dd-MMM-yyyy hh:mm") & "'") If SearchItems.Count > 0 Then 'Dim i As Int16 'For i = 1 To SearchItems.Count ' FoundItem = SearchItems(i) ' Dim DAppItem As New ddlAppItem ' DAppItem.AppItem = FoundItem ' UID = DAppItem.GetReference() ' If LastMoved = UID Then ' Exit For ' Else ' NAR(FoundItem) ' End If 'Next FoundItem = SearchItems(1) DAppItem.AppItem = SearchItems(1) Dim Isrecurring As Boolean = FoundItem.IsRecurring If (onDate.Length > 0) Then CodeSite.Send(onDate) Dim App As Outlook.AppointmentItem = Nothing If Isrecurring And onDate.Length > 0 Then 'GetException(FoundItem, onDate) 'If App Is Nothing Then Dim rp As Outlook.RecurrencePattern = FoundItem.GetRecurrencePattern() Try Dim start As Date = FoundItem.Start App = rp.GetOccurrence(OurDate + " " + start.ToShortTimeString) Catch End Try If App Is Nothing Then App = GetException(rp, onDate) 'App.ClearRecurrencePattern() 'End If NAR(FoundItem) NAR(rp) If Not App Is Nothing Then FoundItem = App Else FoundItem = Nothing End If End If CodeSite.Send(FoundItem.Start) If Not FoundItem Is Nothing Then If FoundItem.Location <> Loc Then Dim msg As String = "Room " Dim oldloc As String = FoundItem.Location FoundItem.Location = Loc FoundItem.Save() If Warning Then If Loc = "No Room Booked" Then 'No message - they already had it msg = "" ElseIf FoundItem.Location = "No Room Booked" Then msg = msg + "booking" If DateProvided Then msg = msg + " on " + Format(OurDate, "dd-MMM-yyyy") msg = msg + " has been reinstated in " + Loc ElseIf InStr(Loc, "(Waiting)") > 0 And InStr(oldloc, "(Waiting)") <= 0 Then msg = msg + "booking requested" If DateProvided Then msg = msg + " on " + Format(OurDate, "dd-MMM-yyyy") msg = msg + " and is on the waiting list" ElseIf InStr(Loc, "(Waiting)") <= 0 And InStr(oldloc, "(Waiting)") > 0 Then msg = msg + "booking has been confirmed in" + Loc Else msg = msg + oldloc + " not available at this time" If DateProvided Then msg = msg + " on " + Format(OurDate, "dd-MMM-yyyy") msg = msg + ". Booking has been moved to " + Loc End If End If 'FoundItem.Location = Loc 'MsgBox("i am gng to save with location" & Loc & "on date " + OurDate) Dim meetingStatus As Outlook.OlMeetingStatus = FoundItem.MeetingStatus If (meetingStatus = OlMeetingStatus.olMeeting) Then FoundItem.Send() NAR(FoundItem) Dim oldsignature As String = DAppItem.GetSignature Dim newsignature As String = DAppItem.BuildSignature 'If (Loc <> "No Room Booked" And oldsignature = "CancelledFromBrowser") Then DAppItem.SetSignature(newsignature) 'If (meetingStatus = OlMeetingStatus.olNonMeeting) Then ' 'FoundItem.Recipients.Remove(1) ' 'FoundItem.MeetingStatus = OlMeetingStatus.olMeeting 'End If 'FoundItem.Save() 'If (meetingStatus = OlMeetingStatus.olNonMeeting) Then FoundItem.Close(Outlook.OlInspectorClose.olSave) If (msg <> "" And Warning) Then If (Isrecurring) Then Dim oldmsg As String = Me.GetMsgProperty(SearchItems(1)) Dim newmsg As String = oldmsg & Chr(10) & msg Me.SetMsgProperty(SearchItems(1), newmsg) If (oldsignature <> newsignature) Then DAppItem.SetSignature(newsignature) DAppItem.AppItem.Save() 'End If Else MsgBox("Room booking status for " + FoundItem.Subject + Chr(10) + Chr(10) + msg, MsgBoxStyle.OkOnly, "Datacraft Calendar Integration") End If End If 'If meetingStatus = OlMeetingStatus.olNonMeeting Then ' FoundItem = App ' FoundItem.MeetingStatus = meetingStatus ' FoundItem.Save() 'End If End If End If Me.LastMoved = "" End If Catch ex As System.Exception Log("Setlocation error: " + ex.Message) End Try 'FoundItem.MeetingStatus = OlMeetingStatus.olNonMeeting NAR(FoundItem) NAR(DAppItem.AppItem) NAR(SearchItems) ReleaseMemory() End If End Sub Private Function GetException(ByVal rp As Outlook.RecurrencePattern, ByVal ExceptionDate As Date) As Outlook.AppointmentItem Dim Exceptions As Outlook.Exceptions = rp.Exceptions Dim RPex As Outlook.Exception = Nothing Dim App As Outlook.AppointmentItem = Nothing Dim e As Int16 For e = 1 To Exceptions.Count RPex = Exceptions(e) If (Not RPex.Deleted) Then App = RPex.AppointmentItem If App.Start = ExceptionDate Then NAR(RPex) NAR(Exceptions) Return App Else NAR(App) End If End If NAR(RPex) Next NAR(Exceptions) Return Nothing End Function Public Sub NAR(ByVal o As Object) Dim Count As Integer = 1 Try Count = System.Runtime.InteropServices.Marshal.ReleaseComObject(o) CodeSite.Send(Count & " Such" & o.GetType.ToString & "Left To Release") 'End While Catch Finally o = Nothing End Try End Sub Public Function GetMsgProperty(ByVal item As AppointmentItem) As String Dim UserProperties As Outlook.UserProperties Dim MsgProperty As Outlook.UserProperty UserProperties = item.UserProperties MsgProperty = UserProperties.Find("MsgProperty") If MsgProperty Is Nothing Then GetMsgProperty = "" Else GetMsgProperty = MsgProperty.Value End If NAR(MsgProperty) NAR(UserProperties) ReleaseMemory() End Function Public Sub SetMsgProperty(ByVal item As AppointmentItem, ByVal msg As String) Dim UserProperties As Outlook.UserProperties Dim MsgProperty As Outlook.UserProperty UserProperties = item.UserProperties MsgProperty = UserProperties.Find("MsgProperty") If MsgProperty Is Nothing Then MsgProperty = UserProperties.Add("MsgProperty", OlUserPropertyType.olText) 'Things that can be changed without opening the booking MsgProperty.Value = msg NAR(MsgProperty) NAR(UserProperties) ReleaseMemory() End Sub Private Sub ReleaseMemory() Log("Memory used before collection: " & GC.GetTotalMemory(False)) GC.Collect() GC.WaitForPendingFinalizers() GC.Collect() Log("Memory used after full collection: {1}: " & GC.GetTotalMemory(True)) 'CodeSite.AddSeparator() End Sub

    End class

    This is ddlappitem class where write event of appointment is being captured
    Public Class ddlAppItem
        
        Public WithEvents AppItem As Outlook.AppointmentItem
        Public Owner As New DDLMSOI
            Public MeetingRef As String                
       
        Public ItemSaved As Boolean = False
        Public ItemSent As Boolean = False
        Public ItemCancelled As Boolean = False
        Public DUE As Boolean = False               
        
        Public RoomBookingPage As Boolean          'Set 
        Dim OurLocation As String
    	Dim PrevLocation As String
    	Dim PrevSubject As String
        Dim LastSavedReference As String
       
        Dim StartTime As Date
    	Dim EndTime As Date
    	Dim PreviousStartTime As Date
    	Dim PreviousEndTime As Date
        Dim Attendees As String
        Dim RecurrenceState As Integer
    	Dim RecurrencePattern As String
    	Dim meetingTimeSet As Boolean = True
    
    
    Private Sub AppItem_Write(ByRef Cancel As Boolean) Handles AppItem.Write
    
    		CodeSite.EnterMethod("AppItem_Write")
    		If buttonClicked Then
    			Cancel = True
    		Else
    			Dim signature As String = GetSignature()
    			Dim jsonMtgTimes As String = ""
    			Log("ddlAppItem.AppItem_Write: Item Save")
    			'logAppointment("AppItem_Write")
    			If ItemSent And ItemSaved Then
    				ItemSent = False	 'reset for next time - but skip the write event code - we've already dome it
    				Log("ddlAppItem.AppItem_Write: Ignoring Save - just done a Save and a Send")
    			ElseIf signature = "CancelledFromBrowser" And AppItem.Location = "No Room Booked" Then
    				Log("Ignored, due to signatures are CancelledFromBrowser and location is No Room Booked")
    			Else
    				If ItemOpen Then
    					If AppItem.MeetingStatus = OlMeetingStatus.olMeetingCanceled Then
    						If ItemCancelled = False Then
    							AppItem_BeforeDelete(AppItem, Cancel)
    							SetSignature(BuildSignature())
    						End If
    					Else
    						ItemCancelled = False
    						If RoomBookingPage Then
    							If DUE Then	' reload webpage as we need to get new booking details
    								LoadWebPage("", Me)
    							Else
    								RoomBookingPage = False
    								If InStr(AppItem.MessageClass, "IPM.OLE.CLASS") = 1 Then
    									jsonMtgTimes = "{meetingStart:\""" & ToISO8601DateTime(AppItem.Start) & "\"""
    									jsonMtgTimes = jsonMtgTimes & ",meetingEnd:\""" & ToISO8601DateTime(AppItem.End) & "\""}"
    									SetPageProperty(Browser, "meetingTimes", jsonMtgTimes)
    									SetPageProperty(Browser, "title", System.Net.WebUtility.HtmlEncode(AppItem.Subject))
    								End If
    								If InStr(AppItem.Location, "No Rooms") > 0 Then
    									'SetReference("")
    									MsgBox("No matching room - no room booking will be made while saving. Try a different time or room collection." + Chr(13) + "If you want to try booking later then close this window and press NO when prompted to save", MsgBoxStyle.OkOnly, "Datacraft Calendar Integration")
    									RoomBookingPage = True
    									Cancel = True
    								Else
    									CodeSite.Clear()
    									SetPageProperty(Browser, "bookingLoaded", "")
    									If (Not Me.BookingDetailsLoaded) Then
    										RoomBookingPage = True
    										Cancel = True
    										MsgBox("Booking details are still being processed. Please try again. ", MsgBoxStyle.OkOnly, "Datacraft Calendar Integration")
    									Else
    										'BookingDetailsLoaded = True
    										If (Not meetingTimeSet) Then
    											meetingTimeSet = True
    											jsonMtgTimes = "{meetingStart:\""" & ToISO8601DateTime(AppItem.Start) & "\"""
    											jsonMtgTimes = jsonMtgTimes & ",meetingEnd:\""" & ToISO8601DateTime(AppItem.End) & "\""}"
    											SetPageProperty(Browser, "meetingTimes", jsonMtgTimes)
    											Dim NewRP As String = GetRecurrenceProperties()
    											Select Case AppItem.RecurrenceState
    												Case OlRecurrenceState.olApptMaster
    													SetPageProperty(Browser, "setRecurring", True)
    													SetPageProperty(Browser, "setEditSeries", True)
    													SetPageProperty(Browser, "recurrencePatternObject", NewRP)
    												Case OlRecurrenceState.olApptException, OlRecurrenceState.olApptOccurrence
    													SetPageProperty(Browser, "setRecurring", True)
    													SetPageProperty(Browser, "setEditSeries", False)
    												Case OlRecurrenceState.olApptNotRecurring
    													SetPageProperty(Browser, "setRecurring", False)
    													SetPageProperty(Browser, "setEditSeries", False)
    											End Select
    										End If
    										'If AppItem.RecurrenceState <> OlRecurrenceState.olApptOccurrence And (signature <> "CancelledFromBrowser" Or AppItem.Location <> "No Room Booked") Then
    										'	' Don't do occurrences or you make them into exceptions unnecesarily
    										'	'SetSignature(BuildSignature())
    										'	'Dim str As String = GetRecurrenceProperties()
    										'End If
    										'If AppItem.IsRecurring And (PrevLocation <> AppItem.Location) And AppItem.RecurrenceState = OlRecurrenceState.olApptMaster Then
    										'	Dim rp As Outlook.RecurrencePattern = Nothing
    										'	rp = AppItem.GetRecurrencePattern()
    										'	Dim exceptions As Outlook.Exceptions = rp.Exceptions
    										'	If exceptions.Count > 0 Then
    										'		Dim rpex As Outlook.Exception = Nothing
    										'		Dim exception As Outlook.AppointmentItem = Nothing
    										'		Dim e As Int16
    										'		For e = 1 To exceptions.Count
    										'			rpex = exceptions(e)
    										'			If (Not rpex.Deleted) Then
    										'				exception = rpex.AppointmentItem
    										'				exception.Location = AppItem.Location
    										'				exception.Save()
    										'			End If
    										'			NAR(exception)
    										'			NAR(rpex)
    										'		Next
    										'	End If
    										'	NAR(exceptions)
    										'	NAR(rp)
    										'	ReleaseMemory()
    										'End If
    										PrevLocation = ""
    										SetPageProperty(Browser, "saveBooking", "")
    										If AppItem.RecurrenceState <> OlRecurrenceState.olApptOccurrence And (signature <> "CancelledFromBrowser" Or AppItem.Location <> "No Room Booked") Then
    											' Don't do occurrences or you make them into exceptions unnecesarily
    											SetSignature(BuildSignature())
    											'Dim str As String = GetRecurrenceProperties()
    										End If
    										'CodeSite.Send("afterpageprop", GetSignature)
    										Log("ddlAppItem.AppItem_Write: Room Booking Saved")
    										ItemSaved = True
    									End If
    								End If
    								If (GetSignature() <> "CancelledFromBrowser") Then ddlForm.Hide()
    							End If
    						End If
    					End If
    				End If
    			End If
    		End If
    		CodeSite.ExitMethod("AppItem_Write")
    	End Sub
    
    
    Private Function GetRecurrenceProperties() As String
            Dim RP As Outlook.RecurrencePattern          'recurrence pattern object
    		Dim RPex As Outlook.Exception				 'exception object
            Dim jsonRP As String                         'holds json format string
            GetRecurrenceProperties = ""
            Try
                If AppItem.IsRecurring Then
                    RP = AppItem.GetRecurrencePattern
                    jsonRP = "{recurrenceType:\""" & CStr(RP.RecurrenceType) & "\"","
                    jsonRP = jsonRP & "recurrenceInterval:" & CStr(RP.Interval) & ","
                    jsonRP = jsonRP & "instance:" & CStr(RP.Instance) & ","
                    jsonRP = jsonRP & "startTime:\""" & CStr(RP.StartTime) & "\"","
                    jsonRP = jsonRP & "endTime:\""" & CStr(RP.EndTime) & "\"","
                    jsonRP = jsonRP & "patternStartDate:\""" & ToISO8601DateTime(RP.PatternStartDate) & "\"","
                    jsonRP = jsonRP & "patternEndDate:\""" & ToISO8601DateTime(RP.PatternEndDate) & "\"","
                    jsonRP = jsonRP & "occurrences:" & CStr(RP.Occurrences) & ","
                    jsonRP = jsonRP & "DOWMask:" & RP.DayOfWeekMask & ","
                    jsonRP = jsonRP & "DOM:" & RP.DayOfMonth & ","
                    jsonRP = jsonRP & "MOY:" & RP.MonthOfYear & ","
                    jsonRP = jsonRP & "exceptions: ["
                    ' Pass any exception dataf
    				Dim Exceptions As Outlook.Exceptions = RP.Exceptions
    				If Exceptions.Count > 0 Then
    					Dim e As Int16
    					For e = 1 To Exceptions.Count
    						RPex = Exceptions(e)
    						jsonRP = jsonRP & "{"
    						jsonRP = jsonRP & "rpexOriginalDate:\""" & ToISO8601DateTime(RPex.OriginalDate) & "\"","
    						If RPex.Deleted = False Then
    							Dim Exception As Outlook.AppointmentItem = RPex.AppointmentItem
    							jsonRP = jsonRP & "rpexDeleted: false,"
    							jsonRP = jsonRP & "rpexStart:\""" & ToISO8601DateTime(Exception.Start) & "\"","
    							jsonRP = jsonRP & "rpexEnd:\""" & ToISO8601DateTime(Exception.End) & "\"","
    							jsonRP = jsonRP & "rpexTitle:\""" & System.Net.WebUtility.HtmlEncode(Exception.Subject) & "\""},"
    							NAR(Exception)
    						Else
    							jsonRP = jsonRP & "rpexDeleted: true,"
    							jsonRP = jsonRP & "rpexStart:\""\"","
    							jsonRP = jsonRP & "rpexEnd:\""\"","
    							jsonRP = jsonRP & "rpexTitle:\""\""},"
    						End If
    						NAR(RPex)
    						ReleaseMemory()
    					Next
    				End If
    				NAR(Exceptions)
                    If Right(jsonRP, 1) = "," Then jsonRP = Left(jsonRP, Len(jsonRP) - 1)
                    jsonRP = jsonRP & "]}"
                    ' Tell Our page that we're done - object can be used
                    GetRecurrenceProperties = jsonRP
    				NAR(RP)
    				ReleaseMemory()
                End If
            Catch ex As System.Exception
                Log(ex.Message)
            End Try
        End Function
    
    
    Private Function GetException(ByVal rp As Outlook.RecurrencePattern, ByVal ExceptionDate As Date) As Outlook.AppointmentItem
            Dim Exceptions As Outlook.Exceptions = rp.Exceptions
            Dim RPex As Outlook.Exception = Nothing
            Dim App As Outlook.AppointmentItem = Nothing
            Dim e As Int16
            For e = 1 To Exceptions.Count
                RPex = Exceptions(e)
                If (Not RPex.Deleted) Then
    				App = RPex.AppointmentItem
    				If App.Start = ExceptionDate Then
    					NAR(RPex)
    					NAR(Exceptions)
    					Return App
    				Else
    					NAR(App)
    				End If
                End If
                NAR(RPex)
            Next
            NAR(Exceptions)
            Return Nothing
        End Function
    
    Public Function BuildSignature() As String
            BuildSignature = ToISO8601DateTime(AppItem.Start) & ToISO8601DateTime(AppItem.End) & AppItem.Subject
            If AppItem.IsRecurring Then
                BuildSignature = BuildSignature & GetRecurrenceProperties()
    		End If
        End Function
    
        Public Function GetSignature() As String
            Dim UserProperties As Outlook.UserProperties
            Dim DDLSignature As Outlook.UserProperty
    		UserProperties = AppItem.UserProperties
    		DDLSignature = UserProperties.Find("DDL Signature")
            If DDLSignature Is Nothing Then
                GetSignature = ""
            Else
                GetSignature = DDLSignature.Value
            End If
            NAR(DDLSignature)
    		NAR(UserProperties)
    		ReleaseMemory()
        End Function
    
        Public Sub SetSignature(ByVal Signature As String)
            Dim UserProperties As Outlook.UserProperties
            Dim DDLSignature As Outlook.UserProperty
            UserProperties = AppItem.UserProperties
            DDLSignature = UserProperties.Find("DDL Signature")
    		If DDLSignature Is Nothing Then DDLSignature = UserProperties.Add("DDL Signature", OlUserPropertyType.olText)
            'Things that can be changed without opening the booking
            DDLSignature.Value = Signature
            NAR(DDLSignature)
    	NAR(UserProperties)
    	ReleaseMemory()
        End Sub
    
    
    
    



    Ken Slovak MVP - Outlook
    Tuesday, June 12, 2012 6:58 PM
    Moderator
  • Ken,

    Sorry, i think i used wrong word "Thread" in the line.

    it looks like if outlook held an exception already and with in same thread again we try to get its instance of that exception then problem arises and  it do not update things correctly.

    Actually , i mean to say its with in same function. see this scenario, i hold an exception of a recurring appointment for updating location and in the next line i am calling a function which will build a string of properties of exceptions for same recurring appointment. see GetRecurrenceProperties() in my code.

    one more thing, using exception.send()(in my code it is FoundItem.send) for the exception whose meeting status is Olmeeting ,always updates location correctly and make sure everything in place, so same code just works fine for me.

    i found that using send() method, item closes correctly. I  was wondering if there is any method which will make sure NonMeeting type appointment also has been closed correctly.

    note that, i am already using Marshal.ReleaseComObject and GC.collect,GC.waitForPendingFinalizers() in my code.

    Thanks

    Tuesday, June 12, 2012 10:33 PM
  • I think you're going to have to do any of that sort of processing outside of the Outlook event handler.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Nitrup" <=?utf-8?B?Tml0cnVw?=> wrote in message news:64111f75-be95-4cdc-8ae7-f0d620122c89...

    Ken,

    Sorry, i think i used wrong word "Thread" in the line.

    it looks like if outlook held an exception already and with in same thread again we try to get its instance of that exception then problem arises and  it do not update things correctly.

    Actually , i mean to say its with in same function. see this scenario, i hold an exception of a recurring appointment for updating location and in the next line i am calling a function which will build a string of properties of exceptions for same recurring appointment. see GetRecurrenceProperties() in my code.

    one more thing, using exception.send()(in my code it is FoundItem.send) for the exception whose meeting status is Olmeeting ,always updates location correctly and make sure everything in place, so same code just works fine for me.

    i found that using send() method, item closes correctly. I  was wondering if there is any method which will make sure NonMeeting type appointment also has been closed correctly.

    note that, i am already using Marshal.ReleaseComObject and GC.collect,GC.waitForPendingFinalizers() in my code.

    Thanks


    Ken Slovak MVP - Outlook
    Wednesday, June 13, 2012 3:29 PM
    Moderator
  • Ken,

    I am not facing this problem only in event handler , but with in another functions also. see this function

    Public Sub SetLocation(ByVal Loc As String, Optional ByVal Warning As Boolean = False, _
                                Optional ByVal onDate As String = "", _
                                Optional ByVal email As String = "", _
                                Optional ByVal LastMoved As String = "")

    Dim SearchItems As Outlook.Items = Nothing
            Dim FoundItem As Outlook.AppointmentItem = Nothing
            Dim DAppItem As New ddlAppItem (its a class and having property as ApptItem having type as AppointmentItem)
            Dim CalendarFolderItems As Outlook.Items = Nothing

    Dim OurDate As Date = Nothing
            Dim DateProvided As Boolean = onDate.Length > 0
            If DateProvided Then
                OurDate = New Date(Left(onDate, 4), Mid(onDate, 6, 2), Mid(onDate, 9, 2))
            Else
                OurDate = Now
            End If
            If (LastMoved = "") Then LastMoved = Me.LastMoved
            Log("ddlMSOI setlocation: " + Loc)


    I have declared a global collection list which will hold the references of all the calendar folders and a key is associated with each entry in collection as a email address

    If LastMoved.Length > 0 Then
                Try
                    If (email <> "") Then
                        Dim index As Integer
                        For index = 1 To CalendarCollection.Count
                            If (CalendarCollection(index).EmailAddress = email) Then
                                CalendarFolderItems = CalendarCollection(index).FolderItems
                                Exit For
                            End If
                        Next
                    End If
                    SearchItems = CalendarFolderItems.Restrict("[DDL Reference] = '" & LastMoved & "' And [start] > '" & Format(DateAdd(DateInterval.Minute, -1, LastMovedTime), "dd-MMM-yyyy hh:mm") & "'")


    As you can see in above code , will try to find the calendar and then i will find out an Appointmentment having userproperty DDL Reference = LastMoved and will make sure its a future appointment.

    If SearchItems.Count > 0 Then

    DAppItem.AppItem = SearchItems(1) -- will point to master appointment item

    Dim Isrecurring As Boolean = DAppItem.AppItem.IsRecurring

    Dim App As Outlook.AppointmentItem = Nothing
               If Isrecurring And onDate.Length > 0 Then
               Dim rp As Outlook.RecurrencePattern = DAppItem.AppItem.GetRecurrencePattern()

    Try
         Dim start As Date = DAppItem.AppItem.Start
         App = rp.GetOccurrence(OurDate + " " + start.ToShortTimeString)
         Catch
         End Try
        if App Is Nothing Then App = GetException(rp, onDate)' see GetException definition below

    NAR(rp)
                            If Not App Is Nothing Then
                                FoundItem = App
                            Else
                                FoundItem = Nothing
                            End If
                        End If

    If Not FoundItem Is Nothing Then
                            If FoundItem.Location <> Loc Then
                                Dim msg As String = "Room "
                                Dim oldloc As String = FoundItem.Location
                                FoundItem.Location = Loc
                                FoundItem.Save() --- This should save the exception with the new location,currently it sometime does and sometime it do not

    If Warning Then
                                    If Loc = "No Room Booked" Then
                                        'No message - they already had it
                                        msg = ""
                                    ElseIf FoundItem.Location = "No Room Booked" Then
                                        msg = msg + "booking"
                                        If DateProvided Then msg = msg + " on " + Format(OurDate, "dd-MMM-yyyy")
                                        msg = msg + " has been reinstated in " + Loc
                                    ElseIf InStr(Loc, "(Waiting)") > 0 And InStr(oldloc, "(Waiting)") <= 0 Then
                                        msg = msg + "booking requested"
                                        If DateProvided Then msg = msg + " on " + Format(OurDate, "dd-MMM-yyyy")
                                        msg = msg + " and is on the waiting list"
                                    ElseIf InStr(Loc, "(Waiting)") <= 0 And InStr(oldloc, "(Waiting)") > 0 Then
                                        msg = msg + "booking has been confirmed in" + Loc
                                    Else
                                        msg = msg + oldloc + " not available at this time"
                                        If DateProvided Then msg = msg + " on " + Format(OurDate, "dd-MMM-yyyy")
                                        msg = msg + ".  Booking has been moved to " + Loc
                                    End If
                                End If

    The msg variable above is just to store the changed location of the Exception

    Dim meetingStatus As Outlook.OlMeetingStatus = FoundItem.MeetingStatus
                                If (meetingStatus = OlMeetingStatus.olMeeting) Then FoundItem.Send() --- if this happens then everything works fine  with the same code
                                NAR(FoundItem)

    Dim oldsignature As String = DAppItem.GetSignature
    Dim newsignature As String = DAppItem.BuildSignature

    For one ajax request,setLocation method will be called number of times depends on how many occurrences a particular recurring appointment have, so each time location string we have to save in userproperty and string in userproerty will keep on appending each time and will be used later after all occurences has been saved

    If you will see definition of BuildSignature() its calling another function GetRecurrenceProperties() , this function will try to get the all the properties of occurrences of same recurring appointment which we are currently updating in this function, and i found that after GetRecurrenceProperties() has been called and then when i try to save the master appointment item, it gives me really inconsistent behavior. sometime it left all occurrences not updated and sometime it updates all of them. this is the problem i am facing

    If (msg <> "" And Warning) Then
          If (Isrecurring) Then
             Dim oldmsg As String = Me.GetMsgProperty(SearchItems(1))
             Dim newmsg As String = oldmsg & Chr(10) & msg
             Me.SetMsgProperty(SearchItems(1), newmsg)
            If (oldsignature <> newsignature) Then DAppItem.SetSignature(newsignature)
            DAppItem.AppItem.Save()
       Else
              MsgBox("Room booking status for " + FoundItem.Subject + Chr(10) + Chr(10) + msg, MsgBoxStyle.OkOnly, "Datacraft Calendar Integration")
       End If

       End If
       End If
       End If
       Me.LastMoved = ""
       End If
       catch ex As System.Exception
          Log("Setlocation error: " + ex.Message)
         End Try
                'FoundItem.MeetingStatus = OlMeetingStatus.olNonMeeting
                NAR(FoundItem)
                NAR(DAppItem.AppItem)
                NAR(SearchItems)
                ReleaseMemory()
            End If
        End Sub


    Private Function GetException(ByVal rp As Outlook.RecurrencePattern, ByVal ExceptionDate As Date) As Outlook.AppointmentItem
            Dim Exceptions As Outlook.Exceptions = rp.Exceptions
            Dim RPex As Outlook.Exception = Nothing
            Dim App As Outlook.AppointmentItem = Nothing
            Dim e As Int16
            For e = 1 To Exceptions.Count
                RPex = Exceptions(e)
                If (Not RPex.Deleted) Then
                    App = RPex.AppointmentItem
                    If App.Start = ExceptionDate Then
                        NAR(RPex)
                        NAR(Exceptions)
                        Return App
                    Else
                        NAR(App)
                    End If
                End If
                NAR(RPex)
            Next
            NAR(Exceptions)
            Return Nothing
        End Function


    Public Function GetMsgProperty(ByVal item As AppointmentItem) As String
            Dim UserProperties As Outlook.UserProperties
            Dim MsgProperty As Outlook.UserProperty
            UserProperties = item.UserProperties
            MsgProperty = UserProperties.Find("MsgProperty")
            If MsgProperty Is Nothing Then
                GetMsgProperty = ""
            Else
                GetMsgProperty = MsgProperty.Value
            End If
            NAR(MsgProperty)
            NAR(UserProperties)
            ReleaseMemory()
        End Function

        Public Sub SetMsgProperty(ByVal item As AppointmentItem, ByVal msg As String)
            Dim UserProperties As Outlook.UserProperties
            Dim MsgProperty As Outlook.UserProperty
            UserProperties = item.UserProperties
            MsgProperty = UserProperties.Find("MsgProperty")
            If MsgProperty Is Nothing Then MsgProperty = UserProperties.Add("MsgProperty", OlUserPropertyType.olText)
            'Things that can be changed without opening the booking
            MsgProperty.Value = msg
            NAR(MsgProperty)
            NAR(UserProperties)
            ReleaseMemory()
        End Sub


    Public Function BuildSignature() As String BuildSignature = ToISO8601DateTime(AppItem.Start) & ToISO8601DateTime(AppItem.End) & AppItem.Subject If AppItem.IsRecurring Then BuildSignature = BuildSignature & GetRecurrenceProperties() End If End Function Public Function GetSignature() As String Dim UserProperties As Outlook.UserProperties Dim DDLSignature As Outlook.UserProperty UserProperties = AppItem.UserProperties DDLSignature = UserProperties.Find("DDL Signature") If DDLSignature Is Nothing Then GetSignature = "" Else GetSignature = DDLSignature.Value End If NAR(DDLSignature) NAR(UserProperties) ReleaseMemory() End Function Public Sub SetSignature(ByVal Signature As String) Dim UserProperties As Outlook.UserProperties Dim DDLSignature As Outlook.UserProperty UserProperties = AppItem.UserProperties DDLSignature = UserProperties.Find("DDL Signature") If DDLSignature Is Nothing Then DDLSignature = UserProperties.Add("DDL Signature", OlUserPropertyType.olText) 'Things that can be changed without opening the booking DDLSignature.Value = Signature NAR(DDLSignature) NAR(UserProperties) ReleaseMemory() End Sub

    Private Function GetRecurrenceProperties() As String
            Dim RP As Outlook.RecurrencePattern          'recurrence pattern object
    		Dim RPex As Outlook.Exception				 'exception object
            Dim jsonRP As String                         'holds json format string
            GetRecurrenceProperties = ""
            Try
                If AppItem.IsRecurring Then
                    RP = AppItem.GetRecurrencePattern
                    jsonRP = "{recurrenceType:\""" & CStr(RP.RecurrenceType) & "\"","
                    jsonRP = jsonRP & "recurrenceInterval:" & CStr(RP.Interval) & ","
                    jsonRP = jsonRP & "instance:" & CStr(RP.Instance) & ","
                    jsonRP = jsonRP & "startTime:\""" & CStr(RP.StartTime) & "\"","
                    jsonRP = jsonRP & "endTime:\""" & CStr(RP.EndTime) & "\"","
                    jsonRP = jsonRP & "patternStartDate:\""" & ToISO8601DateTime(RP.PatternStartDate) & "\"","
                    jsonRP = jsonRP & "patternEndDate:\""" & ToISO8601DateTime(RP.PatternEndDate) & "\"","
                    jsonRP = jsonRP & "occurrences:" & CStr(RP.Occurrences) & ","
                    jsonRP = jsonRP & "DOWMask:" & RP.DayOfWeekMask & ","
                    jsonRP = jsonRP & "DOM:" & RP.DayOfMonth & ","
                    jsonRP = jsonRP & "MOY:" & RP.MonthOfYear & ","
                    jsonRP = jsonRP & "exceptions: ["
                    ' Pass any exception dataf
    				Dim Exceptions As Outlook.Exceptions = RP.Exceptions
    				If Exceptions.Count > 0 Then
    					Dim e As Int16
    					For e = 1 To Exceptions.Count
    						RPex = Exceptions(e)
    						jsonRP = jsonRP & "{"
    						jsonRP = jsonRP & "rpexOriginalDate:\""" & ToISO8601DateTime(RPex.OriginalDate) & "\"","
    						If RPex.Deleted = False Then
    							Dim Exception As Outlook.AppointmentItem = RPex.AppointmentItem
    							jsonRP = jsonRP & "rpexDeleted: false,"
    							jsonRP = jsonRP & "rpexStart:\""" & ToISO8601DateTime(Exception.Start) & "\"","
    							jsonRP = jsonRP & "rpexEnd:\""" & ToISO8601DateTime(Exception.End) & "\"","
    							jsonRP = jsonRP & "rpexTitle:\""" & System.Net.WebUtility.HtmlEncode(Exception.Subject) & "\""},"
    							NAR(Exception)
    						Else
    							jsonRP = jsonRP & "rpexDeleted: true,"
    							jsonRP = jsonRP & "rpexStart:\""\"","
    							jsonRP = jsonRP & "rpexEnd:\""\"","
    							jsonRP = jsonRP & "rpexTitle:\""\""},"
    						End If
    						NAR(RPex)
    						ReleaseMemory()
    					Next
    				End If
    				NAR(Exceptions)
                    If Right(jsonRP, 1) = "," Then jsonRP = Left(jsonRP, Len(jsonRP) - 1)
                    jsonRP = jsonRP & "]}"
                    ' Tell Our page that we're done - object can be used
                    GetRecurrenceProperties = jsonRP
    				NAR(RP)
    				ReleaseMemory()
                End If
            Catch ex As System.Exception
                Log(ex.Message)
            End Try
        End Function
    
    Private Sub ReleaseMemory()
            Log("Memory used before collection: " & GC.GetTotalMemory(False))
            GC.Collect()
            GC.WaitForPendingFinalizers()
            GC.Collect()
            Log("Memory used after full collection: {1}: " & GC.GetTotalMemory(True))
            'CodeSite.AddSeparator()
        End Sub
    Public Sub NAR(ByVal o As Object)
            Dim Count As Integer = 1
            Try
                Count = System.Runtime.InteropServices.Marshal.ReleaseComObject(o)
                CodeSite.Send(Count & " Such" & o.GetType.ToString & "Left To Release")
                'End While
            Catch
            Finally
                o = Nothing
            End Try
        End Sub


     let me know what problem do you see in SetLocation, i am really struggling in fixing this.

    the same problem i am facing in item write event handler, each time when we update a recurring appointment, we have to update DDL Signature userproperty, and as you as can see its calling BuildSignature() also. if i remove BuildSignature() form everywhere location updates everytime

    Private Sub AppItem_Write(ByRef Cancel As Boolean) Handles AppItem.Write

                                               
                                                SetSignature(BuildSignature())
                                               
     End If

    Note that, Setlocation method will be called after write event handler has been excuted and  inspector has been closed, so if i remove BuildSignature() from above event handler, then location updated through setLocation updates correctly.

    I agrre, with my code items are being locked and not being release correctly , but where and how i do not know.

    I hope , i made you understand my problem this time.

    Thanks once again for your replies earlier.


    Thursday, June 14, 2012 10:09 AM
  • I don't know where the problem is coming in. You might be able to see what's going on from the Locals window and seeing if any unexpected objects are being held. Or if that doesn't work you might need to file a support request and get an MS support engineer to help with this, they have special tools that would be helpful.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Nitrup" <=?utf-8?B?Tml0cnVw?=> wrote in message news:eb346c31-5600-43b5-92ef-26ada28423dd...

    Ken,

    I am not facing this problem only in event handler , but with in another functions also. see this function

    Public Sub SetLocation(ByVal Loc As String, Optional ByVal Warning As Boolean = False, _
                                Optional ByVal onDate As String = "", _
                                Optional ByVal email As String = "", _
                                Optional ByVal LastMoved As String = "")

    Dim SearchItems As Outlook.Items = Nothing
            Dim FoundItem As Outlook.AppointmentItem = Nothing
            Dim DAppItem As New ddlAppItem (its a class and having property as ApptItem having type as AppointmentItem)
            Dim CalendarFolderItems As Outlook.Items = Nothing

    Dim OurDate As Date = Nothing
            Dim DateProvided As Boolean = onDate.Length > 0
            If DateProvided Then
                OurDate = New Date(Left(onDate, 4), Mid(onDate, 6, 2), Mid(onDate, 9, 2))
            Else
                OurDate = Now
            End If
            If (LastMoved = "") Then LastMoved = Me.LastMoved
            Log("ddlMSOI setlocation: " + Loc)


    I have declared a global collection list which will hold the references of all the calendar folders and a key is associated with each entry in collection as a email address

    If LastMoved.Length > 0 Then
                Try
                    If (email <> "") Then
                        Dim index As Integer
                        For index = 1 To CalendarCollection.Count
                            If (CalendarCollection(index).EmailAddress = email) Then
                                CalendarFolderItems = CalendarCollection(index).FolderItems
                                Exit For
                            End If
                        Next
                    End If
                    SearchItems = CalendarFolderItems.Restrict("[DDL Reference] = '" & LastMoved & "' And [start] > '" & Format(DateAdd(DateInterval.Minute, -1, LastMovedTime), "dd-MMM-yyyy hh:mm") & "'")


    As you can see in above code , will try to find the calendar and then i will find out an Appointmentment having userproperty DDL Reference = LastMoved and will make sure its a future appointment.

    If SearchItems.Count > 0 Then

    DAppItem.AppItem = SearchItems(1) -- will point to master appointment item

    Dim Isrecurring As Boolean = DAppItem.AppItem.IsRecurring

    Dim App As Outlook.AppointmentItem = Nothing
               If Isrecurring And onDate.Length > 0 Then
               Dim rp As Outlook.RecurrencePattern = DAppItem.AppItem.GetRecurrencePattern()

    Try
         Dim start As Date = DAppItem.AppItem.Start
         App = rp.GetOccurrence(OurDate + " " + start.ToShortTimeString)
         Catch
         End Try
        if App Is Nothing Then App = GetException(rp, onDate)' see GetException definition below

    NAR(rp)
                            If Not App Is Nothing Then
                                FoundItem = App
                            Else
                                FoundItem = Nothing
                            End If
                        End If

    If Not FoundItem Is Nothing Then
                            If FoundItem.Location <> Loc Then
                                Dim msg As String = "Room "
                                Dim oldloc As String = FoundItem.Location
                                FoundItem.Location = Loc
                                FoundItem.Save() --- This should save the exception with the new location,currently it sometime does and sometime it do not

    If Warning Then
                                    If Loc = "No Room Booked" Then
                                        'No message - they already had it
                                        msg = ""
                                    ElseIf FoundItem.Location = "No Room Booked" Then
                                        msg = msg + "booking"
                                        If DateProvided Then msg = msg + " on " + Format(OurDate, "dd-MMM-yyyy")
                                        msg = msg + " has been reinstated in " + Loc
                                    ElseIf InStr(Loc, "(Waiting)") > 0 And InStr(oldloc, "(Waiting)") <= 0 Then
                                        msg = msg + "booking requested"
                                        If DateProvided Then msg = msg + " on " + Format(OurDate, "dd-MMM-yyyy")
                                        msg = msg + " and is on the waiting list"
                                    ElseIf InStr(Loc, "(Waiting)") <= 0 And InStr(oldloc, "(Waiting)") > 0 Then
                                        msg = msg + "booking has been confirmed in" + Loc
                                    Else
                                        msg = msg + oldloc + " not available at this time"
                                        If DateProvided Then msg = msg + " on " + Format(OurDate, "dd-MMM-yyyy")
                                        msg = msg + ".  Booking has been moved to " + Loc
                                    End If
                                End If

    The msg variable above is just to store the changed location of the Exception

    Dim meetingStatus As Outlook.OlMeetingStatus = FoundItem.MeetingStatus
                                If (meetingStatus = OlMeetingStatus.olMeeting) Then FoundItem.Send() --- if this happens then everything works fine  with the same code
                                NAR(FoundItem)

    Dim oldsignature As String = DAppItem.GetSignature
    Dim newsignature As String = DAppItem.BuildSignature

    For one ajax request,setLocation method will be called number of times depends on how many occurrences a particular recurring appointment have, so each time location string we have to save in userproperty and string in userproerty will keep on appending each time and will be used later after all occurences has been saved

    If you will see definition of BuildSignature() its calling another function GetRecurrenceProperties() , this function will try to get the all the properties of occurrences of same recurring appointment which we are currently updating in this function, and i found that after GetRecurrenceProperties() has been called and then when i try to save the master appointment item, it gives me really inconsistent behavior. sometime it left all occurrences not updated and sometime it updates all of them. this is the problem i am facing

    If (msg <> "" And Warning) Then
          If (Isrecurring) Then
             Dim oldmsg As String = Me.GetMsgProperty(SearchItems(1))
             Dim newmsg As String = oldmsg & Chr(10) & msg
             Me.SetMsgProperty(SearchItems(1), newmsg)
            If (oldsignature <> newsignature) Then DAppItem.SetSignature(newsignature)
            DAppItem.AppItem.Save()
       Else
              MsgBox("Room booking status for " + FoundItem.Subject + Chr(10) + Chr(10) + msg, MsgBoxStyle.OkOnly, "Datacraft Calendar Integration")
       End If

       End If
       End If
       End If
       Me.LastMoved = ""
       End If
       catch ex As System.Exception
          Log("Setlocation error: " + ex.Message)
         End Try
                'FoundItem.MeetingStatus = OlMeetingStatus.olNonMeeting
                NAR(FoundItem)
                NAR(DAppItem.AppItem)
                NAR(SearchItems)
                ReleaseMemory()
            End If
        End Sub


    Private Function GetException(ByVal rp As Outlook.RecurrencePattern, ByVal ExceptionDate As Date) As Outlook.AppointmentItem
            Dim Exceptions As Outlook.Exceptions = rp.Exceptions
            Dim RPex As Outlook.Exception = Nothing
            Dim App As Outlook.AppointmentItem = Nothing
            Dim e As Int16
            For e = 1 To Exceptions.Count
                RPex = Exceptions(e)
                If (Not RPex.Deleted) Then
                    App = RPex.AppointmentItem
                    If App.Start = ExceptionDate Then
                        NAR(RPex)
                        NAR(Exceptions)
                        Return App
                    Else
                        NAR(App)
                    End If
                End If
                NAR(RPex)
            Next
            NAR(Exceptions)
            Return Nothing
        End Function


    Public Function GetMsgProperty(ByVal item As AppointmentItem) As String
            Dim UserProperties As Outlook.UserProperties
            Dim MsgProperty As Outlook.UserProperty
            UserProperties = item.UserProperties
            MsgProperty = UserProperties.Find("MsgProperty")
            If MsgProperty Is Nothing Then
                GetMsgProperty = ""
            Else
                GetMsgProperty = MsgProperty.Value
            End If
            NAR(MsgProperty)
            NAR(UserProperties)
            ReleaseMemory()
        End Function

        Public Sub SetMsgProperty(ByVal item As AppointmentItem, ByVal msg As String)
            Dim UserProperties As Outlook.UserProperties
            Dim MsgProperty As Outlook.UserProperty
            UserProperties = item.UserProperties
            MsgProperty = UserProperties.Find("MsgProperty")
            If MsgProperty Is Nothing Then MsgProperty = UserProperties.Add("MsgProperty", OlUserPropertyType.olText)
            'Things that can be changed without opening the booking
            MsgProperty.Value = msg
            NAR(MsgProperty)
            NAR(UserProperties)
            ReleaseMemory()
        End Sub


    Public Function BuildSignature() As String BuildSignature = ToISO8601DateTime(AppItem.Start) & ToISO8601DateTime(AppItem.End) & AppItem.Subject If AppItem.IsRecurring Then BuildSignature = BuildSignature & GetRecurrenceProperties() End If End Function Public Function GetSignature() As String Dim UserProperties As Outlook.UserProperties Dim DDLSignature As Outlook.UserProperty UserProperties = AppItem.UserProperties DDLSignature = UserProperties.Find("DDL Signature") If DDLSignature Is Nothing Then GetSignature = "" Else GetSignature = DDLSignature.Value End If NAR(DDLSignature) NAR(UserProperties) ReleaseMemory() End Function Public Sub SetSignature(ByVal Signature As String) Dim UserProperties As Outlook.UserProperties Dim DDLSignature As Outlook.UserProperty UserProperties = AppItem.UserProperties DDLSignature = UserProperties.Find("DDL Signature") If DDLSignature Is Nothing Then DDLSignature = UserProperties.Add("DDL Signature", OlUserPropertyType.olText) 'Things that can be changed without opening the booking DDLSignature.Value = Signature NAR(DDLSignature) NAR(UserProperties) ReleaseMemory() End Sub

    Private Function GetRecurrenceProperties() As String
            Dim RP As Outlook.RecurrencePattern          'recurrence pattern object
    		Dim RPex As Outlook.Exception				 'exception object
            Dim jsonRP As String                         'holds json format string
            GetRecurrenceProperties = ""
            Try
                If AppItem.IsRecurring Then
                    RP = AppItem.GetRecurrencePattern
                    jsonRP = "{recurrenceType:\""" & CStr(RP.RecurrenceType) & "\"","
                    jsonRP = jsonRP & "recurrenceInterval:" & CStr(RP.Interval) & ","
                    jsonRP = jsonRP & "instance:" & CStr(RP.Instance) & ","
                    jsonRP = jsonRP & "startTime:\""" & CStr(RP.StartTime) & "\"","
                    jsonRP = jsonRP & "endTime:\""" & CStr(RP.EndTime) & "\"","
                    jsonRP = jsonRP & "patternStartDate:\""" & ToISO8601DateTime(RP.PatternStartDate) & "\"","
                    jsonRP = jsonRP & "patternEndDate:\""" & ToISO8601DateTime(RP.PatternEndDate) & "\"","
                    jsonRP = jsonRP & "occurrences:" & CStr(RP.Occurrences) & ","
                    jsonRP = jsonRP & "DOWMask:" & RP.DayOfWeekMask & ","
                    jsonRP = jsonRP & "DOM:" & RP.DayOfMonth & ","
                    jsonRP = jsonRP & "MOY:" & RP.MonthOfYear & ","
                    jsonRP = jsonRP & "exceptions: ["
                    ' Pass any exception dataf
    				Dim Exceptions As Outlook.Exceptions = RP.Exceptions
    				If Exceptions.Count > 0 Then
    					Dim e As Int16
    					For e = 1 To Exceptions.Count
    						RPex = Exceptions(e)
    						jsonRP = jsonRP & "{"
    						jsonRP = jsonRP & "rpexOriginalDate:\""" & ToISO8601DateTime(RPex.OriginalDate) & "\"","
    						If RPex.Deleted = False Then
    							Dim Exception As Outlook.AppointmentItem = RPex.AppointmentItem
    							jsonRP = jsonRP & "rpexDeleted: false,"
    							jsonRP = jsonRP & "rpexStart:\""" & ToISO8601DateTime(Exception.Start) & "\"","
    							jsonRP = jsonRP & "rpexEnd:\""" & ToISO8601DateTime(Exception.End) & "\"","
    							jsonRP = jsonRP & "rpexTitle:\""" & System.Net.WebUtility.HtmlEncode(Exception.Subject) & "\""},"
    							NAR(Exception)
    						Else
    							jsonRP = jsonRP & "rpexDeleted: true,"
    							jsonRP = jsonRP & "rpexStart:\""\"","
    							jsonRP = jsonRP & "rpexEnd:\""\"","
    							jsonRP = jsonRP & "rpexTitle:\""\""},"
    						End If
    						NAR(RPex)
    						ReleaseMemory()
    					Next
    				End If
    				NAR(Exceptions)
                    If Right(jsonRP, 1) = "," Then jsonRP = Left(jsonRP, Len(jsonRP) - 1)
                    jsonRP = jsonRP & "]}"
                    ' Tell Our page that we're done - object can be used
                    GetRecurrenceProperties = jsonRP
    				NAR(RP)
    				ReleaseMemory()
                End If
            Catch ex As System.Exception
                Log(ex.Message)
            End Try
        End Function
    
    Private Sub ReleaseMemory()
            Log("Memory used before collection: " & GC.GetTotalMemory(False))
            GC.Collect()
            GC.WaitForPendingFinalizers()
            GC.Collect()
            Log("Memory used after full collection: {1}: " & GC.GetTotalMemory(True))
            'CodeSite.AddSeparator()
        End Sub
    Public Sub NAR(ByVal o As Object)
            Dim Count As Integer = 1
            Try
                Count = System.Runtime.InteropServices.Marshal.ReleaseComObject(o)
                CodeSite.Send(Count & " Such" & o.GetType.ToString & "Left To Release")
                'End While
            Catch
            Finally
                o = Nothing
            End Try
        End Sub


     let me know what problem do you see in SetLocation, i am really struggling in fixing this.

    the same problem i am facing in item write event handler, each time when we update a recurring appointment, we have to update DDL Signature userproperty, and as you as can see its calling BuildSignature() also. if i remove BuildSignature() form everywhere location updates everytime

    Private Sub AppItem_Write(ByRef Cancel As Boolean) Handles AppItem.Write

                                               
                                                SetSignature(BuildSignature())
                                               
     End If

    Note that, Setlocation method will be called after write event handler has been excuted and  inspector has been closed, so if i remove BuildSignature() from above event handler, then location updated through setLocation updates correctly.

    I agrre, with my code items are being locked and not being release correctly , but where and how i do not know.

    I hope , i made you understand my problem this time.

    Thanks once again for your replies earlier.



    Ken Slovak MVP - Outlook
    Monday, June 18, 2012 6:35 PM
    Moderator
  • Ok ken, i will see what i can i do .

    Thanks for your help and valuable time.

    But before closing thread, can you give some tips on how we should loop through all the exceptions, like at what point we should release the exception, exceptions and recurrencepattern type object while looping through ,to make sure all com objects has been released during this loop execution.

    when we should call GC.Collect and GC.WaitForPendingFinalizers, is it ok if we call just at the end of calling function or everytime when we will release

    com objects?

    it will be better if you can give some snippet of code

    Thanks


    • Edited by Nitrup Tuesday, June 19, 2012 12:17 PM
    Tuesday, June 19, 2012 12:17 PM
  • All of this sort of thing is much more an art than a science in my experience. Generally in a case like that I'd make sure of each instance of objects I'd create and make sure to declare the objects outside any loops and then instantiate them inside the loops.
     
    In every loop pass I first start by nulling the objects and seeing if that's enough and I can avoid calling the GC repeatedly, as that's expensive in terms of time. If that isn't enough I call Marshal.ReleaseComObject() in every pass, then set the object to null. I'd try calling the GC not on every pass in the loop, but at intervals such as maybe every 30 or 100 passes in the loop. If that's not enough, I'd call the GC on each pass.
     
    If I was running into problems I'd probably start out with the most comprehensive types of nulling objects and make sure that fixed the problem. If it did I'd maybe try to back off a bit until the problem came back, assuming any performance problems surfaced.
     
    I'd avoid using Marshal.FinalReleaseComObject() until the end of the procedure, when the objects and their RCW's aren't needed any longer. Otherwise I'd expect to see RCW errors unless I declared a new object and instantiated it each time, which is really expensive.

    --
    Ken Slovak
    [MVP-Outlook]
    http://www.slovaktech.com
    Author: Professional Programming Outlook 2007
    "Nitrup" <=?utf-8?B?Tml0cnVw?=> wrote in message news:2897e0f7-a3bd-40e7-98bb-5f6ec766ef01...

    Ok ken, i will see what i can i do .

    Thanks for your help and valuable time.

    But before closing thread, can you give some tips on how we should loop through all the exceptions, like at what point we should release the exception, exceptions and recurrencepattern type object while looping through ,to make sure all com objects has been released during this loop execution.

    when we should call GC.Collect and GC.WaitForPendingFinalizers, is it ok if we call just at the end of calling function or everytime when we will release

    com objects?

    it will be better if you can give some snippet of code

    Thanks



    Ken Slovak MVP - Outlook
    • Marked as answer by Nitrup Tuesday, June 19, 2012 2:34 PM
    Tuesday, June 19, 2012 2:14 PM
    Moderator
  • Thanks Ken, really appreciate your reply. i will close this thread now and will see if applying above tips fix my problem or not.
    Tuesday, June 19, 2012 2:34 PM