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

Context:语境:

I am able to copy (using CTRL-C) and paste programmatically a file from the clipboard when the file copied to the clipboard is for example a file on the desktop.当复制到剪贴板的文件例如是桌面上的文件时,我可以复制(使用 CTRL-C)并以编程方式粘贴剪贴板中的文件。 This is simple enough using the following syntax:这很简单,使用以下语法:

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

where Clipboard.GetFileDropList()[0] returns the path of the copied file and savePath is the paste location.其中 Clipboard.GetFileDropList()[0] 返回复制文件的路径, savePath 是粘贴位置。

However, i find that the above syntax does NOT work if the copied file (using CTRL-C) is a file attachment in an Outlook email.但是,我发现如果复制的文件(使用 CTRL-C)是 Outlook email 中的文件附件,则上述语法不起作用。 In that scenario, Clipboard.ContainsFileDropList() returns false and Clipboard.GetFileDropList()[0] results in the following error message:在这种情况下,Clipboard.ContainsFileDropList() 返回 false 并且 Clipboard.GetFileDropList()[0] 导致以下错误消息:

"ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index" “ArgumentOutOfRangeException:索引超出范围。必须为非负数且小于集合的大小。参数名称:索引”

This is despite the fact that pressing CTRL-V does successfully paste the file, confirming that the file was initially successfully copied to the clipboard.尽管按下 CTRL-V 确实成功粘贴了文件,但确认文件最初已成功复制到剪贴板。

Question:问题:

Sorry if i missed something very basic.对不起,如果我错过了一些非常基本的东西。 My question is how to programmatically paste/save an email attachment (PDF, Word, etc...) from the clipboard to a file location when that email attachment was copied into the clipboard using CTRL-C from within Outlook.我的问题是如何以编程方式将 email 附件从 Z038E648F69B213B2A2A24D 中的 email 附件复制到剪贴板中时,以编程方式将 email 附件(PDF、Word 等)粘贴/保存到文件位置

Note that i do understand that what i am trying to do can be solved by skipping the Clipboard and interacting programmatically with Outlook to access a selected email attachment.请注意,我确实明白我想要做的事情可以通过跳过剪贴板并以编程方式与 Outlook 交互以访问选定的 email 附件来解决。 However, my goal here is to learn how to interact programmatically with the Clipboard under different scenario.但是,我的目标是学习如何在不同场景下以编程方式与剪贴板交互。

You are using the wrong DataFormat .您使用了错误的DataFormat You can always get a list of currently present data formats by calling Clipboard.GetDataObject().GetFormats() .您始终可以通过调用Clipboard.GetDataObject().GetFormats()来获取当前存在的数据格式列表。

You need to use:你需要使用:

"FileGroupDescriptor" to retrieve the file names "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" to retrieve the raw file contents "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;
}

Save attached file to disk将附件保存到磁盘

Since Windows only adds the first selected attachment to the system clipboard, this solution can only save a single attachment.由于 Windows 仅将第一个选择的附件添加到系统剪贴板,因此此解决方案只能保存单个附件。 Apparently the office clipboard is not accessible.显然无法访问办公室剪贴板。

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);
    }
  }
}

Save attached files to disk using the Office API使用 Office API 将附件保存到磁盘

Requires to reference Microsoft.Office.Interop.Outlook.dll .需要参考Microsoft.Office.Interop.Outlook.dll This solution does not depend on the system clipboard.此解决方案不依赖于系统剪贴板。 It just reaads the selected attachments from the currently open message item in the Outlook explorer.它只是从 Outlook 资源管理器中当前打开的消息项中读取选定的附件。
You still can monitor the system clipboard to trigger the process to save the attachments.您仍然可以监视系统剪贴板以触发保存附件的过程。

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.

相关问题 如何使用C#在Outlook电子邮件中获取附件类型 - How to Get the Attachment Type in an Outlook email using C# 如何使用 C# 从 Outlook 保存附件? - How do I save attachment from Outlook using C#? 如何发送到剪贴板的数据网格视图内容,如CTRL-C - How to send to clipboard datagridview content like CTRL-C C#:如何在单个图像(例如* .png)中保存图表和文本框? - c#: how can i save a chart and a textbox in a single image (e.g. *.png)? 如何使用CodeDOM / T4 / PostSharp /等用c#自动创建(例如)单例? - How to automatically create (e.g.) singleton with c# using CodeDOM / T4 / PostSharp / whatever? C#使用Outlook发送电子邮件-发件箱中没有附件 - C# send email with Outlook - No attachment in Outbox 如何在 C# 中以编程方式创建桌面快捷方式(链接),但使用自己的快捷方式文件扩展名(例如 .appfolder)而不是 .lnk? - How to create a desktop shortcut (link), but with own shortcut file extension (e.g. .appfolder) instead of .lnk programmatically in C#? C#如何将模糊输入的对象(例如“ var”)作为特定类型的对象(例如“ Form”)访问 - C# How to access an ambiguously typed object (e.g. 'var') as a specifically typed object (e.g. 'Form') 如何仅验证特定字母的C#代码? 例如,用户应仅输入A或S或B,也应输入不带正则表达式并使用if语句 - How to validate c# code for specific alphabets only? e.g., the user should input only A or S or B and that too without regex and using if statement 如何将生成的pdf文件作为附件发送到C#的电子邮件中? - How to send generated pdf file as attachment in email from C#?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM