簡體   English   中英

如何在 C# 中以編程方式保存已由用戶使用 CTRL-C 復制到剪貼板的 outlook email 附件(例如 PDF)

[英]How to programmatically save an outlook email attachment (e.g. PDF) that has been copied to clipboard by the user using CTRL-C, in C#

語境:

當復制到剪貼板的文件例如是桌面上的文件時,我可以復制(使用 CTRL-C)並以編程方式粘貼剪貼板中的文件。 這很簡單,使用以下語法:

File.Copy(Clipboard.GetFileDropList()[0], savePath)

其中 Clipboard.GetFileDropList()[0] 返回復制文件的路徑, savePath 是粘貼位置。

但是,我發現如果復制的文件(使用 CTRL-C)是 Outlook email 中的文件附件,則上述語法不起作用。 在這種情況下,Clipboard.ContainsFileDropList() 返回 false 並且 Clipboard.GetFileDropList()[0] 導致以下錯誤消息:

“ArgumentOutOfRangeException:索引超出范圍。必須為非負數且小於集合的大小。參數名稱:索引”

盡管按下 CTRL-V 確實成功粘貼了文件,但確認文件最初已成功復制到剪貼板。

問題:

對不起,如果我錯過了一些非常基本的東西。 我的問題是如何以編程方式將 email 附件從 Z038E648F69B213B2A2A24D 中的 email 附件復制到剪貼板中時,以編程方式將 email 附件(PDF、Word 等)粘貼/保存到文件位置

請注意,我確實明白我想要做的事情可以通過跳過剪貼板並以編程方式與 Outlook 交互以訪問選定的 email 附件來解決。 但是,我的目標是學習如何在不同場景下以編程方式與剪貼板交互。

您使用了錯誤的DataFormat 您始終可以通過調用Clipboard.GetDataObject().GetFormats()來獲取當前存在的數據格式列表。

你需要使用:

"FileGroupDescriptor"檢索文件名

private static async Task<List<string>> GetAttachedFileNamesFromClipboardAsync(IDataObject clipboardData)
{
  if (!clipboardData.GetDataPresent("FileGroupDescriptor"))
  {
    return new List<string>();
  }

  using (var descriptorStream = clipboardData.GetData("FileGroupDescriptor", true) as MemoryStream)
  {
    using (var streamReader = new StreamReader(descriptorStream))
    {
      var streamContent = await streamReader.ReadToEndAsync();
      string[] fileNames = streamContent.Split(new[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);
      return new List<string>(fileNames.Skip(1));
    }
  }
}

"FileContents"檢索原始文件內容

// Returns the attachment file content as string
private static async Task<string> GetAttachmentFromClipboardAsync(IDataObject clipboardData)
{
  if (!clipboardData.GetDataPresent("FileContents"))
  {
    return string.Empty;
  }

  using (var fileContentStream = clipboardData.GetData("FileContents", true) as MemoryStream)
  {
    using (var streamReader = new StreamReader(fileContentStream))
    {
      return await streamReader.ReadToEndAsync();
    }
  }
}

// Returns the attachment file content as MemoryStream
private static MemoryStream GetAttachmentFromClipboard(IDataObject clipboardData)
{
  if (!clipboardData.GetDataPresent("FileContents"))
  {
    return null;
  }

  return clipboardData.GetData("FileContents", true) as MemoryStream;
}

將附件保存到磁盤

由於 Windows 僅將第一個選擇的附件添加到系統剪貼板,因此此解決方案只能保存單個附件。 顯然無法訪問辦公室剪貼板。

private static async Task SaveAttachmentFromClipboardToFileAsync(IDataObject clipboardData, string destinationFilePath)
{
  if (!clipboardData.GetDataPresent("FileContents"))
  {
    return;
  }

  using (var attachedFileStream = clipboardData.GetData("FileContents", true) as MemoryStream)
  {
    using (var destinationFileStream = File.Open(destinationFilePath, FileMode.OpenOrCreate))
    {
      await attachedFileStream.CopyToAsync(destinationFileStream);
    }
  }
}

使用 Office API 將附件保存到磁盤

需要參考Microsoft.Office.Interop.Outlook.dll 此解決方案不依賴於系統剪貼板。 它只是從 Outlook 資源管理器中當前打開的消息項中讀取選定的附件。
您仍然可以監視系統剪貼板以觸發保存附件的過程。

private static void SaveSelectedAttachementsToFolder(string destinationFolderPath)
{
  var outlookApplication = new Microsoft.Office.Interop.Outlook.Application();
  Explorer activeOutlookExplorer = outlookApplication.ActiveExplorer();
  AttachmentSelection selectedAttachments = activeOutlookExplorer.AttachmentSelection;

  foreach(Attachment attachment in selectedAttachments)
  {
    attachment.SaveAsFile(Path.Combine(destinationFolderPath, attachment.FileName));
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM