2015-04-17 109 views
0

我需要通過IIS創建一個outlook .msg文件,它可以當我在「IIS Express」中運行它,但無法在IIS中運行甚至將應用程序池設置爲本地系統。ASP.NET無法調用Outlook功能來創建.msg文件

錯誤消息:操作中止(從HRESULT異常:0x80004004(E_ABORT))在Microsoft.Office.Interop.Outlook.Attachments.Add(對象源,對象類型,對象的位置,對象顯示名稱)

環境: Win7的32位,Office 2010中,Vistual Studio Pro中2013

的源代碼如下:

Try 
     Dim oApp As Interop.Outlook._Application 
     Dim oMsg As Interop.Outlook._MailItem 
     oApp = New Interop.Outlook.Application 
     oMsg = oApp.CreateItem(Interop.Outlook.OlItemType.olMailItem) 
     oMsg.Subject = "Test Subject" 
     oMsg.Body = "Test Body" 
     oMsg.To = "" 

     Dim attachedFilePath As String = "C:\\temp\\A1234563A.zip" 
     If String.IsNullOrEmpty(attachedFilePath) = False Then 
      Dim sBodyLen As Integer = Int(oMsg.Body) 
      Dim oAttachs As Interop.Outlook.Attachments = oMsg.Attachments 
      Dim oAttach As Interop.Outlook.Attachment 
      oAttach = oAttachs.Add(attachedFilePath, , sBodyLen, "A1234563A.zip") 
     End If 
     oMsg.SaveAs("c:\\temp\\abcd.msg", Microsoft.Office.Interop.Outlook.OlSaveAsType.olMSG) 

    Catch ex As System.Exception 
     'xxxxx 
    Finally 
     GC.Collect() 
     GC.WaitForPendingFinalizers() 
    End Try 
+2

對不起,但您無法從Web服務器訪問客戶端Outlook實例,因爲Web服務器通常在單獨的計算機上運行。您需要直接訪問Exchange Server。 –

+0

尤爾根有權利。如果你想爲你的客戶創建一個.msg,你不能這樣做。在IISExpress上,它可以工作,因爲它是您的機器和客戶端。如果要在IIS服務器上創建該文件,則必須在其上安裝Outlook,在服務器上創建.msg文件以讀取該文件並將其回覆給客戶端。但出於安全考慮,您將無法在Web服務器上安裝Outlook,並在Web服務器上創建文件來讀取它並將其回覆給您的客戶端顯然不是一個乾淨的解決方案^^。 – D4rkTiger

回答

2

微軟目前並不提倡,不支持,Microsoft Office應用程序fr的自動化om在任何無人蔘與的非交互式客戶端應用程序或組件(包括ASP,ASP.NET,DCOM和NT服務)中,因爲Office在此環境中運行時可能會出現不穩定的行爲和/或死鎖。

如果您正在構建一個在服務器端上下文中運行的解決方案,那麼您應該嘗試使用對於無人執行安全的組件。或者,您應該嘗試找到允許至少部分代碼運行客戶端的替代方案。如果您從服務器端解決方案使用Office應用程序,則該應用程序將缺少成功運行所需的許多必要功能。此外,您將面臨整體解決方案穩定性的風險。

閱讀更多關於Considerations for server-side Automation of Office文章。

+0

謝謝,現在我創建.msg文件沒有Outlook。它似乎有用。 –

0

我使用System.Net.Mail代替 - https://msdn.microsoft.com/en-us/library/system.net.mail(v=vs.110).aspx

你建立一個MAILMESSAGE,您可以添加附件,並設置重要性,並做你上面做的一切。

這對我來說很好,你不需要在服務器上安裝任何東西。

編輯

下面是一些對你的示例代碼 - 導入System.Net.MailSystem.Configuration命名空間。在這個例子中,我發送一個日誌,所以我從App.Config獲得地址和SMTP中繼。您可以根據需要更改這些設置。

這也從App.Config中指定的位置附加文件。

string[] recipients = ConfigurationManager.AppSettings["recipients"].ToString().Split(','); 


      MailMessage msg = new MailMessage(); 
      msg.From = new MailAddress("[email protected]"); 
      msg.Subject = "Log Error Report"; 

      foreach (string addr in recipients) 
      { 
       msg.To.Add(new MailAddress(addr)); 
      } 

      string body = System.Environment.NewLine + "Please check these logs for errors."; 
      body += System.Environment.NewLine + "Message line 2"; 

      msg.Body = body; 
      msg.Priority = MailPriority.High; 

      String attchMnts = ConfigurationManager.AppSettings["logfile"].ToString(); 
      String[] attchPaths = attchMnts.Split(','); 

      foreach (string path in attchPaths) 
      { 
       Attachment atch = new Attachment(path); 
       msg.Attachments.Add(atch); 
      } 

      SmtpClient client = new SmtpClient(ConfigurationManager.AppSettings["smtpRelay"].ToString()); 
      client.Send(msg); 
+0

謝謝,我需要添加附件並保存爲用戶的.msg文件。 –

+0

System.Net.Mail支持附件。我已經用日誌文件完成了。我會更新我的帖子,爲您添加一個樣本。 – Tim

1

