Mapi-Restriction does not work on Exchange

P

Peter Marchert

Hello,

there is a problem with a restriction on a MapiTable object only with
Exchange. The following restriction works without problems for pst
files:

' This restricton search for all appointments which
' have not the field CONTACT_ENTRY_ID and the word
' "Test" in the subject or does have the field
' CONTACT_ENTRY_ID:

Set objRestrOR = objFilter.SetKind(RES_OR)
Set objRestrAND = objRestrOR.Add(RES_AND)

Set objRestrNOT = objRestrAND.Add(RES_NOT)
Set objRestrNOTEXIST = objRestrNOT.SetKind(RES_EXIST)
objRestrNOTEXIST.ulPropTag = CONTACT_ENTRY_ID

Set objRestrCONTENT = objRestrAND.Add(RES_CONTENT)
objRestrCONTENT.ulFuzzyLevel = FL_SUBSTRING Or FL_IGNORECASE
objRestrCONTENT.ulPropTag = PR_SUBJECT
objRestrCONTENT.lpProp = "Test"

Set objRestrEXIST = objRestrOR.Add(RES_EXIST)
objRestrEXIST.ulPropTag = CONTACT_ENTRY_ID

Same code on Exchange does nothing restrict and returns empty rows
(before the restriction the rows were not empty).

Peter
 
K

Ken Slovak - [MVP - Outlook]

What's CONTACT_ENTRY_ID, what property tag? Are you accounting for the
possibility with Exchange of short and long term entryid's?




Hello,

there is a problem with a restriction on a MapiTable object only with
Exchange. The following restriction works without problems for pst
files:

' This restricton search for all appointments which
' have not the field CONTACT_ENTRY_ID and the word
' "Test" in the subject or does have the field
' CONTACT_ENTRY_ID:

Set objRestrOR = objFilter.SetKind(RES_OR)
Set objRestrAND = objRestrOR.Add(RES_AND)

Set objRestrNOT = objRestrAND.Add(RES_NOT)
Set objRestrNOTEXIST = objRestrNOT.SetKind(RES_EXIST)
objRestrNOTEXIST.ulPropTag = CONTACT_ENTRY_ID

Set objRestrCONTENT = objRestrAND.Add(RES_CONTENT)
objRestrCONTENT.ulFuzzyLevel = FL_SUBSTRING Or FL_IGNORECASE
objRestrCONTENT.ulPropTag = PR_SUBJECT
objRestrCONTENT.lpProp = "Test"

Set objRestrEXIST = objRestrOR.Add(RES_EXIST)
objRestrEXIST.ulPropTag = CONTACT_ENTRY_ID

Same code on Exchange does nothing restrict and returns empty rows
(before the restriction the rows were not empty).

Peter
 
P

Peter Marchert

What's CONTACT_ENTRY_ID, what property tag?

It is a field created by my program with the entryid of a contact
(type: PT_STRING8).
Are you accounting for the possibility with Exchange of short and long term entryid's?

No, I don`t know the difference beteween short and long term entryids.

Thank you
Peter
--
Ken Slovak
[MVP - Outlook]http://www.slovaktech.com
Author: Professional Programming Outlook 2007
Reminder Manager, Extended Reminders, Attachment Optionshttp://www.slovaktech.com/products.htm


Hello,

there is a problem with a restriction on a MapiTable object only with
Exchange. The following restriction works without problems for pst
files:

' This restricton search for all appointments which
' have not the field CONTACT_ENTRY_ID and the word
' "Test" in the subject or does have the field
' CONTACT_ENTRY_ID:

Set objRestrOR = objFilter.SetKind(RES_OR)
Set objRestrAND = objRestrOR.Add(RES_AND)

Set objRestrNOT = objRestrAND.Add(RES_NOT)
Set objRestrNOTEXIST = objRestrNOT.SetKind(RES_EXIST)
objRestrNOTEXIST.ulPropTag = CONTACT_ENTRY_ID

Set objRestrCONTENT = objRestrAND.Add(RES_CONTENT)
objRestrCONTENT.ulFuzzyLevel = FL_SUBSTRING Or FL_IGNORECASE
objRestrCONTENT.ulPropTag = PR_SUBJECT
objRestrCONTENT.lpProp = "Test"

Set objRestrEXIST = objRestrOR.Add(RES_EXIST)
objRestrEXIST.ulPropTag = CONTACT_ENTRY_ID

Same code on Exchange does nothing restrict and returns empty rows
(before the restriction the rows were not empty).

Peter
 
K

Ken Slovak - [MVP - Outlook]

If this is a user property then short and long term id's don't apply.

Are you hard coding the property tag for that property or are you using a
call to a GetIdsFromNames method?

You should always use a call to a GetIdsFromNames method for anything other
than a standard Outlook property, even properties added by Outlook itself
such as ReminderSet. The numeric value of the property tag will differ from
store to store, and store provider to store provider.

If you request an EntryID from a PST provider you will always get the same
EntryID, that's a long-term id. If you request one from an Exchange server
you might get a short-term id that's only valid for that Outlook session. In
MAPI tables you always ask for both types of id's and check to see what gets
returned. Here's the type of code I usually use for that (VB6, I can show C#
code if you want):

Public Const PR_ENTRYID = &HFFF0102
Public Const PR_LONGTERM_ENTRYID_FROM_TABLE = &H66700102

varColumns(0) = PR_ENTRYID
varColumns(1) = PR_LONGTERM_ENTRYID_FROM_TABLE

strEntryID = ""

If rdmFilter.FindFirst(True) Then
Row = .GetRow
If Not IsEmpty(Row) Then
strEntryID = rdmUtils.HrArrayToString(Row(1)) 'long term

If strEntryID = "" Then
strEntryID = rdmUtils.HrArrayToString(Row(0)) 'short term
End If
End If




What's CONTACT_ENTRY_ID, what property tag?

It is a field created by my program with the entryid of a contact
(type: PT_STRING8).
Are you accounting for the possibility with Exchange of short and long
term entryid's?

No, I don`t know the difference beteween short and long term entryids.

Thank you
Peter
 
P

Peter Marchert

Yes, this was an own property created with a guid and I hard coded the
number tag by the hex value I spyed with Outlook Spy. This number tag
is different in pst and exchange. I tryed it with the GetIDsFromNames
and that works. This is my code to get the ID:

Private Function GetIdFromDaslProperty(ByVal strProperty As String) As
Long

Dim objItem As Object
Dim objSafeItem As Object
Dim PrProperty

On Error Resume Next

Set objSafeItem = CreateObject("Redemption.SafeMailItem")

Set objItem = g_objOutlook.CreateItem(olMailItem)

objSafeItem.Item = objItem

PrProperty = objSafeItem.GetIDsFromNames(DASLGUID, strProperty)

PrProperty = PrProperty + PT_STRING8

GetIdFromDaslProperty = PrProperty

Set objSafeItem.Item = Nothing
Set objSafeItem = Nothing
Set objItem = Nothing

End Function

Should this work reliably because I`m working with a unsaved mailitem?
In my test it works, but I´m not sure if it works on other machines/
configurations. Dmitry is working on the examples on his homepage with
the first item of a folder but may be the folder is empty.

Thanks for the code. PR_LONGTERM_ENTRYID_FROM_TABLE I cannot find in
Outlook Spy when opening a message on an exchange server. Where is
this property?

Last question: If a short entryid is only valid for the actual session
how can I store an id? Next time this Id may be different?
For example: Get the entryid of an contact and store it in an
appointmentitem. Outlook close and opens. Get this Id from the
appointmentitem and reference the contact. This should not work if I
understand this.

Thank you very much for your help!

Peter


If this is a user property then short and long term id's don't apply.

Are you hard coding the property tag for that property or are you using a
call to a GetIdsFromNames method?

You should always use a call to a GetIdsFromNames method for anything other
than a standard Outlook property, even properties added by Outlook itself
such as ReminderSet. The numeric value of the property tag will differ from
store to store, and store provider to store provider.

If you request an EntryID from a PST provider you will always get the same
EntryID, that's a long-term id. If you request one from an Exchange server
you might get a short-term id that's only valid for that Outlook session.In
MAPI tables you always ask for both types of id's and check to see what gets
returned. Here's the type of code I usually use for that (VB6, I can showC#
code if you want):

Public Const PR_ENTRYID = &HFFF0102
Public Const PR_LONGTERM_ENTRYID_FROM_TABLE = &H66700102

varColumns(0) = PR_ENTRYID
varColumns(1) = PR_LONGTERM_ENTRYID_FROM_TABLE

strEntryID = ""

If rdmFilter.FindFirst(True) Then
Row = .GetRow
If Not IsEmpty(Row) Then
strEntryID = rdmUtils.HrArrayToString(Row(1)) 'long term

If strEntryID = "" Then
strEntryID = rdmUtils.HrArrayToString(Row(0)) 'short term
End If
End If

--
Ken Slovak
[MVP - Outlook]http://www.slovaktech.com
Author: Professional Programming Outlook 2007
Reminder Manager, Extended Reminders, Attachment Optionshttp://www.slovaktech.com/products.htm


What's CONTACT_ENTRY_ID, what property tag?

It is a field created by my program with the entryid of a contact
(type: PT_STRING8).
Are you accounting for the possibility with Exchange of short and long
term entryid's?

No, I don`t know the difference beteween short and long term entryids.

