1
votes

I am writing a script that at the end will send an email with logs from a completed process. We use Outlook 2013 at work and I'm testing this on both outlook 2013 and Outlook 2010 with the same results.

The script will only generate a mailitem if Outlook is closed. If it is open it throws a bunch of errors. Anyone have an idea?

Here is the code:

############ Setup the outlook object#####

$outlook = New-Object -ComObject Outlook.Application
$datestr = get-date -Format yyyyMM
$message = $outlook.CreateItem(0)

###### Create an email and add the logs as attachments ######

$toaddress1 = "[email protected]"
$msub = "Monthly load - logs attached $datestr" 
$message.Recipients.Add($toaddress1)  
$message.Subject = "$msub"  
$message.htmlbody = "See attached logs for this months file load<br><br>" 

$filepath = get-childitem  "c:\path\log" | ? {$_.PSISContainer -eq $false} | select -ExpandProperty fullname
    foreach($file in $filepath) {

$message.Attachments.Add($file)
$message.display()
  } 

Like I said, it works when Outlook is not open but with it open it generates the following errors from PowerShell:

New-Object : Retrieving the COM class factory for component with CLSID
{0006F03A-0000-0000-C000-000000000046} failed due to the following error:
80080005 Server execution failed (Exception from HRESULT: 0x80080005
(CO_E_SERVER_EXEC_FAILURE)).
At c:\scripts\mailtest.ps1:4 char:13
+ $message = (New-Object -ComObject Outlook.Application)
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : ResourceUnavailable: (:) [New-Object], COMException
    + FullyQualifiedErrorId : NoCOMClassIdentified,Microsoft.PowerShell.Commands.NewObjectCommand

Exception calling "CreateItem" with "1" argument(s): "The RPC server is
unavailable. (Exception from HRESULT: 0x800706BA)"
At c:\scripts\mailtest.ps1:7 char:1
+ $message = $outlook.CreateItem(1)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : COMException

You cannot call a method on a null-valued expression.
At c:\scripts\mailtest.ps1:13 char:1
+ $message.Recipients.Add($toaddress1)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At c:\scripts\mailtest.ps1:14 char:1
+ $message.Subject = "$msub"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], COMException
    + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException

The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At c:\scripts\mailtest.ps1:15 char:1
+ $message.htmlbody = "Jeff attached are the logs from this months load ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], COMException
    + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException

You cannot call a method on a null-valued expression.
At c:\scripts\mailtest.ps1:20 char:1
+ $message.Attachments.Add($file)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At c:\scripts\mailtest.ps1:21 char:1
+ $message.display()
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], COMException
    + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException

You cannot call a method on a null-valued expression.
At c:\scripts\mailtest.ps1:20 char:1
+ $message.Attachments.Add($file)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At c:\scripts\mailtest.ps1:21 char:1
+ $message.display()
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], COMException
    + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException

You cannot call a method on a null-valued expression.
At c:\scripts\mailtest.ps1:20 char:1
+ $message.Attachments.Add($file)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At c:\scripts\mailtest.ps1:21 char:1
+ $message.display()
+ ~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : OperationStopped: (:) [], COMException
    + FullyQualifiedErrorId : System.Runtime.InteropServices.COMException

I went on MSDN and could not find any updated methods for Outlook.Application so it looks like I'm doing this right or maybe a better way? In this case Outlook is always going to be open in our environment.

1
Can you check File, Options, Trust Center, Trust Center Settings, Programmatic Access. You may need to open up the settings there to allow PowerShell to manipulate the Outlook mail files while it is open. - user4039065
Thanks, good idea but it appears to be set to allow pragmatic access to send mail on my behalf. I also went as far as turning off my Anti-virus temporarily to see if that would allow it to work but it doesn't. I have other VB scripts that do this successfully however. Seems silly that it only works when Outlook is not a running process. Thank you ! - PCPaul
Oh and I may add this is happening on Both Windows 8.1 Enterprise (Work) and Windows 10 Professional. I did some investigating and found this interesting article about it blogs.msdn.com/b/adioltean/archive/2005/06/24/432519.aspx - PCPaul

1 Answers

1
votes

I think that Outlook only allows a single instance to be running at any time, especially for a non-exchange mailbox (it locks the PST).

You might consider checking for a running instance, and then retrieving the instance instead of creating a new one. Maybe something like this:

if (Get-Process Outlook) {
    $outlook = [System.Runtime.InteropServices.Marshal]::GetActiveObject('Outlook.Application')
} else {
    $outlook = New-Object -ComObject Outlook.Application
}

I haven't thoroughly tested this though.

Also, if Outlook is running under a different user account than this code, then it probably won't work anyway.