您的選項是

  1. 擴展MAPI(OpenImsgOnIStg等)來創建一個MSG文件,並設置所有相關的MAPI屬性,但它是從C只能訪問++或Delphi

  2. 使用Windows API在代碼中明確構建文件(它的格式已記錄) - https://msdn.microsoft.com/en-us/library/cc463912(v=exchg.80).aspx

  3. 使用Redemption - 這是一個擴展的MAPI包裝器,可以從任何語言的服務中使用,包括C#,VB。Net或VB腳本:

 


     set Session = CreateObject("Redemption.RDOSession") 
     set Msg = Session.CreateMessageFromMsgFile("C:\Temp\test.msg") 
     Msg.Sent = true 
     set recip = Msg.Recipients.AddEx("This user", "[email protected]", "SMTP", olTo) 
     Msg.Subject = "fake received message" 
     Msg.Body = "just a test" 
     Msg.SentOn = Now 
     Msg.ReceivedTime = Now 
     'set the sender related properties 
     vSenderEntryId = Session.CreateOneOffEntryID("Joe The Sender", "SMTP", "[email protected]", false, true) 
     'PR_SENDER_xyz 
     Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0C1E001F") = "SMTP" 
     Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0C1F001F") = "[email protected]" 
     Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0C190102") = vSenderEntryId 
     Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0C1A001F") = "Joe The Sender" 
     'PR_SENT_REPRESENTING_xyz 
     Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0064001F") = "SMTP" 
     Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0065001F") = "[email protected]" 
     Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x00410102") = vSenderEntryId 
     Msg.Fields("http://schemas.microsoft.com/mapi/proptag/0x0042001F") = "Joe The Sender" 
     'all done 
     Msg.Save 

 
+0

謝謝,現在我創建.msg文件沒有Outlook。它似乎有用。 –

+0

@chenshuguang,你用什麼方法創建msg文件? – par

1

感謝所有,最後我做到這一點如下:1. 手動創建由Outlook模板.msg文件。 2.打開它並複製到新的流。來自intenet的許多代碼。 3.將我的信息更新到此流,並保存爲新的.msg文件。 (以下是我更新.msg文件中的附件文件時的源代碼,並且您應該從OutlookStorage.cs中獲取其他源代碼)。

//create a ILockBytes (unmanaged byte array) and then create a IStorage using the byte array as a backing store 
NativeMethods.CreateILockBytesOnHGlobal(IntPtr.Zero, true, out memoryStorageBytes); 
        NativeMethods.StgCreateDocfileOnILockBytes(memoryStorageBytes, NativeMethods.STGM.CREATE | NativeMethods.STGM.READWRITE | NativeMethods.STGM.SHARE_EXCLUSIVE, 0, out memoryStorage); 

//copy the save storage into the new storage 
saveMsg.storage.CopyTo(0, null, IntPtr.Zero, memoryStorage); 

//Attachments (37xx): 
//0x3701: Attachment data  <- This is the binary attachment 
//0x3703: Attach extension 
//0x3704: Attach filename 
//0x3707: Attach long filenm 
//0x370E: Attach mime tag 
//0x3712: Attach ID (?) 

// replace attachment with myself file 
var myNameIdSourceStorage = memoryStorage.OpenStorage(OutlookStorage.ATTACH_STORAGE_PREFIX + "00000000", IntPtr.Zero, NativeMethods.STGM.READWRITE | NativeMethods.STGM.SHARE_EXCLUSIVE,IntPtr.Zero, 0); 
            myNameIdSourceStorage.DestroyElement("__substg1.0_37010102"); 

// Create the property stream again and write in the padded version 
var pStream = myNameIdSourceStorage.CreateStream("__substg1.0_37010102", 
         NativeMethods.STGM.READWRITE | NativeMethods.STGM.SHARE_EXCLUSIVE, 0, 0); 
pStream.Write(newFileByte, newFileByte.Length, IntPtr.Zero); 

// Open stream from the storage 
var mystream = myNameIdSourceStorage.OpenStream("__properties_version1.0", IntPtr.Zero, 
         NativeMethods.STGM.READWRITE | NativeMethods.STGM.SHARE_EXCLUSIVE, 0); 

System.Runtime.InteropServices.ComTypes.STATSTG elementStats; 
mystream.Stat(out elementStats, 0);      

// Read the stream into a managed byte array 
var iStreamContent = new byte[elementStats.cbSize]; 
mystream.Read(iStreamContent, iStreamContent.Length, IntPtr.Zero); 
iStreamContent[0xc0] = (byte)(newFileByte.Length & 0xFF); 
iStreamContent[0xc1] = (byte)(newFileByte.Length >> 8); 
iStreamContent[0xc2] = (byte)(newFileByte.Length >> 16); 
iStreamContent[0xc3] = (byte)(newFileByte.Length >> 24); 
mystream.Write(iStreamContent, 0, IntPtr.Zero); 

//0x3704: Attach filename 
myNameIdSourceStorage.DestroyElement("__substg1.0_3704001F"); 
pStream = myNameIdSourceStorage.CreateStream("__substg1.0_3704001F", 
         NativeMethods.STGM.READWRITE | NativeMethods.STGM.SHARE_EXCLUSIVE, 0, 0); 
pStream.Write(newProps, 8, IntPtr.Zero);