Thank you
Peter
 
K

Ken Slovak - [MVP - Outlook]

I don't usually use the Safe* objects, I generally use the RDO objects, but
it's pretty much the same thing. I usually add a dummy item to a folder if
the folder is empty and I usually use something like
RDOFolder.GetIDsFromNames. I run that code every time the application runs
so I always get an accurate property tag value for the current store.

If you fall back to the OOM you will always get the long-term id, so
Outlook.MailItem.EntryID will always give you the long-term id. If you
retrieve a short-term id you just have to know not to cache it.

I've never seen PR_LONGTERM_ENTRYID_FROM_TABLE in OutlookSpy. I know about
it from Dmitry, and from reading the MAPI header files in the SDK.

One thing, if you use the code I showed on a PST file you will get back a
valid result only from PR_ENTRY_ID, PR_LONGTERM_ENTRYID_FROM_TABLE will
always be empty.

I usually prefer to work with saved items for stability reasons but a user
property added to an item should be OK, although of course if changes are
discarded the user property will also be discarded unless a save was called
at some point.




Yes, this was an own property created with a guid and I hard coded the
number tag by the hex value I spyed with Outlook Spy. This number tag
is different in pst and exchange. I tryed it with the GetIDsFromNames
and that works. This is my code to get the ID:

Private Function GetIdFromDaslProperty(ByVal strProperty As String) As
Long

Dim objItem As Object
Dim objSafeItem As Object
Dim PrProperty

On Error Resume Next

Set objSafeItem = CreateObject("Redemption.SafeMailItem")

Set objItem = g_objOutlook.CreateItem(olMailItem)

objSafeItem.Item = objItem

PrProperty = objSafeItem.GetIDsFromNames(DASLGUID, strProperty)

PrProperty = PrProperty + PT_STRING8

GetIdFromDaslProperty = PrProperty

Set objSafeItem.Item = Nothing
Set objSafeItem = Nothing
Set objItem = Nothing

End Function

Should this work reliably because I`m working with a unsaved mailitem?
In my test it works, but I´m not sure if it works on other machines/
configurations. Dmitry is working on the examples on his homepage with
the first item of a folder but may be the folder is empty.

Thanks for the code. PR_LONGTERM_ENTRYID_FROM_TABLE I cannot find in
Outlook Spy when opening a message on an exchange server. Where is
this property?

Last question: If a short entryid is only valid for the actual session
how can I store an id? Next time this Id may be different?
For example: Get the entryid of an contact and store it in an
appointmentitem. Outlook close and opens. Get this Id from the
appointmentitem and reference the contact. This should not work if I
understand this.

Thank you very much for your help!

Peter
 
D

Dmitry Streblechenko

You might want to try the new (for version 4.4) MAPITable.ExecSQL method -
you will be able to specify the conditions in the SQL format and specify the
property names in the DASL (or OOM) format.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool

Yes, this was an own property created with a guid and I hard coded the
number tag by the hex value I spyed with Outlook Spy. This number tag
is different in pst and exchange. I tryed it with the GetIDsFromNames
and that works. This is my code to get the ID:

Private Function GetIdFromDaslProperty(ByVal strProperty As String) As
Long

Dim objItem As Object
Dim objSafeItem As Object
Dim PrProperty

On Error Resume Next

Set objSafeItem = CreateObject("Redemption.SafeMailItem")

Set objItem = g_objOutlook.CreateItem(olMailItem)

objSafeItem.Item = objItem

PrProperty = objSafeItem.GetIDsFromNames(DASLGUID, strProperty)

PrProperty = PrProperty + PT_STRING8

GetIdFromDaslProperty = PrProperty

Set objSafeItem.Item = Nothing
Set objSafeItem = Nothing
Set objItem = Nothing

End Function

Should this work reliably because I`m working with a unsaved mailitem?
In my test it works, but I´m not sure if it works on other machines/
configurations. Dmitry is working on the examples on his homepage with
the first item of a folder but may be the folder is empty.

Thanks for the code. PR_LONGTERM_ENTRYID_FROM_TABLE I cannot find in
Outlook Spy when opening a message on an exchange server. Where is
this property?

Last question: If a short entryid is only valid for the actual session
how can I store an id? Next time this Id may be different?
For example: Get the entryid of an contact and store it in an
appointmentitem. Outlook close and opens. Get this Id from the
appointmentitem and reference the contact. This should not work if I
understand this.

Thank you very much for your help!

Peter


If this is a user property then short and long term id's don't apply.

Are you hard coding the property tag for that property or are you using a
call to a GetIdsFromNames method?

You should always use a call to a GetIdsFromNames method for anything
other
than a standard Outlook property, even properties added by Outlook itself
such as ReminderSet. The numeric value of the property tag will differ
from
store to store, and store provider to store provider.

If you request an EntryID from a PST provider you will always get the same
EntryID, that's a long-term id. If you request one from an Exchange server
you might get a short-term id that's only valid for that Outlook session.
In
MAPI tables you always ask for both types of id's and check to see what
gets
returned. Here's the type of code I usually use for that (VB6, I can show
C#
code if you want):

Public Const PR_ENTRYID = &HFFF0102
Public Const PR_LONGTERM_ENTRYID_FROM_TABLE = &H66700102

varColumns(0) = PR_ENTRYID
varColumns(1) = PR_LONGTERM_ENTRYID_FROM_TABLE

strEntryID = ""

If rdmFilter.FindFirst(True) Then
Row = .GetRow
If Not IsEmpty(Row) Then
strEntryID = rdmUtils.HrArrayToString(Row(1)) 'long term

If strEntryID = "" Then
strEntryID = rdmUtils.HrArrayToString(Row(0)) 'short term
End If
End If

--
Ken Slovak
[MVP - Outlook]http://www.slovaktech.com
Author: Professional Programming Outlook 2007
Reminder Manager, Extended Reminders, Attachment
Optionshttp://www.slovaktech.com/products.htm


What's CONTACT_ENTRY_ID, what property tag?

It is a field created by my program with the entryid of a contact
(type: PT_STRING8).
Are you accounting for the possibility with Exchange of short and long
term entryid's?

No, I don`t know the difference beteween short and long term entryids.

Thank you
Peter
 
P

Peter Marchert

Thanks for all answers.

I use on some procedures the ExcecSQL method but it seems to be slower
than the restriction method? The code with the restriction is called
aproximately 100 times per second (or more). I create/change
appointments by looping through contact items. And on any item I have
to check if the appointment already exists.

Seems that one question is missing or I didn`t understand all answers:
Can I use the short entryid getting from an Exchange server to
reference a contact in a future Outlook session? Or is thi only the
case by using Mapi? Ken wrote in OOM I always get the long entryid but
I`m not sure if this is on Exchange so too.

Thanks Ken and Dmirty!
Peter

You might want to try the new (for version 4.4) MAPITable.ExecSQL method -
you will be able to specify the conditions in the SQL format and specify the
property names in the DASL (or OOM) format.

Dmitry Streblechenko (MVP)http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool


Yes, this was an own property created with a guid and I hard coded the
number tag by the hex value I spyed with Outlook Spy. This number tag
is different in pst and exchange. I tryed it with the GetIDsFromNames
and that works. This is my code to get the ID:

Private Function GetIdFromDaslProperty(ByVal strProperty As String) As
Long

Dim objItem As Object
Dim objSafeItem As Object
Dim PrProperty

On Error Resume Next

Set objSafeItem = CreateObject("Redemption.SafeMailItem")

Set objItem = g_objOutlook.CreateItem(olMailItem)

objSafeItem.Item = objItem

PrProperty = objSafeItem.GetIDsFromNames(DASLGUID, strProperty)

PrProperty = PrProperty + PT_STRING8

GetIdFromDaslProperty = PrProperty

Set objSafeItem.Item = Nothing
Set objSafeItem = Nothing
Set objItem = Nothing

End Function

Should this work reliably because I`m working with a unsaved mailitem?
In my test it works, but I´m not sure if it works on other machines/
configurations. Dmitry is working on the examples on his homepage with
the first item of a folder but may be the folder is empty.

Thanks for the code. PR_LONGTERM_ENTRYID_FROM_TABLE I cannot find in
Outlook Spy when opening a message on an exchange server. Where is
this property?

Last question: If a short entryid is only valid for the actual session
how can I store an id? Next time this Id may be different?
For example: Get the entryid of an contact and store it in an
appointmentitem. Outlook close and opens. Get this Id from the
appointmentitem and reference the contact. This should not work if I
understand this.

Thank you very much for your help!

Peter

