Programmatically sending email via Outlook COM Add-In

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

I'm trying to send email from a VB6 program via a COM Add-In. I've created a
simple Add In along the lines in Thomas Rizzo's book Programming Microsoft
Outlook... Chapter 7. I've added a Public Function SendEmail.

But I can't call my SendEmail function from another application. If anyone
has experience of calling functions in Add Ins from another application,
please let me know how you did it!

I created a VB6 project with a form and button Command1:

Private Sub Command1_Click()
Dim objOutlook As Outlook.Application
Dim objAddIn As Object
Dim MyAddIn As Object

Set objOutlook = Outlook.Application

On Error Resume Next
Set objAddIn = objOutlook.COMAddIns("MyCOMAddIn.Connect")
If Err.Number = 0 Then
'This will fail with Object doesn't support this property or method.
'objAddIn.SendMail "(e-mail address removed)", "Test Subject", "Test Message"
'So try the method shown in Rizzo's book
Set MyAddIn = GetObject("", "MyCOMAddIn.Connect")
'This won't work, because the oHostApp variable in MyAddIn is nothing.
MyAddIn.SendMail "(e-mail address removed)", "Test Subject", "Test Message"
End If

Set objOutlook = Nothing

End Sub

I saw a discussion that suggested adding the line highlighted below to the
OnConnection event in the Add In, but this fails with Object doesn't support
this property or method. I tried this line with 'Set' at the start, this
makes no difference.

Private Sub IDTExtensibility2_OnConnection(ByVal Application As Object, _
ByVal ConnectMode As AddInDesignerObjects.ext_ConnectMode, _
ByVal AddInInst As Object, custom() As Variant)

Set oHostApp = Application

'Thought this might help...
'oHostApp.COMAddIns.Item("MyComAddIn.Connect").Object = Me

If (ConnectMode <> ext_cm_Startup) Then
Call IDTExtensibility2_OnStartupComplete(custom)
End If
End Sub
 
Thanks for your reply.

My post had a typo, the function is SendMail not SendEmail, and I do have a
Public Function SendMail(params...) in the Connect class.

The function is accessible when I use this:
Set MyAddIn = GetObject("", "MyCOMAddIn.Connect")
'This won't work, because the oHostApp variable in MyAddIn is nothing.
MyAddIn.SendMail "(e-mail address removed)", "Test Subject", "Test Message"

But it fails within the AddIn because the oHostApp variable set in the
OnConnection event is Nothing. I guess because there is no reference to this
in the COMAddIns.Item("MyComAddIn.Connect").Object, but I can't see how to
correct this.

Thanks
 
If your Addin gets loaded by Outlook then the Application variable is set.
So it's important to declare oHostApp where it stays valid.

This works:

<connect.cls>
Private oHostApp as Outlook.Application

Private Sub IDTExtensibility2_OnConnection(ByVal Application As Object, _
ByVal ConnectMode As AddInDesignerObjects.ext_ConnectMode, _
ByVal AddInInst As Object, custom() As Variant)

Set oHostApp = Application
End Sub

Public Sub SendMail()
End Sub
</connect.cls>

Don't forget to set oHostApp=Nothing in OnDisconnection.

