title: C# Drag and Drop from Outlook using .NET 4.5 or later
body: <p>Does anyone have any C# code to accept Drag and Drop from Outlook to a Winforms application that works under <strong>.Net Framework 4.5</strong> or later please?</p>
  
  <p>I have some code that's been in use for about 12 years now, which includes the ability to drag and drop items, including emails from Outlook.</p>
  
  <p>The code has been running perfectly when compiled with the Target Framework set to <strong>.Net Framework 4</strong>, however some new features I've been working on require <strong>.Net Framework 4.5</strong> or later. This however prevents the Drag and Drop from Outlook working.</p>
  
  <p>The code is quite convoluted, it does a ton of stuff unrelated to the issue to determine where the file goes, and who it shows up for etc, so I won't include all that, but the point at which it breaks is nice and simple...</p>
  
  <pre><code>public string ImportEmail(DragEventArgs e)
      {
          string strResult = string.Empty;
          var dataObject = new OutlookDataObject(e.Data);
          var filenames = (string[]) dataObject.GetData("FileGroupDescriptor");
  </code></pre>
  
  <p>Under <strong>.NET 4</strong>, the last line above returns the filename(s) as expected.</p>
  
  <p>Under <strong>.NET 4.5 or later</strong>, the last line above returns <strong>null</strong>.</p>
  
  <p>I tested it under .NET 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2 and 4.7.2 (all the versions I have installed), it doesn't work on any of them.</p>
  
  <p>I've been trawling around for a couple of days trying out all the Drag and Drop code I could find, and none of it seems to work under .Net 4.5 or later.</p>
  
  <p>Below is the complete code for a test form I did, using code I dug up from here and elsewhere. This code works perfectly under .Net Framework 4, whether you drag and drop a file or an email from Outlook, but neither works under .Net Framework 4.5 or later (tested all the same versions again).</p>
  
  <pre><code>using System;
  using System.IO;
  using System.Collections.Generic;
  using System.Runtime.InteropServices;
  using System.Runtime.InteropServices.ComTypes;
  using System.Text;
  using System.Reflection;
  using System.Windows.Forms;
  
  namespace OutlookDragNDropTest
  {
      public partial class OutlookDragNDropTest : Form
      {
          public OutlookDragNDropTest()
          {
              InitializeComponent();
          }
  
          private void Form1_DragEnter(object sender, DragEventArgs e)
          {
              if (e.Data.GetDataPresent(DataFormats.FileDrop))
              {
                  e.Effect = DragDropEffects.Copy;
              }
              //    or this tells us if it is an Outlook attachment drop
              else if (e.Data.GetDataPresent("FileGroupDescriptor"))
              {
                  e.Effect = DragDropEffects.Copy;
              }
              //    or none of the above
              else
              {
                  e.Effect = DragDropEffects.None;
              }
          }
  
          private void Form1_DragDrop(object sender, DragEventArgs e)
          {
              try
              {
                  //wrap standard IDataObject in OutlookDataObject
                  OutlookDataObject dataObject = new OutlookDataObject(e.Data);
  
                  //get the names and data streams of the files dropped
                  string[] filenames = (string[])dataObject.GetData("FileGroupDescriptor");
                  MemoryStream[] filestreams = (MemoryStream[])dataObject.GetData("FileContents");
  
                  string tempPath = Path.GetTempPath();
  
                  for (int fileIndex = 0; fileIndex &lt; filenames.Length; fileIndex++)
                  {
                      //use the fileindex to get the name and data stream
                      string filename = tempPath + filenames[fileIndex];
                      MemoryStream filestream = filestreams[fileIndex];
  
                      //save the file stream using its name to the application path
                      FileStream outputStream = File.Create(filename);
                      filestream.WriteTo(outputStream);
                      outputStream.Close();
                      MessageBox.Show("Output to " + filename);
                  }
              }
              catch (Exception ex)
              {
                  MessageBox.Show("Error : " + ex.ToString());
              }
          }
      }
  }
  </code></pre>
  
  <p>(Ok, seems that code was too long for one post, the OutlookDataObject class will be in a reply below)...</p>
  
  <p>The only other thing is the form itself, which is just a blank Winforms form, with the following Properties set:-</p>
  
  <p>AllowDrop : True</p>
  
  <p>DragEnter event : Form1_DragEnter</p>
  
  <p>DragDrop event : Form1_DragDrop</p>
  
  <p>If it's relevant, I'm using Visual Studio 2017 Professional, and running on Windows 10, although the Drag and Drop not working has also been reported by clients running Windows 7.</p>