If this is a user property then short and long term id's don't apply.
Are you hard coding the property tag for that property or are you usinga
call to a GetIdsFromNames method?
You should always use a call to a GetIdsFromNames method for anything
other
than a standard Outlook property, even properties added by Outlook itself
such as ReminderSet. The numeric value of the property tag will differ
from
store to store, and store provider to store provider.
If you request an EntryID from a PST provider you will always get the same
EntryID, that's a long-term id. If you request one from an Exchange server
you might get a short-term id that's only valid for that Outlook session.
In
MAPI tables you always ask for both types of id's and check to see what
gets
returned. Here's the type of code I usually use for that (VB6, I can show
C#
code if you want):
Public Const PR_ENTRYID = &HFFF0102
Public Const PR_LONGTERM_ENTRYID_FROM_TABLE = &H66700102
varColumns(0) = PR_ENTRYID
varColumns(1) = PR_LONGTERM_ENTRYID_FROM_TABLE
strEntryID = ""
If rdmFilter.FindFirst(True) Then
Row = .GetRow
If Not IsEmpty(Row) Then
strEntryID = rdmUtils.HrArrayToString(Row(1)) 'long term
If strEntryID = "" Then
strEntryID = rdmUtils.HrArrayToString(Row(0)) 'short term
End If
End If
--
Ken Slovak
[MVP - Outlook]http://www.slovaktech.com
Author: Professional Programming Outlook 2007
Reminder Manager, Extended Reminders, Attachment
Optionshttp://www.slovaktech.com/products.htm
"Peter Marchert" <[email protected]> wrote in message
On 4 Okt., 15:43, "Ken Slovak - [MVP - Outlook]" <[email protected]>
wrote:
What's CONTACT_ENTRY_ID, what property tag?
It is a field created by my program with the entryid of a contact
(type: PT_STRING8).
No, I don`t know the difference beteween short and long term entryids.
Thank you
Peter- Zitierten Text ausblenden -

- Zitierten Text anzeigen -
 
K

Ken Slovak - [MVP - Outlook]

Using the Outlook object model you always get an EntryID that can be
persisted. Where you have to look out for short-term id's that are only
valid for that session is in MAPI (and Redemption). Even CDO 1.21 only
returns long-term id's.

I can't speak to the speed of ExecSQL as opposed to using a MAPI
restriction, I've only used ExecSQL in tests and in playing with things to
get the bugs squashed out of ExecSQL. I always use MAPI restrictions myself.

Dmitry can speak to the relative speed of ExecSQL better than I can.




Thanks for all answers.

I use on some procedures the ExcecSQL method but it seems to be slower
than the restriction method? The code with the restriction is called
aproximately 100 times per second (or more). I create/change
appointments by looping through contact items. And on any item I have
to check if the appointment already exists.

Seems that one question is missing or I didn`t understand all answers:
Can I use the short entryid getting from an Exchange server to
reference a contact in a future Outlook session? Or is thi only the
case by using Mapi? Ken wrote in OOM I always get the long entryid but
I`m not sure if this is on Exchange so too.

Thanks Ken and Dmirty!
Peter
 
D

Dmitry Streblechenko

How much slower? Keep in mind that calling Restrict() will cause the
restriction to be persisted on the Exchange Server (if that is waht you are
using) potentially causing a severe performance degradation. ExecSQL
collects rows one at a time avoiding IMAPITable::Restrict() MAPI call.
You can also always use RDOItems.Restrict - it takes a SQL expression and
returns a restricted collection.
If you know there will always be only or at most one item returned, use
RDOItems.Find, followed by (if you expect more items) FindNext.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool

Thanks for all answers.

I use on some procedures the ExcecSQL method but it seems to be slower
than the restriction method? The code with the restriction is called
aproximately 100 times per second (or more). I create/change
appointments by looping through contact items. And on any item I have
to check if the appointment already exists.

Seems that one question is missing or I didn`t understand all answers:
Can I use the short entryid getting from an Exchange server to
reference a contact in a future Outlook session? Or is thi only the
case by using Mapi? Ken wrote in OOM I always get the long entryid but
I`m not sure if this is on Exchange so too.

Thanks Ken and Dmirty!
Peter

You might want to try the new (for version 4.4) MAPITable.ExecSQL method -
you will be able to specify the conditions in the SQL format and specify
the
property names in the DASL (or OOM) format.

Dmitry Streblechenko (MVP)http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool


Yes, this was an own property created with a guid and I hard coded the
number tag by the hex value I spyed with Outlook Spy. This number tag
is different in pst and exchange. I tryed it with the GetIDsFromNames
and that works. This is my code to get the ID:

Private Function GetIdFromDaslProperty(ByVal strProperty As String) As
Long

Dim objItem As Object
Dim objSafeItem As Object
Dim PrProperty

On Error Resume Next

Set objSafeItem = CreateObject("Redemption.SafeMailItem")

Set objItem = g_objOutlook.CreateItem(olMailItem)

objSafeItem.Item = objItem

PrProperty = objSafeItem.GetIDsFromNames(DASLGUID, strProperty)

PrProperty = PrProperty + PT_STRING8

GetIdFromDaslProperty = PrProperty

Set objSafeItem.Item = Nothing
Set objSafeItem = Nothing
Set objItem = Nothing

End Function

Should this work reliably because I`m working with a unsaved mailitem?
In my test it works, but I´m not sure if it works on other machines/
configurations. Dmitry is working on the examples on his homepage with
the first item of a folder but may be the folder is empty.

Thanks for the code. PR_LONGTERM_ENTRYID_FROM_TABLE I cannot find in
Outlook Spy when opening a message on an exchange server. Where is
this property?

Last question: If a short entryid is only valid for the actual session
how can I store an id? Next time this Id may be different?
For example: Get the entryid of an contact and store it in an
appointmentitem. Outlook close and opens. Get this Id from the
appointmentitem and reference the contact. This should not work if I
understand this.

Thank you very much for your help!

Peter

If this is a user property then short and long term id's don't apply.
Are you hard coding the property tag for that property or are you using
a
call to a GetIdsFromNames method?
You should always use a call to a GetIdsFromNames method for anything
other
than a standard Outlook property, even properties added by Outlook
itself
such as ReminderSet. The numeric value of the property tag will differ
from
store to store, and store provider to store provider.
If you request an EntryID from a PST provider you will always get the
same
EntryID, that's a long-term id. If you request one from an Exchange
server
you might get a short-term id that's only valid for that Outlook
session.
In
MAPI tables you always ask for both types of id's and check to see what
gets
returned. Here's the type of code I usually use for that (VB6, I can
show
C#
code if you want):
Public Const PR_ENTRYID = &HFFF0102
Public Const PR_LONGTERM_ENTRYID_FROM_TABLE = &H66700102
varColumns(0) = PR_ENTRYID
varColumns(1) = PR_LONGTERM_ENTRYID_FROM_TABLE
strEntryID = ""
If rdmFilter.FindFirst(True) Then
Row = .GetRow
If Not IsEmpty(Row) Then
strEntryID = rdmUtils.HrArrayToString(Row(1)) 'long term
If strEntryID = "" Then
strEntryID = rdmUtils.HrArrayToString(Row(0)) 'short term
End If
End If
--
Ken Slovak
[MVP - Outlook]http://www.slovaktech.com
Author: Professional Programming Outlook 2007
Reminder Manager, Extended Reminders, Attachment
Optionshttp://www.slovaktech.com/products.htm
"Peter Marchert" <[email protected]> wrote in message
On 4 Okt., 15:43, "Ken Slovak - [MVP - Outlook]" <[email protected]>
wrote:
What's CONTACT_ENTRY_ID, what property tag?
It is a field created by my program with the entryid of a contact
(type: PT_STRING8).
No, I don`t know the difference beteween short and long term entryids.
Thank you
Peter- Zitierten Text ausblenden -

- Zitierten Text anzeigen -
 
P

Peter Marchert

How much slower?

Hmm, I don`t know. I didn´t compare times by the same code with
different methods. May be there is no significant difference.

Thanks for the hint to the Find/FindNext method. I use this method in
the creation/change code and the restrict method in a function which
is not very often used.

But here is the next problem:

Public Function FindAppointment(ByVal objCalendar As Object, ByVal
strEntryID As String) As Boolean

Const RES_AND As Long = 0
Const RES_NOT As Long = 2
Const RES_OR As Long = 1
Const RES_EXIST As Long = 8
Const RES_CONTENT As Long = 3
Const FL_SUBSTRING As Long = 1
Const FL_IGNORECASE As Long = &H10000

Const PR_SUBJECT As Long = &H37001E
Const PR_ENTRYID As Long = &HFFF0102

Dim CONTACT_ENTRY_ID As Long

Dim objRDOSession As Object
Dim objUtils As Object
Dim objRow
Dim objFilter
Dim objTable

Dim objAppointment As Outlook.AppointmentItem

Dim Columns(1)
Dim objRestrOR, objRestrAND1, objRestrAND2, objRestr1
Dim objRestr1a, objRestr1b, objRestr2, objRestr2a, objRestr2b

Dim strStoreID As String

