none
The RPC server is unavailable. (Exception from HRESULT: 0x800706BA) and other errors RRS feed

  • Question

  • Hello,

    I have developed application that send email using outlook. The reason I used outlook so that if there is any connectivity issue with Exchange, the message remains in outbox and upon restoring of connection, the emails go out automatically. 

    Here is the problem: My application creates instance of outlook which created a new process outlook.exe under processes. All ok. Now if any users logs in to the machine and open outlook and then closes it, this also closes the instance of outlook my app created and then eventually my app fails. When I see task manager, there is always one outlook.exe running. 

    Sometimes I get RPC unavailable error and other times Null references depending upon which line of code I hit when the outlook got closed.

    How do I work around this problem?

    Thanks,

    Wednesday, May 31, 2017 3:57 PM

All replies

  • Hi Me.Saqib,

    to solve the issue , you can try to check whether Outlook process is running or not before performing any operation.

    if no Outlook process is running then you can create a new one.

    if already process is running then you can use that instance.

    this way you can avoid the error.

    you had mentioned that there are other errors.

    what are other errors?

    you can try to post sample codes , we will try to test that codes on our side and let you know about the testing results.

    Regards

    Deepak


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, June 1, 2017 7:16 AM
    Moderator
  • Hi Deepak,

    Thanks for replying to my post. In the beginning, I had a check in my code if there is already Outlook processing is running but it didnt help me. It worked fine if the outlook is really open (by a user) but if the outlook is opened by my App (after sending first email) then it shows up in taskbar with little asterisk symbol and then eventually it exits out.  This works fine till I m ready to send a second email. My app will see outlook.exe is still running but I guess its not ... This is the error message: 

    operation unavailable (exception from hresult: 0x800401e3 (mk_e_unavailable)) outlook

    Upon googling, people said I m running VS not in admin mode but even I run it is in admin mode, I still get error. I build my exe and run from it and still get same error. I have also changed outlook exe properties to run as administrator under Compatibility tab but no help.

    This is the code  that fails:

    If Process.GetProcessesByName("OUTLOOK").Count > 0 Then
          _outlookApp = DirectCast(Marshal.GetActiveObject("Outlook.Application.14"), Outlook.Application

    Also it is possible that outlook.exe is there when I m checking the instance but may not be there when I m going to logon to namespace or may not be there when I m ready to send an email...Thats what I meant that we dont when outlook.exe would not be there anymore.

    Thanks,

    Friday, June 2, 2017 3:27 AM
  • Any word here?
    Sunday, June 4, 2017 8:40 PM
  • Hi Me.Saqib,

    try to use example below.

    if (Process.GetProcessesByName("OUTLOOK").Count() > 0)
          {
             // Check whether there is an Outlook process running
             // If so, use the GetActiveObject method to obtain the application process
              var app = Marshal.GetActiveObject("Outlook.Application") as Outlook._Application;
      
             // use the Quit method to close the running instance
              app.Quit();
          }
      
          Thread.Sleep(500); // Put a few milliseconds delay before launching the app again
      
         // Create a new process to restart Outlook
          Process process = new Process();
          process.StartInfo = new ProcessStartInfo(OutlookFilepath);
          process.Start();
    

    Regards

    Deepak


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, June 5, 2017 8:28 AM
    Moderator
  • Hi Deepak,

    If you see my last reply, I mentioned that I already had same exact check to check for Outlook process is running and then next line below when I try to do GetActiveObject, I get error operation unavailable (exception from hresult: 0x800401e3 (mk_e_unavailable)) outlook.

    So I m not sure if the code sample will help me any.

    Currently I m not doing that check anymore.  Only problem I have if my app is running and someone closes the outlook then I get RPC unavailable error.

    If no one open/close outlook or leave it open then all ok. Only problem while sending email if someone closes outlook, then I get RPC unavailable error.

    Tuesday, June 6, 2017 3:00 AM
  • Hi Me.Saqib,

    I just try to provide a full code for the example.

    when you try to create an instance of the outlook , did you make that visible?

    you can try to work without making it visible so that no one can close it using interface.

    and you can use that instance when you send mail.

    you can try to post that code. I will also try to test that.

    Regards

    Deepak


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, June 6, 2017 8:09 AM
    Moderator
  • No, I didnt make outlook instance visible from the code. It is set to display=false.

    It is user when he logs in to machine, open outlook from program menu which shares same process that is already running.

    Here is my code: 2 sections with two separate files:

    Imports System.Net.Mail
    Imports Outlook = Microsoft.Office.Interop.Outlook
    Imports System.Runtime.InteropServices
    
    Public Class SendMailv2
    
    #Region "Properties"
    
        Public Property ProfileName As String
        Private _outlookApp As Outlook.Application
    
        Public ReadOnly Property OutlookApp
            Get
                'If _outlookApp Is Nothing Then
                '    Init()
                'End If
                Return _outlookApp
            End Get
        End Property
    
    #End Region
    
        ' this is default constructor as an anonymous email.
        ' The reason I m not using because with other constructor, the user will provide email from / account.
        Public Sub New()
    
        End Sub
    
        ' This function only set service object. The function NewMailMessage returns also mailobject on top of initializing service.
        Public Sub Init()
    
            Dim PROC_NAME As String = "SendMailv2 Init"
            Dim ns As Outlook.NameSpace
    
            ' start outlook
            Try
                ' check if outlook is already running
                'If Process.GetProcessesByName("OUTLOOK").Count > 0 Then
                '   _outlookApp = DirectCast(Marshal.GetActiveObject("Outlook.Application.14"), Outlook.Application)
                'Else
                ' If not, create a new instance of Outlook and log on to the default profile. 
                _outlookApp = CreateObject("Outlook.Application.14")
                ns = OutlookApp.GetNamespace("MAPI")
                ns.Logon(Me.ProfileName, "", False, True)
                ns = Nothing
                'End If
    
            Catch ex As Exception
                _outlookApp = Nothing
                ns = Nothing
                Throw ex
            End Try
    
        End Sub
    
    End Class

    Imports System.Runtime.InteropServices
    Imports Outlook = Microsoft.Office.Interop.Outlook
    
    Public Class OutlookMailMessage
    
        Private _mailTo As New List(Of String)
        Private _mailCc As New List(Of String)
        Private _mailBcc As New List(Of String)
        Private _attachments As New List(Of String)
        Private _mailMessage As Outlook.MailItem
        Private _body As String
    
    #Region "Properties"
    
        Public ProfileName As String
        Public Property OutlookApp As Outlook.Application
        Public Property MailFrom As String
        Public Property Subject As String
        Public Property Important As Outlook.OlImportance = Outlook.OlImportance.olImportanceNormal
        Public Property MailBodyFormat As Outlook.OlBodyFormat = Outlook.OlBodyFormat.olFormatHTML
    
        ' these are readonly properties which will return parsed emails stored in collection.
        Public ReadOnly Property MailTo As List(Of String)
            Get
                Return _mailTo
            End Get
        End Property
    
        ' These are writeonly properties which means only caller would set them and then they would store values in readonly properties.
        ' if you give me one email in string, it will be added to list or multiple emails and they will be added too in the list. 
        ' You can also call this property multiple times with single email and emails will be keep added.
        Public WriteOnly Property MailToRecipients As String
            Set(value As String)
                _mailTo.AddRange(ParseMailString(value))
            End Set
        End Property
    
        Public ReadOnly Property MailCc As List(Of String)
            Get
                Return _mailCc
            End Get
        End Property
    
        Public WriteOnly Property MailCcRecipients As String
            Set(value As String)
                _mailCc.AddRange(ParseMailString(value))
            End Set
        End Property
    
        Public ReadOnly Property MailBcc As List(Of String)
            Get
                Return _mailBcc
            End Get
        End Property
    
        Public WriteOnly Property MailBccRecipients As String
            Set(value As String)
                _mailBcc.AddRange(ParseMailString(value))
            End Set
        End Property
    
        Public ReadOnly Property MailMessage
            Get
                If _mailMessage Is Nothing Then
                    _mailMessage = OutlookApp.CreateItem(Outlook.OlItemType.olMailItem)
                End If
                Return _mailMessage
            End Get
        End Property
    
        ' Modify anything that you want in body using this property
        Public Property Body As String
            Get
                Return _body
            End Get
            Set(value As String)
                _body = value
            End Set
        End Property
    
        Public Property Attachments As Object ' String()
            Get
                'If _attachments Is Nothing Then ReDim _attachments(0)
                Return _attachments
            End Get
            Set(value As Object)
                Try
                    If Not value Is Nothing Then
                        _attachments.Add(value)
                    End If
                Catch ex As System.Exception
                    'MsgBox(ex.Source + ex.Message)
                    Throw ex
                End Try
            End Set
        End Property
    
    #End Region
    
        Public Sub New()
    
        End Sub
    
        Public Sub SendMail()
    
            Try
                Dim outlookMailMsg As Outlook.MailItem = Me.MailMessage
                'Threading.Thread.Sleep(2000)
    
                AddMailAddresses(outlookMailMsg, Me.MailTo, "to")
    
                If outlookMailMsg.Recipients.Count = 0 Then
                    Throw New Exception("To Email Address cannot be empty. Atleast one email need to be specified.")
                End If
    
                If Me.MailCc.Count > 0 Then
                    AddMailAddresses(outlookMailMsg, Me.MailCc, "cc")
                End If
    
                If Me.MailBcc.Count > 0 Then
                    AddMailAddresses(outlookMailMsg, Me.MailBcc, "bcc")
                End If
    
                If Me.Attachments.count > 0 Then
                    AddAttachments(outlookMailMsg, Me.Attachments)
                End If
    
                'Try
                With outlookMailMsg
                    .Subject = Me.Subject
                    .Body = Me.Body
                    .Importance = Me.Important   
                    .BodyFormat = Me.MailBodyFormat
                    .Send()
                End With
    
            Catch ex As Exception
                ' if error because some human open/close outlook then reconnect again.
                If ex.Message.Contains("The RPC server is unavailable. (Exception from HRESULT: 0x800706BA).") Then
                    Dim s As New SendMailv2
                    s.ProfileName = Me.ProfileName
                    s.Init()
                    Me.OutlookApp = s.OutlookApp
                    SendMail()
                Else
                    Throw ex
                End If
    
            End Try
    
        End Sub
    
    
    End Class

    Wednesday, June 7, 2017 5:42 AM
  • Hi Deepak,

    Any word here?

    Thursday, June 8, 2017 9:32 PM
  • Hi Me.Saqib,

    I will try to check the code and let you inform about the result.

    Regards

    Deepak 


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Friday, June 9, 2017 9:01 AM
    Moderator
  • Outlook always runs as a singleton.  You won't be able to start more than one instance of the program.

    I'm not aware of any technique to prevent a user from closing Outlook.  They don't even have to open the program to use it.  All they have to do is click on the notification area icon and select "Exit" to terminate the running instance that was started through COM.

    You might consider changing the approach taken when a call to the Outlook object model returns unexpected errors or null references.  Release all held interfaces and try to restart processing.  You could also consider including code to receive the Outlook Application Object's Quit Event.  That would assist in determining that a user has caused Outlook to shut down.
    Friday, June 9, 2017 8:51 PM
  • I tried to use Application Quit Event but I m not understanding the flow of it. I see that Event fires when I close outlook interface and then I have msgbox which pops up but then if I dont click OK on msgbox, the execution goes back to my function (in my test to SendMail()) and then execution begins there and mail sent out. 

    But If I dont have msgbox then the event function complete and then I will get RPC error.So I m not completing getting the behavior for this event because the execution goes back to same function where it was running with msgbox being there for 'ok' to be clicked.

    Sunday, June 11, 2017 2:53 PM
  • The point is that if your application receives Outlook's Quit event you know that held interfaces are no longer valid and that you must restart Outlook through COM to enable further processing.  The event is a notification.  Displaying a MsgBox while handling the event will not prevent Outlook from shutting down.
    Sunday, June 11, 2017 3:22 PM
  • So lets say I was at SendMail function and then Quit function fired, now where do I restart processing again? Inside Quit function? I guess not.
    Sunday, June 11, 2017 7:27 PM
  • When you receive the Quit event set a flag.  If during mail processing a function fails check the flag.  If it is set you know you need to restart.
    Sunday, June 11, 2017 7:40 PM
  • But I cant check flag at each statement in sendmail function...It will be too many checks and I dont see I do put those checks after each statement...
    Sunday, June 11, 2017 8:07 PM
  • If you don't want to handle errors then your code will not be robust and will be prone to failure.  It's your choice.
    Sunday, June 11, 2017 8:11 PM
  • Essentially it is same check that I have already in my sendmail function. I have Try Catch block where I m checking for RPC error (which only happens when outlook interface is closed) and then in catch block I m restarting outlook again..

    I dont think Quit function is buying me anything here instead making me to do more checks etc.

    Sunday, June 11, 2017 11:38 PM
  • As i pointed out earlier the Quit event would assist in determining that an exception was due to Outlook having been closed by the user.  Feel free to omit it if this information doesn't interest you.
    Sunday, June 11, 2017 11:52 PM
  • Hi Me.Saqib,

    I will try to check the code and let you inform about the result.

    Regards

    Deepak

    Hi Deepak,

    Have you got chance to check code?

    Thanks,

    Monday, June 12, 2017 3:22 PM
  • Hi Me.Saqib,

    can I know when you run first file and when you run second file?

    I find that you are using send mail method.

    where you called this method?

    Regards

    Deepak


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, June 13, 2017 7:43 AM
    Moderator
  • I have separate module (test project) that calls both files (they are part of Class). 

    Here is the code of my test file.

            Dim obj As New SendMailv2
            obj.ProfileName = "outlook"
            obj.Init()
    
            Dim array(2) As String
    
            Dim olMail As OutlookMailMessage = New OutlookMailMessage
            olMail.OutlookApp = obj.OutlookApp
            olMail.ProfileName = obj.ProfileName
    
            'olMail.MailMessage = ""
            olMail.MailToRecipients = "test@myemail.com"
    
            olMail.Subject = "from dotnet"
            olMail.Body = "test email"
            olMail.Important = 2
            olMail.MailBodyFormat = 0
    
            array(0) = ("C:\test.PNG")
    
            For Each item As String In array
                olMail.Attachments = item
            Next
    
            olMail.SendMail()
    

    Thursday, June 15, 2017 6:16 PM
  • Hi Me.Saqib,

    did you created ParseMailString() method in your code.

    when I try to test the code I did not find that method in above sample.

    Regards

    Deepak


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, June 20, 2017 5:07 AM
    Moderator
  • Sorry, here are 2 functions that I had in my helper module. You can add them to sendmail function.

        Public Function ParseMailString(ByVal mailAddresses As String) As String()
    
            Dim PROC_NAME As String = "ParseMailString"
            Dim list(0) As String '= Nothing
            Try
                If mailAddresses.Contains(";") OrElse mailAddresses.Contains(",") OrElse mailAddresses.Contains("|") Then
                    list = Split(mailAddresses, ";")
                    If list.Count = 1 Then
                        list = Split(mailAddresses, ",")
                    End If
                    If list.Count = 1 Then
                        list = Split(mailAddresses, "|")
                    End If
                Else
                    list = New String(0) {}
                    list(0) = mailAddresses
                End If
            Catch ex As Exception
                Throw ex
            End Try
    
            Return list
        End Function
    
        Public Sub AddMailAddresses(email As Object, ByVal addressList As List(Of String), Optional ByVal AddressAs As String = "to")
    
            Dim recip As Outlook.Recipient
            
            If Not addressList Is Nothing Then
                For Each item In addressList
                    If item <> "" Then
                        If TypeOf (email) Is Outlook.MailItem Then
                            Select Case AddressAs
                                Case "to"
                                    recip = DirectCast(email, Outlook.MailItem).Recipients.Add(item)
                                    recip.Type = Outlook.OlMailRecipientType.olTo
                                Case "cc"
                                    recip = DirectCast(email, Outlook.MailItem).Recipients.Add(item)
                                    recip.Type = Outlook.OlMailRecipientType.olCC
                            End Select
                        ElseIf TypeOf email Is MailMessage Then
                        End If
                    End If
                Next
            End If
    
        End Sub

    • Edited by Me.Saqib Wednesday, June 21, 2017 10:06 PM
    Wednesday, June 21, 2017 10:06 PM
  • Hello Saqib,

    Why do you need to keep Outlook alive all the time?

    Instead of holding COM references and their objects in memory it will be more efficient to create or get access to them when required only. So, you will avoid such situations and will be dealing with the alive Outlook instance only.

    Another possible solution is to handle the Close event of the Explorer class. Outlook is closed when the last Explorer window is closed as a rule. So, you may consider cancelling the default action be setting the Cancel parameter to true. Thus,  you will be sure Outlook is running all the time, i.e. prevent it from closing by users.


    profile for Eugene Astafiev at Stack Overflow, Q&A for professional and enthusiast programmers

    Thursday, June 22, 2017 12:36 PM

  • Another possible solution is to handle the Close event of the Explorer class. Outlook is closed when the last Explorer window is closed as a rule. So, you may consider cancelling the default action be setting the Cancel parameter to true. Thus,  you will be sure Outlook is running all the time, i.e. prevent it from closing by users.

    The referenced documentation seems to indicate that it pertains to Office 365.

    For Outlook 2013 and earlier the Explorer Close event documentation does not include a cancel option. And there is no cancel parameter for the close event contained in Outlook's type libraries for those versions.

    Am I missing something?




    • Edited by RLWA32 Thursday, June 22, 2017 2:44 PM typo
    Thursday, June 22, 2017 2:04 PM
  • The referenced documentation is not related to Office 365 only. So, I think you are on the wrong avenue. I am far away from my computer at the moment and can't give you any information at the moment. 

    profile for Eugene Astafiev at Stack Overflow, Q&A for professional and enthusiast programmers

    Thursday, June 22, 2017 3:04 PM
  • The referenced documentation is not related to Office 365 only. So, I think you are on the wrong avenue. I am far away from my computer at the moment and can't give you any information at the moment. 

    The following screenshots are from the MSOUTL.olb type library for Outlook 2013.

    Following Outlook 2013 docs have a parameter but it seems to confuse Inspector close with Explorer close.  The text makes no sense for an Explorer (e.g., olPromptForSave) and conflicts with the typelibs.

    and also


    Finally, the online documentation in the link has the same confused discussion of Inspector objects just like the Outlook 2013 excerpt posted above.

    • Edited by RLWA32 Thursday, June 22, 2017 3:39 PM added comment
    Thursday, June 22, 2017 3:27 PM
  • Yeah, I've seen that in the type library viewer. As a possible workaround Outlook can be launched from the Quit event handler as the Outlook 2010 add-in, how do I cancel close event, minimize window? (C#) page describes. 

    profile for Eugene Astafiev at Stack Overflow, Q&A for professional and enthusiast programmers

    Thursday, June 22, 2017 4:16 PM
  • IMHO I believe the docs are inaccurate regarding the Explorer Close event.  It seems that one cannot programatically  prevent a user from terminating Outlook.

    I remember the good old old days when MS Office programs used to respect the COM rules that a running server would not terminate while there were outstanding references to its COM objects. Sigh.

    Thursday, June 22, 2017 5:00 PM
  • Hi Me.Saqib,

    I will try to check the code and let you inform about the result.

    Regards

    Deepak 

    Deepak, were you able to find anything ?

    Friday, July 14, 2017 4:11 PM
  • Of course you can prevent Outlook from closing :-)

    As long as you keep a reference to an Inspector or an Explorer object (they don't need to be visible), Outlook won't close.

    You can open a folder (e.g. GetDefaultFolder.(olFolderInbox)), retrieve Explorer by calling MAPIFolder.GetExplorer, and by keeping that Explorer referenced Outlook will be prevented from closing.

    Of course I doubt your users would appreciate that - when I close Outlook, I expect it to go away so that I can launch it using a different profile.  


    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Friday, July 14, 2017 5:08 PM
  • Dmitry,

    Thanks for the interesting idea.

    However, a quick test with Outlook 2013 (x86) on Win 8.1 showed that although holding an Explorer reference was helpful it did not prevent the user from terminating Outlook by selecting "Exit Now" from the context menu of the tray notification icon.

    Friday, July 14, 2017 5:58 PM
  • True. In that case the best you can do is attach to the new instance of Outlook when you get an RPC error.  And the Application.Quit event should fire.

    Dmitry Streblechenko (MVP)
    http://www.dimastr.com/redemption
    Redemption - what the Outlook
    Object Model should have been
    Version 5.5 is now available!

    Friday, July 14, 2017 6:13 PM
  • After starting Outlook from my test application through COM and grabbing an Explorer reference I opened it from the start menu.  Upon closing the visible Explorer, Outlook 2013 fired the Application Quit event even though it did not close. It did not fire the event again when it was closed from the icon context menu.
    Friday, July 14, 2017 6:24 PM
  • There is another possibility.  The following administrative template setting prevented Outlook from closing while it was being used through COM from another process.  It was not necessary to create and hold any extra references (such as an explorer ref.).  As in other scenarios, the user could always terminate Outlook through the notification tray icon context menu.

    This is the setting that prevented premature closing while Outlook was being automated -


    • Edited by RLWA32 Wednesday, July 19, 2017 1:33 PM clarified comment
    Wednesday, July 19, 2017 12:40 PM
  • One strange issue that whenever I reboot my server, my application throws error only for first time:

    "Cannot create ActiveX component" on this line CreateObject("Outlook.Application.14")

    and then it is ok after that.

    Any one has any suggestions?

    Friday, July 28, 2017 5:27 PM
  • Hi Me.Saqib,

    I can see that you are mentioning the version in your line of code.

    CreateObject("Outlook.Application.14")

    so when you are trying to using any other version of Outlook then it generates an error.

    so you can try to change the version in code according to your Outlook .

    Regards

    Deepak


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, July 31, 2017 5:29 AM
    Moderator
  • I have only outlook 2010 installed on that machine. This is what I have specified.
    Tuesday, August 1, 2017 7:49 PM
  • Hi Me.Saqib,

    you can try to repair your Office suite.

    it is possible that something corrupted and because of that you are getting an error.

    and again try to check for the issue.

    Regards

    Deepak


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Monday, August 7, 2017 7:52 AM
    Moderator