繁体   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