CONTACT_ENTRY_ID = GetIdFromDaslProperty("ContactEntryID")
strStoreID = objCalendar.StoreID

Set objRDOSession = CreateObject("SafeOutlook.SecureRDOSession")
objRDOSession.Logon "", "", False, False, 0

Set objUtils = CreateObject("SafeOutlook.SecureMAPIUtils")
Set objTable = CreateObject("SafeOutlook.SecureMAPITable")

objTable.Item = objRDOSession.GetFolderFromID(objCalendar.EntryID,
objCalendar.StoreID).Items

Set objFilter = objTable.Filter

objFilter.Clear

Set objRestrOR = objFilter.SetKind(RES_OR)
Set objRestrAND1 = objRestrOR.Add(RES_AND)

Set objRestr1 = objRestrAND1.Add(RES_NOT)
Set objRestr1a = objRestr1.SetKind(RES_EXIST)
objRestr1a.ulPropTag = CONTACT_ENTRY_ID

Set objRestr1b = objRestrAND1.Add(RES_CONTENT)
objRestr1b.ulFuzzyLevel = FL_SUBSTRING Or FL_IGNORECASE
objRestr1b.ulPropTag = PR_SUBJECT
objRestr1b.lpProp = "Geburtstag von"

Set objRestrAND2 = objRestrOR.Add(RES_AND)

Set objRestr2a = objRestrAND2.Add(RES_EXIST)
objRestr2a.ulPropTag = CONTACT_ENTRY_ID

Set objRestr2b = objRestrAND2.Add(RES_CONTENT)
objRestr2b.ulFuzzyLevel = FL_SUBSTRING Or FL_IGNORECASE
objRestr2b.ulPropTag = CONTACT_ENTRY_ID
objRestr2b.lpProp = strEntryID

Columns(0) = PR_ENTRYID
Columns(1) = CONTACT_ENTRY_ID

objTable.Columns = Columns

If objFilter.FindFirst(True) Then

Do

objRow = objTable.GetRow

If Not IsEmpty(objRow) Then
Set objAppointment =
Outlook.Session.GetItemFromID(objUtils.HrArrayToString(objRow(0)),
strStoreID)
' Error: -2147221241 (80040107)
End If

Loop Until Not objFilter.FindNext(True)

End If

End Function

Interesting is the line "Set objAppointment = ...". Here araise an
error in 2007 if the folder (objCalendar) is a public folder. Same
item in the default calendar of the users mail box can be created with
out error. The item can also be created in a public folder with
2002/2003.

I´m not the Mapi-Expert and tell you only something what I have tried.
In 2002/2003 I use for RDOSessions the MAPIOBJECT method and for
2000/2007 I use the logon method. In 2000 there is no MAPIOBJECT so
there is no choose. If in 2007 I use the MAPIOBJECT some strange
things happens and will not work as expected. For example if a
RDOSession was started the user cannot longer access his folders and
have to restart Outlook. That`s the reasen to use the logon method.
Ok, but with this method the described error occurs.

Please help!

Peter

How much slower? Keep in mind that calling Restrict() will cause the
restriction to be persisted on the Exchange Server (if that is waht you are
using) potentially causing a severe performance degradation. ExecSQL
collects rows one at a time avoiding IMAPITable::Restrict() MAPI call.
You can also always use RDOItems.Restrict - it takes a SQL expression and
returns a restricted collection.
If you know there will always be only or at most one item returned, use
RDOItems.Find, followed by (if you expect more items) FindNext.

Dmitry Streblechenko (MVP)http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool


Thanks for all answers.

I use on some procedures the ExcecSQL method but it seems to be slower
than the restriction method? The code with the restriction is called
aproximately 100 times per second (or more). I create/change
appointments by looping through contact items. And on any item I have
to check if the appointment already exists.

Seems that one question is missing or I didn`t understand all answers:
Can I use the short entryid getting from an Exchange server to
reference a contact in a future Outlook session? Or is thi only the
case by using Mapi? Ken wrote in OOM I always get the long entryid but
I`m not sure if this is on Exchange so too.

Thanks Ken and Dmirty!
Peter

You might want to try the new (for version 4.4) MAPITable.ExecSQL method -
you will be able to specify the conditions in the SQL format and specify
the
property names in the DASL (or OOM) format.
Dmitry Streblechenko (MVP)http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
"Peter Marchert" <[email protected]> wrote in message
Yes, this was an own property created with a guid and I hard coded the
number tag by the hex value I spyed with Outlook Spy. This number tag
is different in pst and exchange. I tryed it with the GetIDsFromNames
and that works. This is my code to get the ID:
Private Function GetIdFromDaslProperty(ByVal strProperty As String) As
Long
Dim objItem As Object
Dim objSafeItem As Object
Dim PrProperty
On Error Resume Next
Set objSafeItem = CreateObject("Redemption.SafeMailItem")
Set objItem = g_objOutlook.CreateItem(olMailItem)
objSafeItem.Item = objItem
PrProperty = objSafeItem.GetIDsFromNames(DASLGUID, strProperty)
PrProperty = PrProperty + PT_STRING8
GetIdFromDaslProperty = PrProperty
Set objSafeItem.Item = Nothing
Set objSafeItem = Nothing
Set objItem = Nothing
End Function
Should this work reliably because I`m working with a unsaved mailitem?
In my test it works, but I´m not sure if it works on other machines/
configurations. Dmitry is working on the examples on his homepage with
the first item of a folder but may be the folder is empty.
Thanks for the code. PR_LONGTERM_ENTRYID_FROM_TABLE I cannot find in
Outlook Spy when opening a message on an exchange server. Where is
this property?
Last question: If a short entryid is only valid for the actual session
how can I store an id? Next time this Id may be different?
For example: Get the entryid of an contact and store it in an
appointmentitem. Outlook close and opens. Get this Id from the
appointmentitem and reference the contact. This should not work if I
understand this.
Thank you very much for your help!

On 4 Okt., 17:18, "Ken Slovak - [MVP - Outlook]" <[email protected]>
wrote:
If this is a user property then short and long term id's don't apply.
Are you hard coding the property tag for that property or are you using
a
call to a GetIdsFromNames method?
You should always use a call to a GetIdsFromNames method for anything
other
than a standard Outlook property, even properties added by Outlook
itself
such as ReminderSet. The numeric value of the property tag will differ
from
store to store, and store provider to store provider.
If you request an EntryID from a PST provider you will always get the
same
EntryID, that's a long-term id. If you request one from an Exchange
server
you might get a short-term id that's only valid for that Outlook
session.
In
MAPI tables you always ask for both types of id's and check to see what
gets
returned. Here's the type of code I usually use for that (VB6, I can
show
C#
code if you want):
Public Const PR_ENTRYID = &HFFF0102
Public Const PR_LONGTERM_ENTRYID_FROM_TABLE = &H66700102
varColumns(0) = PR_ENTRYID
varColumns(1) = PR_LONGTERM_ENTRYID_FROM_TABLE
strEntryID = ""
If rdmFilter.FindFirst(True) Then
Row = .GetRow
If Not IsEmpty(Row) Then
strEntryID = rdmUtils.HrArrayToString(Row(1)) 'long term
If strEntryID = "" Then
strEntryID = rdmUtils.HrArrayToString(Row(0)) 'short term
End If
End If
--
Ken Slovak
[MVP - Outlook]http://www.slovaktech.com
Author: Professional Programming Outlook 2007
Reminder Manager, Extended Reminders, Attachment
Optionshttp://www.slovaktech.com/products.htm
On 4 Okt., 15:43, "Ken Slovak - [MVP - Outlook]" <[email protected]>
wrote:
What's CONTACT_ENTRY_ID, what property tag?
It is a field created by my program with the entryid of a contact
(type: PT_STRING8).
Are you accounting for the possibility with Exchange of short and long
term entryid's?
No, I don`t know the difference beteween short and long term entryids.
Thank you
Peter- Zitierten Text ausblenden -
- Zitierten Text anzeigen -- Zitierten Text ausblenden -

- Zitierten Text anzeigen -
 
P

Peter Marchert

Thank you Dan for this link. If I have more time and don`t forget this
post I will study this kb.

Peter
 
D

Dmitry Streblechenko

What is the exact error? Are you sure the item in question is really an
appointment?
The fact that you Outlook says that it can no longer display the folder
contents is a very strong indication taht you are calling RDOSession.Logoff,
which you should never be doing if you are using a shared session.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool

Peter Marchert said:
How much slower?