--
Viele Gruesse / Best regards
Michael Bauer - MVP Outlook
Keep your Outlook categories organized!
http://www.shareit.com/product.html?productid=300120654&languageid=1
(German: http://www.VBOffice.net/product.html?pub=6)


Am Sat, 27 Jan 2007 09:04:00 -0800 schrieb pollyanna65:
 
Thanks for your reply.

I do have oHostApp declared at module level.

It seems to me the problem is that GetObject("",MyCOMAddIn.Connect") in the
calling application gets a new instance of the object, which is the
advertised behaviour for this syntax. But I copied this workaround as-is
from Thomas Rizzo's example. I tried using GetObject(,MyCOMAddIn.Connect")
which should return the existing instance, but this gives ActiveX component
can't create object. That rather suggests the AddIn has been created as a
single-instance object? But then the first syntax should return the running
object.

I tested this as follows. I created a new Add In which just sets a module
level variable to "Hello World". The Add In is registered OK. I start
Outlook 2003. The message box in the add-in confirms it is started up.
oHostApp is valid at this point. Then I run my test application in the VB
IDE. The message box in the test app shows "Value is '', oHostApp Is Nothing
is True". So it seems to me I have got a new object, not a reference to the
object created when Outlook was started.

This is the code. Any thoughts would be welcome!

Private Sub Command1_Click()
Dim objOutlook As Outlook.Application
Dim objAddIn As Office.COMAddIn
Dim MyAddIn As MyCOMAddIn.Connect

'This is getting the global outlook object (no New)

Set objOutlook = Outlook.Application

On Error Resume Next
' Set reference to COM add-in.
Set objAddIn = objOutlook.COMAddIns("MyCOMAddIn.Connect")
If Err.Number = 0 Then
'This gives ActiveX Component can't create Object'
'Set MyAddIn = GetObject(, "MyCOMAddIn.Connect")
Set MyAddIn = GetObject("", "MyCOMAddIn.Connect")
If Err.Number = 0 Then
MsgBox "Value is '" & MyAddIn.testvalue & "', oHostApp Is Nothing is
" & MyAddIn.oHostAppIsNothing
Else
MsgBox Err.Description & Err.Number
End If
End If

Set objOutlook = Nothing

End Sub

This is the add-in:

Option Explicit
Implements IDTExtensibility2

Dim oHostApp As Object
Dim sValue As String

Private Sub IDTExtensibility2_OnConnection(ByVal Application As Object, _
ByVal ConnectMode As AddInDesignerObjects.ext_ConnectMode, _
ByVal AddInInst As Object, custom() As Variant)

On Error Resume Next
' Set a reference to the host application...
Set oHostApp = Application

If oHostApp Is Nothing Then
MsgBox "oHostApp is Nothing in OnConnection"
End If

sValue = "Hello World"

'If you aren't in startup, then manually call OnStartupComplete...
If (ConnectMode <> ext_cm_Startup) Then
Call IDTExtensibility2_OnStartupComplete(custom)
End If

End Sub

Private Sub IDTExtensibility2_OnStartupComplete(custom() As Variant)

MsgBox "Started in " & oHostApp.Name & "."

End Sub

Private Sub IDTExtensibility2_OnDisconnection(ByVal RemoveMode As _
AddInDesignerObjects.ext_DisconnectMode, custom() As Variant)

If RemoveMode <> ext_dm_HostShutdown Then
Call IDTExtensibility2_OnBeginShutdown(custom)
End If

MsgBox "Clearing oHostApp Reference"
Set oHostApp = Nothing

End Sub

Private Sub IDTExtensibility2_OnBeginShutdown(custom() As Variant)
MsgBox "Our custom Add-In is unloading."
End Sub

Private Sub IDTExtensibility2_OnAddInsUpdate(custom() As Variant)
'Do nothing
End Sub

Public Property Get TestValue() As String
TestValue = sValue
End Property

Public Property Get oHostAppIsNothing() As Boolean
oHostAppIsNothing = (oHostApp Is Nothing)
End Property
 
Outlook must be running, of course, to get an existing instance. And you
must use GetObject(,"MyCOMAddIn.Connect") for not to create a new instance.

If you then get an error (can't create instance) then the object isn't
registered in the ROT (Running Object Table). This sample from Olaf Schmidt
(www.datenhaus.de) shows how to insert and remove an object from the ROT:

Private Declare Function CLSIDFromProgID& Lib "ole32.dll" (ByVal ProgID&,
rclsid As Any)
Private Declare Function CoDisconnectObject& Lib "ole32.dll" (ByVal punk As
Object, ByVal pvReserved&)
Private Declare Function RegisterActiveObject& Lib "oleaut32.dll" (ByVal
punk As Object, rclsid As Any, ByVal dwFlags&, pdwRegister&)
Private Declare Function RevokeActiveObject& Lib "oleaut32.dll" (ByVal
dwRegister&, ByVal pvReserved&)
Private hReg&

Sub Register(ByVal punk As Object, ByVal sProgID As String)
Dim GUID&(3) ' ROT-Register
If CLSIDFromProgID(StrPtr(sProgID), GUID(0)) = 0 Then
RegisterActiveObject punk, GUID(0), 1, hReg
End If
End Sub

Sub Unregister(ByVal punk As Object)
If hReg Then ' ROT-Unregister
RevokeActiveObject hReg, 0
CoDisconnectObject punk, 0
hReg = 0
End If
End Sub

--
Viele Gruesse / Best regards
Michael Bauer - MVP Outlook
Keep your Outlook categories organized!
http://www.shareit.com/product.html?productid=300120654&languageid=1
(German: http://www.VBOffice.net/product.html?pub=6)

Am Mon, 29 Jan 2007 01:33:00 -0800 schrieb pollyanna65:
 
Thanks for your help, I have found the line that does the trick:

In the OnConnection event add:

AddInInst.Object = Me

Then in the calling program I can use the code you would expect:

Set objAddIn = objOutlook.COMAddIns("AmCatOutlookMail.Connect")
If Err.Number = 0 Then
objAddIn.Connect = True
Set MyAddIn = objOutlook.COMAddIns("AmCatOutlookMail.Connect").Object

Now the Object reference is valid.

Thanks for spending time on this.
 
Back
Top