[英]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);
}
}
}
需要參考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.