Hmm, I don`t know. I didn´t compare times by the same code with
different methods. May be there is no significant difference.

Thanks for the hint to the Find/FindNext method. I use this method in
the creation/change code and the restrict method in a function which
is not very often used.

But here is the next problem:

Public Function FindAppointment(ByVal objCalendar As Object, ByVal
strEntryID As String) As Boolean

Const RES_AND As Long = 0
Const RES_NOT As Long = 2
Const RES_OR As Long = 1
Const RES_EXIST As Long = 8
Const RES_CONTENT As Long = 3
Const FL_SUBSTRING As Long = 1
Const FL_IGNORECASE As Long = &H10000

Const PR_SUBJECT As Long = &H37001E
Const PR_ENTRYID As Long = &HFFF0102

Dim CONTACT_ENTRY_ID As Long

Dim objRDOSession As Object
Dim objUtils As Object
Dim objRow
Dim objFilter
Dim objTable

Dim objAppointment As Outlook.AppointmentItem

Dim Columns(1)
Dim objRestrOR, objRestrAND1, objRestrAND2, objRestr1
Dim objRestr1a, objRestr1b, objRestr2, objRestr2a, objRestr2b

Dim strStoreID As String

CONTACT_ENTRY_ID = GetIdFromDaslProperty("ContactEntryID")
strStoreID = objCalendar.StoreID

Set objRDOSession = CreateObject("SafeOutlook.SecureRDOSession")
objRDOSession.Logon "", "", False, False, 0

Set objUtils = CreateObject("SafeOutlook.SecureMAPIUtils")
Set objTable = CreateObject("SafeOutlook.SecureMAPITable")

objTable.Item = objRDOSession.GetFolderFromID(objCalendar.EntryID,
objCalendar.StoreID).Items

Set objFilter = objTable.Filter

objFilter.Clear

Set objRestrOR = objFilter.SetKind(RES_OR)
Set objRestrAND1 = objRestrOR.Add(RES_AND)

Set objRestr1 = objRestrAND1.Add(RES_NOT)
Set objRestr1a = objRestr1.SetKind(RES_EXIST)
objRestr1a.ulPropTag = CONTACT_ENTRY_ID

Set objRestr1b = objRestrAND1.Add(RES_CONTENT)
objRestr1b.ulFuzzyLevel = FL_SUBSTRING Or FL_IGNORECASE
objRestr1b.ulPropTag = PR_SUBJECT
objRestr1b.lpProp = "Geburtstag von"

Set objRestrAND2 = objRestrOR.Add(RES_AND)

Set objRestr2a = objRestrAND2.Add(RES_EXIST)
objRestr2a.ulPropTag = CONTACT_ENTRY_ID

Set objRestr2b = objRestrAND2.Add(RES_CONTENT)
objRestr2b.ulFuzzyLevel = FL_SUBSTRING Or FL_IGNORECASE
objRestr2b.ulPropTag = CONTACT_ENTRY_ID
objRestr2b.lpProp = strEntryID

Columns(0) = PR_ENTRYID
Columns(1) = CONTACT_ENTRY_ID

objTable.Columns = Columns

If objFilter.FindFirst(True) Then

Do

objRow = objTable.GetRow

If Not IsEmpty(objRow) Then
Set objAppointment =
Outlook.Session.GetItemFromID(objUtils.HrArrayToString(objRow(0)),
strStoreID)
' Error: -2147221241 (80040107)
End If

Loop Until Not objFilter.FindNext(True)

End If

End Function

Interesting is the line "Set objAppointment = ...". Here araise an
error in 2007 if the folder (objCalendar) is a public folder. Same
item in the default calendar of the users mail box can be created with
out error. The item can also be created in a public folder with
2002/2003.

I´m not the Mapi-Expert and tell you only something what I have tried.
In 2002/2003 I use for RDOSessions the MAPIOBJECT method and for
2000/2007 I use the logon method. In 2000 there is no MAPIOBJECT so
there is no choose. If in 2007 I use the MAPIOBJECT some strange
things happens and will not work as expected. For example if a
RDOSession was started the user cannot longer access his folders and
have to restart Outlook. That`s the reasen to use the logon method.
Ok, but with this method the described error occurs.

Please help!

Peter

How much slower? Keep in mind that calling Restrict() will cause the
restriction to be persisted on the Exchange Server (if that is waht you
are
using) potentially causing a severe performance degradation. ExecSQL
collects rows one at a time avoiding IMAPITable::Restrict() MAPI call.
You can also always use RDOItems.Restrict - it takes a SQL expression and
returns a restricted collection.
If you know there will always be only or at most one item returned, use
RDOItems.Find, followed by (if you expect more items) FindNext.

Dmitry Streblechenko (MVP)http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool


Thanks for all answers.

I use on some procedures the ExcecSQL method but it seems to be slower
than the restriction method? The code with the restriction is called
aproximately 100 times per second (or more). I create/change
appointments by looping through contact items. And on any item I have
to check if the appointment already exists.

Seems that one question is missing or I didn`t understand all answers:
Can I use the short entryid getting from an Exchange server to
reference a contact in a future Outlook session? Or is thi only the
case by using Mapi? Ken wrote in OOM I always get the long entryid but
I`m not sure if this is on Exchange so too.

Thanks Ken and Dmirty!
Peter

You might want to try the new (for version 4.4) MAPITable.ExecSQL
method -
you will be able to specify the conditions in the SQL format and specify
the
property names in the DASL (or OOM) format.
Dmitry Streblechenko (MVP)http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
"Peter Marchert" <[email protected]> wrote in message
Yes, this was an own property created with a guid and I hard coded the
number tag by the hex value I spyed with Outlook Spy. This number tag
is different in pst and exchange. I tryed it with the GetIDsFromNames
and that works. This is my code to get the ID:
Private Function GetIdFromDaslProperty(ByVal strProperty As String) As
Long
Dim objItem As Object
Dim objSafeItem As Object
Dim PrProperty
On Error Resume Next
Set objSafeItem = CreateObject("Redemption.SafeMailItem")
Set objItem = g_objOutlook.CreateItem(olMailItem)
objSafeItem.Item = objItem
PrProperty = objSafeItem.GetIDsFromNames(DASLGUID, strProperty)
PrProperty = PrProperty + PT_STRING8
GetIdFromDaslProperty = PrProperty
Set objSafeItem.Item = Nothing
Set objSafeItem = Nothing
Set objItem = Nothing
End Function
Should this work reliably because I`m working with a unsaved mailitem?
In my test it works, but I´m not sure if it works on other machines/
configurations. Dmitry is working on the examples on his homepage with
the first item of a folder but may be the folder is empty.
Thanks for the code. PR_LONGTERM_ENTRYID_FROM_TABLE I cannot find in
Outlook Spy when opening a message on an exchange server. Where is
this property?
Last question: If a short entryid is only valid for the actual session
how can I store an id? Next time this Id may be different?
For example: Get the entryid of an contact and store it in an
appointmentitem. Outlook close and opens. Get this Id from the
appointmentitem and reference the contact. This should not work if I
understand this.
Thank you very much for your help!

On 4 Okt., 17:18, "Ken Slovak - [MVP - Outlook]" <[email protected]>
wrote:
If this is a user property then short and long term id's don't apply.
Are you hard coding the property tag for that property or are you
using
a
call to a GetIdsFromNames method?
You should always use a call to a GetIdsFromNames method for anything
other
than a standard Outlook property, even properties added by Outlook
itself
such as ReminderSet. The numeric value of the property tag will differ
from
store to store, and store provider to store provider.
If you request an EntryID from a PST provider you will always get the
same
EntryID, that's a long-term id. If you request one from an Exchange
server
you might get a short-term id that's only valid for that Outlook
session.
In
MAPI tables you always ask for both types of id's and check to see
what
gets
returned. Here's the type of code I usually use for that (VB6, I can
show
C#
code if you want):
Public Const PR_ENTRYID = &HFFF0102
Public Const PR_LONGTERM_ENTRYID_FROM_TABLE = &H66700102
varColumns(0) = PR_ENTRYID
varColumns(1) = PR_LONGTERM_ENTRYID_FROM_TABLE
strEntryID = ""
If rdmFilter.FindFirst(True) Then
Row = .GetRow
If Not IsEmpty(Row) Then
strEntryID = rdmUtils.HrArrayToString(Row(1)) 'long term
If strEntryID = "" Then
strEntryID = rdmUtils.HrArrayToString(Row(0)) 'short term
End If
End If
--
Ken Slovak
[MVP - Outlook]http://www.slovaktech.com
Author: Professional Programming Outlook 2007
Reminder Manager, Extended Reminders, Attachment
Optionshttp://www.slovaktech.com/products.htm
On 4 Okt., 15:43, "Ken Slovak - [MVP - Outlook]" <[email protected]>
wrote:
What's CONTACT_ENTRY_ID, what property tag?
It is a field created by my program with the entryid of a contact
(type: PT_STRING8).
Are you accounting for the possibility with Exchange of short and
long
term entryid's?
No, I don`t know the difference beteween short and long term entryids.
Thank you
Peter- Zitierten Text ausblenden -
- Zitierten Text anzeigen -- Zitierten Text ausblenden -

- Zitierten Text anzeigen -
 
P

Peter Marchert

Thank you for your answer, Dmitry.

The error (translated by google) is "-2147221241 (80040107): A client
procedure failed". Yes, the item is an appointmentitem.

Thanks for the hint with the logoff method. I used this method because
in 2002/2003 this works fine. But now I commented the lines to logoff
out and the MAPIOBJECT works in 2007 as well. Now it is possible to
create the appointment in a public folder too.

Thank you!
Peter

What is the exact error? Are you sure the item in question is really an
appointment?
The fact that you Outlook says that it can no longer display the folder
contents is a very strong indication taht you are calling RDOSession.Logoff,
which you should never be doing if you are using a shared session.

Dmitry Streblechenko (MVP)http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool


How much slower?

Hmm, I don`t know. I didn´t compare times by the same code with
different methods. May be there is no significant difference.

Thanks for the hint to the Find/FindNext method. I use this method in
the creation/change code and the restrict method in a function which
is not very often used.

But here is the next problem:

Public Function FindAppointment(ByVal objCalendar As Object, ByVal
strEntryID As String) As Boolean

Const RES_AND As Long = 0
Const RES_NOT As Long = 2
Const RES_OR As Long = 1
Const RES_EXIST As Long = 8
Const RES_CONTENT As Long = 3
Const FL_SUBSTRING As Long = 1
Const FL_IGNORECASE As Long = &H10000

Const PR_SUBJECT As Long = &H37001E
Const PR_ENTRYID As Long = &HFFF0102

Dim CONTACT_ENTRY_ID As Long

Dim objRDOSession As Object
Dim objUtils As Object
Dim objRow
Dim objFilter
Dim objTable

Dim objAppointment As Outlook.AppointmentItem

Dim Columns(1)
Dim objRestrOR, objRestrAND1, objRestrAND2, objRestr1
Dim objRestr1a, objRestr1b, objRestr2, objRestr2a, objRestr2b

Dim strStoreID As String

CONTACT_ENTRY_ID = GetIdFromDaslProperty("ContactEntryID")
strStoreID = objCalendar.StoreID

Set objRDOSession = CreateObject("SafeOutlook.SecureRDOSession")
objRDOSession.Logon "", "", False, False, 0

Set objUtils = CreateObject("SafeOutlook.SecureMAPIUtils")
Set objTable = CreateObject("SafeOutlook.SecureMAPITable")

objTable.Item = objRDOSession.GetFolderFromID(objCalendar.EntryID,
objCalendar.StoreID).Items

Set objFilter = objTable.Filter

objFilter.Clear

Set objRestrOR = objFilter.SetKind(RES_OR)
Set objRestrAND1 = objRestrOR.Add(RES_AND)

Set objRestr1 = objRestrAND1.Add(RES_NOT)
Set objRestr1a = objRestr1.SetKind(RES_EXIST)
objRestr1a.ulPropTag = CONTACT_ENTRY_ID

Set objRestr1b = objRestrAND1.Add(RES_CONTENT)
objRestr1b.ulFuzzyLevel = FL_SUBSTRING Or FL_IGNORECASE
objRestr1b.ulPropTag = PR_SUBJECT
objRestr1b.lpProp = "Geburtstag von"

Set objRestrAND2 = objRestrOR.Add(RES_AND)

Set objRestr2a = objRestrAND2.Add(RES_EXIST)
objRestr2a.ulPropTag = CONTACT_ENTRY_ID

Set objRestr2b = objRestrAND2.Add(RES_CONTENT)
objRestr2b.ulFuzzyLevel = FL_SUBSTRING Or FL_IGNORECASE
objRestr2b.ulPropTag = CONTACT_ENTRY_ID
objRestr2b.lpProp = strEntryID

Columns(0) = PR_ENTRYID
Columns(1) = CONTACT_ENTRY_ID

objTable.Columns = Columns

If objFilter.FindFirst(True) Then

Do

objRow = objTable.GetRow

If Not IsEmpty(objRow) Then
Set objAppointment =
Outlook.Session.GetItemFromID(objUtils.HrArrayToString(objRow(0)),
strStoreID)
' Error: -2147221241 (80040107)
End If

Loop Until Not objFilter.FindNext(True)

End If

End Function

Interesting is the line "Set objAppointment = ...". Here araise an
error in 2007 if the folder (objCalendar) is a public folder. Same
item in the default calendar of the users mail box can be created with
out error. The item can also be created in a public folder with
2002/2003.

I´m not the Mapi-Expert and tell you only something what I have tried.
In 2002/2003 I use for RDOSessions the MAPIOBJECT method and for
2000/2007 I use the logon method. In 2000 there is no MAPIOBJECT so
there is no choose. If in 2007 I use the MAPIOBJECT some strange
things happens and will not work as expected. For example if a
RDOSession was started the user cannot longer access his folders and
have to restart Outlook. That`s the reasen to use the logon method.
Ok, but with this method the described error occurs.

Please help!

Peter

How much slower? Keep in mind that calling Restrict() will cause the
restriction to be persisted on the Exchange Server (if that is waht you
are
using) potentially causing a severe performance degradation. ExecSQL
collects rows one at a time avoiding IMAPITable::Restrict() MAPI call.
You can also always use RDOItems.Restrict - it takes a SQL expression and
returns a restricted collection.
If you know there will always be only or at most one item returned, use
RDOItems.Find, followed by (if you expect more items) FindNext.
Dmitry Streblechenko (MVP)http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
"Peter Marchert" <[email protected]> wrote in message
Thanks for all answers.
I use on some procedures the ExcecSQL method but it seems to be slower
than the restriction method? The code with the restriction is called
aproximately 100 times per second (or more). I create/change
appointments by looping through contact items. And on any item I have
to check if the appointment already exists.
Seems that one question is missing or I didn`t understand all answers:
Can I use the short entryid getting from an Exchange server to
reference a contact in a future Outlook session? Or is thi only the
case by using Mapi? Ken wrote in OOM I always get the long entryid but
I`m not sure if this is on Exchange so too.
Thanks Ken and Dmirty!
Peter
You might want to try the new (for version 4.4) MAPITable.ExecSQL
method -
you will be able to specify the conditions in the SQL format and specify
the
property names in the DASL (or OOM) format.
Dmitry Streblechenko (MVP)http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
Yes, this was an own property created with a guid and I hard coded the
number tag by the hex value I spyed with Outlook Spy. This number tag
is different in pst and exchange. I tryed it with the GetIDsFromNames
and that works. This is my code to get the ID:
Private Function GetIdFromDaslProperty(ByVal strProperty As String) As
Long
Dim objItem As Object
Dim objSafeItem As Object
Dim PrProperty
On Error Resume Next
Set objSafeItem = CreateObject("Redemption.SafeMailItem")
Set objItem = g_objOutlook.CreateItem(olMailItem)
objSafeItem.Item = objItem
PrProperty = objSafeItem.GetIDsFromNames(DASLGUID, strProperty)
PrProperty = PrProperty + PT_STRING8
GetIdFromDaslProperty = PrProperty
Set objSafeItem.Item = Nothing
Set objSafeItem = Nothing
Set objItem = Nothing
End Function
Should this work reliably because I`m working with a unsaved mailitem?
In my test it works, but I´m not sure if it works on other machines/
configurations. Dmitry is working on the examples on his homepage with
the first item of a folder but may be the folder is empty.
Thanks for the code. PR_LONGTERM_ENTRYID_FROM_TABLE I cannot find in
Outlook Spy when opening a message on an exchange server. Where is
this property?
Last question: If a short entryid is only valid for the actual session
how can I store an id? Next time this Id may be different?
For example: Get the entryid of an contact and store it in an
appointmentitem. Outlook close and opens. Get this Id from the
appointmentitem and reference the contact. This should not work if I
understand this.
Thank you very much for your help!
Peter
On 4 Okt., 17:18, "Ken Slovak - [MVP - Outlook]" <[email protected]>
wrote:
If this is a user property then short and long term id's don't apply.
Are you hard coding the property tag for that property or are you
using
a
call to a GetIdsFromNames method?
You should always use a call to a GetIdsFromNames method for anything
other
than a standard Outlook property, even properties added by Outlook
itself
such as ReminderSet. The numeric value of the property tag will differ
from
store to store, and store provider to store provider.
If you request an EntryID from a PST provider you will always get the
same
EntryID, that's a long-term id. If you request one from an Exchange
server
you might get a short-term id that's only valid for that Outlook
session.
In
MAPI tables you always ask for both types of id's and check to see
what
gets
returned. Here's the type of code I usually use for that (VB6, I can
show
C#
code if you want):
Public Const PR_ENTRYID = &HFFF0102
Public Const PR_LONGTERM_ENTRYID_FROM_TABLE = &H66700102
varColumns(0) = PR_ENTRYID
varColumns(1) = PR_LONGTERM_ENTRYID_FROM_TABLE
strEntryID = ""
If rdmFilter.FindFirst(True) Then
Row = .GetRow
If Not IsEmpty(Row) Then
strEntryID = rdmUtils.HrArrayToString(Row(1)) 'long term
If strEntryID = "" Then
strEntryID = rdmUtils.HrArrayToString(Row(0)) 'short term
End If
End If
--

...

Erfahren Sie mehr »- Zitierten Text ausblenden -

- Zitierten Text anzeigen -
 
D

Dmitry Streblechenko

The error is MAPI_E_INVALID_ENTRYID.
Make sure you pass both the item entry id (EntryID property) and the parent
store entry id (Parent.StoreID), especially if you are calling
RDOSession.Logon rather than setting the RDOSession.MAPIOBJECT property.

Dmitry Streblechenko (MVP)
http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool

Thank you for your answer, Dmitry.

The error (translated by google) is "-2147221241 (80040107): A client
procedure failed". Yes, the item is an appointmentitem.

Thanks for the hint with the logoff method. I used this method because
in 2002/2003 this works fine. But now I commented the lines to logoff
out and the MAPIOBJECT works in 2007 as well. Now it is possible to
create the appointment in a public folder too.

Thank you!
Peter

What is the exact error? Are you sure the item in question is really an
appointment?
The fact that you Outlook says that it can no longer display the folder
contents is a very strong indication taht you are calling
RDOSession.Logoff,
which you should never be doing if you are using a shared session.

Dmitry Streblechenko (MVP)http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool


How much slower?

Hmm, I don`t know. I didn´t compare times by the same code with
different methods. May be there is no significant difference.

Thanks for the hint to the Find/FindNext method. I use this method in
the creation/change code and the restrict method in a function which
is not very often used.

But here is the next problem:

Public Function FindAppointment(ByVal objCalendar As Object, ByVal
strEntryID As String) As Boolean

Const RES_AND As Long = 0
Const RES_NOT As Long = 2
Const RES_OR As Long = 1
Const RES_EXIST As Long = 8
Const RES_CONTENT As Long = 3
Const FL_SUBSTRING As Long = 1
Const FL_IGNORECASE As Long = &H10000

Const PR_SUBJECT As Long = &H37001E
Const PR_ENTRYID As Long = &HFFF0102

Dim CONTACT_ENTRY_ID As Long

Dim objRDOSession As Object
Dim objUtils As Object
Dim objRow
Dim objFilter
Dim objTable

Dim objAppointment As Outlook.AppointmentItem

Dim Columns(1)
Dim objRestrOR, objRestrAND1, objRestrAND2, objRestr1
Dim objRestr1a, objRestr1b, objRestr2, objRestr2a, objRestr2b

Dim strStoreID As String

CONTACT_ENTRY_ID = GetIdFromDaslProperty("ContactEntryID")
strStoreID = objCalendar.StoreID

Set objRDOSession = CreateObject("SafeOutlook.SecureRDOSession")
objRDOSession.Logon "", "", False, False, 0

Set objUtils = CreateObject("SafeOutlook.SecureMAPIUtils")
Set objTable = CreateObject("SafeOutlook.SecureMAPITable")

objTable.Item = objRDOSession.GetFolderFromID(objCalendar.EntryID,
objCalendar.StoreID).Items

Set objFilter = objTable.Filter

objFilter.Clear

Set objRestrOR = objFilter.SetKind(RES_OR)
Set objRestrAND1 = objRestrOR.Add(RES_AND)

Set objRestr1 = objRestrAND1.Add(RES_NOT)
Set objRestr1a = objRestr1.SetKind(RES_EXIST)
objRestr1a.ulPropTag = CONTACT_ENTRY_ID

Set objRestr1b = objRestrAND1.Add(RES_CONTENT)
objRestr1b.ulFuzzyLevel = FL_SUBSTRING Or FL_IGNORECASE
objRestr1b.ulPropTag = PR_SUBJECT
objRestr1b.lpProp = "Geburtstag von"

Set objRestrAND2 = objRestrOR.Add(RES_AND)

Set objRestr2a = objRestrAND2.Add(RES_EXIST)
objRestr2a.ulPropTag = CONTACT_ENTRY_ID

Set objRestr2b = objRestrAND2.Add(RES_CONTENT)
objRestr2b.ulFuzzyLevel = FL_SUBSTRING Or FL_IGNORECASE
objRestr2b.ulPropTag = CONTACT_ENTRY_ID
objRestr2b.lpProp = strEntryID

Columns(0) = PR_ENTRYID
Columns(1) = CONTACT_ENTRY_ID

objTable.Columns = Columns

If objFilter.FindFirst(True) Then

Do

objRow = objTable.GetRow

If Not IsEmpty(objRow) Then
Set objAppointment =
Outlook.Session.GetItemFromID(objUtils.HrArrayToString(objRow(0)),
strStoreID)
' Error: -2147221241 (80040107)
End If

Loop Until Not objFilter.FindNext(True)

End If

End Function

Interesting is the line "Set objAppointment = ...". Here araise an
error in 2007 if the folder (objCalendar) is a public folder. Same
item in the default calendar of the users mail box can be created with
out error. The item can also be created in a public folder with
2002/2003.

I´m not the Mapi-Expert and tell you only something what I have tried.
In 2002/2003 I use for RDOSessions the MAPIOBJECT method and for
2000/2007 I use the logon method. In 2000 there is no MAPIOBJECT so
there is no choose. If in 2007 I use the MAPIOBJECT some strange
things happens and will not work as expected. For example if a
RDOSession was started the user cannot longer access his folders and
have to restart Outlook. That`s the reasen to use the logon method.
Ok, but with this method the described error occurs.

Please help!

Peter

How much slower? Keep in mind that calling Restrict() will cause the
restriction to be persisted on the Exchange Server (if that is waht you
are
using) potentially causing a severe performance degradation. ExecSQL
collects rows one at a time avoiding IMAPITable::Restrict() MAPI call.
You can also always use RDOItems.Restrict - it takes a SQL expression
and
returns a restricted collection.
If you know there will always be only or at most one item returned, use
RDOItems.Find, followed by (if you expect more items) FindNext.
Dmitry Streblechenko (MVP)http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
"Peter Marchert" <[email protected]> wrote in message
Thanks for all answers.
I use on some procedures the ExcecSQL method but it seems to be slower
than the restriction method? The code with the restriction is called
aproximately 100 times per second (or more). I create/change
appointments by looping through contact items. And on any item I have
to check if the appointment already exists.
Seems that one question is missing or I didn`t understand all answers:
Can I use the short entryid getting from an Exchange server to
reference a contact in a future Outlook session? Or is thi only the
case by using Mapi? Ken wrote in OOM I always get the long entryid but
I`m not sure if this is on Exchange so too.
Thanks Ken and Dmirty!
Peter
You might want to try the new (for version 4.4) MAPITable.ExecSQL
method -
you will be able to specify the conditions in the SQL format and
specify
the
property names in the DASL (or OOM) format.
Dmitry Streblechenko (MVP)http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
Yes, this was an own property created with a guid and I hard coded the
number tag by the hex value I spyed with Outlook Spy. This number tag
is different in pst and exchange. I tryed it with the GetIDsFromNames
and that works. This is my code to get the ID:
Private Function GetIdFromDaslProperty(ByVal strProperty As String) As
Long
Dim objItem As Object
Dim objSafeItem As Object
Dim PrProperty
On Error Resume Next
Set objSafeItem = CreateObject("Redemption.SafeMailItem")
Set objItem = g_objOutlook.CreateItem(olMailItem)
objSafeItem.Item = objItem
PrProperty = objSafeItem.GetIDsFromNames(DASLGUID, strProperty)
PrProperty = PrProperty + PT_STRING8
GetIdFromDaslProperty = PrProperty
Set objSafeItem.Item = Nothing
Set objSafeItem = Nothing
Set objItem = Nothing
End Function
Should this work reliably because I`m working with a unsaved mailitem?
In my test it works, but I´m not sure if it works on other machines/
configurations. Dmitry is working on the examples on his homepage with
the first item of a folder but may be the folder is empty.
Thanks for the code. PR_LONGTERM_ENTRYID_FROM_TABLE I cannot find in
Outlook Spy when opening a message on an exchange server. Where is
this property?
Last question: If a short entryid is only valid for the actual session
how can I store an id? Next time this Id may be different?
For example: Get the entryid of an contact and store it in an
appointmentitem. Outlook close and opens. Get this Id from the
appointmentitem and reference the contact. This should not work if I
understand this.
Thank you very much for your help!
Peter
On 4 Okt., 17:18, "Ken Slovak - [MVP - Outlook]" <[email protected]>
wrote:
If this is a user property then short and long term id's don't
apply.
Are you hard coding the property tag for that property or are you
using
a
call to a GetIdsFromNames method?
You should always use a call to a GetIdsFromNames method for
anything
other
than a standard Outlook property, even properties added by Outlook
itself
such as ReminderSet. The numeric value of the property tag will
differ
from
store to store, and store provider to store provider.
If you request an EntryID from a PST provider you will always get
the
same
EntryID, that's a long-term id. If you request one from an Exchange
server
you might get a short-term id that's only valid for that Outlook
session.
In
MAPI tables you always ask for both types of id's and check to see
what
gets
returned. Here's the type of code I usually use for that (VB6, I can
show
C#
code if you want):
Public Const PR_ENTRYID = &HFFF0102
Public Const PR_LONGTERM_ENTRYID_FROM_TABLE = &H66700102
varColumns(0) = PR_ENTRYID
varColumns(1) = PR_LONGTERM_ENTRYID_FROM_TABLE
strEntryID = ""
If rdmFilter.FindFirst(True) Then
Row = .GetRow
If Not IsEmpty(Row) Then
strEntryID = rdmUtils.HrArrayToString(Row(1)) 'long term
If strEntryID = "" Then
strEntryID = rdmUtils.HrArrayToString(Row(0)) 'short term
End If
End If
--

...

Erfahren Sie mehr »- Zitierten Text ausblenden -

- Zitierten Text anzeigen -
 
P

Peter Marchert

Ok, I will do so.

Thank you again!
Peter

The error is MAPI_E_INVALID_ENTRYID.
Make sure you pass both the item entry id (EntryID property) and the parent
store entry id (Parent.StoreID), especially if you are calling
RDOSession.Logon rather than setting the RDOSession.MAPIOBJECT property.

Dmitry Streblechenko (MVP)http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool


Thank you for your answer, Dmitry.

The error (translated by google) is "-2147221241 (80040107): A client
procedure failed". Yes, the item is an appointmentitem.

Thanks for the hint with the logoff method. I used this method because
in 2002/2003 this works fine. But now I commented the lines to logoff
out and the MAPIOBJECT works in 2007 as well. Now it is possible to
create the appointment in a public folder too.

Thank you!
Peter

What is the exact error? Are you sure the item in question is really an
appointment?
The fact that you Outlook says that it can no longer display the folder
contents is a very strong indication taht you are calling
RDOSession.Logoff,
which you should never be doing if you are using a shared session.
Dmitry Streblechenko (MVP)http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
Hmm, I don`t know. I didn´t compare times by the same code with
different methods. May be there is no significant difference.
Thanks for the hint to the Find/FindNext method. I use this method in
the creation/change code and the restrict method in a function which
is not very often used.
But here is the next problem:
Public Function FindAppointment(ByVal objCalendar As Object, ByVal
strEntryID As String) As Boolean
Const RES_AND As Long = 0
Const RES_NOT As Long = 2
Const RES_OR As Long = 1
Const RES_EXIST As Long = 8
Const RES_CONTENT As Long = 3
Const FL_SUBSTRING As Long = 1
Const FL_IGNORECASE As Long = &H10000
Const PR_SUBJECT As Long = &H37001E
Const PR_ENTRYID As Long = &HFFF0102
Dim CONTACT_ENTRY_ID As Long
Dim objRDOSession As Object
Dim objUtils As Object
Dim objRow
Dim objFilter
Dim objTable
Dim objAppointment As Outlook.AppointmentItem
Dim Columns(1)
Dim objRestrOR, objRestrAND1, objRestrAND2, objRestr1
Dim objRestr1a, objRestr1b, objRestr2, objRestr2a, objRestr2b
Dim strStoreID As String
CONTACT_ENTRY_ID = GetIdFromDaslProperty("ContactEntryID")
strStoreID = objCalendar.StoreID
Set objRDOSession = CreateObject("SafeOutlook.SecureRDOSession")
objRDOSession.Logon "", "", False, False, 0
Set objUtils = CreateObject("SafeOutlook.SecureMAPIUtils")
Set objTable = CreateObject("SafeOutlook.SecureMAPITable")
objTable.Item = objRDOSession.GetFolderFromID(objCalendar.EntryID,
objCalendar.StoreID).Items
Set objFilter = objTable.Filter

Set objRestrOR = objFilter.SetKind(RES_OR)
Set objRestrAND1 = objRestrOR.Add(RES_AND)
Set objRestr1 = objRestrAND1.Add(RES_NOT)
Set objRestr1a = objRestr1.SetKind(RES_EXIST)
objRestr1a.ulPropTag = CONTACT_ENTRY_ID
Set objRestr1b = objRestrAND1.Add(RES_CONTENT)
objRestr1b.ulFuzzyLevel = FL_SUBSTRING Or FL_IGNORECASE
objRestr1b.ulPropTag = PR_SUBJECT
objRestr1b.lpProp = "Geburtstag von"
Set objRestrAND2 = objRestrOR.Add(RES_AND)
Set objRestr2a = objRestrAND2.Add(RES_EXIST)
objRestr2a.ulPropTag = CONTACT_ENTRY_ID
Set objRestr2b = objRestrAND2.Add(RES_CONTENT)
objRestr2b.ulFuzzyLevel = FL_SUBSTRING Or FL_IGNORECASE
objRestr2b.ulPropTag = CONTACT_ENTRY_ID
objRestr2b.lpProp = strEntryID
Columns(0) = PR_ENTRYID
Columns(1) = CONTACT_ENTRY_ID
objTable.Columns = Columns
If objFilter.FindFirst(True) Then

objRow = objTable.GetRow
If Not IsEmpty(objRow) Then
Set objAppointment =
Outlook.Session.GetItemFromID(objUtils.HrArrayToString(objRow(0)),
strStoreID)
' Error: -2147221241 (80040107)
End If
Loop Until Not objFilter.FindNext(True)
End Function
Interesting is the line "Set objAppointment = ...". Here araise an
error in 2007 if the folder (objCalendar) is a public folder. Same
item in the default calendar of the users mail box can be created with
out error. The item can also be created in a public folder with
2002/2003.
I´m not the Mapi-Expert and tell you only something what I have tried.
In 2002/2003 I use for RDOSessions the MAPIOBJECT method and for
2000/2007 I use the logon method. In 2000 there is no MAPIOBJECT so
there is no choose. If in 2007 I use the MAPIOBJECT some strange
things happens and will not work as expected. For example if a
RDOSession was started the user cannot longer access his folders and
have to restart Outlook. That`s the reasen to use the logon method.
Ok, but with this method the described error occurs.
Please help!

How much slower? Keep in mind that calling Restrict() will cause the
restriction to be persisted on the Exchange Server (if that is waht you
are
using) potentially causing a severe performance degradation. ExecSQL
collects rows one at a time avoiding IMAPITable::Restrict() MAPI call.
You can also always use RDOItems.Restrict - it takes a SQL expression
and
returns a restricted collection.
If you know there will always be only or at most one item returned, use
RDOItems.Find, followed by (if you expect more items) FindNext.
Dmitry Streblechenko (MVP)http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
Thanks for all answers.
I use on some procedures the ExcecSQL method but it seems to be slower
than the restriction method? The code with the restriction is called
aproximately 100 times per second (or more). I create/change
appointments by looping through contact items. And on any item I have
to check if the appointment already exists.
Seems that one question is missing or I didn`t understand all answers:
Can I use the short entryid getting from an Exchange server to
reference a contact in a future Outlook session? Or is thi only the
case by using Mapi? Ken wrote in OOM I always get the long entryid but
I`m not sure if this is on Exchange so too.
Thanks Ken and Dmirty!
Peter
You might want to try the new (for version 4.4) MAPITable.ExecSQL
method -
you will be able to specify the conditions in the SQL format and
specify
the
property names in the DASL (or OOM) format.
Dmitry Streblechenko (MVP)http://www.dimastr.com/
OutlookSpy - Outlook, CDO
and MAPI Developer Tool
Yes, this was an own property created with a guid and I hard coded the
number tag by the hex value I spyed with Outlook Spy. This number tag
is different in pst and exchange. I tryed it with the GetIDsFromNames
and that works. This is my code to get the ID:
Private Function GetIdFromDaslProperty(ByVal strProperty As String)As
Long
Dim objItem As Object
Dim objSafeItem As Object
Dim PrProperty
On Error Resume Next
Set objSafeItem = CreateObject("Redemption.SafeMailItem")
Set objItem = g_objOutlook.CreateItem(olMailItem)
objSafeItem.Item = objItem
PrProperty = objSafeItem.GetIDsFromNames(DASLGUID, strProperty)
PrProperty = PrProperty + PT_STRING8
GetIdFromDaslProperty = PrProperty
Set objSafeItem.Item = Nothing
Set objSafeItem = Nothing
Set objItem = Nothing
End Function
Should this work reliably because I`m working with a unsaved mailitem?
In my test it works, but I´m not sure if it works on other machines/
configurations. Dmitry is working on the examples on his homepage with
the first item of a folder but may be the folder is empty.
Thanks for the code. PR_LONGTERM_ENTRYID_FROM_TABLE I cannot find in
Outlook Spy when opening a message on an exchange server. Where is
this property?
Last question: If a short entryid is only valid for the actual session
how can I store an id? Next time this Id may be different?
For example: Get the entryid of an contact and store it in an
appointmentitem. Outlook close and opens. Get this Id from the
appointmentitem and reference the contact. This should not work if I
understand this.
Thank you very much for your help!
Peter
On 4 Okt., 17:18, "Ken Slovak - [MVP - Outlook]" <[email protected]>
wrote:
If this is a user property then short and long term id's don't
apply.
Are you hard coding the property tag for that property or are you
using
a
call to a GetIdsFromNames method?

...

Erfahren Sie mehr »- Zitierten Text ausblenden -

- Zitierten Text anzeigen -
 
Top